第一章:升级机制基础——嵌入式固件升级的常见方式

大家好,我是老李。做嵌入式这行十几年了,今天咱们聊聊固件升级。

说实话,刚入行那会儿,我对升级这事儿不太上心。觉得不就是把新固件写进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」,但用起来可不简单。

它的工作流程是这样的:

  1. U-Boot作为客户端,向TFTP服务器发起请求
  2. 服务器把固件分成512字节的数据块,一块一块发
  3. U-Boot每收到一块,回一个ACK确认
  4. 如果ACK丢了,服务器会重传
  5. 全部收完,校验文件大小

我在项目中遇到过一个问题: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里就留下了一堆半残数据。

我的小技巧: 下载完成后,先校验一下内存里的数据完整性,再往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
注意: Fastboot模式下,U-Boot会进入一个循环等待状态。如果主机端没发命令,它会一直等下去。我曾经遇到过一个问题:fastboot命令执行到一半,USB线被碰掉了,U-Boot就卡死在等待状态,只能硬重启。

1.3 两种升级方式的对比

我整理了一个对比表,方便大家选型时参考:

对比项 TFTP Fastboot
传输介质 以太网 USB
传输速度 受网络限制,一般1-10MB/s USB 2.0可达30MB/s
可靠性 有重传机制,但超时处理弱 USB协议本身可靠
适用场景 产线批量、远程升级 现场刷机、调试
中断恢复 需要自己实现断点续传 需要自己处理USB断开
配置复杂度 需要网络环境 需要USB驱动支持

1.4 核心逻辑框架图

下面这张图,是我自己画的升级流程框架。你看一眼,基本就能理解整个升级过程了:

嵌入式固件升级核心流程 阶段一:获取固件 TFTP下载 / Fastboot推送 / 串口传输 / SD卡读取 / OTA接收 ↓ 传输过程中可能中断(网络断开、USB拔出、信号丢失) 阶段二:完整性校验 CRC32校验 / MD5/SHA256哈希比对 / 文件大小验证 ↓ 校验失败则丢弃,不写入Flash 阶段三:写入Flash 擦除目标分区 → 逐块写入 → 读取验证 ↓ 写入过程中断电或异常,可能导致分区损坏 阶段四:启动切换 更新启动标志 → 重启 → 加载新固件 ↑ 如果新固件启动失败,需要回滚机制 中断风险点 ⚠ 网络断开 ⚠ USB拔出 ⚠ 信号丢失 ⚠ 校验失败 ⚠ 数据损坏 ⚠ 写入中断 ⚠ Flash坏块 ⚠ 启动失败 ⚠ 回滚异常

从这张图你能看出来,每个阶段都有中断风险。我个人的经验是:不要等到出了问题再想办法,而是在设计阶段就把中断处理考虑进去。

1.5 避坑指南

最后,分享几个我这些年踩过的坑:

坑一:升级过程中断电

我曾经在一个户外设备项目上,没有做双备份。结果升级到一半,现场施工人员拉了电闸。设备再也起不来了。后来我强制要求:所有产品必须支持A/B分区备份,或者至少有一个不可擦除的恢复分区。

坑二:Flash写入超时

有一次用TFTP升级,固件下载到内存很快,但往Flash里写的时候,因为Flash擦除时间太长,U-Boot的看门狗超时复位了。解决方案:在擦除Flash之前,先喂一次狗,或者把看门狗超时时间设长一点。

坑三:Fastboot命令顺序搞错

我记得有个同事,用fastboot刷机时先刷了boot分区,然后刷system分区。结果刷到一半USB断了。重启后boot分区是新固件,system分区是旧固件,两个版本不兼容,直接卡死在开机动画。从那以后,我要求必须整包升级,或者做好版本兼容性检查。

好了,第一章就聊到这儿。升级机制的基础,说白了就是「怎么把固件安全可靠地写进去」。后面的章节,咱们会深入讲中断发生时怎么处理、怎么恢复。这些东西,都是我用真金白银的教训换来的,希望能帮到你。

可可精品资料库