IAP升级实验演示
193.2.1 IAP升级实验演示
本课只演示已经编译好的 Bootloader、参数文件和 APP 固件的烧写与升级,没有现场讲解新的业务源码,因此不在标题下强行补造代码;代码流程从第 195 课开始分析。
一、实验演示
1.1 实验目的与整体流程
本实验先用 ST-Link 完成一次“出厂初始化”,再让板上的自定义 Bootloader 通过 USART2 和 YMODEM 接收新 APP。完整数据流是:
首次部署:PC ──ST-Link──> Bootloader + info.bin + APP1.bin
触发升级:PC ──USART1──> APP1(收到升级命令、写升级标志、复位)
传输固件:PC ──USART2/YMODEM──> Bootloader ──写 Flash──> APP2
升级完成:Bootloader ──跳转──> APP2
这里应读作 IAP(In-Application Programming),不是字幕识别出的“IP”。
1.2 硬件连接
课程使用 STM32F103ZET6 开发板、ST-Link 和两路串口:
| 通道 | MCU 引脚/接口 | PC 侧工具 | 用途 |
|---|---|---|---|
| ST-Link | SWDIO、SWCLK、GND,并按开发板要求连接参考电压/供电 | ST-LINK Utility | 首次擦除并烧写 Bootloader、参数和初始 APP |
| USART1 | PA9/TX、PA10/RX | 普通串口助手 | 打印日志、向 APP 发送升级控制命令 |
| USART2 | PA2/TX、PA3/RX | CH340 + Xshell | 用 YMODEM 向 Bootloader 发送 .bin 固件 |
两路串口在配套工程中均配置为 115200 bit/s、8 数据位、无校验、1 停止位、无硬件流控。
外接 CH340 时要满足:
- MCU TX 接转换模块 RX,MCU RX 接转换模块 TX;
- 两侧 GND 必须相连;
- 使用与开发板兼容的 3.3 V TTL 电平串口,不要把真正的 ±RS-232 电平直接接入 MCU;
- 不确定哪个 COM 口对应 USART1/USART2 时,可在设备管理器中观察插拔前后的端口变化。
1.3 三个文件及其地址
STM32F103ZET6 有 512 KiB Flash,地址范围为 0x08000000~0x0807FFFF。课程工程采用以下布局:
| 文件 | 烧写起始地址 | 内容 | 地址空间意义 |
|---|---|---|---|
08Ymodem_Bootloader 生成的 HEX | 0x08000000 | 自定义 Bootloader | 链接器为它预留 0x6000,即 24 KiB |
info.bin | 0x08006000 | 版本、升级标志、校验等配置 | APP 从 0x08008000 开始,因此中间共保留 0x2000,即 8 KiB |
APP1.bin | 0x08008000 | 初始用户程序 | 从此地址到 Flash 末尾共 480 KiB |
必须特别注意:
0x08006000不是0x08000600,0x08008000也不是0x08000800。- HEX 文件通常携带编译时地址信息;BIN 只是连续原始字节,没有目标地址,所以烧写
info.bin和APP1.bin时必须手动指定地址。 - 课程语音识别中的
0x...630、0x...830是错误的,源码宏和链接文件都明确使用0x08006000、0x08008000。
配套 info.bin 只有 12 字节,实际内容为:
偏移 00:AA BB CC DD magic
偏移 04:02 08 04 01 ota_bin_version(按 Cortex-M 小端序解释)
偏移 08:00 ota_flag,0 表示当前不要求升级
偏移 09:1D 前 9 字节的 8 位累加和
偏移 0A:00 00 占位字节
0x08006000 到 0x08007FFF 的地址间隔是 8 KiB;但当前参数结构只有 12 字节,参数写回函数实际擦写从 0x08006000 开始的一页。STM32F103ZE 属于高密度器件,一页为 2 KiB。不要把“单页大小 2 KiB”和“整个保留间隔 8 KiB”混为一谈。
1.4 首次烧写步骤
1.4.1 擦除 Flash
- 连接 ST-Link 和目标板。
- 在 ST-LINK Utility 中连接目标芯片。
- 使用整片擦除功能,把主 Flash 恢复为擦除态
0xFF。 - 确认工具识别到的器件、Flash 起始地址和容量正确。
整片擦除适合本课的首次部署或地址烧错后的恢复。正常 IAP 更新时不能每次都整片擦除,否则 Bootloader 和参数区也会被删除。
1.4.2 烧写 Bootloader
- 选择
08Ymodem_Bootloader工程生成的.hex文件。 - 确认其目标从
0x08000000开始。 - 执行 Program/Start,并启用或查看下载校验结果。
Bootloader 必须位于复位后 MCU 默认取向量表的 Flash 起始处,这样复位后才会先运行它。
1.4.3 烧写 info.bin
- 选择课程目录中的
info.bin。 - 把二进制文件的 Start Address 设置为
0x08006000。 - 执行烧写并校验。
如果遗漏这个文件,Bootloader 初始化时读到的 magic 和 checksum 会无效;课程源码会停在错误打印循环中,而不是正常跳转 APP。
1.4.4 烧写 APP1.bin
- 选择
APP1.bin。 - 把 Start Address 设置为
0x08008000。 - 执行烧写并校验。
这个 APP 不能是一个仍链接到 0x08000000 的普通工程。配套 APP 的 Keil scatter 文件已经把加载/执行地址改为 0x08008000,system_stm32f1xx.c 也把 SCB->VTOR 设置为 0x08008000。
1.5 首次启动现象
打开 USART1 对应的串口助手后复位开发板,正常日志顺序应当是:
- 先出现
Bootloader; - Bootloader 校验
info.bin,读到ota_flag=0; - 打印
jump app; - 随后出现
APP1 Start一类的 APP 日志。
这不是两个程序同时运行,而是 MCU 先执行 Bootloader,之后修改主栈指针并跳到 APP 的复位入口。跳转成功后,CPU 继续执行 APP,Bootloader 不再并行运行。
1.6 触发 IAP 升级
1.6.1 通过 USART1 发送升级命令
在普通串口助手中:
- 选择 USART1 对应的 COM 口;
- 选择十六进制发送,而不是把
AF等字符当作 ASCII 文本发送; - 发送课程给出的升级帧。
配套 APP 的接收协议格式是:
| HEAD 0xAF | LEN | DATA(课程用作版本号) | TAIL 0xFA |
LEN 表示 DATA 长度。APP 收齐帧并验证头、长度和尾后,把 RAM 中的 ota_flag 置 1;主循环再将 Flash 参数区的升级标志写成 1,打印 Restarting...,延时后调用系统复位。
复位后 Bootloader 重新启动。它这次从参数区读到 ota_flag=1,不再跳到旧 APP,而是进入 YMODEM 接收状态。
1.6.2 在 USART2 上建立 Xshell 串口会话
课程字幕中的“X12/X11”均是 Xshell 的识别错误。建立会话时应选择 SERIAL 串口协议,而不是 SSH:
- 新建会话并选择 USART2/CH340 对应的 COM 口;
- 设置 115200、8N1、无流控;
- 连接后观察终端是否持续收到字符
C。
字符 C 的字节值是 0x43。它表示接收方已准备好,并请求发送方采用 CRC-16 模式开始 YMODEM 传输;它不是乱码,也不是要求在键盘上手动输入 C。
1.6.3 使用 YMODEM 发送 APP2.bin
在 Xshell 串口窗口中:
- 选择 传输 → YMODEM → 发送;
- 选择课程提供的
APP2.bin,不要选择.hex; - 等待进度完成,不要在擦写 Flash 时断电、复位或拔串口;
- 同时观察 USART1 日志中的文件名、大小、分页写入和完成信息。
YMODEM 首先发送包含文件名和文件大小的 0 号包,随后发送带序号和 CRC 的数据包。接收端验证正确后回复 ACK,失败则可用 NAK 请求重传。Bootloader 将有效载荷写入从 0x08008000 开始的 APP 区域。
传输成功后,课程 Bootloader:
- 把参数区
ota_flag清回 0; - 跳转到
0x08008000; - USART1 最终显示
APP2 Start,证明新固件已经运行。
可以再次向 APP2 发送升级命令,再通过 YMODEM 发送 APP1.bin,验证两版固件能够来回切换。
1.7 常见故障定位
| 现象 | 优先检查 |
|---|---|
| 复位后没有 Bootloader 日志 | ST-Link 烧写是否成功、USART1 COM 口和 115200 配置、Bootloader 是否位于 0x08000000 |
| 一直报 magic/checksum 错误 | info.bin 是否烧到 0x08006000、12 字节内容是否完整、参数页是否被误擦除 |
| Bootloader 打印后不进入 APP | APP 是否烧到并链接到 0x08008000、首字是否为合法 SRAM 栈地址、VTOR 是否重定位 |
| 发送升级命令后无反应 | USART1 是否用 HEX 发送、帧头/长度/尾是否正确、APP 是否重新开启中断接收 |
| Xshell 看不到连续的 C | 是否已触发升级并复位、是否连到 USART2、TX/RX 是否交叉、GND 和波特率是否正确 |
| YMODEM 立即失败 | 是否选择 YMODEM Send、文件是否为 APP 的 .bin、COM 口是否被其他软件占用 |
| 地址填错 | 停止继续操作,整片擦除后按 Bootloader → info.bin → APP1.bin 的顺序重新部署 |
1.8 安全边界
本课程是便于理解流程的单 APP 槽实验,并不等同于量产 OTA:
- 更新时直接覆盖现有 APP,中途掉电可能留下不完整固件;
- magic、累加和与 YMODEM CRC 只能帮助发现部分传输/参数错误,不能验证固件来源是否合法;
- 量产系统通常还需要固件长度边界、整包哈希、数字签名、版本防回滚、失败重试或 A/B 分区等机制;
- 无论如何都应保护 Bootloader 所在页,避免升级数据越界覆盖恢复入口。
ST 的 AN4657:STM32 IAP using USART给出了 IAP、YMODEM、Flash 写入和跳转用户程序的官方参考流程。
二、学习检查
完成实验后,应能不看步骤回答:
- 为什么三个文件要分别烧到三个地址?
- 为什么 BIN 必须手动指定地址,而 APP 还必须用同一地址重新链接?
- APP 收到升级命令后为什么要先写 Flash 标志,再复位?
- USART1 和 USART2 在本实验中分别承担什么任务?
- Xshell 中不断出现
C表示什么? - 为什么初始部署可整片擦除,而正常 IAP 不能整片擦除?