第一章:升级机制基础——嵌入式固件升级的常见方式
大家好,我是老李。做嵌入式这行十几年了,今天咱们聊聊固件升级。
说实话,刚入行那会儿,我对升级这事儿不太上心。觉得不就是把新固件写进Flash嘛,有啥难的?直到有一次,我在一个智能网关项目上,升级到一半突然断电了……嗯,那台设备直接变砖了。老板盯着我,客户等着用,那滋味,啧,不想再体验第二次。
从那以后,我养成了一个习惯:做任何升级方案,先想好怎么处理中断和异常。这也是为什么我把这个主题放在课程第一章的原因。
1.1 嵌入式固件升级的常见方式
嵌入式设备的升级方式,说白了就那几种。我按自己的经验给大家梳理一下:
| 升级方式 | 传输介质 | 典型场景 | 我踩过的坑 |
|---|---|---|---|
| 串口升级(XMODEM/YMODEM) | UART | 调试阶段、小批量产 | 波特率不匹配,传一半乱码 |
| 网络升级(TFTP/HTTP) | 以太网 | 产线批量、远程维护 | 网络抖动导致校验失败 |
| USB升级(U盘/DFU) | USB | 现场运维、消费类产品 | 文件系统不识别,U盘格式不对 |
| 无线升级(OTA) | WiFi/BLE/NB-IoT | 物联网终端 | 信号差,下载一半断了 |
| SD卡升级 | SDIO/SPI | 工业设备、车载 | 接触不良,读到一半卡死 |
你想想看,这些方式有个共同点——传输过程都是不可靠的。不管用哪种方式,都有可能在中途被打断。所以,升级中断处理不是锦上添花,而是保命技能。
1.2 U-Boot中的升级命令原理
U-Boot作为bootloader,承担着「最后一公里」的升级任务。我常用的两个命令是tftp和fastboot。咱们一个一个说。
1.2.1 tftp命令——网络升级的老兵
TFTP,全称Trivial File Transfer Protocol。名字里带个「Trivial」,但用起来可不简单。
它的工作流程是这样的:
- U-Boot作为客户端,向TFTP服务器发起请求
- 服务器把固件分成512字节的数据块,一块一块发
- U-Boot每收到一块,回一个ACK确认
- 如果ACK丢了,服务器会重传
- 全部收完,校验文件大小
我在项目中遇到过一个问题:TFTP传大文件时,如果网络环境不好,重传次数太多,U-Boot会直接超时报错。后来我改了U-Boot源码里的TFTP_TIMEOUT宏定义,把超时时间从5秒改成了15秒,问题就解决了。
典型的tftp升级命令长这样:
# 设置网络参数
setenv ipaddr 192.168.1.100
setenv serverip 192.168.1.1
setenv netmask 255.255.255.0
# 下载固件到内存地址0x82000000
tftp 0x82000000 firmware.bin
# 擦除Flash并写入
sf probe 0
sf erase 0x100000 0x800000
sf write 0x82000000 0x100000 0x800000
注意看,这里有个关键点:先下载到内存,再写入Flash。为什么要这样?因为Flash写入速度慢,如果边下载边写,万一网络断了,Flash里就留下了一堆半残数据。
crc32命令算一下校验值,跟服务器上的比对。
1.2.2 fastboot命令——Android生态的标配
Fastboot是Google推的协议,主要用于Android设备的刷机。但说实话,现在很多非Android设备也在用,因为它确实好用。
Fastboot的原理跟TFTP不太一样:
- 它是USB协议,走的是USB Bulk传输,速度比TFTP快不少
- 它是主机主动推送,U-Boot这边被动接收,不需要U-Boot去发起请求
- 它支持分区操作,可以直接指定往哪个分区写
我记得有一次,客户要求设备支持fastboot升级。我翻了一遍U-Boot源码,发现CONFIG_CMD_FASTBOOT这个宏默认没开。打开之后,还要配置USB控制器、定义分区表。折腾了两天才搞定。
Fastboot的典型用法:
# 在U-Boot中启动fastboot模式
fastboot 0
# 在PC端执行(需要安装adb/fastboot工具)
fastboot flash boot boot.img
fastboot flash system system.img
fastboot reboot
1.3 两种升级方式的对比
我整理了一个对比表,方便大家选型时参考:
| 对比项 | TFTP | Fastboot |
|---|---|---|
| 传输介质 | 以太网 | USB |
| 传输速度 | 受网络限制,一般1-10MB/s | USB 2.0可达30MB/s |
| 可靠性 | 有重传机制,但超时处理弱 | USB协议本身可靠 |
| 适用场景 | 产线批量、远程升级 | 现场刷机、调试 |
| 中断恢复 | 需要自己实现断点续传 | 需要自己处理USB断开 |
| 配置复杂度 | 需要网络环境 | 需要USB驱动支持 |
1.4 核心逻辑框架图
下面这张图,是我自己画的升级流程框架。你看一眼,基本就能理解整个升级过程了:
从这张图你能看出来,每个阶段都有中断风险。我个人的经验是:不要等到出了问题再想办法,而是在设计阶段就把中断处理考虑进去。
1.5 避坑指南
最后,分享几个我这些年踩过的坑:
坑一:升级过程中断电
我曾经在一个户外设备项目上,没有做双备份。结果升级到一半,现场施工人员拉了电闸。设备再也起不来了。后来我强制要求:所有产品必须支持A/B分区备份,或者至少有一个不可擦除的恢复分区。
坑二:Flash写入超时
有一次用TFTP升级,固件下载到内存很快,但往Flash里写的时候,因为Flash擦除时间太长,U-Boot的看门狗超时复位了。解决方案:在擦除Flash之前,先喂一次狗,或者把看门狗超时时间设长一点。
坑三:Fastboot命令顺序搞错
我记得有个同事,用fastboot刷机时先刷了boot分区,然后刷system分区。结果刷到一半USB断了。重启后boot分区是新固件,system分区是旧固件,两个版本不兼容,直接卡死在开机动画。从那以后,我要求必须整包升级,或者做好版本兼容性检查。
好了,第一章就聊到这儿。升级机制的基础,说白了就是「怎么把固件安全可靠地写进去」。后面的章节,咱们会深入讲中断发生时怎么处理、怎么恢复。这些东西,都是我用真金白银的教训换来的,希望能帮到你。