mcu_hi3321_watch/tjd/ble/firmware_ota/ble_ota_execute.c
2025-05-26 20:15:20 +08:00

992 lines
35 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file ota_execute.c
* @brief OTA 功能实现文件供OTA协议层调用
* @details
* @author George
* @date 2021/6/28
* @version A001
* @par Copyright (c):
* SmartFenda.
* @par History:
* version: author, date, desc\n
*/
#include "am_util_debug.h"
#include "sys_config.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "crc32.h"
#include "am_bootloader.h"
#include "am_multi_boot.h"
//#include "amota_profile_config.h"
#include "am_hal_mram.h"
#include "ble_ota_execute.h"
#include "ble_protocol.h"
#include "flash_api.h"
//#include "user_gps.h"
#include "ppg_api.h"
#include "task_ble.h"
#include "log_api.h"
#include "rtc_api.h"
#include "user_adapter.h"
#include "motor_api.h"
#include "sys_adapter.h"
#include "user_pack_analysis.h"
#include "sys_typedef.h"
#include "ui_event.h"
#include "task_ui.h"
#include "user_charge.h"
#include "ui_port_fw.h"
#include "charge_api.h"
#define ENABLE_STATIC_PRINT false
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
#define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__)
#if ENABLE_STATIC_PRINT
#define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)
#else
#define static_print_info(...)
#endif
#define OTA_READ_BUFSIZE 1024 // 若空间不够可以设1024或更小的值
#define BYTES_2_UINT32(n, p) {n = ((uint32_t)(p)[0] + ((uint32_t)(p)[1] << 8) + \
((uint32_t)(p)[2] << 16) + ((uint32_t)(p)[3] << 24));}
// Protection against NULL pointer
//#define FLASH_OPERATE(pFlash, func) ((pFlash)->func ? (pFlash)->func() : 0)
#define FLASH_OPERATE(pFlash, func)
#if 1
//MBR INFO 此定义OTA与BOOT工程中MBR严格对齐
enum {
FW_SOUR_CS_NULL,
FW_SOUR_CS_RAM,
FW_SOUR_CS_ROM,
FW_SOUR_CS_FLASH,
FW_SOUR_CS_FS,
FW_SOUR_CS_MAX,
};
typedef struct {
// 固件源地址
uint32_t fw_sour_addr;
// 固件目的地址(运行地址)
uint32_t fw_dest_addr;
// 固件源片选
uint32_t fw_sour_cs:8;
// 固件目的片选
uint32_t fw_dest_cs:8;//固件源存放片选。NULL、RAM、ROM、EXT_FLASH、FS
// 保留字节
uint32_t fw_reserve1:16;
// 固件版本号
uint8_t fw_version[4];
// 固件大小, 单位字节
uint32_t fw_bytes;
// 固件 crc32 值
uint32_t fw_crc32;
}fw_parm_t;
typedef struct {
// 0x01 不需要搬运固件, 直接跳转到 APP 区(正式固件) 执行;
// 0x02 不需要搬运固件, 直接跳转到 APP 区(厂测固件) 执行;
// 0x03 不需要搬运固件, 直接跳转到 APP 区DTM固件 执行;
// 0x10 需要搬运正式固件;
// 0x20 需要搬运厂测固件;
// 0x30 需要搬运DTM固件;
uint32_t carry_fw_flag;
// 标签
char mark[32];
// 正式固件参数
fw_parm_t formal;
// 厂测固件参数
fw_parm_t factory;
// DTM固件参数
fw_parm_t dmt;
// OTA 参数区的 crc32 校验值
uint32_t crc32;
}mbr_parm_t;
#endif
//
// Data structure for Breakpoint continuation
//
typedef struct
{
uint32_t fileOffset;
uint32_t fileSize;
uint32_t fileCrc32;
uint32_t ifResume;
uint32_t crc;
uint32_t res; // 8字节对齐
}FwBreakPointInfo_t;
otasFlashOp_t otaFlashOp = {
.bufferIndex = 0,
};
static FwBreakPointInfo_t g_otaBreakPoint = {0};
static TimerHandle_t ota_timeout_time_handle = NULL;
static TimerHandle_t g_otaResendTimer = NULL;
static OtaCtrlBlock_t g_otaCtrlBlock = {0};
static am_multiboot_flash_info_t *g_pFlash = NULL;
static am_multiboot_flash_info_t g_ext_flash = {0};
static uint8_t OtasReadBuf[OTA_READ_BUFSIZE] = {0};
static head_desc_parm g_ota_head_param;
static head_struct_parm g_ota_head_struct;
static mbr_parm_t g_boot_mbr_info;
extern void user_update_percent_show(uint8_t percent);
extern void DeviceRequestOTAFileData(uint32_t offset,uint16_t DataLen,uint32_t TotalFileSise,uint32_t ReceivedFileSize);
void OtaUpdateBreakPoint(void);
extern uint8_t user_dog_get_timeout_status(void);
int ota_flash_read_func(uint32_t ui32DestAddr, uint32_t *pSrc, uint32_t ui32Length)
{
return flash_api_read(ui32DestAddr, pSrc, ui32Length);
}
int ota_flash_write_func(uint32_t ui32DestAddr, uint32_t *pSrc, uint32_t ui32Length)
{
return flash_api_write(ui32DestAddr, pSrc, ui32Length);
}
int ota_flash_erase_func(uint32_t ui32Addr)
{
return flash_api_erase(ui32Addr);
}
int ota_ext_flash_info_init(am_multiboot_flash_info_t *pFlash)
{
pFlash->flashPageSize = flash_api_get_erase_unit_size();
pFlash->flashSectorSize = flash_api_get_erase_unit_size();
pFlash->flash_init = NULL;
pFlash->flash_deinit = NULL;
pFlash->flash_enable = NULL;
pFlash->flash_disable = NULL;
pFlash->flash_read_page = ota_flash_read_func;
pFlash->flash_write_page = ota_flash_write_func;
pFlash->flash_erase_sector = ota_flash_erase_func;
return true;
}
static void OtaTimeoutCb(TimerHandle_t xTimer)
{
static_print_info("?????ota_timeout?????\r\n");
OtaFailed(PACK_WAIE_TIMEOUT_ERROR);
}
void OtaCreatTimeoutTimer(void)
{
ota_timeout_time_handle = xTimerCreate("ota_timeout_task_time",(1000 * 10), false, NULL, OtaTimeoutCb);
if(ota_timeout_time_handle==NULL)
{
static_print_info("?????ota_timeout_creat_time fail?????\r\n");
}
}
void OtaTimeoutReset(void)
{
if(ota_timeout_time_handle != NULL)
{
xTimerReset(ota_timeout_time_handle, 0);
}
}
void OtaTimeoutTimerStop(void)
{
if(ota_timeout_time_handle != NULL)
{
xTimerStop(ota_timeout_time_handle, 0);
}
}
static void OtaResendTimerCallback(TimerHandle_t xTimer)
{
static_print_info("need resend, offset=%x!\r\n", g_otaCtrlBlock.pkt.offset);
DeviceRequestOTAFileData(g_otaCtrlBlock.pkt.offset, g_otaCtrlBlock.pkt.ApplyLen,
g_otaCtrlBlock.pkt.FileSize, g_otaCtrlBlock.pkt.offset);
}
void OtaFrameResendTimerLoad(void)
{
if(g_otaResendTimer == NULL)
{
g_otaResendTimer = xTimerCreate("otaResendTimer",(1000 * 3), false, NULL, OtaResendTimerCallback);
static_print_info("g_otaResendTimer=0x%08X\r\n", g_otaResendTimer);
if(g_otaResendTimer != NULL)
{
xTimerStart(g_otaResendTimer, 0);
}
}
else
{
xTimerReset(g_otaResendTimer, 0);
}
}
void OtaFrameResendTimerStop(void)
{
if(g_otaResendTimer != NULL)
{
xTimerStop(g_otaResendTimer, 0);
}
}
bool_t OtaIsStarted(void)
{
return g_otaCtrlBlock.ota_start_flag;
}
/*!
* brief: Get Ota CtrlBlock, for OTA service call
*/
void GetOtaCtrlBlock(OtaCtrlBlock_t *ctrl)
{
memcpy(ctrl, &g_otaCtrlBlock, sizeof(OtaCtrlBlock_t));
}
/*!
* brief: Check whether the device can be OTAfor OTA service call
*/
uint8_t OtaRequest(uint32_t FwLen)
{
uint8_t CurrBattPercent;
chg_status_e charge_status;
CurrBattPercent = ui_port_get_battary_percent();
charge_status = charge_api_get_charge_status();
static_print_remind ("Current Batt Percent:%d%. - status = %d \r\n",CurrBattPercent,charge_status);
if(charge_status == BATT_STAT_CHARGE_TEMPER_0_5
|| charge_status == BATT_STAT_CHARGE_TEMPER_6_15
|| charge_status == BATT_STAT_CHARGE_TEMPER_16_45
|| charge_status == BATT_STAT_CHARGE_DONE_NOT_CHARGE
)
{
CurrBattPercent = 80; // 若处于充电状态则不用检测电量
}
if(CurrBattPercent < OTA_BATT_THRESHOLD)
{
return 1; //1不能升级
}
memset(&g_otaCtrlBlock, 0, sizeof(g_otaCtrlBlock));
g_otaCtrlBlock.pkt.FileSize = FwLen;
return 0;
}
/*!
* brief: OTA completed, for OTA service call
*/
void OtaSucceed(void)
{
uint32_t BreakPointPtrVal = 0;
OtaTimeoutTimerStop();
OtaFrameResendTimerStop();
BreakPointPtrVal = *((uint32_t *)USER_OTA_BREAK_POINT_ADDR);
if((BreakPointPtrVal != 0xFFFFFFFF) && (BreakPointPtrVal != 0))
{// 若存在断点续传信息则清除
memset(&g_otaBreakPoint, 0, sizeof(g_otaBreakPoint));
OtaUpdateBreakPoint();
}
if(g_otaCtrlBlock.HeaderInfo.fwDataType == MARK_MCU_FW_BIN)
{
OtaUpdateFwInfo();
}
task_ui_notify(EVENT_OTA_TRANSMITTING, 100, NULL, 0);
// log_api_record_action(rtc_api_get_utc_timestamp(), EVT_OTA_UPDATE, INFO1_OTA_SUCC, 0, 0, NULL);
task_ble_notify(BLE_RESET_AFTER_OTA_MSG, 0); //退出升级,延时复位
}
/*!
* brief: OTA Failed, for OTA service call
*/
void OtaFailed(uint8_t reason)
{
OtaTimeoutTimerStop();
OtaFrameResendTimerStop();
recovery_ble_task_priority();
g_otaCtrlBlock.ota_start_flag = FALSE;
if(g_otaCtrlBlock.ota_status == OTA_STATE_FW_DATA && g_otaCtrlBlock.pkt.offset > AM_HAL_FLASH_PAGE_SIZE)
{
static_print_info("we need storage breakpoint info:0x%x-0x%x-0x%x\r\n",g_otaCtrlBlock.HeaderInfo.fwCrc,g_otaCtrlBlock.pkt.offset,g_otaCtrlBlock.HeaderInfo.fwLength);
g_otaBreakPoint.fileCrc32 = g_otaCtrlBlock.HeaderInfo.fwCrc;
g_otaBreakPoint.fileOffset = g_otaCtrlBlock.pkt.offset;
g_otaBreakPoint.fileSize = g_otaCtrlBlock.HeaderInfo.fwLength;
g_otaBreakPoint.ifResume = 1;
OtaUpdateBreakPoint();
}
else if(g_otaCtrlBlock.ota_status == OTA_STATE_FW_RESET)
{
int32_t BreakPointPtrVal = 0;
BreakPointPtrVal = *((uint32_t *)OTA_BREAK_POINT_ADDR);
if((BreakPointPtrVal != 0xFFFFFFFF) && (BreakPointPtrVal != 0))
{// 若存在断点续传信息则清除
memset(&g_otaBreakPoint, 0, sizeof(g_otaBreakPoint));
//OtaUpdateBreakPoint();
}
}
task_ui_notify(EVENT_OTA_FAIL, 0, NULL, 0);
log_api_record_action(rtc_api_get_utc_timestamp(), EVT_OTA_UPDATE, INFO1_OTA_FAIL, reason, g_otaBreakPoint.fileOffset, NULL);
task_ble_notify(BLE_RESET_AFTER_OTA_MSG, 0); //退出升级,延时复位
// task_ui_notify(UI_MSG_GOTO_MAINMENU, 0, NULL, 0);
}
void OtaStop(void)
{
if(!OtaIsStarted())
return;
OtaFailed(DEVICE_DISCONNECT);
}
/*!
* brief: Start OTAfor OTA service call
*/
void OtaStart(void)
{
task_ui_notify(EVENT_OTA_TRANSMITTING, 0, NULL, 0);
log_api_record_action(rtc_api_get_utc_timestamp(), EVT_OTA_UPDATE, INFO1_OTA_START, 0, 0, NULL);
motor_api_stop();
//user_gps_shutdown();
gsensor_api_close();
ppg_api_close();
//g_user_tp_ops.close(); // 关闭tp
/* OTA 过程中 主频使用48M */
sys_smart_delay_ms(100);
sys_burst_mode_switch(0, 1, false);
g_otaCtrlBlock.ota_start_flag = TRUE;
g_otaCtrlBlock.ota_status = OTA_STATE_FW_HEADER;
g_otaCtrlBlock.pkt.ApplyLen = FW_HEAD_INFO_IEN; //请求的第一包为固定长度0x30的固件头部信息
}
/*!
* brief: Verify the currently written data
*/
static int OtaVerifyFlashContent(uint32_t flashAddr, uint32_t *pSram, uint32_t len, am_multiboot_flash_info_t *pFlash)
{
// read back and check
uint32_t offset = 0;
uint32_t remaining = len;
int ret = 0;
if(remaining < g_pFlash->flashPageSize)
{
remaining = g_pFlash->flashPageSize;
}
while (remaining)
{
uint32_t tmpSize = (remaining > OTA_READ_BUFSIZE) ? OTA_READ_BUFSIZE : remaining;
//pFlash->flash_read_page((uint32_t)OtasReadBuf, (uint32_t *)(flashAddr + offset), tmpSize);
ret = pFlash->flash_read_page((flashAddr + offset), (uint32_t *)OtasReadBuf, tmpSize);
ret = memcmp(OtasReadBuf, (uint8_t*)((uint32_t)pSram + offset), tmpSize);
if ( ret != 0 )
{
// there is write failure happened.
static_print_info("\r\n??????flash write verify failed. address 0x%x. length %d????? - tmpSize = %d - ret = %x \r\n", flashAddr, len,tmpSize );
for(uint16_t i = 0; i < tmpSize; i++ )
static_print_info("i = %d >>> read =%x - tran = %x \n",i,OtasReadBuf[i], ((uint8_t*)pSram)[i]);
break;
}
offset += tmpSize;
remaining -= tmpSize;
}
return ret;
}
/*!
* brief: OTA firmware writing to flash
*/
static uint32_t OtaWrite2Flash(uint16_t len, uint8_t *buf, uint32_t addr, bool lastPktFlag)
{
uint16_t ui16BytesRemaining = len;
uint32_t ui32TargetAddress = 0;
uint8_t ui8PageCount = 0;
uint32_t error_code = FENDA_SUCCESS;
uint16_t i;
uint8_t indx = 0;
uint32_t write_result = 0x10000;
addr -= otaFlashOp.bufferIndex;
//
// Check the target flash address to ensure we do not operation the wrong address
// make sure to write to page boundary
//
static_print_remind("len=0x%x,buf=0x%x,addr=0x%x,lastPktFlag=%d,Index=%d\n",len,buf,addr,lastPktFlag,otaFlashOp.bufferIndex);
if (((uint32_t)g_otaCtrlBlock.newFwFlashInfo.addr > addr) ||
(addr & (g_pFlash->flashPageSize - 1)))
{
//
// application is trying to write to wrong address
//
static_print_info(" application is trying to write to wrong address addr = %x\n",addr);
return DEVICE_FW_OTA_ERROR;
}
FLASH_OPERATE(g_pFlash, flash_enable);
while (ui16BytesRemaining)
{
uint16_t ui16Bytes2write = g_pFlash->flashPageSize - otaFlashOp.bufferIndex;
if (ui16Bytes2write > ui16BytesRemaining)
{
ui16Bytes2write = ui16BytesRemaining;
}
// move data into buffer
for ( i = 0; i < ui16Bytes2write; i++ )
{
// avoid using memcpy
otaFlashOp.writeBuffer[otaFlashOp.bufferIndex++] = buf[i];
}
ui16BytesRemaining -= ui16Bytes2write;
buf += ui16Bytes2write;
static_print_info("ui16BytesRemaining = %d - ui16Bytes2write = %d \n",ui16BytesRemaining,ui16Bytes2write);
//
// Write to flash when there is data more than 1 page size
// For last fragment write even if it is less than one page
//
if (lastPktFlag || (otaFlashOp.bufferIndex == g_pFlash->flashPageSize))
{
ui32TargetAddress = (addr + ui8PageCount*g_pFlash->flashPageSize);
for(indx = 0; indx < 3; indx++)
{
error_code = g_pFlash->flash_erase_sector(ui32TargetAddress);
static_print_info(" flash_erase_sector = %d \n",error_code);
if(error_code == AM_HAL_STATUS_SUCCESS)
//if(g_pFlash->flash_erase_sector(ui32TargetAddress) == AM_HAL_STATUS_SUCCESS)
{
error_code = g_pFlash->flash_write_page(ui32TargetAddress, (uint32_t *)otaFlashOp.writeBuffer, g_pFlash->flashPageSize);
static_print_info(" flash_write_page = %d \n",error_code);
if( error_code == write_result)
//if(g_pFlash->flash_write_page(ui32TargetAddress, (uint32_t *)otaFlashOp.writeBuffer, g_pFlash->flashPageSize) == AM_HAL_STATUS_SUCCESS)
{
if(OtaVerifyFlashContent(ui32TargetAddress, (uint32_t *)otaFlashOp.writeBuffer, otaFlashOp.bufferIndex, g_pFlash) == AM_HAL_STATUS_SUCCESS)
{
static_print_info("Flash write succeeded to address 0x%x. length %d\n", ui32TargetAddress, otaFlashOp.bufferIndex);
ui8PageCount++;
otaFlashOp.bufferIndex = 0;
error_code = FENDA_SUCCESS;
break;
}
else
{
error_code = DATA_CRC_OTA_ERROR;
static_print_remind("\r\n\r\n\n\nFlash verify failed to address: 0x%x. indx = %d\r \n", ui32TargetAddress, indx);
}
}
else
{
error_code = FLASH_WRITE_OTA_ERROR;
static_print_remind("\r\n\r\n\n\nFlash write failed to address: 0x%x. indx = %d - %d\r \n", ui32TargetAddress, indx,g_pFlash->flashPageSize);
}
}
else
{
error_code = FLASH_ERASE_OTA_ERROR;
static_print_remind("\r\n\r\n\n\nFlash erase sector failed to address: 0x%x. indx = %d\r\n", ui32TargetAddress, indx);
}
vTaskDelay(100);
}
if(indx >= 3)
{
OtaFailed(DEVICE_DISCONNECT);
static_print_remind("try 3 times to write flash, but all failed\r\n");
break;
}
// FlashOperationStatus = g_pFlash->flash_erase_sector(ui32TargetAddress);
// // Always write whole pages
// if ((g_pFlash->flash_write_page(ui32TargetAddress, (uint32_t *)otaFlashOp.writeBuffer, g_pFlash->flashPageSize) != 0)
// || (OtaVerifyFlashContent(ui32TargetAddress, (uint32_t *)otaFlashOp.writeBuffer, otaFlashOp.bufferIndex, g_pFlash) != 0))
// //if (g_pFlash->flash_write_page(ui32TargetAddress, (uint32_t *)otaFlashOp.writeBuffer, g_pFlash->flashPageSize) != 0)
// {
// static_print_info("FlashOperationStatus = %d, Flash write failed to address: 0x%x \n", FlashOperationStatus, ui32TargetAddress);
//
// bResult = false;
// break;
// }
// static_print_info("Flash write succeeded to address 0x%x. length %d\n", ui32TargetAddress, otaFlashOp.bufferIndex);
// ui8PageCount++;
// otaFlashOp.bufferIndex = 0;
// bResult = true;
}
}
FLASH_OPERATE(g_pFlash, flash_disable);
//
// If we get here, operations are done correctly
//
return error_code;
}
/*!
* brief: Verify Firmware Image CRC
*/
static bool_t OtaVerifyFirmwareCrc(void)
{
// read back the whole firmware image from flash and calculate CRC
uint32_t ui32CRC = 0;
uint32_t ui32_addr = 0;
uint32_t ui32_length = 0;
uint32_t blk_start,blk_end,blk_num,index;
uint16_t read_start_size = 0;
uint16_t read_end_size = 0;
uint32_t len_op=0;
uint32_t i=0;
// uint32_t ret=0;
//
// Check crc in external flash
//
FLASH_OPERATE(g_pFlash, flash_enable);
// if(g_otaCtrlBlock.HeaderInfo.fwDataType != MARK_MCU_FW_BIN)
{
ui32_addr = g_otaCtrlBlock.newFwFlashInfo.addr + g_otaCtrlBlock.HeaderInfo.secInfoLen;
ui32_length = g_otaCtrlBlock.HeaderInfo.fwLength - g_otaCtrlBlock.HeaderInfo.secInfoLen;
}
blk_start = ui32_addr/AMOTAS_TEMP_BUFSIZE;
len_op = ui32_addr%AMOTAS_TEMP_BUFSIZE;
if(len_op)
{
read_start_size = AMOTAS_TEMP_BUFSIZE - len_op;
if(read_start_size>ui32_length)
{
read_start_size = ui32_length;
}
}
else if(ui32_length<AMOTAS_TEMP_BUFSIZE)
{
read_start_size = ui32_length;
}
blk_end = (ui32_addr + ui32_length)/AMOTAS_TEMP_BUFSIZE;
if(blk_end>blk_start)
{
read_end_size = (ui32_addr + ui32_length)%AMOTAS_TEMP_BUFSIZE;
}
else
{
read_end_size = 0;
}
blk_num = (ui32_length - read_start_size - read_end_size)/AMOTAS_TEMP_BUFSIZE;
index = 0;
if(read_start_size)
{
len_op = read_start_size;
g_pFlash->flash_read_page((uint32_t)(ui32_addr + index),
(uint32_t *)otaFlashOp.writeBuffer,
len_op);
ui32CRC = crc32_ex(ui32CRC, otaFlashOp.writeBuffer, len_op);
blk_start++;
index += len_op;
}
if(blk_num)
{
len_op = AMOTAS_TEMP_BUFSIZE;
for(i=0;i<blk_num;i++)
{
g_pFlash->flash_read_page((uint32_t)(ui32_addr + index),
(uint32_t *)otaFlashOp.writeBuffer,
len_op);
ui32CRC = crc32_ex(ui32CRC, otaFlashOp.writeBuffer, len_op);
blk_start++;
index += len_op;
}
}
if(read_end_size)
{
len_op = read_end_size;
g_pFlash->flash_read_page((uint32_t)(ui32_addr + index),
(uint32_t *)otaFlashOp.writeBuffer,
len_op);
ui32CRC = crc32_ex(ui32CRC, otaFlashOp.writeBuffer, len_op);
blk_start++;
index += len_op;
}
if(index != ui32_length)
{
static_print_remind("error:[OtaVerifyFirmwareCrc()] ui32_addr %d index %d ui32_length %d\r\n",ui32_addr,index,ui32_length);
}
FLASH_OPERATE(g_pFlash, flash_disable);
static_print_remind("addr = 0x%x,len = %d-%d,ui32CRC = 0x%x,fwCrc = 0x%x\r\n",ui32_addr,ui32_length,index,ui32CRC, g_otaCtrlBlock.HeaderInfo.fwCrc);
return (ui32CRC == g_otaCtrlBlock.HeaderInfo.fwCrc);
}
/*!
* brief: Processing firmware header information.
*/
uint32_t ProcessingFwHeader(void)
{
uint32_t bResult = FENDA_SUCCESS;
g_otaCtrlBlock.HeaderInfo.encrypted = 0;
if(g_ota_head_struct.sour_addr)
{
g_otaCtrlBlock.HeaderInfo.fwStartAddr = g_ota_head_struct.sour_addr;
}
else
{
g_otaCtrlBlock.HeaderInfo.fwStartAddr = 0x28000;//default
}
g_otaCtrlBlock.HeaderInfo.fwLength = g_ota_head_struct.file_size+g_ota_head_param.h_len;
g_otaCtrlBlock.HeaderInfo.fwCrc = g_ota_head_struct.file_crc32;
g_otaCtrlBlock.HeaderInfo.secInfoLen = g_ota_head_param.h_len;
g_otaCtrlBlock.HeaderInfo.storageAddr = g_ota_head_struct.dest_addr;
g_otaCtrlBlock.HeaderInfo.fwDataType = g_ota_head_param.mark;
if(g_ota_head_struct.dest_cs && (g_ota_head_struct.dest_cs < FW_SOUR_CS_MAX))
{
g_otaCtrlBlock.HeaderInfo.storageType = g_ota_head_struct.dest_cs;//config
}
else
{
g_otaCtrlBlock.HeaderInfo.storageType = FW_SOUR_CS_FLASH;//default
}
static_print_info("============= fw header start ===============\n");
static_print_info("encrypted = 0x%x\n", g_otaCtrlBlock.HeaderInfo.encrypted);
//static_print_info("version = 0x%x\n", g_otaCtrlBlock.HeaderInfo.version);
static_print_info("fwLength = 0x%x\n", g_otaCtrlBlock.HeaderInfo.fwLength);
static_print_info("fwCrc = 0x%x\n", g_otaCtrlBlock.HeaderInfo.fwCrc);
static_print_info("fwStartAddr = 0x%x\n", g_otaCtrlBlock.HeaderInfo.fwStartAddr);
static_print_info("fwDataType = 0x%x\n", g_otaCtrlBlock.HeaderInfo.fwDataType);
static_print_info("storageType = 0x%x\n", g_otaCtrlBlock.HeaderInfo.storageType);
static_print_info("storageAddr = 0x%x\n", g_otaCtrlBlock.HeaderInfo.storageAddr);
static_print_info("fw_size = 0x%x\n",g_ota_head_struct.file_size);
static_print_info("============= fw header end ===============\n");
otaFlashOp.bufferIndex = 0;
g_otaCtrlBlock.pkt.offset = 0;
g_otaCtrlBlock.pkt.FileSize = g_otaCtrlBlock.HeaderInfo.fwLength;
g_otaCtrlBlock.ota_status = OTA_STATE_FW_DATA;
g_otaCtrlBlock.newFwFlashInfo.offset = 0;
// Initialize the flash operation interface and the new firmware storage address
if ( g_otaCtrlBlock.HeaderInfo.storageType == FW_SOUR_CS_ROM )
{
g_pFlash = &g_intFlash;
// Check to make sure the incoming image will fit in the space allocated for OTA
if (g_otaCtrlBlock.HeaderInfo.fwLength < AMOTA_INT_FLASH_OTA_MAX_SIZE)
{
g_otaCtrlBlock.newFwFlashInfo.addr = g_otaCtrlBlock.HeaderInfo.storageAddr;
}
else
{
static_print_info("\n??????not enough space. (len = %d)??????\n",g_otaCtrlBlock.HeaderInfo.fwLength);
bResult = DATA_PACK_SIZE_ERROR;
}
}
else if ( g_otaCtrlBlock.HeaderInfo.storageType == FW_SOUR_CS_FLASH )
{
ota_ext_flash_info_init(&g_ext_flash);
g_pFlash = &g_ext_flash;
if (g_pFlash->flash_read_page &&
g_pFlash->flash_write_page &&
g_pFlash->flash_erase_sector)
{
if(g_otaCtrlBlock.HeaderInfo.fwDataType == MARK_MCU_FW_BIN) // is a run image
{
if(g_otaCtrlBlock.HeaderInfo.fwLength > MAX_IMAGE_SIZE)
{
bResult = DATA_PACK_SIZE_ERROR;
}
}
g_otaCtrlBlock.newFwFlashInfo.addr = g_otaCtrlBlock.HeaderInfo.storageAddr;
}
else
{
bResult = DEVICE_FORBIT_OTA_ERROR;
}
}
return bResult;
}
/*!
* brief: Check whether breakpoint continuation is required.
*/
bool_t IfBreakPointValid(void)
{
uint32_t BreakPointPtrVal = 0;
BreakPointPtrVal = *((uint32_t *)USER_OTA_BREAK_POINT_ADDR);
static_print_remind("BreakPointPtrVal = %x\n", BreakPointPtrVal);
if((BreakPointPtrVal != 0xFFFFFFFF) && (BreakPointPtrVal != 0))
{
memcpy(&g_otaBreakPoint, (FwBreakPointInfo_t *)USER_OTA_BREAK_POINT_ADDR, sizeof(FwBreakPointInfo_t));
static_print_remind("g_otaBreakPoint.fileSize = %x,g_otaBreakPoint.fileCrc32 = %x\n",
g_otaBreakPoint.fileSize, g_otaBreakPoint.fileCrc32);
if(g_otaBreakPoint.ifResume &&
g_otaBreakPoint.fileSize == g_otaCtrlBlock.HeaderInfo.fwLength &&
g_otaBreakPoint.fileCrc32 == g_otaCtrlBlock.HeaderInfo.fwCrc)
{
return true;
}
else
{
memset(&g_otaBreakPoint, 0, sizeof(g_otaBreakPoint));
OtaUpdateBreakPoint();
}
}
return false;
}
/*!
* brief: New FW packet handler, for OTA service call
*/
uint32_t OtaPacketHandler(uint16_t len, uint8_t *buf)
{
uint32_t error_code = FENDA_SUCCESS;
int ret;
switch(g_otaCtrlBlock.ota_status)
{
case OTA_STATE_FW_HEADER:
ret = user_pack_json_head((char *)buf,&g_ota_head_param,&g_ota_head_struct);
static_print_info("OtaPacketHandler h_len %d = %d - %d - %d - %d- %d\n ",len,g_ota_head_param.h_len,g_ota_head_param.pack_len,g_ota_head_param.ext_offset,g_ota_head_param.struct_len,g_ota_head_param.struct_offset);
if(ret)
{
static_print_info("g_ota_head_struct %d = %d - %x - %x - %x -%x \n",
g_ota_head_struct.sour_addr,g_ota_head_struct.dest_addr,g_ota_head_struct.file_version[0],g_ota_head_struct.file_version[1],g_ota_head_struct.file_version[2],g_ota_head_struct.file_version[3]);
#if 1
//task_ui_notify(UI_MSG_DISPLAY_OPEN, 0, NULL, 0);
task_ui_notify(EVENT_OTA_TRANS_START, 0, NULL, 0);
// GoToResouceOTAScreen();
error_code = ProcessingFwHeader();
if(error_code != FENDA_SUCCESS)
{
static_print_info("\n ????? DEVICE_FW_OTA_ERROR=%d ????? \n",error_code);
return error_code;
}
if(IfBreakPointValid())
{
static_print_info("read fileOffset from BreakPointInfo = %x\r\n",g_otaBreakPoint.fileOffset);
g_otaCtrlBlock.pkt.offset = g_otaBreakPoint.fileOffset;
g_otaCtrlBlock.newFwFlashInfo.offset = g_otaBreakPoint.fileOffset;
}
else
{
//保存包头 saimen add
error_code = OtaWrite2Flash(len, buf, g_otaCtrlBlock.newFwFlashInfo.addr + g_otaCtrlBlock.newFwFlashInfo.offset,
((g_otaCtrlBlock.newFwFlashInfo.offset + len) == g_otaCtrlBlock.HeaderInfo.fwLength));
if (error_code != FENDA_SUCCESS)
{
static_print_info("\n ?????OTA FLASH WRITE ERROR ????? \n");
return error_code;
}
else
{
g_otaCtrlBlock.pkt.offset += len;//更新申请数据的地址
g_otaCtrlBlock.newFwFlashInfo.offset += len;
}
}
// Length of application firmware
g_otaCtrlBlock.pkt.ApplyLen = g_otaCtrlBlock.pkt.FileSize - g_otaCtrlBlock.pkt.offset;
g_otaCtrlBlock.pkt.ApplyLen = g_otaCtrlBlock.pkt.ApplyLen > APPLY_FW_DATA_LEN ? APPLY_FW_DATA_LEN:g_otaCtrlBlock.pkt.ApplyLen;
/* 因断点续传信息获取,第一包数据在此处申请 */
DeviceRequestOTAFileData(g_otaCtrlBlock.pkt.offset, g_otaCtrlBlock.pkt.ApplyLen,
g_otaCtrlBlock.pkt.FileSize, g_otaCtrlBlock.pkt.offset);
#endif
}
break;
case OTA_STATE_FW_DATA:
//static_print_info("ota write2flash len %x addr %x\n",len,
// g_otaCtrlBlock.newFwFlashInfo.addr + g_otaCtrlBlock.newFwFlashInfo.offset);
error_code = OtaWrite2Flash(len, buf, g_otaCtrlBlock.newFwFlashInfo.addr + g_otaCtrlBlock.newFwFlashInfo.offset,
((g_otaCtrlBlock.newFwFlashInfo.offset + len) == g_otaCtrlBlock.HeaderInfo.fwLength));
if (error_code != FENDA_SUCCESS)
{
static_print_info("\n ?????OTA FLASH WRITE ERROR ????? \n");
return error_code;
}
else
{
g_otaCtrlBlock.pkt.offset += len;//更新申请数据的地址
g_otaCtrlBlock.newFwFlashInfo.offset += len;
}
if(g_otaCtrlBlock.pkt.offset >= g_otaCtrlBlock.pkt.FileSize)
{// get the last pkg
static_print_info("ReceivedSuccess. pkt.offset = %x,\r\n", g_otaCtrlBlock.pkt.offset);
g_otaCtrlBlock.crc_verify = OtaVerifyFirmwareCrc();
g_otaCtrlBlock.ota_status = OTA_STATE_FW_RESET;
return error_code;
}
// Length of application firmware
g_otaCtrlBlock.pkt.ApplyLen = (g_otaCtrlBlock.pkt.FileSize) - g_otaCtrlBlock.pkt.offset;
g_otaCtrlBlock.pkt.ApplyLen = g_otaCtrlBlock.pkt.ApplyLen > APPLY_FW_DATA_LEN ? APPLY_FW_DATA_LEN : g_otaCtrlBlock.pkt.ApplyLen;
task_ui_notify(EVENT_OTA_TRANSMITTING, (g_otaCtrlBlock.pkt.offset * 100) / g_otaCtrlBlock.pkt.FileSize, NULL, 0);
break;
case OTA_STATE_FW_VERIFY:
break;
case OTA_STATE_FW_RESET:
break;
default:
break;
}
return error_code;
}
/*!
* updata user boot --saimen
*/
void ota_user_boot (void)
{
uint32_t ui32_crc;
uint8_t rw_boot_times = 3;
static uint32_t boot_run_addr = 0x00018000;
uint32_t r_boot_addr = 0;
uint32_t w_boot_addr = 0;
uint32_t rw_boot_len = 0;
uint32_t op_len = 0;
uint8_t *p_boot_data = otaFlashOp.writeBuffer;
if(g_otaCtrlBlock.HeaderInfo.fwStartAddr == boot_run_addr && g_otaCtrlBlock.HeaderInfo.storageType == FW_SOUR_CS_FLASH)//user boot addr
{
while(rw_boot_times--)
{
r_boot_addr = g_otaCtrlBlock.HeaderInfo.storageAddr + g_otaCtrlBlock.HeaderInfo.secInfoLen;
w_boot_addr = boot_run_addr;
ui32_crc = 0;
for(rw_boot_len = g_otaCtrlBlock.HeaderInfo.secInfoLen;rw_boot_len<g_otaCtrlBlock.HeaderInfo.fwLength;)
{
op_len = ((g_otaCtrlBlock.HeaderInfo.fwLength - rw_boot_len) > MCU_ROM_PAGE_SIZE)? MCU_ROM_PAGE_SIZE:(g_otaCtrlBlock.HeaderInfo.fwLength - rw_boot_len);
g_pFlash->flash_read_page(r_boot_addr, (uint32_t *)p_boot_data, op_len);
rom_api_erase(w_boot_addr);
rom_api_write(w_boot_addr, p_boot_data, op_len);
r_boot_addr += op_len;
w_boot_addr += op_len;
rw_boot_len += op_len;
static_print_remind("r_boot_addr=0x%x,w_boot_addr=0x%x,op_len=0x%x\n",r_boot_addr,w_boot_addr,op_len);
}
ui32_crc = crc32_ex(ui32_crc, (uint8_t *)boot_run_addr, g_otaCtrlBlock.HeaderInfo.fwLength - g_otaCtrlBlock.HeaderInfo.secInfoLen);
if(ui32_crc == g_otaCtrlBlock.HeaderInfo.fwCrc)
{
break;
}
static_print_remind("error:obj_crc=0x%x,temp_crc=0x%x\n",g_otaCtrlBlock.HeaderInfo.fwCrc,ui32_crc);
}
}
}
/*!
* brief: Update Flag Page with Firmware Information, for OTA service call.
*/
void OtaUpdateFwInfo(void)
{
uint32_t ui32CRC = 0;
uint32_t otaPtrPageAddr = (USER_BOOTLOADER_MBR_ADDR & ~(AM_HAL_FLASH_PAGE_SIZE - 1));
g_boot_mbr_info.carry_fw_flag = 0x10;
g_boot_mbr_info.formal.fw_sour_addr = (g_otaCtrlBlock.newFwFlashInfo.addr + g_otaCtrlBlock.HeaderInfo.secInfoLen);
g_boot_mbr_info.formal.fw_dest_addr = g_otaCtrlBlock.HeaderInfo.fwStartAddr;
g_boot_mbr_info.formal.fw_sour_cs = g_otaCtrlBlock.HeaderInfo.storageType;
g_boot_mbr_info.formal.fw_dest_cs = FW_SOUR_CS_ROM;
//g_boot_mbr_info.formal.fw_reserve1 = ;
g_boot_mbr_info.formal.fw_bytes = g_otaCtrlBlock.HeaderInfo.fwLength -g_otaCtrlBlock.HeaderInfo.secInfoLen;
g_boot_mbr_info.formal.fw_crc32 = g_otaCtrlBlock.HeaderInfo.fwCrc;
ui32CRC = 0;
ui32CRC = crc32_ex(ui32CRC, (uint8_t *)&g_boot_mbr_info, sizeof(g_boot_mbr_info) - 4);
g_boot_mbr_info.crc32 = ui32CRC;
static_print_remind("*****************************************************\n");
static_print_remind("OtaUpdateFwInfo()\n");
static_print_remind("carry_fw_flag=0x%x\n", g_boot_mbr_info.carry_fw_flag);
static_print_remind("fw_sour_addr=0x%x\n", g_boot_mbr_info.formal.fw_sour_addr);
static_print_remind("fw_dest_addr=0x%x\n", g_boot_mbr_info.formal.fw_dest_addr);
static_print_remind("fw_sour_cs=0x%x\n", g_boot_mbr_info.formal.fw_sour_cs);
static_print_remind("fw_dest_cs=0x%x\n", g_boot_mbr_info.formal.fw_dest_cs);
static_print_remind("fw_reserve1=0x%x\n", g_boot_mbr_info.formal.fw_reserve1);
static_print_remind("fw_bytes=0x%x\n", g_boot_mbr_info.formal.fw_bytes);
static_print_remind("fw_crc32=0x%x\n", g_boot_mbr_info.formal.fw_crc32);
static_print_remind("MBR CRC=0x%x\n",g_boot_mbr_info.crc32);
static_print_remind("*****************************************************\n");
// Copy the OTA descriptor
memcpy(otaFlashOp.writeBuffer, &g_boot_mbr_info, sizeof(g_boot_mbr_info));
// Write the flash Page
if(g_otaCtrlBlock.HeaderInfo.fwStartAddr < 0x28000)
{
//saimen add
static_print_remind("warning:boot ota addr=0x%x--size=%d--crc=0x%x\n",
g_otaCtrlBlock.HeaderInfo.fwStartAddr,g_otaCtrlBlock.HeaderInfo.fwLength,g_otaCtrlBlock.HeaderInfo.fwCrc);
ota_user_boot();
}
else
{
am_bootloader_program_flash_page(otaPtrPageAddr, (uint32_t *)otaFlashOp.writeBuffer, AMOTAS_TEMP_BUFSIZE);
}
}
/*!
* brief: Update Flag Page with Break Point Information .
*/
void OtaUpdateBreakPoint(void)
{
uint32_t BreakPointPtrPageAddr = (USER_OTA_BREAK_POINT_ADDR & ~(AM_HAL_FLASH_PAGE_SIZE - 1));
uint32_t otaPtrOffset = USER_OTA_BREAK_POINT_ADDR - BreakPointPtrPageAddr;
memcpy(otaFlashOp.writeBuffer, (uint8_t *)BreakPointPtrPageAddr, AM_HAL_FLASH_PAGE_SIZE);
static_print_remind("addr = %x, off = %x\r\n", BreakPointPtrPageAddr, otaPtrOffset);
memcpy(&otaFlashOp.writeBuffer[otaPtrOffset], (uint8_t *)&g_otaBreakPoint, sizeof(g_otaBreakPoint));
am_bootloader_program_flash_page(BreakPointPtrPageAddr, (uint32_t *)otaFlashOp.writeBuffer, AM_HAL_FLASH_PAGE_SIZE);
}