硬件介绍
本次使用的MCU为HC32FA0的2M Flash版本,因此支持下文说明的第二种方法
两种实现方式
实现方式一: bootloader + app
这是常见的较为传统的方法,可以尝试工程文件iap_ymodem_boot和iap_ymodem_app的示例使用Ymodem协议传输程序到程序运行分区
实现方式二:引导交换
这是我接触HC32第一次听说的方法,有点像Android的A/B分区
引导交换的具体技术细节见 《HC32F4A0 系列参考手册》 Page255
具体实现
方式一
方案概述
我的方案为BootLoader仅做Flash搬运,将程序文件由B分区搬运至A分区;程序文件的接收在App中进行,接收的程序文件写入B分区;程序传输物理接口为串口,软件协议自己定义(大致包含帧大小、帧序号、校验和、bin文件分片,(虽然用了那麽多次11500波特率,传输360k的程序文件未出现过错误)
EFM划分
EFM划分如下
/******************FLASH使用详情********************/
//
// ----------------- 0x00000000 -----
// | | |
// | | |
// | boot | |
// | | |
// | | |
// |-----------------|0x00008000 } BLOCK0
// | | |
// | | |
// | | |
// | A | |
// | | |
// | | |
// | | |
// |-----------------|0x00100000--------
// | | |
// | | |
// | | |
// | B | } BLOCK1
// | | |
// | | |
// | |0x001fffff |
// ----------------------------------
/**************************************/
其中boot为BootLoader实现的分区,A分区为当前App运行的分区,B分区为存储程序文件的分区
BootLoader
解锁寄存器,初始化时钟、EFM设备(我还初始化了滴答定时器和LED灯,用于判断BootLoader的工作状态 检查升级标志位(使用iap_ymodem_boot中的APP_EXIST_FLAG标志位存储在0x8000前的4字节 升级标志位存在时,将B分区程序搬移至A分区搬移并检查程序是否符合要求并 设置栈栈顶地址 并跳转;若标志位不存在,则尝试检查地址是否符合要求 设置栈栈顶地址 并跳转 注意在跳转前,需要解除注册设备,外设和寄存器等iap_ymodem_boot中也有示例
App
解锁寄存器,初始化时钟、初始化EFM设备、初始化程序运行所需的外设 此部分解析串口的报文,提取、校验报文中的bin片段,将其顺序写入到B分区;写入并校验完毕后,写升级标志位并软重启MCu即可进入BootLoader
方式二
方案概述
借助HC32F4A0的引导交换功能,这更为简单,没有所谓的BootLoader部分,不用搬移Flash数据,对Flash寿命更加友好且升级速度快,但是可自定义程度小(方式一可以不使用片内Flash,比如各种外置存储器也可实现升级)、且无法迁移到其他单片机(其他型号单片机可能不支持引导交换,如果需要更换MCU,迁移项目是个问题)
EFM划分
/******************FLASH使用详情********************/
//
// ----------------- 0x00000000 -----
// | | |
// | | |
// | | |
// | A | |
// | | } BLOCK0
// | | |
// | | |
// |-----------------|0x00100000--------
// | | |
// | | |
// | | |
// | B | } BLOCK1
// | | |
// | | |
// | |0x001fffff |
// ----------------------------------
/**************************************/
实现方法
操作时,无论引导交换是否处于启动状态,均只对BLOCK1做读写操作,当程序接收并校验完毕后判断当前是否为引导交换状态,是引导交换则关闭引导交换并重启MCU,不是引导交换则启用引导交换并重启MCU;这样就实现了程序升级