OpenBLT 嵌入式 BootLoader 技术解析
OpenBLT 嵌入式 BootLoader 技术解析
基于 STM32F407 + Modbus RTU(RS485)的实战经验总结
一、什么是 OpenBLT
OpenBLT(Open BootLoader Technology)是荷兰 Feaser 公司开源的嵌入式 BootLoader 框架(GPL v3),提供了一套完整的固件远程升级方案:
- MCU 端:一个极简的 BootLoader 固件,常驻 Flash 头部
- PC 端:一个开箱即用的 GUI 上位机(MicroBoot)
它的最大价值在于:即使你完全没写过 BootLoader,也能在几小时内给 STM32 加上远程固件升级功能。
二、整体架构
┌─────────────────────────┐ RS485/Modbus RTU ┌──────────────────────────┐
│ 上位机 (Windows) │ ──────────────────────────→ │ BCU 控制器 (STM32F407) │
│ │ ←─────────────────────────── │ │
│ ┌───────────────────┐ │ │ ┌────────────────────┐ │
│ │ MicroBoot.exe │ │ 功能码 109(自定义) │ │ BootLoader 固件 │ │
│ │ (Pascal GUI) │ │ [地址][109][len][XCP][CRC] │ │ 位于 Flash 头部 │ │
│ └────────┬──────────┘ │ │ └────────────────────┘ │
│ ↓ │ │ ↓ │
│ ┌───────────────────┐ │ │ 跳到用户 APP(如果有效) │
│ │ LibOpenBLT.dll │ │ │ │
│ │ (C 语言库) │ │ │ │
│ └────────┬──────────┘ │ │ │
│ ↓ │ │ │
│ ┌───────────────────┐ │ │ │
│ │ XCP 协议层 │ │ │ │
│ │ (会话/编程/擦除) │ │ │ │
│ └────────┬──────────┘ │ │ │
│ ↓ │ │ │
│ ┌───────────────────┐ │ │ │
│ │ Modbus RTU 传输层 │ │ │ │
│ │ (xoxtpmbrtu.c) │ │ │ │
│ └───────────────────┘ │ │ │
└─────────────────────────┘ └──────────────────────────┘
三、MCU 端:BootLoader 固件
3.1 Flash 布局
MCU 内部 Flash(STM32F407VE, 512KB)
┌───────────────────────────┐ 0x08000000 低地址
│ BootLoader │
│ 32KB(sector 0~1) │
├───────────────────────────┤ 0x08008000
│ 用户 APP 固件 │
│ 480KB(sector 2~11) │
│ │
│ ... │
└───────────────────────────┘ 0x08080000 高地址
BootLoader 通过链接脚本限定为 32KB:FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K。同时 flash.c 中的 flashLayout[] 表将 sector 0~1 注释掉(保留给 BootLoader),APP 可用扇区从 0x08008000 的 sector 2 开始。OpenBLT 的擦写操作只针对 flashLayout[] 中列出的扇区,绝对不会误擦 BootLoader 自身。
3.2 上电启动流程
上电/复位
↓
BootLoader 初始化(HAL、时钟、串口)
↓
检查 APP 是否有校验和?
├─ 有 → 校验和验证通过?
│ ├─ 通过 → 跳转到 APP ✓ 正常启动
│ └─ 失败 → 留在 BootLoader 等升级
└─ 无 → 留在 BootLoader 等升级
留在 BootLoader 后的主循环:
while(1) {
收 Modbus 帧 → 解析 XCP 包 → 执行命令(擦除/编程/跳转)
CopService(); // 喂狗
}
3.3 文件结构
BootLoader 工程/
├── App/
│ ├── blt_conf.h ← ★ 核心配置(晶振、Flash大小、通信接口、超时参数)
│ ├── hooks.c ← 回调钩子(LED、看门狗、后门入口)
│ └── app.c/h ← BootLoader 启动入口
│
├── Core/ ← STM32CubeIDE 生成的 HAL 层(main.c、时钟、外设初始化)
├── Drivers/ ← CMSIS + HAL 库
│
├── Loader/ ← OpenBLT 源码
│ ├── *.c/h ← 核心:boot.c、com.c、xcp.c、backdoor.c...
│ └── ARMCM4_STM32F4/
│ ├── cpu.c ← MCU 初始化(中断向量重映射)
│ ├── flash.c ← 内部 Flash 驱动(擦除/编程)
│ ├── nvm.c ← 非易失存储抽象层
│ ├── timer.c ← 定时器(1ms 系统时钟 + 100kHz 自由计数器)
│ ├── rs232.c ← RS232 传输层
│ ├── can.c ← CAN 传输层
│ └── mbrtu.c ← ★ Modbus RTU 传输层(自研添加)
3.4 核心配置:blt_conf.h
// ===== 时钟 =====
#define BOOT_CPU_XTAL_SPEED_KHZ 25000 // 外部晶振 25MHz
#define BOOT_CPU_SYSTEM_SPEED_KHZ 160000 // 系统频率 160MHz
// ===== 通信接口选择 =====
#define BOOT_COM_MBRTU_ENABLE 1 // Modbus RTU
#define BOOT_COM_MBRTU_BAUDRATE 9600 // 9600bps
#define BOOT_COM_MBRTU_CHANNEL_INDEX 2 // USART3
#define BOOT_COM_MBRTU_PARITY 2 // 偶校验
#define BOOT_COM_MBRTU_NODE_ID 1 // Modbus 从站地址
// ===== Flash =====
#define BOOT_NVM_SIZE_KB 512 // Flash 大小
#define BOOT_FLASH_VECTOR_TABLE_CS_OFFSET 0x1AC // 校验和位置(F4 系列)
// ===== 超时参数 =====
#define BOOT_COM_MBRTU_RX_MAX_DATA 129 // 收包最大数据量
#define BOOT_COM_MBRTU_TX_MAX_DATA 129 // 发包最大数据量
// ===== 功能钩子 =====
#define BOOT_COP_HOOKS_ENABLE 1 // 看门狗
#define BOOT_BACKDOOR_HOOKS_ENABLE 1 // 后门入口
#define BOOT_CPU_USER_PROGRAM_START_HOOK 1 // 跳转前回调
四、通信协议:XCP over Modbus RTU
这是整个系统最精妙的设计——把 XCP 标定协议嵌入 Modbus RTU 帧。
4.1 为什么选 Modbus RTU?
| 对比 | CAN | RS232 | Modbus RTU |
|---|---|---|---|
| 需要额外硬件 | CAN 收发器 | 直连 | RS485 收发器 |
| 总线拓扑 | 多节点 | 点对点 | 多节点(一主多从) |
| BMS 行业通用性 | 一般 | 差 | 高(储能/工业标配) |
| 抗干扰 | 强 | 弱 | 强(差分信号) |
BMS 现场本来就是 RS485 + Modbus 的总线,BootLoader 共用同一根线,不增加硬件成本。
4.2 帧格式
┌──────────┬──────────┬──────────┬───────────────┬──────────┐
│ 从站地址 │ 功能码 │ XCP长度 │ XCP 数据 │ CRC-16 │
│ 1 byte │ 1 byte │ 1 byte │ N bytes │ 2 bytes │
├──────────┼──────────┼──────────┼───────────────┼──────────┤
│ 0x01 │ 109 │ 0x14 │ XCP 包原始字节 │ 计算值 │
└──────────┴──────────┴──────────┴───────────────┴──────────┘
←──── Modbus RTU 帧头 ──→ ←── XCP 载荷 ──→ ← Modbus 尾 →
功能码 109:用户自定义功能码(65~72 或 100~110 范围内),
表示"本帧数据是一个 XCP 协议包"
4.3 发送过程(MCU 端 mbrtu.c)
void MbRtuTransmitPacket(blt_int8u *data, blt_int8u len) {
blt_int8u txPacket[BOOT_COM_MBRTU_TX_MAX_DATA + 5];
// 1. 拼 Modbus 帧头
txPacket[0] = BOOT_COM_MBRTU_NODE_ID; // 从站地址 = 0x01
txPacket[1] = 109; // 功能码 = XCP 包
txPacket[2] = len; // XCP 数据长度
// 2. 原样拷贝 XCP 数据
memcpy(&txPacket[3], data, len);
// 3. 计算 CRC-16(Modbus 算法)
checksum = MbRtuCrcCalculate(txPacket, len + 3);
txPacket[len+3] = checksum & 0xFF;
txPacket[len+4] = checksum >> 8;
// 4. RS485 DE 拉高 → 发送 → DE 拉低
MbRtuDriverOutputControlHook(BLT_TRUE);
for (i = 0; i < len + 5; i++)
MbRtuTransmitByte(txPacket[i], ...);
MbRtuDriverOutputControlHook(BLT_FALSE);
}
4.4 接收过程
收到一帧 Modbus RTU 数据后,按顺序校验:
1. T3_5 帧间隔 → 收到完整帧
2. CRC-16 校验 → 数据正确
3. rxPacket[0] == 我的地址?→ 不是就丢弃
4. rxPacket[1] == 109? → 不是就丢弃
5. rxPacket[2] == 实际长度?→ 不匹配就丢弃
6. 全部通过 → 提取 rxPacket[3] 开始的 N 字节 = XCP 包
4.5 XCP 协议在做什么?
XCP(Universal Measurement and Calibration Protocol)是 ASAM 标准的标定协议,这里只用它的内存操作功能:
| XCP 命令 | 作用 |
|---|---|
| CONNECT | 建立连接(握手) |
| SET_MTA | 设置目标内存地址 |
| PROGRAM | 写入一段数据到内存 |
| PROGRAM_RESET | 写入后复位 MCU,跳转到新 APP |
| GET_SEED / UNLOCK | Seed/Key 安全解锁(可选) |
五、上位机:MicroBoot
5.1 技术栈
| 组件 | 语言 | 说明 |
|---|---|---|
| MicroBoot.exe | Pascal(Lazarus/Free Pascal) | GUI 主程序 |
| LibOpenBLT.dll | C | 核心库(XCP 协议 + 传输层 + S-Record 解析) |
| libseednkey.dll | C | Seed/Key 安全算法(可选) |
5.2 固件升级流程
MicroBoot 工作线程的状态机:
IDLE
↓
INITIALIZING 加载 S-Record 固件文件,解析段信息
↓
CONNECTING XCP CONNECT 命令,失败自动重试(后门模式)
↓
CHECK_INFO_TABLE 校验固件兼容性(可选,防刷错型号)
↓
ERASING_MEMORY 擦除 Flash(按 32KB 分段,占进度 20%)
↓
PROGRAMMING 写入 Flash(按 256 字节分段,占进度 80%)
↓
FINISHING_UP 断开连接,MCU 自动跳转到新 APP
↓
IDLE
5.3 上位机从哪来?
不需要自己开发。OpenBLT 自带 MicroBoot 的完整源码,按以下步骤就能用:
1. cd Host/Source/MicroBoot/
2. 用 Lazarus IDE 打开 MicroBoot.lpr
3. 编译 → 得到 MicroBoot.exe
4. 打开后选 "XCP on Modbus RTU" → 配 COM 口 → 选 .srec 文件 → 点 Start
六、总结
| 问题 | OpenBLT 的答案 |
|---|---|
| BootLoader 怎么写? | 不需要从头写,改 blt_conf.h 几个宏就行 |
| 上位机怎么写? | 自带 MicroBoot,编译即用 |
| 走什么通信? | RS232 / CAN / USB / TCP / Modbus RTU 可配 |
| 安全性? | Seed/Key 握手 + 校验和完整性检查(可选) |
| APP 崩溃了怎么办? | 后门入口——上电 1.5 秒内强制进 BootLoader |
| 固件格式? | 标准 Motorola S-Record(.srec) |
| 移植到新 MCU? | 换平台驱动 + 改 blt_conf.h,核心代码不变 |
OpenBLT 的核心价值不是"提供了多牛的算法",而是把 BootLoader 开发中所有踩坑的地方都封装好了——你只需要关心板子的硬件配置,剩下的协议、校验、超时、重试、安全、上位机,全都有现成的。
更多推荐


所有评论(0)