开源项目

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 分区

  • Bootloader:存储 Bootloader 固件,MCU 上电后首先运行该固件。

  • FLAG:存储有关升级的相关标志位,Bootloader 和 APP 分区都需要操作该区域。

升级标志位(2B)

固件大小(4B)

MD5加密数据(16B)

  • APP 分区:存储用户程序固件。

  • APPBAK 分区:临时存储云端下发的新固件,升级固件的一个过渡存储区。

BOOTLOADER分区部分

Bootloader程序流程

Bootloader 的主要职能是在有升级任务的时候将 APPBAK 分区里面的固件拷贝到 APP 区域。当然,这期间需要做很多的工作,比如升级失败的容错等等。具体的流程可以参考图示。需要注意的是,在校验 MD5 正确后开始搬运固件数据期间,MCU 出现故障(包括突然断电),MCU 应发生复位操作(FLAG 区域数据未破坏),复位后重新开始执行 Bootloader,从而避免 MCU 刷成板砖。

Bootloader编译设置


APP分区部分

固件接收流程

做好 BOOTLOADER 工作后,我们开始写 APP 分区的代码。APP 分区固件的编写要注意硬件版本号和软件版本号,软件版号作为升级迭代很重要的标志。

App编译设置


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[count]); //в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[count]=*(uint64_t *)(readFlashAddr + count*8);
		count++;
	}
}
/*写Flash,控制写长度,Flash地址偏移*/
void wFlashData(uint8_t * buf_to_save , uint16_t len , uint32_t wFlashAddr)
{
    uint8_t WriteFlashTempBuf[PIECE_MAX_LEN];//写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[PIECE_MAX_LEN];//读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代码:

typedef  void (*iapfun)(void);
iapfun jump2app; 
uint16_t iapbuf[1024];   

#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_t  u32;
typedef uint16_t u16;
typedef uint8_t  u8;

typedef __IO uint32_t  vu32;
typedef __IO uint16_t vu16;
typedef __IO uint8_t  vu8;

/* 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_t  ssl_data[SSL_MAX_LEN];
}update_param_def;

#define PIECE_MAX_LEN  256

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


配置时钟


生成代码


代码移植

添加Flash.c/h和gagent_md5.c/h到工程中

新建app.c

#include "app.h"
#include "../Src/md5/gagent_md5.h"
#include "flash.h"
#include "usart.h"

/*Global Variable*/
/**
  * @brief  Main program.
  * @param  None
  * @retval None
  */
update_param_def update_param;
uint8_t md5_calc[SSL_MAX_LEN];
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[PIECE_MAX];
    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[i]);
        }
        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[PIECE_MAX];
    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

APP分区OTA功能代码移植

代码移植

添加Flash.c/h和gagent_md5.c/h到工程中


中断向量偏移地址修改:


app.c


gizwits_protocol.h


gizwits_protocol.c



尾部添加以下代码:

/**
* @brief Pro_W2D_UpdateCmdHandle

* Handle OTA Ask , Transform MD5 Char2Hex

* @param[in]  :
* @param[out] :
* @return  0,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_t  fileMD5value[FILE_MD5_MAX_LEN];
    uint16_t fileMD5len;			//MD5 Length

    if(NULL == inData)
    {
        return -1;
    }

    romUpdate.updateFileSize = ((uint32_t)(inData[0]<<24))|((uint32_t)(inData[1]<<16))|((uint32_t)(inData[2]<<8))|((uint32_t)(inData[3]));

    //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[4]*256 + inData[5];
    GIZWITS_LOG("FileMD5len  = %d ", fileMD5len);

    memcpy(fileMD5value,&inData[6],fileMD5len);
#ifdef PROTOCOL_DEBUG
    GIZWITS_LOG("MD5: ");
    for(uint16_t i=0; i<32; i++)
    {
        GIZWITS_LOG("x ", fileMD5value[i]);
    }
    GIZWITS_LOG("\r\n");
#endif

    for(uint16_t j = 0; j<SSL_MAX_LEN; j++)
    {
        romUpdate.update_param.ssl_data[j] = char2hex(fileMD5value[k],fileMD5value[k+1]);
        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[i]);
    }
    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

* @param[in]  md5Data: Input md5 char data
* @param[in]  md5Len : Input md5 length
* @param[out] :
* @return  0,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[100];
		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[7] |= UPDATE_IS_HEX_FORMAT<<0;//TERRY WARNING
    pTxBuf += 1;

    *pTxBuf ++= (uint8_t)(md5Len>>8);//len
    *pTxBuf ++= (uint8_t)(md5Len);

    memcpy(&txBuf[8 + 2],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[in] indata   : Piece Data
* @param[in] dataLen    : Piece Length
* @param[in] formatType : Piece Data Format
* @param[out]
* @return  0,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[SSL_MAX_LEN];//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[i]);
            }
            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[i]);
            }
            GIZWITS_LOG("\r\n");
#endif
            memset((uint8_t *)&romUpdate.update_param,0,sizeof(updateParamSave_t));

            return -2;
        }
        else
        {
            GIZWITS_LOG("MD5 Check Success ,Storage  ROM 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[in]    : Void
* @param[out] 	:
* @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[in]    : Void
* @param[out] 	:
* @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.h

MCU OTA验证

一次用stlink烧录boot和app代码后,mcu日志如图

准备OTA,先让设备连上机智云


OTA成功