概述
项目场景:
很多有关MCU的项目应用,都需要具备远程升级程序的功能。功能实现起来容易,但是会遇到例如程序文件传输失败,bin文件原本就有BUG,中途掉电等原因导致产品死机。这时就只能由维护人员到现场重新烧程序解决,增加一大笔的维护费用。
方案概述:
由于MCU本身的资源限制,要么跑裸核,要么就是跑FreeRTOS一类的微内核操作系统,无法像linux一样能做到内核态和用户态分离。一旦运行的程序有问题就死机,死得很彻底,无法恢复,以下介绍一种程序设计方法来解决这个问题。
硬件支持:
1.外部看门狗
作用程序死机时复位。
2.外部Flash
常见的MCU程序执行方式有两种:一种是具有片内Flash的直接执行(STM32),另一种是程序存储在片外Flash用XIP的模式执行代码(NXP的i.mxRT系列)。在正常运行时,均无法直接擦出程序空间,所以这里单独加一片Flash,用于存储需要更新的程序文件和备份文件。
软件方案:
1.外部Flash驱动及分区
(1)常用的Flash都是SPI接口,根据手册实现其驱动,用于存储APP文件。
(2)根据具体的APP文件大小划定三个分区,分别是:程序区、备份程序区、程序更新信息区。
注:备份程序是产品出厂时需要写入的一个包含主要功能的有效程序。
2.APP文件传输方式
根据具体产品应用,有线可用485、SPI、CAN网传输;无线可通过蓝牙、WIFI传输之后,存储到外部Flash。至于传输协议,可自行设计,或采用例如xyzmodem等标准协议。
3.程序更新信息结构
这个结构很重要,用于区分在程序升级时发生各种异常情况之后进行程序引导,结构如下:
typedef struct TProgramFile
{
uint32_t magic; //魔术数 0x9f5abeef
uint32_t appLen;
uint32_t backupsLen;
uint32_t appCrc;
uint32_t backupsCrc;
uint8_t updateFlag; //1--新的APP程序写入外部flash,0--写入失败
uint8_t startFlag; //1--成功启动,0--启动失败
}TProgramFile;
4.BootLoader
裸核编程,实现最基本的外设,主要用于引导程序启动。
引导程序:将已经存储在外部Flash中的程序读取出来写入程序Flash区。程序空间如下:
软件流程:
updateFlag与startFlag的更新机制是实现该方案的重点,流程如下:
当更新的程序有bug,或者引导时遇到中途掉电的情况,均会导致跳转失败。此时,updateFlag == 0 && startFlag == 0,重新引导备份程序。成功跳转APP启动之后,置位startFlag = 1。之后再次上电就可以直接跳转APP,不再执行引导。
BootLoader主要代码:
TProgramFile fileHead;
uint32_t readFlashAddr = 0,crc = 0,i = 0;
uint32_t programSize = 0,programCrc = 0,offset = 0,writeCnt = 0;
//硬件初始化
.....
spiDevice_read(g_flashFlagtAddr,(uint8_t*)&fileHead,sizeof(TProgramFile));
if(fileHead.magic != BOOT_MAGIC)
{
JumpApplication();
}
if(fileHead.updateFlag == 0 && fileHead.startFlag == 1)
{
JumpApplication();
}
if(fileHead.updateFlag == 0 && fileHead.startFlag == 0)
{
readFlashAddr = g_flashBackAppAddr;
programSize = fileHead.backupsLen;
programCrc = fileHead.backupsCrc;
}
if(fileHead.updateFlag == 1 && fileHead.startFlag == 0)
{
readFlashAddr = g_flashAppAddr;
programSize = fileHead.appLen;
programCrc = fileHead.appCrc;
}
//擦除程序空间
if(EraseSectionAPP(FLASH_APP_OFFSET) != status_success)
{
printf("EraseSectionAPP error !n");
return 0;
}
while(programSize)
{
writeCnt = (programSize > 1024) ? 1024 : programSize;
spiDevice_read(readFlashAddr + offset,fileBuf,writeCnt);
//写入程序空间
...............
crc += SumCheck(fileBuf,writeCnt);
programSize -= writeCnt;
offset += writeCnt;
}
if(crc != programCrc)
{
return 0;
}
fileHead.updateFlag = 0;
spi_flash_sector_erase(g_flashFlagtAddr);
spiDevice_write(g_flashFlagtAddr,(uint8_t *)&fileHead,sizeof(TProgramFile));
JumpApplication();
最后
以上就是悦耳鸵鸟为你收集整理的MCU远程升级方案,可解决升级错误死机问题项目场景:方案概述:硬件支持:软件方案:软件流程:BootLoader主要代码:的全部内容,希望文章能够帮你解决MCU远程升级方案,可解决升级错误死机问题项目场景:方案概述:硬件支持:软件方案:软件流程:BootLoader主要代码:所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复