【官方】通过机智云OTA升级MCU固件
GAgent OTA教程MCU OTA教程(2.0)MCU OTA教程(3.0)MCU OTA教程(3.1)源文档及源参考代码下载概述MCU OTA可以对MCU程序进行无线远程升级。原本MCU程序软件版本号是01,想升级到02,但是设备已经量产了不可能再去一个一个设备重新烧录新的程序,这时候就需要用到MCU OTA.本文以MCU OTA教程(3.1)的基础上移植到STM32G071RBT6芯片。下载源文档及源参考代码。
FLASH分区STM32G071RBT6芯片Flash 空间划分出 4 个区域:Bootloader、FLAG、APP 分区、APPBAK 分区https://www.stmcu.com.cn/upload/20200103/6.png
[*]Bootloader:存储 Bootloader 固件,MCU 上电后首先运行该固件。
[*]FLAG:存储有关升级的相关标志位,Bootloader 和 APP 分区都需要操作该区域。
升级标志位(2B)固件大小(4B)MD5加密数据(16B)
[*]APP 分区:存储用户程序固件。
[*]APPBAK 分区:临时存储云端下发的新固件,升级固件的一个过渡存储区。
BOOTLOADER分区部分
Bootloader程序流程Bootloader 的主要职能是在有升级任务的时候将 APPBAK 分区里面的固件拷贝到 APP 区域。当然,这期间需要做很多的工作,比如升级失败的容错等等。具体的流程可以参考图示。需要注意的是,在校验 MD5 正确后开始搬运固件数据期间,MCU 出现故障(包括突然断电),MCU 应发生复位操作(FLAG 区域数据未破坏),复位后重新开始执行 Bootloader,从而避免 MCU 刷成板砖。https://www.stmcu.com.cn/upload/20200103/7.pngBootloader编译设置https://www.stmcu.com.cn/upload/20200103/8.png
APP分区部分固件接收流程做好 BOOTLOADER 工作后,我们开始写 APP 分区的代码。APP 分区固件的编写要注意硬件版本号和软件版本号,软件版号作为升级迭代很重要的标志。https://www.stmcu.com.cn/upload/20200103/9.pngApp编译设置
https://www.stmcu.com.cn/upload/20200103/10.pnghttps://www.stmcu.com.cn/upload/20200103/11.pnghttps://www.stmcu.com.cn/upload/20200103/12.png
FLASH驱动编写Flash.c#include "flash.h"
#include <stdio.h>
#include <string.h>
volatile uint32_t flashWriteOffset = SYS_APP_BAK_SAVE_ADDR_BASE;
volatile uint32_t flashReadOffset = SYS_APP_BAK_SAVE_ADDR_BASE;
/* MCU OTA */
void flash_erase_page(uint8_t flashPage , uint32_t addr_base)
{
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef f;
f.TypeErase = FLASH_TYPEERASE_PAGES;
f.Page = flashPage + (addr_base - SYS_Bootloader_SAVE_ADDR_BASE)/FLASH_PAGE_SIZE;
f.NbPages = 1;
uint32_t PageError = 0;
HAL_FLASHEx_Erase(&f, &PageError);
HAL_FLASH_Lock();
}
void flash_erase(uint32_t size , uint32_t addr_base)
{
uint32_t flashPageSum;
uint32_t i;
/*如果小于2048做处理*/
if(size < FLASH_PAGE_SIZE)
size = FLASH_PAGE_SIZE; //
/* 计算需要擦写的Flash页 */
if((size % FLASH_PAGE_SIZE) == 0)
{
flashPageSum = size / FLASH_PAGE_SIZE; //小于一页擦除一页
}
else
{
flashPageSum = (size / FLASH_PAGE_SIZE) + 1; //大于一页擦除n+1页
}
for(i = 0;i<flashPageSum;i++)
{
flash_erase_page(i,addr_base); //基址累加擦除flash
}
}
void writeFlash(uint64_t * buf_to_save , uint16_t len , uint32_t wFlashAddr)
{
uint16_t count=0;
if(wFlashAddr >= 0x08020000)
{
#ifdef DEBUG
printf("Waring:Flash Write Addr Error\r\n");
#endif
flashWriteOffset = SYS_APP_BAK_SAVE_ADDR_BASE;
return;
}
HAL_FLASH_Unlock();
while(count < len)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,(wFlashAddr + count*8),buf_to_save); //вflashһٶַ֘дɫѫؖè16λé
count ++;
}
HAL_FLASH_Lock();
}
void readFlash(uint64_t * buf_to_get,uint16_t len , uint32_t readFlashAddr)
{
uint16_t count=0;
while(count<len)
{
buf_to_get=*(uint64_t *)(readFlashAddr + count*8);
count++;
}
}
/*写Flash,控制写长度,Flash地址偏移*/
void wFlashData(uint8_t * buf_to_save , uint16_t len , uint32_t wFlashAddr)
{
uint8_t WriteFlashTempBuf;//写Flash临时缓冲区
uint16_t WriteFlashTempLen = 0;//写Flash长度
uint8_t rem;
memset(WriteFlashTempBuf,0xEE,sizeof(WriteFlashTempBuf));//写Flash临时缓冲区首先全部填充0xEE
memcpy(WriteFlashTempBuf,buf_to_save,len);//临时缓冲区
WriteFlashTempLen = len;
if(len%8 != 0)
{
rem = len%8;
WriteFlashTempLen = len +8 - rem;
}
writeFlash((uint64_t *)&WriteFlashTempBuf ,WriteFlashTempLen/8 , wFlashAddr);
}
void rFlashData(uint8_t * buf_to_get , uint16_t len , uint32_t rFlashAddr)
{
uint8_t ReadFlashTempBuf;//读Flash临时缓冲区
uint16_t ReadFlashTempLen = 0;//读Flash长度
uint8_t rem;
if(len%8 == 0)
{
ReadFlashTempLen = len;
readFlash((uint64_t *)&ReadFlashTempBuf,ReadFlashTempLen/8 , rFlashAddr);
memcpy(buf_to_get,ReadFlashTempBuf,len);
}
else
{
rem = len%8;
ReadFlashTempLen = len + 8 - rem;
readFlash((uint64_t *)&ReadFlashTempBuf,ReadFlashTempLen/8 , rFlashAddr);
memcpy(buf_to_get,ReadFlashTempBuf,len);
}
}跳转到APP代码:typedefvoid (*iapfun)(void);
iapfun jump2app;
uint16_t iapbuf;
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
#define MEM_ADDR(addr)*((volatile unsigned long*)(addr))
#define BIT_ADDR(addr, bitnum) MEM_ADDR(BITBAND(addr, bitnum))
//设置栈顶指针
__asm void MSR_MSP(uint32_t addr)
{
MSR MSP, r0 //set Main Stack value
BX r14
}
void iap_load_app(uint32_t appxaddr)
{
if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000)
{
#ifdef DEBUG
printf("Stack Success!\r\n");
#endif
jump2app=(iapfun)*(vu32*)(appxaddr+4);
MSR_MSP(*(vu32*)appxaddr);
jump2app();
}
else
{
#ifdef DEBUG
printf("Stack Failed!\r\n");
#endif
}
}Flash.h#ifndef _FLASH_
#define _FLASH_
#include <stm32g0xx.h>
#define DEBUG
#define PROTOCOL_DEBUG
typedef uint32_tu32;
typedef uint16_t u16;
typedef uint8_tu8;
typedef __IO uint32_tvu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_tvu8;
/* BootLoader Flash首地址 */
#define SYS_Bootloader_SAVE_ADDR_BASE 0x08000000//Bootloader首地址//支持Bootloader大小14KB
/* 升级参数存储 */
#define UPDATE_PARAM_SAVE_ADDR_BASE 0x08003800
#define UPDATE_PARAM_MAX_SIZE (2*1024)//支持参数大小2KB
/* APP Flash首地址 */
#define SYS_APP_SAVE_ADDR_BASE 0x08004000
#define APP_DATA_MAX_SIZE (56*1024)//支持APP大小56KB
/* APP BAK Flash首地址 */
#define SYS_APP_BAK_SAVE_ADDR_BASE 0x08012000
#define APP_BAK_DATA_MAX_SIZE (56*1024)//支持APP_BAK大小56KB
/* 升级参数 */
#define PIECE_MAX 256
#define SSL_MAX_LEN 16
typedef struct
{
uint16_t rom_statue;
uint32_t rom_size;
uint8_tssl_data;
}update_param_def;
#define PIECE_MAX_LEN256
void save_param_to_flash(uint16_t * buf_to_save,uint16_t len );
void read_param_from_flash(uint16_t * buf_to_get,uint16_t len);
void set_flash_flag_to_updata(uint16_t crc_code);
void rFlashData(uint8_t * buf_to_get , uint16_t len , uint32_t rFlashAddr);
void wFlashData(uint8_t * buf_to_save , uint16_t len , uint32_t wFlashAddr);
void iap_load_app(uint32_t appxaddr);
void flash_erase(uint32_t size , uint32_t addr_base);
#endif
BOOTLOADER分区OTA功能代码移植通过CubMX新建工程配置GPIO和UART4
https://www.stmcu.com.cn/upload/20200103/13.png
配置时钟
https://www.stmcu.com.cn/upload/20200103/14.png
生成代码https://www.stmcu.com.cn/upload/20200103/15.png
代码移植
添加Flash.c/h和gagent_md5.c/h到工程中https://www.stmcu.com.cn/upload/20200103/16.png
新建app.c
#include "app.h"
#include "../Src/md5/gagent_md5.h"
#include "flash.h"
#include "usart.h"
/*Global Variable*/
/**
* @briefMain program.
* @paramNone
* @retval None
*/
update_param_def update_param;
uint8_t md5_calc;
MD5_CTX ctx;
void mcu_restart()
{
//__set_FAULTMASK(1);
NVIC_SystemReset();
}
int8_t ROM_MD5_Check(uint32_t sys_size , uint32_t FlashAddr , uint8_t *ssl)
{
uint8_t update_data_tmp;
uint32_t load_loop = 0;
uint32_t remaind_data_len = sys_size;
uint32_t valid_data_len = 0;
GAgent_MD5Init(&ctx);
if(0 == sys_size%PIECE_MAX)
{
load_loop = sys_size / PIECE_MAX;
}
else
{
load_loop = sys_size / PIECE_MAX + 1;
}
#ifdef DEBUG
printf("Check New Sys ...loop = %d\r\n",load_loop);
#endif
for(uint32_t i = 0;i<load_loop;i++)
{
if(remaind_data_len > PIECE_MAX)
{
valid_data_len = PIECE_MAX;
}
else
{
valid_data_len = remaind_data_len;
}
memset(update_data_tmp,0,PIECE_MAX);
rFlashData(update_data_tmp, valid_data_len, FlashAddr + i*PIECE_MAX);
GAgent_MD5Update(&ctx, update_data_tmp, valid_data_len);
remaind_data_len = remaind_data_len - valid_data_len;
#ifdef DEBUG
printf("*");
#endif
}
#ifdef DEBUG
printf("\r\n");
#endif
GAgent_MD5Final(&ctx, md5_calc);
#ifdef DEBUG
printf("MD5 Calculate Success \r\n ");
#endif
if(memcmp(ssl, md5_calc, SSL_MAX_LEN) != 0)
{
#ifdef DEBUG
printf("Md5_Cacl Check Faild ,MCU OTA Faild\r\n ");
#endif
#ifdef PROTOCOL_DEBUG
printf("MD5: ");
for(uint16_t i=0; i<SSL_MAX_LEN; i++)
{
printf("x ", md5_calc);
}
printf("\r\n");
#endif
return -1;
}
else
{
#ifdef DEBUG
printf("MD5 Check Success ,MCU OTA Success\r\n ");
#endif
return 0;
}
}
uint8_t update_new_system(uint32_t sys_size)
{
uint8_t update_data_tmp;
uint32_t load_loop = 0;
uint32_t remaind_data_len = sys_size;
uint32_t valid_data_len = 0;
if(0 == sys_size%PIECE_MAX)
{
load_loop = sys_size / PIECE_MAX;
}
else
{
load_loop = sys_size / PIECE_MAX + 1;
}
#ifdef DEBUG
printf("Copy New Sys ...loop = %d\r\n",load_loop);
#endif
flash_erase(update_param.rom_size , SYS_APP_SAVE_ADDR_BASE);
#ifdef DEBUG
printf("Copy New Sys\r\n");
#endif
for(uint32_t i = 0;i<load_loop;i++)
{
if(remaind_data_len > PIECE_MAX)
{
valid_data_len = PIECE_MAX;
}
else
{
valid_data_len = remaind_data_len;
}
memset(update_data_tmp,0,PIECE_MAX);
rFlashData(update_data_tmp, valid_data_len, SYS_APP_BAK_SAVE_ADDR_BASE + i*PIECE_MAX);
wFlashData(update_data_tmp , valid_data_len , SYS_APP_SAVE_ADDR_BASE + i*PIECE_MAX);
remaind_data_len = remaind_data_len - valid_data_len;
#ifdef DEBUG
printf(".");
#endif
}
#ifdef DEBUG
printf("\r\n");
printf("Copy Success , Wait to Check... \r\n");
#endif
if(0 == ROM_MD5_Check(update_param.rom_size , SYS_APP_SAVE_ADDR_BASE , update_param.ssl_data))
{
#ifdef DEBUG
printf("New ROM Check Success , Wait to Load New Systerm \r\n");
#endif
flash_erase(sizeof(update_param_def), UPDATE_PARAM_SAVE_ADDR_BASE);
mcu_restart();
}
else
{
#ifdef DEBUG
printf("New ROM Check Faild , Update Faild , MCU Try To Update Again ,MCU Restart... \r\n");
#endif
mcu_restart();
}
return 0;
}
void APP_Process(void)
{
memset((uint8_t *)&update_param, 0 , sizeof(update_param_def));
rFlashData((uint8_t *)&update_param, sizeof(update_param_def), UPDATE_PARAM_SAVE_ADDR_BASE);
if(0xEEEE == update_param.rom_statue)
{
#ifdef DEBUG
printf("Update Task ,Sys Will Load New Sys..Wait For A Moment \r\n");
printf("Update Size [%d] \r\n",update_param.rom_size);
#endif
if(0 == ROM_MD5_Check(update_param.rom_size , SYS_APP_BAK_SAVE_ADDR_BASE , update_param.ssl_data))
{
update_new_system(update_param.rom_size);
}
else
{
#ifdef DEBUG
printf("Check Faild , Go to Old Systerm\r\n");
#endif
flash_erase(sizeof(update_param_def), UPDATE_PARAM_SAVE_ADDR_BASE);
if(((*(vu32*)(SYS_APP_SAVE_ADDR_BASE + 4)) & 0xFF000000) == 0x08000000)
{
#ifdef DEBUG
printf("Sys Will Load APP.....\r\n");
#endif
iap_load_app(SYS_APP_SAVE_ADDR_BASE);
}
else
{
#ifdef DEBUG
printf("Start APP Failed!\r\n");
#endif
}
}
}
else
{
#ifdef DEBUG
printf("No Update Task , Go To APP ....X\r\n",update_param.rom_statue);
#endif
if(((*(vu32*)(SYS_APP_SAVE_ADDR_BASE + 4)) & 0xFF000000) == 0x08000000)
{
#ifdef DEBUG
printf("Sys Will Load APP.....\r\n");
#endif
iap_load_app(SYS_APP_SAVE_ADDR_BASE);
}
else
{
#ifdef DEBUG
printf("Start APP Failed!\r\n");
#endif
}
}
}更改主代码main.c
https://www.stmcu.com.cn/upload/20200103/17.pnghttps://www.stmcu.com.cn/upload/20200103/18.png
APP分区OTA功能代码移植代码移植添加Flash.c/h和gagent_md5.c/h到工程中
https://www.stmcu.com.cn/upload/20200103/19.png
中断向量偏移地址修改:
https://www.stmcu.com.cn/upload/20200103/20.png
app.c
https://www.stmcu.com.cn/upload/20200103/21.png
gizwits_protocol.h
https://www.stmcu.com.cn/upload/20200103/22.pnghttps://www.stmcu.com.cn/upload/20200103/23.pnghttps://www.stmcu.com.cn/upload/20200103/24.pnggizwits_protocol.chttps://www.stmcu.com.cn/upload/20200103/25.png
https://www.stmcu.com.cn/upload/20200103/26.png
尾部添加以下代码:
/**
* @brief Pro_W2D_UpdateCmdHandle
* Handle OTA Ask , Transform MD5 Char2Hex
* @param:
* @param :
* @return0,Update Ask Handle Success , Send Ready Success
* -1,Input Param Illegal
* -2,Update Ask Handle Success , Send Ready Faild
*
*/
int8_t Pro_W2D_UpdateCmdHandle(uint8_t *inData,uint32_t dataLen)
{
uint8_t k = 0;
int8_t ret = 0;
uint8_tfileMD5value;
uint16_t fileMD5len; //MD5 Length
if(NULL == inData)
{
return -1;
}
romUpdate.updateFileSize = ((uint32_t)(inData<<24))|((uint32_t)(inData<<16))|((uint32_t)(inData<<8))|((uint32_t)(inData));
//judge flash size
if(romUpdate.updateFileSize > APP_BAK_DATA_MAX_SIZE)
{
GIZWITS_LOG("UpdateFileSize Error ,Update Failed ,fileSize = %d \n",romUpdate.updateFileSize);
return -1;
}
else
{
GIZWITS_LOG("UpdateFileSize Legal ,size = %d \n",romUpdate.updateFileSize);
romUpdate.update_param.rom_size = romUpdate.updateFileSize;
flash_erase(APP_BAK_DATA_MAX_SIZE,SYS_APP_BAK_SAVE_ADDR_BASE);
GIZWITS_LOG("flash erase finished!!\n");
}
fileMD5len = inData*256 + inData;
GIZWITS_LOG("FileMD5len= %d ", fileMD5len);
memcpy(fileMD5value,&inData,fileMD5len);
#ifdef PROTOCOL_DEBUG
GIZWITS_LOG("MD5: ");
for(uint16_t i=0; i<32; i++)
{
GIZWITS_LOG("x ", fileMD5value);
}
GIZWITS_LOG("\r\n");
#endif
for(uint16_t j = 0; j<SSL_MAX_LEN; j++)
{
romUpdate.update_param.ssl_data = char2hex(fileMD5value,fileMD5value);
k += 2;
}
#ifdef PROTOCOL_DEBUG
GIZWITS_LOG("MD5_Hex: ");
for(uint16_t i=0; i<SSL_MAX_LEN; i++)
{
GIZWITS_LOG("x ", romUpdate.update_param.ssl_data);
}
GIZWITS_LOG("\r\n");
#endif
GIZWITS_LOG("GAgent_MD5Init \n");
GAgent_MD5Init(&romUpdate.ctx);
//send ready
ret = Pro_D2W_UpdateReady(fileMD5value,fileMD5len);
if(0 != ret)
{
GIZWITS_LOG("Pro_D2W_UpdateReady Error ,Error Code = %d \n",ret);
return -2;
}
return 0;
}
/**
* @brief Pro_D2W_UpdateReady
* MCU Send Update Ready
* @parammd5Data: Input md5 char data
* @parammd5Len : Input md5 length
* @param :
* @return0,Update Ask Handle Success , Send Ready Success
* -1,Input Param Illegal
* -2,Uart Send Faild
*
*/
int8_t Pro_D2W_UpdateReady(uint8_t *md5Data , uint16_t md5Len)
{
int8_t ret = 0;
uint8_t txBuf;
memset(txBuf,0,100);
uint8_t *pTxBuf = txBuf;
if(NULL == md5Data)
{
return -1;
}
uint16_t dataLen = sizeof(protocolCommon_t) + 2 + md5Len + 2 - 4 ;
*pTxBuf ++= 0xFF;
*pTxBuf ++= 0xFF;
*pTxBuf ++= (uint8_t)(dataLen>>8);
*pTxBuf ++= (uint8_t)(dataLen);
*pTxBuf ++= CMD_BIGDATA_READY;
*pTxBuf ++= gizwitsProtocol.sn++;
*pTxBuf ++= 0x00;//flag
txBuf |= UPDATE_IS_HEX_FORMAT<<0;//TERRY WARNING
pTxBuf += 1;
*pTxBuf ++= (uint8_t)(md5Len>>8);//len
*pTxBuf ++= (uint8_t)(md5Len);
memcpy(&txBuf,md5Data,md5Len);
pTxBuf += md5Len;
*pTxBuf ++= (uint8_t)(PIECE_MAX_LEN>>8);//len
*pTxBuf ++= (uint8_t)(PIECE_MAX_LEN);
*pTxBuf ++= gizProtocolSum(txBuf , (dataLen+4));
ret = uartWrite(txBuf , (dataLen+4));
if(ret < 0)
{
GIZWITS_LOG("ERROR: uart write error %d \n", ret);
return -2;
}
GIZWITS_LOG("MCU Ready To Update ROM \n");
return 0;
}
/**
* @brief Pro_W2D_UpdateDataHandle
* update Piece Handle ,Judge Last Piece
* @param indata : Piece Data
* @param dataLen : Piece Length
* @param formatType : Piece Data Format
* @param
* @return0,Handle Success
* -1,Input Param Illegal
* -2,Last Piece , MD5 Check Faild
*
*/
int8_t Pro_W2D_UpdateDataHandle(uint8_t *inData , uint32_t dataLen , otaDataType formatType)
{
uint16_t piecenum = 0;
uint16_t piececount = 0;
uint32_t tempWFlashAddr = 0;
updataPieceData_TypeDef pieceData;
uint8_t md5_calc;//MD5 Calculate Fact
if(NULL == inData)
{
return -1;
}
memcpy((uint8_t *)&pieceData, inData, dataLen);
piecenum = exchangeBytes(pieceData.piecenum);
piececount = exchangeBytes(pieceData.piececount);
GIZWITS_LOG("****piecenum = %d , piececount = %d, pieceSize = %d****** \r\n",piecenum,piececount,dataLen - 4);
tempWFlashAddr = SYS_APP_BAK_SAVE_ADDR_BASE + (piecenum-1) * PIECE_MAX_LEN;
wFlashData((uint8_t *)pieceData.piececontent , dataLen - 4, tempWFlashAddr);
GAgent_MD5Update(&romUpdate.ctx, (uint8_t *)pieceData.piececontent, dataLen - 4);
/*updata package data ,ack*/
if(piecenum == piececount)
{
memset(md5_calc,0,SSL_MAX_LEN);
GAgent_MD5Final(&romUpdate.ctx, md5_calc);
GIZWITS_LOG("MD5 Calculate Success , Will Check The MD5 ..\n ");
if(0 != memcmp(romUpdate.update_param.ssl_data, md5_calc, SSL_MAX_LEN))
{
GIZWITS_LOG("Md5_Cacl Check Faild ,MCU OTA Faild\r\n ");
#ifdef PROTOCOL_DEBUG
GIZWITS_LOG("Calc MD5: ");
for(uint16_t i=0; i<SSL_MAX_LEN; i++)
{
GIZWITS_LOG("x ", md5_calc);
}
GIZWITS_LOG("\r\n");
#endif
#ifdef PROTOCOL_DEBUG
GIZWITS_LOG("SSL MD5: ");
for(uint16_t i=0; i<SSL_MAX_LEN; i++)
{
GIZWITS_LOG("x ", romUpdate.update_param.ssl_data);
}
GIZWITS_LOG("\r\n");
#endif
memset((uint8_t *)&romUpdate.update_param,0,sizeof(updateParamSave_t));
return -2;
}
else
{
GIZWITS_LOG("MD5 Check Success ,StorageROM Success , Write Update Flag\n ");
flash_erase(sizeof(updateParamSave_t) , UPDATE_PARAM_SAVE_ADDR_BASE);
romUpdate.update_param.rom_statue = 0xEEEE;
wFlashData((uint8_t *)&romUpdate.update_param, sizeof(updateParamSave_t), UPDATE_PARAM_SAVE_ADDR_BASE);
//romUpdate.update_param.rom_statue = 0x1234;
//printf("\n\romUpdate.update_param.rom_statue = X \r\n\n",romUpdate.update_param.rom_statue);
//memset((uint8_t *)&romUpdate, 0 , sizeof(romUpdate));
//rFlashData((uint8_t *)&romUpdate, sizeof(romUpdate), UPDATE_PARAM_SAVE_ADDR_BASE);
//printf("\n\romUpdate.update_param.rom_statue = X \r\n\n",romUpdate.update_param.rom_statue);
GIZWITS_LOG("System Will Restart... \n");
/*******************MCU RESTART*******************/
mcuRestart();
/****************************************************/
//last package , updata ok
//MD5 checkout :Failed clear updata,Success , write flash ,begin updata
}
}
return 0;
}
/**
* @brief Pro_D2W_UpdateSuspend
* Data Receiver
* @param : Void
* @param :
* @return : Void
*
*/
void Pro_D2W_UpdateSuspend()
{
int32_t ret = 0;
protocolCommon_t protocolCommon;
memset(&protocolCommon, 0, sizeof(protocolCommon_t));
gizProtocolHeadInit((protocolHead_t *)&protocolCommon);
protocolCommon.head.len = exchangeBytes(sizeof(protocolCommon_t)-4);
protocolCommon.head.cmd = CMD_D_STOP_BIGDATA_SEND;
protocolCommon.head.sn = gizwitsProtocol.sn++;
protocolCommon.sum = gizProtocolSum((uint8_t *)&protocolCommon, sizeof(protocolCommon_t));
ret = uartWrite((uint8_t *)&protocolCommon,sizeof(protocolCommon_t));
if(ret < 0)
{
GIZWITS_LOG("ERROR: uart write error %d \n", ret);
}
gizProtocolWaitAck((uint8_t *)&protocolCommon,sizeof(protocolCommon_t));
}
/**
* @brief Pro_D2W_Ask_Module_Reboot
* Ask Module Reboot
* @param : Void
* @param :
* @return : Void
*
*/
void Pro_D2W_Ask_Module_Reboot()
{
int32_t ret = 0;
protocolCommon_t protocolCommon;
memset(&protocolCommon, 0, sizeof(protocolCommon_t));
gizProtocolHeadInit((protocolHead_t *)&protocolCommon);
protocolCommon.head.len = exchangeBytes(sizeof(protocolCommon_t)-4);
protocolCommon.head.cmd = CMD_REBOOT_MODULE;
protocolCommon.head.sn = gizwitsProtocol.sn++;
protocolCommon.sum = gizProtocolSum((uint8_t *)&protocolCommon, sizeof(protocolCommon_t));
ret = uartWrite((uint8_t *)&protocolCommon,sizeof(protocolCommon_t));
if(ret < 0)
{
GIZWITS_LOG("ERROR: uart write error %d \n", ret);
}
gizProtocolWaitAck((uint8_t *)&protocolCommon,sizeof(protocolCommon_t));
}更改软件版本号,更改后的版本号要比原先版本号大
gizwits_product.hhttps://www.stmcu.com.cn/upload/20200103/34.png
MCU OTA验证第一次用stlink烧录boot和app代码后,mcu日志如图https://www.stmcu.com.cn/upload/20200103/28.png
准备OTA,先让设备连上机智云
https://www.stmcu.com.cn/upload/20200103/29.pnghttps://www.stmcu.com.cn/upload/20200103/30.pnghttps://www.stmcu.com.cn/upload/20200103/31.pnghttps://www.stmcu.com.cn/upload/20200103/32.png
OTA成功
https://www.stmcu.com.cn/upload/20200103/35.png
页:
[1]