/** * @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 OTA,for 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 OTA,for 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_lengthblk_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;iflash_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 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); }