Files
MXC-A36_2024.04.18/fr3092_mcu/examples/application/bootloader/src/app_ota.c
2024-04-17 19:45:26 +08:00

1149 lines
42 KiB
C
Raw 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.

/******************************************************************************
* Copyright (c) 20203, Freqchip
*
* All rights reserved.
*
*
*/
#include <stdio.h>
#include <string.h>
//#include <core_cm33.h>
#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 校验APPDSPCONTROLLER程序
*/
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;
}