IAP升级实验演示

Tutorial: 卓越工程师 Category: 嵌入式 Published: 2026-10-23 11:05:29 Views: 0 Likes: 0 Comments: 0

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-LinkSWDIO、SWCLK、GND,并按开发板要求连接参考电压/供电ST-LINK Utility首次擦除并烧写 Bootloader、参数和初始 APP
USART1PA9/TX、PA10/RX普通串口助手打印日志、向 APP 发送升级控制命令
USART2PA2/TX、PA3/RXCH340 + 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 生成的 HEX0x08000000自定义 Bootloader链接器为它预留 0x6000,即 24 KiB
info.bin0x08006000版本、升级标志、校验等配置APP 从 0x08008000 开始,因此中间共保留 0x2000,即 8 KiB
APP1.bin0x08008000初始用户程序从此地址到 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
  1. 连接 ST-Link 和目标板。
  2. 在 ST-LINK Utility 中连接目标芯片。
  3. 使用整片擦除功能,把主 Flash 恢复为擦除态 0xFF。
  4. 确认工具识别到的器件、Flash 起始地址和容量正确。

整片擦除适合本课的首次部署或地址烧错后的恢复。正常 IAP 更新时不能每次都整片擦除,否则 Bootloader 和参数区也会被删除。

1.4.2 烧写 Bootloader
  1. 选择 08Ymodem_Bootloader 工程生成的 .hex 文件。
  2. 确认其目标从 0x08000000 开始。
  3. 执行 Program/Start,并启用或查看下载校验结果。

Bootloader 必须位于复位后 MCU 默认取向量表的 Flash 起始处,这样复位后才会先运行它。

1.4.3 烧写 info.bin
  1. 选择课程目录中的 info.bin。
  2. 把二进制文件的 Start Address 设置为 0x08006000。
  3. 执行烧写并校验。

如果遗漏这个文件,Bootloader 初始化时读到的 magic 和 checksum 会无效;课程源码会停在错误打印循环中,而不是正常跳转 APP。

1.4.4 烧写 APP1.bin
  1. 选择 APP1.bin。
  2. 把 Start Address 设置为 0x08008000。
  3. 执行烧写并校验。

这个 APP 不能是一个仍链接到 0x08000000 的普通工程。配套 APP 的 Keil scatter 文件已经把加载/执行地址改为 0x08008000,system_stm32f1xx.c 也把 SCB->VTOR 设置为 0x08008000。

1.5 首次启动现象

打开 USART1 对应的串口助手后复位开发板,正常日志顺序应当是:

  1. 先出现 Bootloader;
  2. Bootloader 校验 info.bin,读到 ota_flag=0;
  3. 打印 jump app;
  4. 随后出现 APP1 Start 一类的 APP 日志。

这不是两个程序同时运行,而是 MCU 先执行 Bootloader,之后修改主栈指针并跳到 APP 的复位入口。跳转成功后,CPU 继续执行 APP,Bootloader 不再并行运行。

1.6 触发 IAP 升级

1.6.1 通过 USART1 发送升级命令

在普通串口助手中:

  1. 选择 USART1 对应的 COM 口;
  2. 选择十六进制发送,而不是把 AF 等字符当作 ASCII 文本发送;
  3. 发送课程给出的升级帧。

配套 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:

  1. 新建会话并选择 USART2/CH340 对应的 COM 口;
  2. 设置 115200、8N1、无流控;
  3. 连接后观察终端是否持续收到字符 C。

字符 C 的字节值是 0x43。它表示接收方已准备好,并请求发送方采用 CRC-16 模式开始 YMODEM 传输;它不是乱码,也不是要求在键盘上手动输入 C。

1.6.3 使用 YMODEM 发送 APP2.bin

在 Xshell 串口窗口中:

  1. 选择 传输 → YMODEM → 发送;
  2. 选择课程提供的 APP2.bin,不要选择 .hex;
  3. 等待进度完成,不要在擦写 Flash 时断电、复位或拔串口;
  4. 同时观察 USART1 日志中的文件名、大小、分页写入和完成信息。

YMODEM 首先发送包含文件名和文件大小的 0 号包,随后发送带序号和 CRC 的数据包。接收端验证正确后回复 ACK,失败则可用 NAK 请求重传。Bootloader 将有效载荷写入从 0x08008000 开始的 APP 区域。

传输成功后,课程 Bootloader:

  1. 把参数区 ota_flag 清回 0;
  2. 跳转到 0x08008000;
  3. USART1 最终显示 APP2 Start,证明新固件已经运行。

可以再次向 APP2 发送升级命令,再通过 YMODEM 发送 APP1.bin,验证两版固件能够来回切换。

1.7 常见故障定位

现象优先检查
复位后没有 Bootloader 日志ST-Link 烧写是否成功、USART1 COM 口和 115200 配置、Bootloader 是否位于 0x08000000
一直报 magic/checksum 错误info.bin 是否烧到 0x08006000、12 字节内容是否完整、参数页是否被误擦除
Bootloader 打印后不进入 APPAPP 是否烧到并链接到 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 写入和跳转用户程序的官方参考流程。

二、学习检查

完成实验后,应能不看步骤回答:

  1. 为什么三个文件要分别烧到三个地址?
  2. 为什么 BIN 必须手动指定地址,而 APP 还必须用同一地址重新链接?
  3. APP 收到升级命令后为什么要先写 Flash 标志,再复位?
  4. USART1 和 USART2 在本实验中分别承担什么任务?
  5. Xshell 中不断出现 C 表示什么?
  6. 为什么初始部署可整片擦除,而正常 IAP 不能整片擦除?