雲栈小驿 · 2022年04月18日

从IAP升级到涂鸦OTA升级介绍(下)

仅作为个人学习笔记使用

OTA--Over-the-Air 即空中下载技术,通过远程网络为设备更新或者升级
Wifi通用串口协议支持MCU OTA功能。通过使用涂鸦iot平台,需要将更新好的固件上传至涂鸦服务器上,Wifi模组通过涂鸦协议对文件进行分包传输,最后MCU接收升级包并写入FLASH中,至此完成整个OTA升级过程。

一、升级流程及协议

升级流程如下图
1.png
1) OTA启动后,模组首先发送0A指令(启动升级指令)告诉MCU升级包的大小,MCU需要返回固件分包的大小
2) 此后模组通过发送0B指令(升级包传出指令)按包传输固件给MCU,MCU需要在5S内予以回复,若未予以回复 在连续发送三次后显示升级失败
3) 模组发送完最后一包数据后,会发送01指令(查询产品信息指令) MCU需要在1min内回复升级后的版本号,如果上报的版本号与云端之前设定的版本号一致则表明升级成功

详细串口协议请参考WIFI协议MCU升级平台配置

二、SDK部分解析

在这里就不做过多的SDK移植方面的介绍,直奔主题。

上一篇文章中我们主要介绍IAP升级的原理和具体实现,采用的方式是直接将队列接收的数据直接写入FLASH指定位置中 再通过BootLoader程序引导进入APP中 从而完成程序更新。而在这里采用wifi模组通过涂鸦协议对文件进行分包下发传输,此时需要分包接收 为了分包接收的数据的准确性需要去检测校验位或者标志位。整个OTA升级思路如下:

代码部分分为BootLoader、APP、OTA三个代码区域。使用BootLoader引导代码,通过识别标志位来判断是直接跳转到APP还是OTA数据。在APP中,如果收到OTA升级数据,将存储到FLASH的OTA区域中 并将在接收完整个OTA数据后 将OTA升级标志位置1,此后重启MCU。重启MCU后,由BootLoader将OTA部分搬运到FLASH的APP中,搬运完后跳转到APP中执行。至此整个OTA升级过程结束。
2.png
1)首先要在protocol.h中 更改对应pid和要升级的版本信息
3.png
2)打开SUPPORT_MCU_FIRM_UPDATE这个宏定义 开启固件升级,其次选择传输包的大小
4.png
3)对串口接受缓存进行修改 根据实际固件大小来决定
这里建议使用环形队列的方式接收处理数据,具体好处在上一篇中有提到
5.png
4)在protocol.c中完成固件升级代码,将接收到的升级包依次写入MCU FLASH

OTA升级部分

前面说到了平台通过协议将升级包分包发送进行升级,那传输过成中校验数据的准确定性是重中之重。OTA升级包每包都由固定大小数据组成,需要根据每包数据偏移量 将数据包按FLAS页的大小进行组合,并写入FLASH 直到最后一包数据完成。此后将OTA升级标志位置1 并对MCU进行重启。

这里Tuya SDK已将协议解析部分写好了,主要完成mcu_firm_update函数功能。
6.png

unsigned long addr;
 
  if(length == 0)
  {
#ifdef ENABLE_BOOT
    //固件数据发送完成
    FlashBuffer.magic_code = FIREWARE_UPDATE_FLAG;
    
    if(Earse_Flash(PARA_ADDR) == ERROR)
      return ERROR;
    
    //写入升级标志
    if(Write_Flash(PARA_ADDR,(unsigned char *)&FlashBuffer,sizeof(FlashBuffer)) == ERROR)
      return ERROR;
    
    Reset();
#endif
  }
  else
  {
    //固件数据处理
    addr = FIREWARE_ADDR_H;
     
    if(position % 1024 == 0)
    {
      if(Earse_Flash(addr + position) == ERROR)
        return ERROR;
    }
    
    if(Write_Flash(addr + position,(unsigned char *)value,length) == ERROR)
      return ERROR;

BootLoader部分

程序启动后,先判断OTA升级标志位是否置1,如果没有,那么将跳转到APP中执行;如果有,将OTA部分代码搬运到APP中,搬运结束后清除OTA升级标志位 最后跳转到APP中。

void main (void)
{
  /*
  //解锁(必须运行在RAM状态下)
  FLASH_Unlock();
  FLASH_ReadOutProtection(DISABLE); 
  */
  uint32_t magic_code;
  uint32_t app_address;
  
  RCC_Configuration();
  
  NVIC_Configuration();
  
  //
  Read_Flash((unsigned char *)&magic_code,PARA_ADDR,4);
    
  if(magic_code == FIREWARE_UPDATE_FLAG)
  {
    if(update_firmware() != SUCCESS)
    {
      Reset();
    }
  }  
  
  //判断程序是否存在
  app_address = FIREWARE_ADDR_L;

  if(Exist_MainProgram((uint32_t *)app_address) == 1)
  {
    JumpToApp(app_address); 
  }

  while(1)
  {

  }
}

1)这里最后提示一下:1)接收 OTA 数据包的时候,要对包偏移进行检测,防止串口通信异常导致重发和漏发
2)MCU建议加上OTA 数据接收超时检测,以免模块或网络异常导致 OTA 失败时,MCU 无法退出,不能重新进行 OTA

这样软件部分就完成了,开始在平台上上传固件吧。

三、Tuya IOT平台使用

请参考链接平台配置

四、升级失败的原因分析

以MCU升级到1.0.2为例,成功升级后在涂鸦智能APP面板上显示如图
1.png
正常流程下的后台日志信息如图,MCU升级 通道9 当前版本1.0.0 目标版本1.0.2。
2.png
3.png

当然在出现升级超时时别慌!稳住!先学会自查 打开后台日志输入你的设备id。
1)先检查升级的通道号是否正确 以常用的为例:MCU升级->通道9;固件升级->通道0
2)检查要升级的版本是否正确
3)设备网络问题 可以更换一个网络环境下重新进行
4)在涂鸦调试助手上 根据通信协议对升级过程中交互数据进行分析
5)如果MCU OTA到98% 那也不一定是失败。看一下是不是后面有模组的重启日志 大多模组供电由MCU 控制,当MCU OTA时 最后会重启,重启阶段模组无法得到正常工作,后续版本号上报的流程终止。看最后是不是版本号正常更新了就可以了
具体的还是得监控一下MCU OTA流程
6)设备上报的固件key与配置的升级固件key不一致导致

推荐阅读

从IAP升级到涂鸦OTA升级介绍(上)

推荐阅读
关注数
1
内容数
2
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息