嵌入式开发笔记:Bootloader固件升级完全指南——从原理到CAN FD实战
嵌入式开发笔记:Bootloader固件升级完全指南——从原理到CAN FD实战
文章目录
1. 前言:为什么每个嵌入式工程师都必须懂Bootloader
在嵌入式系统开发中,Bootloader是系统上电后执行的第一个软件,它像一位沉默的守门人——平时不显山露水,但在关键时刻决定了整个系统的生死。
一位工程师曾分享过一个惨痛经历:价值百万的域控制器因为Bootloader设计缺陷导致刷写失败,最终变成“砖头”。而在工业现场,产线上200多台设备需要更新程序,传统做法是拆机后用JTAG挨个烧录,光是拆装外壳就花了团队整整两天时间。
Bootloader的价值,正是在这些时刻体现的。它允许工程师通过通信总线直接对设备进行固件更新,无需拆卸设备,更高级的应用中还能支持OTA远程升级。
本文将系统讲解Bootloader的核心原理、固件升级流程、Flash分区策略,并以CAN FD总线为例,深入剖析基于UDS协议的完整刷写实现方案。

2. Bootloader的核心原理
2.1 什么是Bootloader
Bootloader(引导加载程序)是嵌入式系统启动时运行的一段小型程序,负责初始化硬件、下载系统固件或加载现有固件并将其控制权移交。
一个典型的Bootloader分为两个执行阶段:
- 第一阶段(汇编层) :初始化CPU、开关中断、设置堆栈以及中断向量表指针,为C语言环境做准备
- 第二阶段(C语言层) :完成更复杂的硬件初始化(如串口、CAN口等),判断是否有固件下载意图,若有则联合上位机完成固件下载更新;若没有则判断当前固件是否有效,有效则加载并启动
2.2 为什么需要Bootloader
在传统的ECU固件更新方式中,工程师需要拆卸设备外壳,使用专用烧写器通过物理连接进行更新。这种方式操作繁琐、效率低下,还存在硬件损坏的风险。
Bootloader的出现彻底改变了这一局面:
- 无需拆机:通过通信总线(CAN、CAN FD、UART、USB等)直接升级
- 支持远程升级:结合无线模块可实现OTA空中升级
- 降低维护成本:产线批量升级、售后远程修复成为可能
2.3 启动流程与APP跳转
Bootloader的启动流程通常如下:
- 硬件初始化:配置时钟、中断、通信外设等
- 判断升级请求:检查是否有编程请求标志(GPIO电平、Flash标志位、通信指令等)
- 若存在编程请求:进入Bootloader编程模式,等待上位机指令
- 若无编程请求:检查APP区是否存在有效固件,若有则跳转执行
从Bootloader跳转到APP的关键在于中断向量表的重映射。APP程序的中断向量表地址与Bootloader不同,必须在跳转前正确配置。常见方案包括:
- 硬件重映射:通过芯片的VTOR寄存器设置中断向量表偏移地址
- 软件重映射:将APP的向量表拷贝到SRAM起始地址,再重映射内存
- 跳转指令方案:在Bootloader的向量表中写入跳转指令,指向APP的向量表区域
💡 关键原则:Bootloader和APP的地址空间绝对不能重叠,否则程序执行时会混乱。
3. Flash分区设计
合理的Flash分区是Bootloader稳定运行的基础。常见的分区方案有以下几种:
3.1 双区方案(Bootloader + APP)
最简单的分区方式,Flash划分为两个区域:
| 分区 | 作用 |
|---|---|
| Bootloader区 | 存放启动代码,通常受写保护 |
| APP区 | 存放应用程序 |
升级时,新固件直接覆盖APP区。风险:如果升级过程中断电或通信中断,APP区被破坏,设备将无法启动。
3.2 三区方案(Bootloader + APP + 备份区)
增加一个备份区存放新固件:
| 分区 | 作用 |
|---|---|
| Bootloader区 | 存放启动代码 |
| APP区(主区) | 存放当前运行的应用程序 |
| 备份区 | 存放升级固件 |
升级流程:新固件先写入备份区 → 校验通过后 → 擦除APP区 → 将备份区固件搬运到APP区。
3.3 A/B分区方案(双Bank)
对于支持双Bank Flash的MCU,可以采用A/B分区方案:
| 分区 | 作用 |
|---|---|
| Bootloader区 | 存放启动代码,受保护 |
| Bank A | 当前运行的应用程序 |
| Bank B | 备份/升级区 |
优势:升级时新固件写入非活动Bank,校验通过后切换活动Bank即可完成升级。即使升级失败,仍可回滚到原来的Bank,实现无缝升级和故障回滚。

4. 固件升级的通用流程
无论使用何种通信总线,固件升级的流程都可以归纳为以下几个核心步骤:
4.1 升级触发
设备如何进入升级模式?常见的触发方式包括:
- 硬件触发:通过GPIO引脚电平(如按下特定按键)
- 软件触发:APP中设置升级标志位,复位后Bootloader检测到标志位进入升级模式
- 通信触发:上位机通过总线发送特定指令,触发设备复位进入Bootloader
4.2 固件传输
上位机将新固件通过通信总线发送给设备。传输过程中需要关注:
- 数据分块:将大固件文件拆分为多个数据包发送
- 流控机制:防止下位机处理不过来导致数据丢失
- 校验机制:每包数据添加校验(CRC、校验和等)
4.3 固件写入
Bootloader接收数据后,将其写入Flash的指定区域。写入过程中需要:
- 按Flash页/扇区对齐:Flash编程有最小粒度要求
- 擦除后再写入:Flash必须先擦除才能编程
- 写入验证:读取写入的数据与原始数据比对
4.4 完整性校验
固件写入完成后,必须进行完整性校验:
- 哈希校验:对完整固件计算哈希值(MD5、SHA-256等)与预设值比对
- CRC校验:计算固件CRC与固件头中的CRC比对
- 签名验证:对固件进行数字签名验证,防止非授权固件被刷入
4.5 跳转执行
校验通过后,Bootloader跳转到APP区执行新固件。
5. CAN FD:为什么它是工业升级的理想选择
5.1 CAN FD vs 传统CAN
CAN FD(CAN with Flexible Data-Rate)是传统CAN 2.0的升级版,核心优势体现在两个方面:
| 特性 | 传统CAN | CAN FD |
|---|---|---|
| 最大数据长度 | 8字节 | 64字节 |
| 最高速率 | 1Mbps | 最高8-10Mbps |
| 速率模式 | 固定速率 | 可变速率(仲裁段与数据段速率不同) |
CAN FD的可变速率特性尤为关键:仲裁段保持与传统CAN兼容的速率(如500kbps或1Mbps),数据段可以切换到更高的速率(最高可达8Mbps)。
5.2 升级效率的质的飞跃
实测数据最能说明问题:用传统CAN升级256KB固件需要8分钟,而CAN FD仅需1分半钟。
对于电机控制器这类对实时性要求严格的设备,缩短升级时间意味着减少产线停摆带来的损失。CAN FD单帧64字节的载荷,结合可变速率,将总线负载率从传统CAN的70%降低至30%以下。
6. 基于UDS over CAN FD的完整刷写流程
在汽车电子和高端工业控制领域,UDS(统一诊断服务,ISO 14229) 是Bootloader刷写的标准协议。它运行于CAN、CAN FD、DoIP甚至车载以太网之上,专为ECU诊断和固件更新设计。
6.1 UDS刷写的“三段式”流程
基于UDS的Bootloader刷写流程分为三个阶段:
第一阶段:预编程阶段(Pre-Programming Phase)
目的是为刷写操作准备环境:
| 步骤 | UDS服务 | 说明 |
|---|---|---|
| 通信控制 | $28 | 停用总线上其他ECU的功能(如常规报文、DTC存储),避免总线冲突 |
| 控制DTC设置 | $85 | 暂停故障诊断码的存储 |
| 诊断会话控制 | $10 | 切换到编程会话(Programming Session),这是进入刷写模式的“钥匙” |
⚠️ 关键注意:正确的方式是APP段程序回复
0x78 NRC,然后跳转到Bootloader段,最后由Bootloader段回复10 02的肯定响应。错误的方式是由APP段直接回复肯定响应。
第二阶段:主编程阶段(Main-Programming Phase)
这是实际传输固件的核心阶段:
| 步骤 | UDS服务 | 说明 |
|---|---|---|
| 安全访问 | $27 | 基于Seed-Key机制完成鉴权,防止未授权刷写 |
| 请求下载 | $34 | 传递目标地址、数据长度和传输模式 |
| 传输数据 | $36 | 分段传输固件数据,这是最核心的数据传输服务 |
| 请求退出传输 | $37 | 通知ECU数据传输完成 |
$27安全访问服务的典型交互流程:
诊断仪 → ECU: 27 01(请求种子)
ECU → 诊断仪: 67 01 00 95 00 06(返回Seed)
诊断仪 → ECU: 27 02 05 D9 40 3C(发送Key)
ECU → 诊断仪: 67 02(验证通过,进入安全访问等级)
$34/$36/$37服务的联动:
- $34请求下载:上位机发送目标地址、数据长度,ECU回复可接收的数据块大小
- $36传输数据:循环发送固件数据块(每个数据块最大4096字节是工程实践中的典型配置)
- $37请求退出传输:通知ECU所有数据发送完毕
在CAN FD场景下,Bootloader通过ISO-TP分段传输协议(ISO 15765-2) ,将多个CAN FD帧重组为UDS TransferData数据块,再按Flash页或扇区聚合写入。
第三阶段:后编程阶段(Post-Programming Phase)
刷写完成后的收尾工作:
| 步骤 | UDS服务 | 说明 |
|---|---|---|
| ECU复位 | $11 | 复位ECU,使新固件生效 |
| 恢复通信 | $28 | 恢复总线上其他ECU的正常通信 |
| 恢复DTC | $85 | 恢复故障诊断码的存储功能 |
6.2 完整刷写流程图解
┌─────────────────────────────────────────────────────────────────────────────┐
│ 预编程阶段 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ $28通信 │ → │ $85控制 │ → │ $10切换 │ → │ 跳转到 │ │
│ │ 控制 │ │ DTC设置 │ │ 编程会话 │ │ Bootloader│ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────────────────────────┤
│ 主编程阶段 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ $27安全 │ → │ $34请求 │ → │ $36传输 │ → │ $37请求 │ │
│ │ 访问 │ │ 下载 │ │ 数据 │ │ 退出传输 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
│ ↑______________↓ (循环) │
├─────────────────────────────────────────────────────────────────────────────┤
│ 后编程阶段 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ $11 ECU │ → │ $28恢复 │ → │ $85恢复 │ → │ 跳转到 │ │
│ │ 复位 │ │ 通信 │ │ DTC存储 │ │ 新APP │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
6.3 工程实践中的关键参数
在实际CAN FD Bootloader工程中,以下参数配置至关重要:
| 参数 | 典型值 | 说明 |
|---|---|---|
| 仲裁段波特率 | 500kbps或1Mbps | 与传统CAN兼容 |
| 数据段波特率 | 2-5Mbps | CAN FD的高速数据阶段 |
| 单帧数据长度 | 64字节 | CAN FD最大载荷 |
| TransferData块大小 | 4096字节 | 平衡传输效率和Flash编程压力 |
| Flash编程粒度 | 按页/扇区 | 取决于MCU的Flash特性 |
6.4 典型硬件平台
当前主流的CAN FD Bootloader方案多基于以下MCU平台:
- STM32G4系列:内置FDCAN控制器,支持CAN FD协议,通信速率最高可达5Mbps
- 英飞凌TLE989X系列:车规级MCU,支持UDS over CAN FD刷写
- NXP MPC5748G:汽车级MCU,广泛用于域控制器Bootloader方案
- dsPIC33C系列:Microchip的CAN FD Bootloader参考设计
6.5 上位机与下位机的协作
完整的Bootloader升级系统由上位机和下位机协同工作:
上位机职责:
- 选择固件文件(HEX/SREC/BIN格式)
- 连接通信设备(如USBCAN FD转换器)
- 按照UDS协议封装并发送诊断请求
- 显示升级进度和错误信息
- 保存升级日志
下位机(Bootloader)职责:
- 解析上位机传来的UDS数据包
- 将APP代码包组合起来,依次写入目标Flash空间
- 进行完整性校验和签名验证
- 校验通过后跳转到APP执行
7. 工程实践要点与常见陷阱
7.1 时钟配置
CAN FD模块时钟必须与APB总线时钟同步。使用CAN FD的BRS(比特率切换)功能时,时钟抖动必须控制在±0.25%以内,建议使用晶体振荡器而非陶瓷谐振器。
7.2 PCB布局
当CAN FD运行在5Mbps时,信号完整性至关重要:
- 差分线等长:CAN_H与CAN_L长度差控制在5mm以内,阻抗保持120Ω
- 隔离设计:采用隔离芯片,电源侧加去耦电容
- 终端电阻:总线两端各接一个120Ω电阻
- 走线避让:远离电机驱动线、PWM信号线至少20mm
- ESD保护:在CAN接口添加TVS二极管阵列
7.3 异常恢复机制
一次升级过程中,通信可能中断、电源可能掉电、Flash编程可能失败。Bootloader必须具备:
- 冷启动恢复:即使应用区刷写中断,ECU复位后仍能进入恢复刷写流程
- 超时机制:每个步骤设置超时,超时后自动退出或重试
- 看门狗监控:独立硬件看门狗防止刷写过程卡死
7.4 Flash驱动分离
出于安全考虑,Bootloader中不应内置Flash擦写驱动,防止意外操作导致Flash被意外修改。正确的做法是:在刷写App之前,先把擦写Flash的驱动代码通过UDS烧写到RAM中执行。
8. 总结
Bootloader是嵌入式系统固件升级的基石。本文从核心原理、Flash分区、通用升级流程三个维度系统梳理了Bootloader的设计要点,并以CAN FD + UDS为例,完整展示了从预编程到主编程再到后编程的工业级刷写流程。
| 关键知识点 | 核心要点 |
|---|---|
| Bootloader本质 | 系统上电后第一个执行的软件,负责引导和升级 |
| Flash分区 | 双区/三区/A-B分区,平衡安全性与灵活性 |
| 升级流程 | 触发→传输→写入→校验→跳转 |
| CAN FD优势 | 64字节载荷 + 最高8Mbps速率,效率提升5倍+ |
| UDS三段式 | 预编程($28/$85/$10) → 主编程($27/$34/$36/$37) → 后编程($11) |
| 工程要点 | 时钟配置、PCB布局、异常恢复、Flash驱动分离 |
掌握Bootloader的设计与实现,不仅是嵌入式工程师的基本功,更是保障产品可维护性、可靠性和安全性的关键能力。希望本文能帮助你在实际项目中少走弯路,构建稳定可靠的固件升级方案。
📚 参考资料
- ISO 14229-1(UDS统一诊断服务)规范
- ISO 15765-2(CAN传输协议)规范
- CAN FD协议规范(CiA)
- 各MCU厂商Bootloader应用笔记与参考设计
更多推荐



所有评论(0)