我是靠谱客的博主 悦耳鸵鸟,最近开发中收集的这篇文章主要介绍MCU远程升级方案,可解决升级错误死机问题项目场景:方案概述:硬件支持:软件方案:软件流程:BootLoader主要代码:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

项目场景:

很多有关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主要代码:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部