admin 发表于 2020-2-7 12:43:05

【官方】通过机智云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]
查看完整版本: 【官方】通过机智云OTA升级MCU固件