客制化键盘刷砖后的固件救援与防护实践

Feng 44 阅读 操作系统

键盘刷成砖,多数不是硬件坏了,而是主控停在了一个你进不去的状态。Teensy 2.0 改的 60% 板子,跑 make <keyboard>:default:flash 时 USB 接触不良,刷写中断,重启后 RGB 常亮红灯、按键无响应——这是主控进了保护模式,Bootloader 区或固件分区表被打断在半途。下面按“先判断状态、再动手救、最后建防线”的顺序讲。

先分清是假死还是真砖

红灯常亮不等于芯片报废。ATmega32U4 这类主控在刷写中断后通常还留着 DFU 入口,只是正常上电不会主动进去。判断方法很直接:插上 USB,用 lsusb 看有没有出现 Atmel Corp. ATmega32U4 或 03eb:2ff4 这类 DFU 设备 ID。出现了,说明引导程序还活着,走软件恢复;完全不枚举,才考虑外部编程器。

客制化键盘刷砖后的固件救援与防护实践

这里有个容易踩的坑:QMK Toolbox 0.2.x 点 Flash 时会先尝试软复位进 DFU,而 QMK CLI 的 :flash 目标依赖 rules.mk 里的 BOOTLOADER 值决定复位方式。配成 atmel-dfu 和配成 caterina,触发时序完全不同。32u4 上原生 DFU 引导程序对应 atmel-dfu,Pro Micro 那类 Leonardo 兼容板才是 caterina。配错的话,工具会一直等一个永远不出现的设备,看起来就像刷砖了。

短接复位触点的正确时序

需要手动进 DFU 时,镊子短接 RST 与 GND 不是随便碰一下。正确顺序是:先按住短接不放,插入 USB,保持约两秒再松开。松手瞬间主控重新采样,才会落到 DFU 区。很多人反过来先插线再短接,结果只是复位了一次正常固件,白忙。

短接用的镊子尖要细,PCB 上 RST 和 GND 焊盘往往挨得近,手抖容易碰到相邻引脚。旁边备一个 USB 电流表很有用:正常待机几十毫安,短路或芯片异常会看到电流异常跳变,能提前排除供电问题。

外部编程器绕过自检

软件进不去 DFU 时,用 USBasp 或 J-Link 从 ICSP 口直接写。命令本身不复杂:

avrdude -p atmega32u4 -c usbasp -U flash:w:original_firmware.hex

这条命令走的是外部编程器,绕开主控自检,直接把 hex 灌进 flash。执行后如果报 verification error,先别急着加 -F。这个报错常见根因有三类:hex 文件本身不完整、目标芯片的熔丝位与固件不匹配、或者 ICSP 排线接触不良导致写入不稳定。

-F 会强制跳过校验,等于放弃了“写进去的东西对不对”这道检查。它适合确认 hex 无误、只是校验读回偶发失败的情况;如果是熔丝位配错,强制覆盖只会让芯片下次上电依旧不启动。安全做法是先 avrdude -p atmega32u4 -c usbasp -U flash:r:readback.hex:i 把当前 flash 读回来,和源文件比对,确认差异出在哪一段。

另一个高频报错是 usbdev_open(): cannot open device。这基本不是芯片问题,而是权限或驱动:Linux 下当前用户不在 plugdev 组、或者 udev 规则没装;Windows 下则是 libusb 驱动没绑到 USBasp 上。先解决这一层,再谈刷写。

分段校验比整体重刷可靠

固件写完后不要只看 avrdude 的返回码。用 objdump -S compiled_firmware.elf > disassembly.txt 生成反汇编,对照原始固件的 .text 段校验值,能确认代码段是否完整落入。存储分区则用 md5sum sector*.bin 逐块比对,定位是哪一段损坏。

EEPROM 是独立存储区,用户层配置(按键映射、宏定义)通常存在这里。刷主固件前先单独备份:

dfu-programmer atmega32u4 read-eeprom > user_config.bin
hexdump -C user_config.bin | grep "keymap"

这样即使主固件重刷,几百条宏定义也不用重设。判定标准很简单:读回的 bin 大小与芯片 EEPROM 容量一致,hexdump 里能看到预期的键码结构,就算备份成功。

RISC-V 主控换一套工具链

GD32VF103 这类 RISC-V 主控,AVR 那套 avrdude 完全用不上。需要 OpenOCD 配 JTAG:

# openocd.cfg 配置片段
adapter driver ftdi
ftdi_vid_pid 0x0403 0x6010
transport select jtag
source [find target/gd32vf103.cfg]

连上后执行 reset halt 解除写保护,再配合 GDB 单步跟踪固件执行。FTDI 适配器的 VID/PID 要按实际硬件填,0x0403:0x6010 是常见 FT2232 模块的值,填错会连不上。

三道防线怎么实现

硬件层,PCB 设计阶段预留 SWD 或 ICSP 调试口,别等出事再飞线。软件层,rules.mk 里明确 BOOTLOADER = atmel-dfu,并确认引导程序支持双区备份。操作层,每次刷机前跑一遍 dfu-programmer atmega32u4 get bootloader-version,能读出正常版本号,说明引导程序状态健康,再动手。

刷写环境本身也要控住:用带磁环的短 USB 线、避免经过无源 HUB、刷写过程中不要插拔其他 USB 设备。原文提到的那次事故,根因就是接口接触不良导致传输中断,这类问题靠事后救不如事前防。

关于无线恢复的现状

UF2 Bootloader 2.0 的无线恢复思路确实存在,但实现范围有限,主要出现在少数量产键盘上,客制化板子基本用不到。自己搭的板子还是老老实实走 DFU 加外部编程器这条路,别把恢复希望押在还没普及的机制上。

养成季度审计的习惯:校验引导程序、检查存储区块 CRC、实测一次应急恢复通道是否可用。恢复通道要真跑一遍才算数,光看配置项没用。

ID:6946

Feng
这位作者很神秘,还没有填写简介。