/****************************************************************************** * Copyright (c) 20203, Freqchip * * All rights reserved. * * */ #include #include //#include #include "fr30xx.h" #include "co_util.h" #include "gap_api.h" #include "gatt_api.h" #include "FreeRTOS.h" #include "timers.h" #include "app_ota.h" #include "app_ota_service.h" /****************************************************************************** * MACROS (宏定义) */ /***************************************************************************** * CONSTANTS (常量定义) */ #define PMU_REG_FLASH_VDD_CTRL 0xFB #define IMAGE_INFO_OTA_MAGIC (0x51525251) /***************************************************************************** * TYPEDEFS (类型定义) */ __PACKED_STRUCT ota_ongoing_t{ uint8_t type; uint8_t start_flag; uint8_t erase_flag; uint8_t mac_addr[6]; }; __PACKED_STRUCT ota_file_version_t{ uint32_t otaboot_version; uint32_t app_version; uint32_t controller_version; uint32_t dsp_version; }; __PACKED_STRUCT file_info_t{ uint32_t file_version; uint32_t file_storage_base; uint32_t file_length; uint32_t file_crc; }; __PACKED_STRUCT ota_info_t{ uint8_t first_check_flag[4]; uint8_t file_type; //烧录文件中,所包含的文件类型 struct file_info_t boot_file_info; struct file_info_t app_file_info; struct file_info_t controller_file_info; struct file_info_t dsp_file_info; uint8_t controller_flag; struct ota_ongoing_t ota_ongoing; uint32_t rsv[10]; }; __PACKED_STRUCT firmware_version { uint32_t firmware_version; } __attribute__((packed)); __PACKED_STRUCT storage_baseaddr { uint32_t baseaddr; } __attribute__((packed)); __PACKED_STRUCT page_erase_rsp { uint32_t base_address; } __attribute__((packed)); __PACKED_STRUCT write_mem_rsp { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT read_mem_rsp { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT write_data_rsp { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT read_data_rsp { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT ota_start_rsp { uint32_t ota_start; } __attribute__((packed)); __PACKED_STRUCT ota_finish_rsp { uint32_t ota_finsih_state; } __attribute__((packed)); __PACKED_STRUCT app_ota_rsp_hdr_t { uint8_t result; uint8_t org_opcode; uint16_t length; __PACKED union { uint8_t nvds_type; struct firmware_version version; struct storage_baseaddr baseaddr; struct page_erase_rsp page_erase; struct write_mem_rsp write_mem; struct read_mem_rsp read_mem; struct write_data_rsp write_data; struct read_data_rsp read_data; struct ota_finish_rsp finsih_rsp; struct ota_start_rsp ota_start; } __attribute__((packed)) rsp; } __attribute__((packed)); __PACKED_STRUCT page_erase_cmd { uint32_t base_address; } __attribute__((packed)); __PACKED_STRUCT write_mem_cmd { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT read_mem_cmd { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT write_data_cmd { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT read_data_cmd { uint32_t base_address; uint16_t length; } __attribute__((packed)); __PACKED_STRUCT firmware_check { uint32_t firmware_length; uint32_t CRC32_data; } __attribute__((packed)); __PACKED_STRUCT app_ota_cmd_hdr_t { uint8_t opcode; uint16_t length; __PACKED union { struct page_erase_cmd page_erase; struct write_mem_cmd write_mem; struct read_mem_cmd read_mem; struct write_data_cmd write_data; struct read_data_cmd read_data; struct firmware_check fir_crc_data; } __attribute__((packed)) cmd; } __attribute__((packed)); struct image_info_t { uint32_t image_version; uint32_t image_offset; // storage offset uint32_t image_length; uint32_t execute_offset; // execute offset uint32_t copy_unit; // 4K, 8K, 16K, 32K, 64K, 128K uint32_t copy_flag_store_step; // 4, 8, 16, 32, 64 uint32_t image_crc; uint32_t image_valid; uint32_t image_tlv_length; // Hash,signa length uint32_t options; uint32_t info_crc; uint32_t ota_magic; // 需要更新标志 }; __PACKED_STRUCT otas_send_rsp { uint8_t conidx; uint16_t length; uint8_t *buffer; }; __PACKED_STRUCT source_file_info_t{ uint8_t check_buff[4]; uint32_t version; uint32_t length; uint32_t crc; }; typedef unsigned int uLong; typedef unsigned int uInt; typedef uLong uLongf; typedef unsigned char Byte; typedef Byte Bytef; #define ZEXPORT #define OF(a) a #define Z_NULL 0 #define local static #define IMAGE_INFO_CRC_ZONE_LEN ((uint32_t)(&((struct image_info_t *)0)->info_crc)) /****************************************************************************** * LOCAL VARIABLES (局部变量) */ static uint8_t first_loop; const uint8_t ota_check_data[4] = {0x43,0x75,0x28,0x19}; const uint8_t app_check_data[4] = {0x55,0xAA,0x55,0xAA}; const uint8_t controller_check_data[4] = {0x55,0xAA,0xAA,0x55}; const uint8_t dsp_check_data[4] = {0xAA,0x55,0x55,0xAA}; static void app_boot_retarget(uint32_t target); static uint32_t ota_imagesize = 0; static TimerHandle_t xTimer_OtaTimerOut = NULL; static uint16_t at_data_idx; static uint32_t firmware_vesion_new = 0; static uint32_t firmware_size_new = 0; static uint32_t ota_ongoing_base = 0; static uint32_t ota_ongoing_max_code_size = 0; static uint8_t file_type = 0; uint32_t Crc32CalByByte(int crc,uint8_t* ptr, int len); /****************************************************************************** * GLOBAL VARIABLES (全局变量) */ struct app_otas_status_t app_otas_status; struct ota_info_t * ota_info; extern adv_handle ota_adv; extern uint8_t ble_static_addr[6]; /****************************************************************************** * LOCAL FUNCTIONS (本地函数) */ __RAM_CODE static uint8_t app_otas_crc_cal(uint32_t firmware_length,uint32_t new_bin_addr,uint32_t crc_data_t); uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len); uint32_t get_boot_crc(uint32_t imagesize,uint32_t length); /****************************************************************************** * EXTERN FUNCTIONS (外部函数) */ extern void wdt_rst_start(void); extern void user_controller_init(void); /********************************************************************* * @fn check_file_integrity * * @brief check file intergrity when ota start, * if file not intergrity,adv always on. * else close ota */ void check_file_integrity(void) { if(ota_info->ota_ongoing.erase_flag) { adv_timeout_TimerStop(); }else{ /*ota disable*/ ota_info->ota_ongoing.start_flag = 0; flash_write(QSPI0,BOOT_B_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info); wdt_rst_start(); } } void show_reg(uint8_t *buffer,uint16_t length) { for(int i = 0; i < length; i++) { printf("%02x ",buffer[i]); } printf("\r\n"); } void print_info(struct source_file_info_t * info) { printf("\ncheck:%02x,%02x,%02x,%02x",info->check_buff[0],info->check_buff[1], info->check_buff[2],info->check_buff[3]); printf("\nversion:%08x",info->version); printf("\nlength:%08x",info->length); printf("\ncrc:%08x\r\n",info->crc); } /********************************************************************* * @fn get_ota_info * * @brief 第一次上电的时候,获取文件有效信息 */ bool get_ota_info(void) { struct ota_info_t get_ota_info; flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)&get_ota_info); /*检查是不是第一次上电,第一次上电,从文件中读取文件信息*/ if(memcmp(get_ota_info.first_check_flag,ota_check_data,4) != 0) { struct source_file_info_t src_info; struct image_info_t image_info; /*获取boot有效信息,版本号,存储地址,程序长度,crc*/ flash_read(QSPI0,BOOT_A_INFO_ADDRESS,sizeof(struct image_info_t),(uint8_t *)&image_info); get_ota_info.boot_file_info.file_version = image_info.image_version; get_ota_info.boot_file_info.file_storage_base = OTA_B_STORAGE_ADDRESS; get_ota_info.boot_file_info.file_length = image_info.image_length; get_ota_info.boot_file_info.file_crc = image_info.image_crc; get_ota_info.file_type = 0; /*获取app有效信息,版本号,存储地址,程序长度,crc*/ flash_read(QSPI0,APP_CODE_STORAGE_ADDRESS+APP_CODE_INFO_OFFSET,sizeof(struct source_file_info_t),(uint8_t *)&src_info); print_info(&src_info); if(memcmp(src_info.check_buff,app_check_data,4) == 0) { uint32_t app_code_crc; get_ota_info.app_file_info.file_version = src_info.version; get_ota_info.app_file_info.file_storage_base = APP_CODE_STORAGE_ADDRESS; get_ota_info.app_file_info.file_length = src_info.length; flash_read(QSPI0,APP_CODE_STORAGE_ADDRESS+src_info.length,4,(uint8_t *)&app_code_crc); get_ota_info.app_file_info.file_crc = app_code_crc; get_ota_info.file_type |= FILE_TYPE_APP; printf("app crc:%x\r\n",get_ota_info.app_file_info.file_crc); }else{ return false; } /* 1、检测controller地址是否controller有效信息,有设置controller flag为1,表示会在应用层初始化controller 否则,boot里面初始化controller 2、获取controller有效信息,版本号,存储地址,程序长度,crc */ flash_read(QSPI0,CONTROLLER_STORAGE_ADDRESS,sizeof(struct source_file_info_t),(uint8_t *)&src_info); printf("controller:%x\r\n",CONTROLLER_STORAGE_ADDRESS); print_info(&src_info); // if(memcmp(src_info.check_buff,controller_check_data,4) == 0 ) { get_ota_info.controller_flag = 1; get_ota_info.controller_file_info.file_version = src_info.version; get_ota_info.controller_file_info.file_storage_base = CONTROLLER_STORAGE_ADDRESS; get_ota_info.controller_file_info.file_crc = src_info.crc; get_ota_info.controller_file_info.file_length = src_info.length; get_ota_info.file_type |= FILE_CONTROLLER; } // else{ // get_ota_info.controller_flag = 0; // } /*获取DSP有效信息,版本号,存储地址,程序长度,crc*/ flash_read(QSPI0,DSP_STORAGE_ADDRESS,sizeof(struct source_file_info_t),(uint8_t *)&src_info); printf("dsp:%x\r\n",DSP_STORAGE_ADDRESS); print_info(&src_info); // if(memcmp(src_info.check_buff,dsp_check_data,4) == 0) { get_ota_info.dsp_file_info.file_version = src_info.version; get_ota_info.dsp_file_info.file_storage_base = DSP_STORAGE_ADDRESS; get_ota_info.dsp_file_info.file_crc = src_info.crc; get_ota_info.dsp_file_info.file_length = src_info.length; get_ota_info.file_type |= FILE_TYPE_DSP; } /*初始化ota 升级时的状态信息*/ get_ota_info.ota_ongoing.start_flag = 0; get_ota_info.ota_ongoing.erase_flag = 0; memcpy(get_ota_info.first_check_flag,ota_check_data,4); flash_erase(QSPI0,OTA_BOOT_INFO_ADDRESS,0x1000); flash_write(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)&get_ota_info); } return true; } /********************************************************************* * @fn Document_validity_check * * @brief 校验APP,DSP,CONTROLLER程序 */ bool Document_validity_check(void) { #if DOCUMENT_CHECK struct ota_info_t get_ota_info; bool status = true; flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)&get_ota_info); printf("validity type:%02x\r\n",get_ota_info.file_type); do { /*对app文件进行校验*/ if(get_ota_info.file_type & FILE_TYPE_APP) { printf("address:%x,length:%x\r\n",get_ota_info.app_file_info.file_storage_base,get_ota_info.app_file_info.file_length); if(get_boot_crc(get_ota_info.app_file_info.file_storage_base,get_ota_info.app_file_info.file_length) == get_ota_info.app_file_info.file_crc) { status = true; }else{ status = false; break; } }else{ status = false; break; } #if 0 /*对control文件进行校验*/ if(get_ota_info.file_type & FILE_TYPE_CONTROLLER) { printf("address:%x,length:%x\r\n",get_ota_info.controller_file_info.file_storage_base,get_ota_info.controller_file_info.file_length); if(get_boot_crc(get_ota_info.controller_file_info.file_storage_base+FILE_CODE_ADDRESS_OFFSET,get_ota_info.controller_file_info.file_length) == get_ota_info.controller_file_info.file_crc) { status = true; }else{ status = false; break; } } /*对dsp文件进行校验*/ if(get_ota_info.file_type & FILE_TYPE_DSP) { printf("address:%x,length:%x\r\n",get_ota_info.dsp_file_info.file_storage_base,get_ota_info.dsp_file_info.file_length); if(get_boot_crc(get_ota_info.dsp_file_info.file_storage_base+FILE_CODE_ADDRESS_OFFSET,get_ota_info.dsp_file_info.file_length) == get_ota_info.dsp_file_info.file_crc) { status = true; }else{ status = false; break; } } #endif }while(0); #else bool status = true; #endif return status; } /********************************************************************* * @fn ota_boot_start * */ void ota_boot_start(void) { if(get_ota_info() == true) { struct ota_info_t get_ota_info; flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)&get_ota_info); /*判断需不需要ota 升级*/ if(get_ota_info.ota_ongoing.start_flag != 0x01) { /*对文件有效性进行检查,如果没有文件则进入默认boot程序*/ if((Document_validity_check() == true)) { /*判断应用层初始化controller还是boot初始化controller*/ if(get_ota_info.controller_flag == 0x01 ) { printf("controller code\r\n"); co_delay_100us(100); /*jump new address*/ app_boot_retarget(RETARGET_APP_CODE_ADDRESS); while(1); }else{ printf("no controller code\r\n"); /*control init*/ user_controller_init(); /*jump new address*/ app_boot_retarget(RETARGET_APP_CODE_ADDRESS); while(1); } }else{ ota_info = pvPortMalloc(sizeof(struct ota_info_t)); flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info); } }else{ /*进入ota程序,获取ota 信息,并且设置ota升级地址*/ ota_info = pvPortMalloc(sizeof(struct ota_info_t)); flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info); memcpy(ble_static_addr,ota_info->ota_ongoing.mac_addr,6); } }else{ ota_info = pvPortMalloc(sizeof(struct ota_info_t)); flash_read(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info); memset(ota_info->first_check_flag,0,4); ota_info->app_file_info.file_version = 0; ota_info->boot_file_info.file_version = 0; ota_info->controller_file_info.file_version = 0; ota_info->dsp_file_info.file_version = 0; ota_info->app_file_info.file_storage_base = APP_CODE_STORAGE_ADDRESS; ota_info->boot_file_info.file_storage_base = OTA_B_STORAGE_ADDRESS; ota_info->controller_file_info.file_storage_base = CONTROLLER_STORAGE_ADDRESS; ota_info->dsp_file_info.file_storage_base = DSP_STORAGE_ADDRESS; ota_info->ota_ongoing.start_flag = 1; ota_info->ota_ongoing.erase_flag = 1; ota_info->file_type = 0; } } /********************************************************************* * @fn ota_init * * @brief Initialization ota */ void ota_init(void) { app_otas_status.read_opcode = OTA_CMD_NULL; first_loop = true; at_data_idx = 0; } /********************************************************************* * @fn ota_deinit * * @brief reset chip,when ota abnormal disconnection */ void ota_deinit(void) { wdt_rst_start(); } /********************************************************************* * @fn platform_reset * * @brief reset chip */ void platform_reset(void) { // Disable interrupts __disable_irq(); ool_write(PMU_REG_FLASH_VDD_CTRL, ool_read(PMU_REG_FLASH_VDD_CTRL) & 0xFE); co_delay_100us(300); NVIC_SystemReset(); } /********************************************************************* * @fn ota_set_imagesize * * @brief set ota file size */ void ota_set_imagesize(uint32_t imagesize) { ota_imagesize = imagesize; } /********************************************************************* * @fn ota_set_imagesize * * @brief get ota file size */ uint32_t ota_get_imagesize(void) { return ota_imagesize; } /********************************************************************* * @fn app_boot_retarget * * @brief 重映射中断向量表,MSP指针,代码跳转RAM执行 */ __RAM_CODE static void app_boot_retarget(uint32_t target) { static str_CoreRemapStart_t *CoreRemapStart; CoreRemapStart = (str_CoreRemapStart_t *)target; /* Disable SysTick */ SysTick->CTRL = 0; /* Modify intrerrupt vector table */ SCB->VTOR = target; __set_MSP((volatile uint32_t)CoreRemapStart->MSP); ((void (*)(void))(CoreRemapStart->Reset_Handler | 0x01))(); } /********************************************************************* * @fn app_otas_read_data * * @brief Read Data * * @param Read Data Buffer. * * * @return Read Data Length. */ uint16_t app_otas_read_data(uint8_t *p_data) { uint16_t length; switch(app_otas_status.read_opcode) { case OTA_CMD_READ_DATA: length = app_otas_status.length; break; case OTA_CMD_READ_MEM: length = app_otas_status.length; break; default: length = 0; break; } app_otas_status.read_opcode = OTA_CMD_NULL; return length; } /********************************************************************* * @fn ota_start_cb * * @brief stop start,reset chip * */ void ota_start_callback(TimerHandle_t pxTimer) { xTimerStop(xTimer_OtaTimerOut,0); ota_deinit(); } /********************************************************************* * @fn ota_start * * @brief ota timeout enable * */ void ota_start(void) { if(xTimer_OtaTimerOut == NULL) { xTimer_OtaTimerOut = xTimerCreate("ota",OTA_START_TIMOUT/portTICK_PERIOD_MS,pdFALSE,NULL,ota_start_callback); xTimerStart(xTimer_OtaTimerOut,0); }else{ xTimerStop(xTimer_OtaTimerOut,0); xTimerStart(xTimer_OtaTimerOut,0); } } /********************************************************************* * @fn ota_stop * * @brief close ota stop * */ void ota_stop(void) { xTimerStop(xTimer_OtaTimerOut,0); } /********************************************************************* * @fn app_otas_recv_data * * @brief Otas Data handler * */ void app_otas_recv_data(uint8_t conidx,uint8_t *p_data,uint16_t len) { struct app_ota_cmd_hdr_t *cmd_hdr = (struct app_ota_cmd_hdr_t *)p_data; struct app_ota_rsp_hdr_t *rsp_hdr; uint16_t rsp_data_len = (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN); if(first_loop) { /*close adv time out*/ adv_timeout_TimerStop(); first_loop = false; } ota_start(); at_data_idx++; switch(cmd_hdr->opcode) { case OTA_CMD_NVDS_TYPE: rsp_data_len += 1; break; case OTA_CMD_GET_STR_BASE: at_data_idx = 0; rsp_data_len += sizeof(struct storage_baseaddr); break; case OTA_CMD_READ_FW_VER: rsp_data_len += sizeof(struct firmware_version); break; case OTA_CMD_PAGE_ERASE: rsp_data_len += sizeof(struct page_erase_rsp); break; case OTA_CMD_WRITE_DATA: rsp_data_len += sizeof(struct write_data_rsp); break; case OTA_CMD_READ_DATA: rsp_data_len += sizeof(struct read_data_rsp) + cmd_hdr->cmd.read_data.length; if(rsp_data_len > OTAS_NOTIFY_DATA_SIZE) { rsp_data_len = sizeof(struct read_data_rsp) + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN); app_otas_status.read_opcode = OTA_CMD_READ_DATA; app_otas_status.length = cmd_hdr->cmd.read_data.length; app_otas_status.base_addr = cmd_hdr->cmd.read_data.base_address; } break; case OTA_CMD_WRITE_MEM: rsp_data_len += sizeof(struct write_mem_rsp); break; case OTA_CMD_READ_MEM: rsp_data_len += sizeof(struct read_mem_rsp) + cmd_hdr->cmd.read_mem.length; if(rsp_data_len > OTAS_NOTIFY_DATA_SIZE) { rsp_data_len = sizeof(struct read_data_rsp) + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN); app_otas_status.read_opcode = OTA_CMD_READ_MEM; app_otas_status.length = cmd_hdr->cmd.read_data.length; app_otas_status.base_addr = cmd_hdr->cmd.read_data.base_address; } else { app_otas_status.read_opcode = OTA_CMD_NULL; } break; case OTA_CMD_START: rsp_data_len += sizeof(struct ota_start_rsp); break; case OTA_CMD_NULL: return; } struct otas_send_rsp *req = pvPortMalloc(sizeof(struct otas_send_rsp)); uint16_t base_length; req->conidx = conidx; req->length = rsp_data_len; req->buffer = pvPortMalloc(rsp_data_len); rsp_hdr = (struct app_ota_rsp_hdr_t *)&req->buffer[0]; rsp_hdr->result = OTA_RSP_SUCCESS; rsp_hdr->org_opcode = cmd_hdr->opcode; rsp_hdr->length = rsp_data_len - (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN); switch(cmd_hdr->opcode) { case OTA_CMD_NVDS_TYPE: rsp_hdr->rsp.nvds_type = 0x01; break; case OTA_CMD_GET_STR_BASE: //获取存储地址 switch(ota_info->ota_ongoing.type) { case FILE_BOOT_LOADER: rsp_hdr->rsp.baseaddr.baseaddr = ota_info->boot_file_info.file_storage_base; ota_ongoing_base = ota_info->boot_file_info.file_storage_base; ota_ongoing_max_code_size = BOOT_CODE_MAX_SIZE; break; case FILE_APP: rsp_hdr->rsp.baseaddr.baseaddr = ota_info->app_file_info.file_storage_base; ota_ongoing_base = ota_info->app_file_info.file_storage_base; ota_ongoing_max_code_size = APP_CODE_MAX_SIZE; break; case FILE_CONTROLLER: rsp_hdr->rsp.baseaddr.baseaddr = ota_info->controller_file_info.file_storage_base; ota_ongoing_base = ota_info->controller_file_info.file_storage_base; ota_ongoing_max_code_size = CONTROLLER_CODE_MAX_SIZE; break; case FILE_DSP: rsp_hdr->rsp.baseaddr.baseaddr = ota_info->dsp_file_info.file_storage_base; ota_ongoing_base = ota_info->dsp_file_info.file_storage_base; ota_ongoing_max_code_size = DSP_CODE_MAX_SIZE; break; } break; case OTA_CMD_READ_FW_VER: //获取版本号 { uint8_t type; type = *(p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN)); switch(type) { case FILE_BOOT_LOADER: rsp_hdr->rsp.version.firmware_version = ota_info->boot_file_info.file_version; break; case FILE_APP: rsp_hdr->rsp.version.firmware_version = ota_info->app_file_info.file_version; break; case FILE_CONTROLLER: rsp_hdr->rsp.version.firmware_version = ota_info->controller_file_info.file_version; break; case FILE_DSP: rsp_hdr->rsp.version.firmware_version = ota_info->dsp_file_info.file_version; break; } } break; case OTA_CMD_PAGE_ERASE: //擦除 { rsp_hdr->rsp.page_erase.base_address = cmd_hdr->cmd.page_erase.base_address; printf("erase:%x\r\n",cmd_hdr->cmd.page_erase.base_address); /*设置擦除状态*/ if(ota_info->ota_ongoing.erase_flag == 0) { ota_info->ota_ongoing.erase_flag = 1; GLOBAL_INT_DISABLE(); flash_erase(QSPI0,OTA_BOOT_INFO_ADDRESS,0x1000); flash_write(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info); GLOBAL_INT_RESTORE(); } /*判断下发的擦除地址是否小于存储地址*/ if(rsp_hdr->rsp.page_erase.base_address < ota_ongoing_base) { /*disconnect link*/ gap_disconnect(conidx); } else if(rsp_hdr->rsp.page_erase.base_address >= (ota_ongoing_base+ota_ongoing_max_code_size)) { /*disconnect link*/ printf("erase over size\r\n"); gap_disconnect(conidx); } else { GLOBAL_INT_DISABLE(); flash_erase(QSPI0,rsp_hdr->rsp.page_erase.base_address, 0x1000); GLOBAL_INT_RESTORE(); } } break; case OTA_CMD_CHIP_ERASE: break; case OTA_CMD_WRITE_DATA: //导入数据 { printf("program:%x,length:%d\r\n",rsp_hdr->rsp.write_data.base_address,rsp_hdr->rsp.write_data.length); rsp_hdr->rsp.write_data.base_address = cmd_hdr->cmd.write_data.base_address; rsp_hdr->rsp.write_data.length = cmd_hdr->cmd.write_data.length; /*判断下发的烧录地址是否小于存储地址*/ if(rsp_hdr->rsp.write_data.base_address < ota_ongoing_base) { /*disconnect link*/ gap_disconnect(conidx); } else if(rsp_hdr->rsp.write_data.base_address+rsp_hdr->rsp.write_data.length > (ota_ongoing_base+ota_ongoing_max_code_size)) { /*disconnect link*/ printf("program over size\r\n"); gap_disconnect(conidx); } else { GLOBAL_INT_DISABLE(); /*flash write*/ flash_write(QSPI0,rsp_hdr->rsp.write_data.base_address, rsp_hdr->rsp.write_data.length, p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN)+sizeof(struct write_data_cmd)); GLOBAL_INT_RESTORE(); } } break; case OTA_CMD_READ_DATA: rsp_hdr->rsp.read_data.base_address = cmd_hdr->cmd.read_data.base_address; rsp_hdr->rsp.read_data.length = cmd_hdr->cmd.read_data.length; base_length = sizeof(struct read_data_rsp) + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN); if(rsp_data_len != base_length) { flash_read(QSPI0,rsp_hdr->rsp.read_data.base_address, rsp_hdr->rsp.read_data.length, (uint8_t*)rsp_hdr+base_length); } break; case OTA_CMD_WRITE_MEM: rsp_hdr->rsp.write_mem.base_address = cmd_hdr->cmd.write_mem.base_address; rsp_hdr->rsp.write_mem.length = cmd_hdr->cmd.write_mem.length; memcpy((void *)rsp_hdr->rsp.write_mem.base_address, p_data + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN)+sizeof(struct write_data_cmd), rsp_hdr->rsp.write_mem.length); break; case OTA_CMD_READ_MEM: rsp_hdr->rsp.read_mem.base_address = cmd_hdr->cmd.read_mem.base_address; rsp_hdr->rsp.read_mem.length = cmd_hdr->cmd.read_mem.length; base_length = sizeof(struct read_mem_rsp) + (OTA_HDR_OPCODE_LEN+OTA_HDR_LENGTH_LEN+OTA_HDR_RESULT_LEN); if(rsp_data_len != base_length) { memcpy((uint8_t*)rsp_hdr+base_length, (void *)rsp_hdr->rsp.read_mem.base_address, rsp_hdr->rsp.read_data.length); } break; case OTA_CMD_REBOOT: //复位重启 { printf("crc base:%x,length:%x\r\n",ota_ongoing_base,cmd_hdr->cmd.fir_crc_data.firmware_length); if(app_otas_crc_cal(cmd_hdr->cmd.fir_crc_data.firmware_length,ota_ongoing_base,cmd_hdr->cmd.fir_crc_data.CRC32_data)) { switch(ota_info->ota_ongoing.type) { case FILE_BOOT_LOADER: { volatile struct image_info_t image_info; flash_read(QSPI0,BOOT_A_INFO_ADDRESS,sizeof(struct image_info_t),(uint8_t *)&image_info); image_info.image_version += 1; image_info.image_offset = OTA_B_STORAGE_ADDRESS; image_info.image_length = cmd_hdr->cmd.fir_crc_data.firmware_length; image_info.ota_magic = IMAGE_INFO_OTA_MAGIC; image_info.image_crc = get_boot_crc(ota_ongoing_base,cmd_hdr->cmd.fir_crc_data.firmware_length); image_info.info_crc = crc32(0x00000000,(uint8_t *)&image_info,IMAGE_INFO_CRC_ZONE_LEN); printf("image_info_crc:%x\r\n",image_info.info_crc); GLOBAL_INT_DISABLE(); flash_erase(QSPI0,BOOT_B_INFO_ADDRESS,0x1000); flash_write(QSPI0,BOOT_B_INFO_ADDRESS,sizeof(struct image_info_t),(uint8_t *)&image_info); GLOBAL_INT_RESTORE(); ota_info->boot_file_info.file_version = image_info.image_version; ota_info->boot_file_info.file_length = image_info.image_length; ota_info->boot_file_info.file_crc = image_info.image_crc; rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 1; ota_info->ota_ongoing.start_flag = 0; ota_info->ota_ongoing.erase_flag = 0; } break; case FILE_APP: { struct source_file_info_t src_info; uint32_t app_code_crc; flash_read(QSPI0,APP_CODE_STORAGE_ADDRESS+APP_CODE_INFO_OFFSET,sizeof(struct source_file_info_t),(uint8_t *)&src_info); if(memcmp(src_info.check_buff,app_check_data,4) == 0) { ota_info->app_file_info.file_version = src_info.version; ota_info->app_file_info.file_length = src_info.length; flash_read(QSPI0,APP_CODE_STORAGE_ADDRESS+src_info.length,4,(uint8_t *)&app_code_crc); ota_info->app_file_info.file_crc = app_code_crc; rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 1; ota_info->ota_ongoing.start_flag = 0; ota_info->ota_ongoing.erase_flag = 0; }else{ rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 0; printf("app ota fail\r\n"); } } break; case FILE_CONTROLLER: { struct source_file_info_t src_info; flash_read(QSPI0,CONTROLLER_STORAGE_ADDRESS,sizeof(struct source_file_info_t),(uint8_t *)&src_info); if(memcmp(src_info.check_buff,controller_check_data,4) == 0 ) { ota_info->controller_file_info.file_length = src_info.length; ota_info->controller_file_info.file_version = src_info.version; ota_info->controller_file_info.file_crc = src_info.crc; rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 1; ota_info->ota_ongoing.start_flag = 0; ota_info->ota_ongoing.erase_flag = 0; }else{ rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 0; printf("controller ota fail\r\n"); } } break; case FILE_DSP: { struct source_file_info_t src_info; flash_read(QSPI0,DSP_STORAGE_ADDRESS,sizeof(struct source_file_info_t),(uint8_t *)&src_info); if(memcmp(src_info.check_buff,dsp_check_data,4) == 0) { ota_info->dsp_file_info.file_length = src_info.length; ota_info->dsp_file_info.file_version = src_info.version; ota_info->dsp_file_info.file_crc = src_info.crc; rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 1; ota_info->ota_ongoing.start_flag = 0; ota_info->ota_ongoing.erase_flag = 0; }else{ rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 0; printf("dsp ota fail\r\n"); } } break; } GLOBAL_INT_DISABLE(); flash_erase(QSPI0,OTA_BOOT_INFO_ADDRESS,0x1000); flash_write(QSPI0,OTA_BOOT_INFO_ADDRESS,sizeof(struct ota_info_t),(uint8_t *)ota_info); GLOBAL_INT_RESTORE(); printf("crc finish\r\n"); wdt_rst_start(); }else{ printf("crc error\r\n"); rsp_hdr->rsp.finsih_rsp.ota_finsih_state = 0; wdt_rst_start(); } } break; case OTA_CMD_START: { rsp_hdr->rsp.ota_start.ota_start = 1; } break; default: rsp_hdr->result = OTA_RSP_UNKNOWN_CMD; break; } ota_gatt_report_notify(conidx,req->buffer,req->length); vPortFree(req->buffer); vPortFree(req); } /********************************************************************* * * @brief Check ota file * */ local const uLongf crc_table[256] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; /* ========================================================================= * This function can be used by asm versions of crc32() */ const uLongf * ZEXPORT get_crc_table(void) { #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif return (const uLongf *)crc_table; } /* ========================================================================= */ #define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); #define DO2(buf) DO1(buf); DO1(buf); #define DO4(buf) DO2(buf); DO2(buf); #define DO8(buf) DO4(buf); DO4(buf); /* ========================================================================= */ uLong ZEXPORT crc32(uLong crc, const Bytef *buf, uInt len) { // if (buf == Z_NULL) return 0L; #ifdef DYNAMIC_CRC_TABLE if (crc_table_empty) make_crc_table(); #endif crc = crc ^ 0xffffffffL; while (len >= 8) { DO8(buf); len -= 8; } if (len) do { DO1(buf); } while (--len); return crc ^ 0xffffffffL; } __RAM_CODE uint32_t Crc32CalByByte(int crc,uint8_t* ptr, int len) { int i = 0; while(len-- != 0) { int high = crc/256; crc <<= 8; crc ^= crc_table[(high^ptr[i])&0xff]; crc &= 0xFFFFFFFF; i++; } return crc&0xFFFFFFFF; } __RAM_CODE static uint8_t app_otas_crc_cal(uint32_t firmware_length,uint32_t new_bin_addr,uint32_t crc_data_t) { uint32_t crc_data = 0,i = 0; uint8_t * crc_check_data = pvPortMalloc(0x1000); uint8_t ret = 0; uint32_t data_size = firmware_length; uint32_t read_address = new_bin_addr; while(data_size > 0x1000) { flash_read(QSPI0,read_address, 0x1000,crc_check_data); crc_data = Crc32CalByByte(crc_data, crc_check_data,0x1000); data_size -= 0x1000; read_address += 0x1000; } flash_read(QSPI0,read_address, data_size,crc_check_data); crc_data = Crc32CalByByte(crc_data, crc_check_data,data_size); printf("crc:%x,%x",crc_data,crc_data_t); vPortFree(crc_check_data); if(crc_data_t == crc_data) ret = 1; return ret; } uint32_t get_boot_crc(uint32_t imagesize,uint32_t length) { uint32_t crc_data = 0,i = 0; uint8_t * crc_check_data = pvPortMalloc(0x1000); uint8_t ret = 0; uint32_t data_size = length; uint32_t read_address = imagesize; while(data_size > 0x1000) { flash_read(QSPI0,read_address, 0x1000,crc_check_data); crc_data = crc32(crc_data, crc_check_data,0x1000); data_size -= 0x1000; read_address += 0x1000; } flash_read(QSPI0,read_address, data_size,crc_check_data); crc_data = crc32(crc_data, crc_check_data,data_size); printf("file crc:%x\r\n",crc_data); vPortFree(crc_check_data); return crc_data; }