MCU OTA升级流程
本文档以 STM32F103C8 为例。此 MCU 的 flash 共 64k,分为 64 页,每页 1k ,flash 的擦除需要以页为单位进行。
OTA 实现的思路是,代码分为 bootload 、应用代码、OTA数据,三个区域。使用 bootload 代码进行引导,可以通过识别 OTA 标志来决定是直接跳转到应用代码还是搬移OTA数据后跳转(此部分可以自行设计)。应用代码执行期间,如果收到 OTA 数据,要存储到 flash 的 OTA 数据区,并在接收完整个 OTA 数据后,将 OTA 升级标志置位,然后重启 MCU 。重启后,由 bootload 搬运 OTA 数据到 flash 的应用代码区,搬运完成之后跳转到应用代码区。由此实现 OTA 升级。
1. flash分区
可以将 flash 分为 bootload 、应用代码、OTA数据,三个区域。
bootload 代码为最开始要运行的代码,所以此区域的起始地址必须是 0x08000000 。bootload 编译完成后的大小可以作为 bootload 分区大小的依据,一般分为8k就可以了(编译的结果为 2k )。
应用代码和 OTA 数据区的大小需要相等,(64 - 8)/ 2 = 28k,所以应用代码的起始地址是 0x08002000,OTA 数据的起始地址是 0x08009000 。
2. OTA流程介绍
OTA流程主要分为两个过程。OTA数据接收和bootload启动。
(1) OTA数据接收
先看一下OTA数据接收的流程图。
首先,这个OTA数据包怎么来的呢?
答:模块下发升级启动命令,MCU收到命令后回复;接着模块下发升级包传输命令,MCU收到命令后接收模块发送的OTA数据包。
MCU在执行应用代码期间,接收模块下发的OTA数据包。OTA数据一般是以固定大小的数据包组成,每包都有包偏移的信息,需要根据包偏移信息,MCU将数据包排序并按照 flash 页的大小进行组合,写入 flash,直至最后一包数据,如下图。接收完成后,要将 OTA 升级标志置位以便于 MCU 重启告诉 bootload (也可以用其他方式)。最后重启 MCU 。
看到这里,可能有人疑问OTA升级标志有什么用?bootload启动又是什么逻辑?
那么,一起来看下第(2)过程。
(2) bootload启动
bootload是系统在加电后执行的第一段代码,负责系统的加载启动任务。
先看一下bootload启动的流程图。
bootload 启动后,需要先识别 OTA 升级标志是否置位 ,如果没有,就直接跳转到应用代码区;如果有 OTA 升级,需要将 OTA 数据区的数据搬到应用代码区,搬运完成之后,清除 OTA 标志,最后跳转到应用代码区。
搬移OTA数据:a、读取OTA data数据区的OTA升级数据;
b、擦除app数据区的原始数据;
c、写入OTA升级数据。
3. 注意事项
(1) 在读写 flash 时,有概率会读写错误,所以在写 flash 之后,建议加上检验,例如读取刚才写入的数据,对比要写入的是否一致。
(2) 接收 OTA 数据包的时候,要对包偏移进行检测,防止串口通信异常导致重发和漏发,避免 OTA 数据错误导致 MCU 变砖。
(3) MCU 建议加上 OTA 数据接收超时检测,以免模块或网络异常导致 OTA 失败时,MCU 无法退出,不能重新进行 OTA 。