关于IAP升级任务开发中遇到的一些问题汇总

 

      【前言】最近正在开发一个具有升级功能的项目,使用的是GD32的E230芯片。这里只阐述个人认知水平的观点,本人很菜,所以酌情观看本文。

      关于IAP升级我还是第一次做,无非就是将内存分两份,一份用于Bootloader,一份用于APP。芯片共64K Flash空间,在做升级前,已经使用了公司的V3协议,所以就顺便也套用了升级的框架,升级的协议是在V3协议的基础上,利用数据段进行了处理,相当于协议套协议,具体内容下面再说。

      一、分配内存:

     将工程只保留最简单的通讯协议部分,以及状态指示灯,以及升级用的框架代码,发现用了22K,预留3K即共用25K做Bootloader。 然后1K作为bin文件的信息段(Info),剩下的64-25-1=38K作为APP程序空间。

     二、程序整体运行

      初始化--》判断能否跳APP--》Loop循环

       Loop循环:{通讯协议、要运行的程序、......}

 

     三、移植对应的升级框架:

    Boot端的升级框架:定义{升级间隔、每包数据大小、Bin文件最大的大小、APP地址、跳转程序、Flash操作结构体}

     Flash操作结构体{Info地址、擦除函数、写入函数、读取函数}

   【准备升级】:通过通讯协议和上位机通讯交换信息,通过校验一些数据来确保固件OK。比如info起始地址、固件大小是否合适、APP起始地址是否......。验证通过后则将准备标记置位,并擦除固件对应大小的Flash为后面的升级做准备。返回包可以包括传输密钥等传输参数。

   【接收升级包】:通过协议接受升级包,保存前要做验证,比如是否准备接受,包长是否合适、密钥是否正确等...。记录当前的包数并写入固件信息到对应的Flash。

  【校验源码完整性】:通过校验传输密钥等操作后,进行包数校验是否足包。

  【跳转APP】:如果上述步骤完成,则可以跳转APP。

 

对Info信息的说明:Info是跟着APP固件走的,里面包括版本号,CRC校验码,等等用于校验固件是否正确等

每次从Boot跳转到APP都是要通过Info判断,如果判断通过则跳转否则不跳转。在APP端使用的时候,点击升级的时候清除掉Info然后再跳到Boot,就可以不自动跳回来APP。

 

===============================分割线=================================

============================细节问题补充=================================

跳转APP程序介绍:

void BUpdataFirm_JumpAddress(uint32_t address)
{
    /* 反向初始化用到的外设、中断等 */
    MCUDriverMain_DeInit();
    Delay(100);
    uint32_t SpInitVal;                        //栈顶的地址存放
    uint32_t JumpAddr;                         //跳转地址存放
    void (*pFun)(void);
    disable_irq();                             //关闭中断(到APP中记得再打开!)
    SpInitVal = *(uint32_t *)address;          //地址中的数据拿出来,作为栈顶的地址
    // JumpAddr = *(uint32_t *)(address + 4);  //栈顶地址+4 就是程序运行的地址
    __asm volatile ("MSR msp, %0" : : "r" (SpInitVal) : );  //设置栈顶
    pFun = (void (*)(void))(*(uint32_t *)0x08006804);       //设置程序执行地址
    (*pFun)();                                              //执行程序
}

 【注意】:

    1、因为跳转前关闭了中断,所以APP中一定要先开启中断!!!否则会有不进中断等问题。

    2、传参address是栈顶地址存放的地址,所以要对address强转(uint32_t*)然后取值。

    3、本来JumpAddr这一句是个函数封装的,因为没在GD库中找到这句话,就直接改了一下,之前是inline内联函数,但是我把inline的标记给删了,然后就会出现一个问题:执行到这一句的时候,一些变量的值会改变,导致跳转的地方不对。是因为没有加inline的时候,前面刷新了栈顶指针,在栈中存放的数据会改变,汇编指令会重新读取数据,导致出错。所以这里直接把这句话放这里了。相当于内联函数的作用。

   4、上位机的跳转可以取巧:直接调用复位函数就可以回到Boot中

/**
  \brief   Disable IRQ Interrupts
  \details Disables IRQ interrupts by setting the I-bit in the CPSR.
           Can only be executed in Privileged modes.
 */
void disable_irq(void)
{
  
	__asm volatile ("cpsid i" : : : "memory");
}

/**
  \brief   Enable IRQ Interrupts
  \details Enables IRQ interrupts by setting the I-bit in the CPSR.
           Can only be executed in Privileged modes.
 */
void enable_irq(void)
{
  
	__asm volatile ("cpsie i" : : : "memory");
}

这是开启和关闭中断向量的函数(本来也是内联的)。

问题一、字节对齐的问题

/*************************************************************
** Function name:     GD32Flash_FlashWrite
** Descriptions:      内存写入
** Input parameters:  flashStart:内存起始地址
**                    *pData:数据指针          必须是4的倍数
**                    size:写入的数据个数       必须是4的倍数
** Output parameters: no
** Returned value:    no
*************************************************************/
void GD32Flash_FlashWrite(
                uint32_t flashStart,
                uint8_t *pData,
                uint16_t size)
{
    uint32_t cir = 0;
    uint32_t data;
    fmc_unlock();                       //内存解锁
    for(cir = 0; cir < size; cir += 4) {
        // data = *(uint32_t *)&pData[cir];
        memcpy(&data,pData+cir,sizeof(uint32_t));
        fmc_word_program(flashStart + cir, data);
        fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_WPERR | FMC_FLAG_PGERR);
    }
    fmc_lock();
}

   这里的pData是一个数组进来的,每次到这里写入的时候都会卡死,不知道为什么。我在初始化的时候也测试了程序是没问题的,但是一到实际升级的时候就出问题。

问大佬:发现是这里data=*(uint32_t)&pData[cir]会卡死,通过单步调试发现此时pData[cir]的地址是E5即0101结尾,为奇数结尾。此时一下读四个字节就会出问题。具体的搜一下其他文章。

其实导致这个主要是因为协议进行了字节对齐,而且使用的过程中没有成双成对的使用,有的是一个字节有的两个,就会导致后面读取使用的时候出问题。但是用memcpy可以解决问题,暂时不知道还有没有其他办法,日后再搜。

问题二、串口无法接收0x11、0x13的问题

调试过程中发现协议数据包不对,仔细核对发现少了0x11这个数据,后来搜了一下,说是上位机的问题。果然换了个上位机就可以了。

上位机需要更改一个关于流控的参数(听大佬说 好像是这样就可以了)

 

===============================分割线=================================

============================MDK软件设置=================================

调试的过程中要Boot和APP两个程序相互跳转,所以配置MDK十分重要。

这是Boot的配置:

Target可以不变,但是程序烧录大小要更改,否则每次烧录全部地址会擦除APP的程序。

 

这是APP的配置:

Target中的起始地址要更改

 

 

 

 

 

 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值