一主多从下的IAP升级(四)

文章详细描述了MCU固件升级(OTA)过程中,boot_ota_process函数的执行流程,包括接收到升级请求的确认、擦除闪存区域、数据包接收与验证、写入闪存及完整性检查,以及升级成功或失败后的处理策略。
摘要由CSDN通过智能技术生成

函数解析:

2、

boot_ota_process(){

   send_to_main_mcu(OTA_START_ACK);
   flash_eara_obj(eFlashApp); 
   while(1){
       ota_deal_sub();//处理自身逻辑
       ota_deal_main(); //处理主mcu发过来要做的逻辑
   }

}

这是ota部分的主要函数

包括几个环节:

①首先要定义一些信号的宏定义:

#define SUBMCU_OTA_START_ACK    0x11  //收到主mcu升级请求,回复ack
#define SUBMCU_OTA_PROCESS_ACK  0x22  //收到主mcu升级包,回复ack
#define SUBMCU_OTA_VERIFY_ACK   0x33  //收到主mcu升级包验证请求,回复ack
#define SUBMCU_OTA_FAIL         0X44  //OTA过程有任何导致ota失败的情况向主机发送

主mcu端发送过来的是相同的宏定义,知识宏定义名字会去掉ACK,也就是主MCU发送给子MCU,SUBMCU_OTA_STAR这条命令时,子MCU通过解析后得到,处理完成会给主MCU回复SUBMCU_OTA_START_ACK

②给主mcu会ACK,因为收到了主机升级准备得请求进入boot,选择进入boot成功回给主机ack告知主机准备好了,并且进行flash擦除工作

send_to_main_mcu(SUBMCU_OTA_START_ACK);

flash_eara_obj(eFlashApp);

③ota_deal_normal();

这个函数涉及主要是处理boot接收到主mcu发过来的包,解析后通过命令判断下一步需要做什么,并且给主mcu会ack的过程

打包的协议一般都是项目中定下来的,如果需要自定协议,建议可以参考成熟的协议,例如TCP/IP这类,一般来说会包含包头、地址、指令、包的大小,包数据,以及CRC校验

我们这里用的串口dma将包传到ringbuf中,这样从ringbuf里去读包

通过包头来识别一帧的包,也能防止粘包,

然后需要对地址,指令的有效性进行判断

然后根据包的大小可以找到crc校验,验证crc是否正确

验证通过此时就可以拿到包的数据,并且根据指令可以区分将解出来的包送给不同的处理函数

-------------------------------------------------------------------------------------------------------------------------

当发给主mcu ACK后,主MCU会开始给子MCU发送升级包,指令SUBMCU_OTA_PROCESS

此时子MCU开始解包,写到flash中

SUBMCU_OTA_PROCESS

sub_mcu_write_flash_process(uint32_offset,uint32_t length,uint8_t*payload){
    s_LastProcessTick=get_ms_tick();//记录本次收到包的时间,以便异常处理
    //offet记录已经写了多少数据,这样才知道下次从哪个位置开始写
    //length是本次要写的长度,payload是本次要写的数据的首地址
    if(FLASH_COMPLETE==write_flash_data(ROM_APP_BASE+offset,length,payload)){
    //写入成功要回ack
        send_to_main_mcu(SUBMCU_OTA_PROCESS_ACK);
    }
}

SUBMCU_OTA_VERIFY

当主MCU将包发完后会通知子MCU,包发送完了,可以做整个代码的检查了,此时子mcu会对已经更新了的flash部分做crc计算,看看是不是与发过来的crc一致,看看是否能够通过

void whole_app_verify(){
    if(true==app_crc_verify()){
        send_to_main_mcu(SUBMCU_OTA_VERIFY_ACK);
        //其实这里就可以重新启动程序了,但是立即重启可能会导致ACK还没发过去,所以最好在这里做个计时,过个一秒后在重启
        g_StartWaitTick=get_ms_tick();
    }else{
        send_to_main_mcu(SUBMCU_OTA_FAIL);         
    }
}

④ota_deal_sub();

自身逻辑无非是升级好了重启或者是升级失败了,卡在里面了

那就是记录了两个tick

一个是上面说的升级成功后害怕重启导致ACK没发过去,可以在这里做个计时过个一两秒在启动

重启的函数:

void boot_restart(void){
    __disable_irq();
    stBootParam.BootFlag = BootFlagNormal;
    flash_save_data(eBOOTFLAG);//这里需要把bootflag改成正常BootFlagNormal,存到flash中    
    NVIC_SystemReset(); 
}

另一种就是升级没成功,使用另一个tick,s_LastProcessTick,计时超时后发送 send_to_main_mcu(SUBMCU_OTA_FAIL)告知主机,等待下一次升级。

3、boot_normal_process();

正常启动的函数

 void boot_normal_process()
 {
         __disable_irq();
  
         jump2app = (void (*)())*(__IO uint32_t*) (ROM_APP_BASE + 4);
  
          __set_MSP(*(__IO uint32_t*) ROM_APP_BASE);
  
         jump2app();
      
  }

①先关闭中断

②取出异常处理程序的地址(Reset_Handler),保存在向量表首地址的第二个元素

③设置MSP的初始值,保存在向量表首地址的第一个元素

④通过函数指针进行跳转

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值