OTA理论实验演示

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

237.5.1 OTA理论实验演示

本节不编写代码,而是先跑通一次完整的固件更新实验:PC 通过串口把新固件发给 STM32F103C8T6,C8T6 再通过 CAN 把固件送到 STM32F103ZET6,ZET6 的 Bootloader 将固件写入内部 Flash,最后跳转到新 APP。先看到整个系统怎样协作,后续再分别学习 APP 移植、Bootloader 和升级工具的代码。

术语纠正:视频语音中的“IP”“ipv”都是 IAP。文中“窗口”应为“串口”,“iPhone/C”应为“I²C”,“看网络/看收发器/看 TP”分别应为“CAN 网络、CAN 收发器、CAN TP”,“X12/XSL”应为 Xshell。

一、OTA 固件更新

1.1 IAP 固件升级理论部分

这一部分建立在前面 IAP、CAN、LVGL 仪表盘和串口数据链路的基础上。建议先确认前面几个专题的工程都能独立运行,再做本实验;否则出现黑屏、CAN 无数据或无法进入升级模式时,很难判断故障属于哪一层。

常见的三类下载或升级方式如下:

缩写全称本课程中的直观理解程序由谁执行
ICPIn-Circuit Programming使用 ST-Link/SWD 等调试器直接烧录外部调试器控制芯片的调试接口
ISPIn-System Programming芯片出厂自带的 System Memory Bootloader 通过串口、CAN、USB 等接口下载芯片 ROM 中的系统 Bootloader
IAPIn-Application Programming用户自己的程序在运行期间接收并写入新 APP用户 Flash 中的 Bootloader/APP

STM32 的 System Memory Bootloader 支持哪些接口,取决于具体芯片型号和版本,不能把“ISP”固定等同于串口;应查对应芯片在 ST AN2606 中的表格。本课程使用的是用户自己放在 Flash 中的 Bootloader,因此属于 IAP,不是调用 STM32 ROM Bootloader。

IAP 与 OTA 也不是严格同义词。 IAP 描述设备内部“由程序更新程序”的机制;OTA(Over-the-Air)强调固件经无线网络远程下发。ST 对 FOTA 的介绍也把它描述为通过蜂窝或 Wi-Fi 等无线连接更新固件,参见 ST 的 FOTA 应用说明。本实验的 PC→串口→C8T6→CAN→ZET6 链路是有线链路,严格说是一次 IAP/远程升级演示;课程沿用“OTA”作为这一整套升级模块的名称。

升级媒介可以是 UART、I²C、USB、以太网、CAN 或无线网络。媒介只负责把字节送达,真正的 IAP 还要解决 Flash 分区、升级状态、数据完整性、异常恢复和 APP 跳转等问题。

1.1.1 实验演示

实验目标是把 ZET6 当前运行的仪表盘 APP,更新为温湿度显示 APP。完整数据路径为:

PC 上的固件文件 → C8T6 的 USART2 → C8T6 升级工具 → CAN TP → ZET6 Bootloader → ZET6 内部 Flash 的 APP 区。

各模块职责如下:

模块本次职责
PC 串口助手先发送 4 字节升级请求
PC 上的 Xshell使用 YMODEM 发送 APP_DHT11.bin
C8T6(31usb_tool)接收请求和 YMODEM 数据,再经 CAN TP 转发;USART1 打印日志,USART2 接收文件
ZET6 当前 APP(32Car_APP)接收升级命令、写入升级标志并软件复位
ZET6 Bootloader(34Bootloader)检查升级标志,接收分包数据,擦写 APP 区,升级结束后跳转
ZET6 新 APP(33DHT11_APP)从 0x08008000 运行并显示温湿度界面

本节重点是验证功能,视频在约 4 分 30 秒处明确说明“不写代码”。因此这里不添加并未在本节编写的源码块;代码在后续课程中逐项讲解。

1.1.1.1 实验测试流程

先接线,再识别串口,最后烧录初始固件。推荐按下面顺序检查:

  1. ZET6 连接 LCD、CAN 收发器和用于日志输出的 USART。
  2. C8T6 连接 CAN 收发器、USART1 和 USART2;USART1 用于观察升级工具日志,USART2 用于接收升级指令和 YMODEM 文件。
  3. 两块 CAN 收发器的 CANH 对 CANH、CANL 对 CANL,两块板必须共地。总线两端按实际硬件配置终端电阻;典型高速 CAN 总线两端各为 120 Ω,断电测量 CANH 与 CANL 约为 60 Ω。若模块已经带终端电阻,不要重复并联。
  4. 串口应交叉连接 TX→RX、RX→TX 并共地,电平必须与开发板兼容。本实验使用 USB 转串口设备,不要把 RS-232 电平直接接到 MCU 引脚。
  5. 打开三个串口窗口,通过复位后的启动日志判断端口归属。视频中的 COM9、COM10、COM11 只对老师当时的电脑有效,不能照抄到自己的电脑。

ZET6 初次准备需要用烧录工具写入三个 .bin 文件。二进制文件本身不带装载地址,所以每次选择文件后都必须核对起始地址:

文件本地文件实际大小烧录地址用途
Bootloader.bin16,704 B(约 16.31 KiB)0x08000000上电后首先执行,决定升级或跳转 APP
info.bin12 B0x08006000初始化升级配置区
APP_Car.bin320,012 B(约 312.51 KiB)0x08008000初始仪表盘 APP
APP_DHT11.bin310,132 B(约 302.86 KiB)不在初始阶段用 ST-Link 烧录;实验中经升级链路写入 0x08008000待升级的新 APP

原笔记把 info.bin 地址写成了 0x06000000,这是错误的;视频思维导图、工程宏定义和本地固件布局都对应 0x08006000。三个关键边界是:

  • Bootloader 从 0x08000000 开始;
  • 参数区从 0x08006000 开始,距 Flash 起点 0x6000,即 24 KiB;
  • APP 从 0x08008000 开始,参数区到 APP 区之间相隔 0x2000,即 8 KiB。

本地 info.bin 的 12 字节为 AA BB CC DD 02 08 04 01 00 1D 00 00。它与工程中的紧凑配置结构相对应,包含 4 字节魔数、版本字段、升级标志、校验字节和保留字节。此处的升级标志初始为 0x00,表示正常启动时不进入升级等待。不要只凭这 12 字节自行改版本或校验值,后续应结合结构体、字节序和校验算法一起理解。

烧录顺序如下:

  1. 连接 ST-Link 到 ZET6,写入 Bootloader.bin,地址设为 0x08000000。
  2. 重新选择 info.bin,先把地址改为 0x08006000,再开始烧录。
  3. 选择 APP_Car.bin,把地址改为 0x08008000 后烧录。
  4. ZET6 复位。若配置区有效且升级标志为 0,Bootloader 会跳转到仪表盘 APP,屏幕应显示仪表盘。
  5. 将 ST-Link 接到 C8T6,打开并烧录 31usb_tool 工程。这个工程名里的 usb_tool 表示它在实验中充当升级适配器;PC 与它的固件通道实际是 USB 转串口后的 UART。

视频中“同时只能插一个 ST-Link”是这次桌面操作的约束:只保留一个并在两块板之间移动,能避免选错下载目标。它不是 ST-Link 的通用硬件定律;专业工具可以按探针序列号管理多个调试器。

1.1.1.2 硬件连接及实验演示
  • 1.1.1.2.1 ZET6 单片机部分

    ZET6 端包含 LCD、CAN 收发器和日志串口。烧完三个初始文件后复位,能看到仪表盘,说明至少完成了以下链路:Bootloader 正常启动、配置区可读、APP 栈顶和复位向量通过基本检查、程序跳到 0x08008000,以及仪表盘 APP 能驱动 LCD。

    “屏幕能亮”还不能证明 CAN 升级已经正常。升级前还应确认 CANH/CANL、公共地、波特率、过滤器和收发器供电都正确。

  • 1.1.1.2.2 C8T6 单片机部分

    C8T6 烧入 31usb_tool 后承担协议桥接任务:

    • USART2 接收 PC 发来的升级命令以及 YMODEM 文件;
    • USART1 输出调试日志;
    • CAN 把升级控制帧和固件数据送往 ZET6;
    • 项目内的 CAN TP 层把超过 8 字节的数据拆成经典 CAN 帧,并处理流控与重组。

    给 C8T6 复位后,USART1 应打印类似 uart1:usb tool... 的启动信息。用日志识别 USART1,再把另一个端口认作 USART2,比记住老师的 COM 号可靠。

  • 1.1.1.2.3 实验测试流程

    1. 保持 ZET6 仪表盘 APP 正常运行,确认两块板与 CAN 总线均已连接。
    2. 在 C8T6 的 USART2 串口助手中启用十六进制发送,发送 AF 00 01 FA。工程固定接收 4 字节,检查首字节 0xAF、末字节 0xFA 和第 3 字节 0x01;第 2 字节在当前代码中没有参与判断。
    3. C8T6 随即以 CAN ID 0x0B3 发送 8 字节升级请求:BE AD BE EF 01 AA AA AA。
    4. 仪表盘 APP 收到请求后把参数区中的升级标志设为 1,等待约 1 秒并执行软件复位。
    5. Bootloader 复位启动后发现升级标志为 1,以 CAN ID 0x0D3 回复确认帧。C8T6 收到确认后启动 YMODEM 接收,并在 USART2 连续发出 ASCII 字符 C,请求发送端采用 CRC 模式。
    6. 关闭 USART2 的串口助手。一个串口通常同一时刻只能被一个桌面程序打开;若不先关闭,Xshell 会因端口占用而连接失败。
    7. 在 Xshell 新建 SERIAL 会话,选择刚才识别出的 C8T6 USART2 端口。视频使用老师电脑上的 COM9,自己的端口号可能不同。波特率等参数应与 CubeMX/工程配置一致。
    8. 连接后确认终端持续出现 C,右键选择“传输 → YMODEM → 用 YMODEM 发送”,选择 APP_DHT11.bin。Xshell 的串口会话和 X/YMODEM 操作也可查阅 Xshell 7 官方手册。
    9. 等待传输完成,不要中途关闭会话、复位设备或拔线。视频第一次发送因误操作中断,随后重新复位、重发 AF 00 01 FA、重新连接 Xshell 才成功。

视频口述的“302 个字节”明显是口误,后面已改称约 302 KB。本地文件的精确大小是 310,132 B(302.86 KiB)。以约 578 B/s 粗算,纯数据时间约为 310132 ÷ 578 ≈ 537 s,即约 8.9 分钟;加上 YMODEM 控制、CAN TP 分包、Flash 擦写和延时,课程按约 10 分钟估算是合理的。Xshell 中瞬时速度会变化,视频结束时约为 571 B/s,无需把某一个速度值当成固定指标。

1.1.1.3 工作流程图

把流程按“控制链路”和“数据链路”拆开,更容易理解:

进入升级模式:

  1. PC 向 C8T6 USART2 发送 AF 00 01 FA。
  2. C8T6 用 CAN ID 0x0B3 向当前 APP 发送 BE AD BE EF 01 AA AA AA。
  3. APP 将内部 Flash 参数区的升级标志写为 1,然后软件复位。
  4. Bootloader 启动并读取升级标志。若为 0,直接跳转旧 APP;若为 1,留在 Bootloader 中等待升级。
  5. Bootloader 用 CAN ID 0x0D3 向 C8T6 确认可以升级。
  6. C8T6 开始运行 YMODEM 接收端,并向 PC 发字符 C。

传输和写入固件:

  1. PC 通过 YMODEM 把文件送给 C8T6。
  2. C8T6 每收到一批数据,就组织成带偏移量和长度的升级数据,经项目中的 ISO-TP 实现发送;C8T6→ZET6 的发送 ID 为 0x0B2,反向流控 ID 为 0x0B1。
  3. ZET6 Bootloader 重组数据,以 0x08008000 + 偏移量 为目标地址,按页擦除并写入内部 Flash。
  4. PC 文件发送结束后,C8T6 用 CAN ID 0x0B3 发送 BE AD BE EF 02 AA AA AA,其中 0x02 表示升级结束。
  5. Bootloader 清除升级标志并跳转到 0x08008000,新 APP 开始运行。

这里的 “CAN TP” 是工程集成的 ISO-TP 风格分包层:经典 CAN 一帧最多只有 8 字节,传输数百 KiB 固件必须分段、编号、流控并在接收端重组。它不是 ST ROM 中的 CAN Bootloader 协议。YMODEM 只覆盖 PC↔C8T6 这一段,CAN TP 覆盖 C8T6↔ZET6 这一段,两个协议不能互换。

二、结束

2.1 后续工作任务

本次实验先证明整体方案可运行,后续还要完成三部分学习:

  • 把普通仪表盘工程和温湿度工程移植成能从 0x08008000 启动、能与 Bootloader 交接的 APP;
  • 阅读 Bootloader 如何检查配置区、接收 CAN TP 数据、擦写 Flash 和跳转 APP;
  • 阅读 C8T6 升级工具如何衔接串口 YMODEM 与 CAN TP。

学习时不要只记操作顺序。每一步都要能回答:哪个 MCU 在执行、数据从哪个接口进入、使用什么协议、写到哪个地址、失败后会停在哪个状态。

2.2 固件升级流程与代码对应关系

课程流程图与工程目录的对应关系如下:

流程节点工程/文件
PC 侧升级适配器31usb_tool,运行在 C8T6
当前仪表盘 APP32Car_APP,运行在 ZET6
待更新温湿度 APP33DHT11_APP,运行在 ZET6
Bootloader34Bootloader,运行在 ZET6
实验用二进制文件30OTA_Bin_Test

Bootloader 和 APP 都在 ZET6 内部 Flash 中,但占用不同地址。APP 工程除了链接地址改到 0x08008000,还要让向量表偏移与该地址一致;否则即使跳转入口看似成功,中断仍可能取错向量。这正是后续“APP 移植”不能省略的原因。

2.3 代码理解与实验演示准备

复杂工程可以沿数据流分层阅读:

  1. 先看 4 字节升级命令如何变成 CAN 0x0B3 控制帧。
  2. 再看 APP 收到命令后怎样写升级标志并复位。
  3. 接着看 Bootloader 怎样读取标志并发送 0x0D3 确认。
  4. 然后看 YMODEM 怎样产生文件名、文件大小和数据包。
  5. 最后看 C8T6 怎样把数据交给 CAN TP,以及 ZET6 怎样按偏移量写 Flash。

这样阅读虽然仍有工作量,但每一层都有明确输入和输出,不会被整个工程同时展开后的细节淹没。实验前应保留各串口启动日志和完整报错信息,不能只记录“升级失败”。

2.4 串口调试与固件重新发送

视频第一次传输被意外操作打断,处理方法是重新建立整个状态机,而不是从中间随意续传:

  1. 复位设备,让 Bootloader/APP 与 C8T6 回到可预期状态。
  2. 关闭占用 USART2 的 Xshell 或串口助手。
  3. 用串口助手重新发送十六进制升级指令 AF 00 01 FA。
  4. 收到连续的 C 后关闭串口助手,再用 Xshell 连接同一端口。
  5. 重新选择 APP_DHT11.bin 并从头发送。

转录中的“重新发送 AT 指令”不准确;这里没有 AT 命令,重发的仍是四字节自定义升级请求。若没有出现 C,应先查 C8T6 USART1 日志、ZET6 日志和 CAN 接线,不要直接反复点击 YMODEM 发送。

2.5 固件更新过程与结果验证

传输期间可同时观察两路日志:C8T6 USART1 显示 YMODEM 包、页计数和转发进度,ZET6 日志显示 CAN TP 收包、偏移量和 Flash 写入状态。课程画面接近结束时显示还剩约 2 KB,随后屏幕从仪表盘自动切换到温湿度界面,证明 Bootloader 已跳入新 APP。

验证升级成功至少要看三个结果:

  • Xshell 的 YMODEM 对话框正常结束,没有取消或超时;
  • ZET6 日志出现升级结束并跳转 APP 的信息;
  • LCD 由仪表盘变为温湿度界面,滑块还能触发板上 LED 的状态变化。

实验没有接 DHT11,所以温湿度显示为 0 是预期现象,不能据此判断升级失败。视频提到此前滑块用于控制风扇,本次界面还可联动灯;画面中直接可确认的是第一个 LED 随滑块变化。连接传感器后,才可继续验证真实温湿度采集。

日志中若出现类似 Size: 536889916Bytes 的巨大数字,不要把它当成固件大小。本地升级工具源码先把文件大小转成字符串数组 number,随后却用 %d 打印了数组地址,因此输出的是指针数值。可信的大小应看原文件或 YMODEM 文件头;本次 APP_DHT11.bin 为 310,132 B。

2.6 OTA 功能实现与总结

本节跑通了“请求升级→写升级标志→复位进 Bootloader→YMODEM 收文件→CAN TP 转发→写 Flash→跳新 APP”的完整闭环。速度慢主要因为链路层次多、经典 CAN 单帧载荷小、工程按 2 KiB 批次转发并在过程中加入 Flash 操作和延时,不应简单归因于某一个软件。

课程工程适合学习基本原理,但工程化升级还应考虑镜像大小边界、整包哈希或签名、版本与硬件型号校验、掉电恢复、失败回滚、写保护以及升级过程中的看门狗处理。YMODEM/ISO-TP 的 CRC 和分包机制主要用于发现传输错误,并不等同于固件来源可信或防篡改;在真实产品里还需要独立的真实性校验方案。

2.7 例题1:APP移植与温湿度显示代码修改

后续例题将把已有仪表盘和温湿度程序改造成 IAP 布局下的 APP。移植的核心不只是“改一个地址”,还包括:

  • 链接器把代码和向量表放到 0x08008000 之后;
  • 系统启动时把 VTOR 指向新的向量表;
  • APP 能接收升级请求、设置 Flash 中的升级标志并复位;
  • Bootloader 与 APP 对参数区结构、标志含义和 CAN 控制帧保持一致;
  • 生成供升级链路传输的 .bin 文件,并确认其大小没有越过 APP 分区边界。

Bootloader 与 C8T6 升级工具由课程提供,但仍应能沿本节流程图定位每个关键动作。只有把“界面业务代码”和“启动/升级基础设施”分开理解,才能把同一套升级框架迁移到新的 APP。