仅作为个人学习笔记使用
下篇
OTA--Over-the-Air 即空中下载技术,通过远程网络为设备更新或者升级
Wifi通用串口协议支持MCU OTA功能。通过使用涂鸦iot平台,需要将更新好的固件上传至涂鸦服务器上,Wifi模组通过涂鸦协议对文件进行分包传输,最后MCU接收升级包并写入FLASH中,至此完成整个OTA升级过程
一、升级流程及协议
升级流程如下图
1) OTA启动后,模组首先发送0A指令(启动升级指令)告诉MCU升级包的大小,MCU需要返回固件分包的大小
2) 此后模组通过发送0B指令(升级包传出指令)按包传输固件给MCU,MCU需要在5S内予以回复,若未予以回复 在连续发送三次后显示升级失败
3) 模组发送完最后一包数据后,会发送01指令(查询产品信息指令) MCU需要在1min内回复升级后的版本号,如果上报的版本号与云端之前设定的版本号一致则表明升级成功
详细串口协议请参考WIFI协议MCU升级
二、SDK部分解析
在这里就不做过多的SDK移植方面的介绍 直奔主题
在上一篇文章从IAP升级到涂鸦OTA升级介绍(上)中我们主要介绍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升级过程结束
1)首先要在protocol.h中 更改对应pid和要升级的版本信息
2)打开SUPPORT_MCU_FIRM_UPDATE这个宏定义 开启固件升级,其次选择传输包的大小
3)对串口接受缓存进行修改 根据实际固件大小来决定
这里建议使用环形队列的方式接收处理数据,具体好处在上一篇中有提到
4)在protocol.c中完成固件升级代码,将接收到的升级包依次写入MCU FLASH
OTA升级部分
前面说到了平台通过协议将升级包分包发送进行升级,那传输过成中校验数据的准确定性是重中之重。OTA升级包每包都由固定大小数据组成,需要根据每包数据偏移量 将数据包按FLAS页的大小进行组合,并写入FLASH 直到最后一包数据完成。此后将OTA升级标志位置1 并对MCU进行重启
这里Tuya SDK已将协议解析部分写好了,主要完成mcu_firm_update函数功能
unsigned char mcu_firm_update_handle(const unsigned char value[],unsigned long position,unsigned short length)
{
// #error "请自行完成MCU固件升级代码,完成后请删除该行"
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;
}
return SUCCESS;
}
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)接收 OTA 数据包的时候,要对包偏移进行检测,防止串口通信异常导致重发和漏发
2)MCU 建议加上 OTA 数据接收超时检测,以免模块或网络异常导致 OTA 失败时,MCU 无法退出,不能重新进行 OTA
这样软件部分就完成了,开始在平台上上传固件吧
三、Tuya IOT平台使用
请参考链接平台配置
四、升级失败的原因分析
以MCU升级到1.0.2为例,成功升级后在涂鸦智能APP面板上显示如图
正常流程下的后台日志信息如图,MCU升级 通道9 当前版本1.0.0 目标版本1.0.2
当然 在出现升级超时时别慌!稳住!先学会自查 打开后台日志输入你的设备id
1)先检查升级的通道号是否正确 以常用的为例:MCU升级->通道9;固件升级->通道0
2)检查要升级的版本是否正确
3)设备网络问题 可以更换一个网络环境下重新进行
4)在涂鸦调试助手上 根据通信协议对升级过程中交互数据进行分析
5)如果MCU OTA到98% 那也不一定是失败。看一下是不是后面有模组的重启日志 大多模组供电由MCU 控制,当MCU OTA时 最后会重启,重启阶段模组无法得到正常工作,后续版本号上报的流程终止。看最后是不是版本号正常更新了就可以了
具体的还是得监控一下MCU OTA流程
6)设备上报的固件key与配置的升级固件key不一致导致