prj to mdks
This commit is contained in:
@@ -0,0 +1,862 @@
|
||||
|
||||
#include "firmware.h"
|
||||
|
||||
|
||||
static uint8_t _fw_start_write_flag; /* 固件开始写入的标志位 */
|
||||
static uint16_t _update_progress; /* 固件更新的进度, 10000 制 */
|
||||
static uint16_t _update_progress_step_num; /* 固件更新进度的步进单位 */
|
||||
static uint16_t _storage_data_size; /* 固件包写入时记录暂存的固件分包大小,单位 byte */
|
||||
static uint32_t _write_part_addr; /* 固件包写入时记录写入 flash 的相对地址 */
|
||||
static uint16_t _write_last_pkg_size; /* 固件包写入时最后一个分包的大小,单位 byte */
|
||||
static uint8_t _fw_first_bytes[CONFIG_WRITE_BYTES_LEASET]; /* 固件包的前几个字节 */
|
||||
static uint8_t _upk_min_handle_buff[UPK_LEAST_HANDLE_BYTE]; /* upk 固件最小处理单位的缓存区,多次使用以降低系统资源开销 */
|
||||
static struct upk_head_t upkHdr; /* 用于存放 upk 固件包头 */
|
||||
|
||||
#if (CONFIG_DECRYPT)
|
||||
static struct AES_ctx aesCtx; /* AES 对象 */
|
||||
#endif
|
||||
|
||||
static struct BSP_FLASH _flash_app_part; /* APP 分区 */
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
static struct BSP_FLASH _flash_download_part; /* download 分区 */
|
||||
#if (CONFIG_CHIP_PARTS == USE_TRIPLE_PARTITION)
|
||||
static struct BSP_FLASH _flash_factory_part; /* factory 分区 */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Extern function prototypes ------------------------------------------------*/
|
||||
extern void Firmware_OperateCallback(uint16_t progress);
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static eErrCode _Write_FirmwareSubPackage( const struct BSP_FLASH *part,
|
||||
uint8_t *data,
|
||||
uint16_t pkg_size,
|
||||
uint8_t decrypt,
|
||||
FM_FIRMWARE_WRITE_DIR write_dir);
|
||||
|
||||
static void _Reset_Write(void);
|
||||
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief 初始化接口
|
||||
* @note
|
||||
* @retval None
|
||||
*/
|
||||
void FM_Init (void)
|
||||
{
|
||||
BSP_Flash_Init(&_flash_app_part, NAME_PART_APPLICATION, BASE_APPLICATION, SIZE_PART_APPLICATION);
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
BSP_Flash_Init(&_flash_download_part, NAME_PART_DOWNLOAD, BASE_DOWNLOAD, SIZE_PART_DOWNLOAD);
|
||||
#if (CONFIG_CHIP_PARTS > USE_DOUBLE_PARTITION)
|
||||
BSP_Flash_Init(&_flash_factory_part, NAME_PART_FACTORY, BASE_FACTORY, SIZE_PART_FACTORY);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
printf("onchip size : 0x%lX\r\n", SIZE_ONCHIP_FLASH);
|
||||
printf("0x%08lX+0x%lX 'parameters'.\r\n", BASE_PARAMETERS, SIZE_PART_PARAMETERS);
|
||||
printf("0x%08X+0x%X 'app'.\r\n", _flash_app_part.addr, _flash_app_part.len);
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
printf("0x%08X+0x%X 'download'.\r\n", _flash_download_part.addr, _flash_app_part.len);
|
||||
#if (CONFIG_CHIP_PARTS > USE_DOUBLE_PARTITION)
|
||||
printf("0x%08X+0x%X 'factory'.\r\n", _flash_factory_part.addr, _flash_app_part.len);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (CONFIG_DECRYPT)
|
||||
AES_init_ctx_iv(&aesCtx, (uint8_t *)AES256_KEY, (uint8_t *)AES256_IV);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 固件包是否有加密
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 0: 未加密。1: 有加密
|
||||
*/
|
||||
inline uint8_t FM_IsEncrypt(void)
|
||||
{
|
||||
/* 读取加密选项 */
|
||||
if (upkHdr.config[1] == 0x01)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 检测某个分区是否为空
|
||||
* @note ERR_OK: 分区数据空
|
||||
* @param[in] part_name: 分区名
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_IsEmpty(const char *part_name)
|
||||
{
|
||||
int read_len = 0;
|
||||
uint16_t i = 0;
|
||||
uint16_t need_read_size = UPK_LEAST_HANDLE_BYTE;
|
||||
uint32_t *p_data = (uint32_t *)_upk_min_handle_buff;
|
||||
uint32_t read_posit = 0;
|
||||
|
||||
ASSERT(part_name != NULL);
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL) {
|
||||
printf("%s: '%s' not found.\r\n", __func__, part_name);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
for (read_posit = 0; read_posit < part->len; ) {
|
||||
if ((part->len - read_posit) < UPK_LEAST_HANDLE_BYTE) {
|
||||
need_read_size = part->len - read_posit;
|
||||
}
|
||||
|
||||
read_len = BSP_Flash_Read(part, read_posit, _upk_min_handle_buff, need_read_size);
|
||||
if (read_len < 0) {
|
||||
printf("%s: read error (%d).\r\n", __func__, __LINE__);
|
||||
return ERR_READ_IS_EMPTY_ERR;
|
||||
}
|
||||
|
||||
for (i = 0; i < (UPK_LEAST_HANDLE_BYTE / sizeof(p_data)); i++) {
|
||||
if (p_data[i] != 0xFFFFFFFF) {
|
||||
printf("part '%s' not empty.\r\n", part_name);
|
||||
return ERR_FLASH_NO_EMPTY;
|
||||
}
|
||||
}
|
||||
read_posit += read_len;
|
||||
}
|
||||
|
||||
//printf("%s: '%s' part empty.\r\n", __func__, part_name);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取固件包的固件版本
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 固件新版本
|
||||
*/
|
||||
inline char * FM_GetNewFirmwareVersion(void)
|
||||
{
|
||||
return upkHdr.fw_new_ver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取源固件的 CRC32 值
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 源固件的 CRC32 值
|
||||
*/
|
||||
inline uint32_t FM_GetRawCRC32(void)
|
||||
{
|
||||
return upkHdr.raw_crc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 暂存固件包头
|
||||
* @note 会同时校验固件包头
|
||||
* @param[in] part_name: 分区名
|
||||
* @param[in] data: 数据
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_StorageFirmwareHead(const char *part_name, uint8_t *data)
|
||||
{
|
||||
uint32_t head_crc = 0xFFFFFFFF;
|
||||
uint8_t *pHdr = (uint8_t *)&upkHdr;
|
||||
|
||||
ASSERT(part_name != NULL);
|
||||
ASSERT(data != NULL);
|
||||
|
||||
_Reset_Write();
|
||||
memcpy(pHdr, data, UPK_HEAD_SIZE);
|
||||
|
||||
#if (!CONFIG_DECRYPT)
|
||||
/* 若固件包加密,检查是否有解密组件 */
|
||||
if (FM_IsEncrypt()) {
|
||||
printf("%s: no decrypt component\r\n", __func__);
|
||||
return ERR_NO_DECRYPT_COMPONENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL) {
|
||||
printf("%s: not found.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
//printf("%s: '%s' part.\r\n", __func__, part_name);
|
||||
|
||||
if (strncmp(upkHdr.name, "upk", sizeof("upk")) != 0) {
|
||||
return ERR_FAULT_FIRMWARE;
|
||||
}
|
||||
|
||||
if ((upkHdr.pkg_size > part->len)
|
||||
|| (upkHdr.raw_size > part->len)) {
|
||||
return ERR_FIRMWARE_OVERSIZE;
|
||||
}
|
||||
|
||||
head_crc = crc32_step(head_crc, pHdr, UPK_HEAD_SIZE - 4);
|
||||
if (head_crc != upkHdr.head_crc) {
|
||||
printf("%s: head crc verify failed. (%.8X - %.8X)\r\n", __func__, upkHdr.head_crc, head_crc);
|
||||
return ERR_FIRMWARE_HEAD_VERIFY_ERR;
|
||||
}
|
||||
|
||||
printf("\n\r--------------------\n\r");
|
||||
printf("head: \t\t%s\n\r", upkHdr.name);
|
||||
printf("config: \t%d %d %d %d\n\r", upkHdr.config[0], upkHdr.config[1], upkHdr.config[2], upkHdr.config[3]);
|
||||
printf("old_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_old_ver[0], upkHdr.fw_old_ver[1], upkHdr.fw_old_ver[2], upkHdr.fw_old_ver[3]);
|
||||
printf("new_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_new_ver[0], upkHdr.fw_new_ver[1], upkHdr.fw_new_ver[2], upkHdr.fw_new_ver[3]);
|
||||
printf("string: \t%s\n\r",upkHdr.user_string);
|
||||
printf("partition: \t%s\n\r", upkHdr.part_name);
|
||||
printf("raw_size: \t%d\n\r", upkHdr.raw_size);
|
||||
printf("pkg_size: \t%d\n\r", upkHdr.pkg_size);
|
||||
printf("timestamp: \t%d\n\r", upkHdr.timestamp);
|
||||
printf("raw_crc: \t%.8X\n\r", upkHdr.raw_crc);
|
||||
printf("pkg_crc: \t%.8X\n\r", upkHdr.pkg_crc);
|
||||
printf("head_crc: \t%.8X\n\r", upkHdr.head_crc);
|
||||
printf("--------------------\n\r");
|
||||
|
||||
/* 计算固件更新进度的最小单位,降低过程计算量,无更新进度需求可删除 */
|
||||
_update_progress_step_num = upkHdr.pkg_size / UPK_LEAST_HANDLE_BYTE;
|
||||
_update_progress_step_num += upkHdr.pkg_size % UPK_LEAST_HANDLE_BYTE;
|
||||
_update_progress_step_num = 10000 / _update_progress_step_num;
|
||||
//printf("%s: progress unit: %d\r\n", __func__, _update_progress_step_num);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 校验已放置在分区的固件包的包体数据的正确性
|
||||
* @note 一般要先校验包头,注意各分区包体的偏移地址有区别
|
||||
* @param[in] part_name: 分区名称
|
||||
* @param[in] crc32: 需进行比对的 CRC32 校验值
|
||||
* @param[in] is_auto_fill: 是否自动填充固件的首地址数据
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_VerifyFirmware (const char *part_name, uint32_t crc32, uint8_t is_auto_fill)
|
||||
{
|
||||
int read_len = 0;
|
||||
uint8_t app_part_flag = 0;
|
||||
uint32_t pkg_size = 0;
|
||||
uint32_t body_crc = 0xFFFFFFFF;
|
||||
uint32_t read_posit = 0;
|
||||
uint32_t read_posit_temp = 0;
|
||||
uint16_t need_read_size = UPK_LEAST_HANDLE_BYTE;
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
uint8_t first_flag = 0;
|
||||
#endif
|
||||
|
||||
ASSERT(part_name != NULL);
|
||||
|
||||
#if (!CONFIG_DECRYPT)
|
||||
/* 若固件包加密,检查是否有解密组件 */
|
||||
if (FM_IsEncrypt()) {
|
||||
printf("%s: no decrypt component\r\n", __func__);
|
||||
return ERR_NO_DECRYPT_COMPONENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strncmp(part_name, NAME_PART_APPLICATION, MAX_NAME_LEN) == 0) {
|
||||
app_part_flag = 1;
|
||||
}
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL) {
|
||||
printf("%s: not found.\r\n", part_name);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
hex_printf((uint8_t *)&upkHdr, UPK_HEAD_SIZE);
|
||||
|
||||
printf("--------------------\n\r");
|
||||
printf("head: \t\t%s\n\r", upkHdr.name);
|
||||
printf("config: \t%d %d %d %d\n\r", upkHdr.config[0], upkHdr.config[1], upkHdr.config[2], upkHdr.config[3]);
|
||||
printf("old_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_old_ver[0], upkHdr.fw_old_ver[1], upkHdr.fw_old_ver[2], upkHdr.fw_old_ver[3]);
|
||||
printf("new_ver: \t%d.%d.%d.%d\n\r", upkHdr.fw_new_ver[0], upkHdr.fw_new_ver[1], upkHdr.fw_new_ver[2], upkHdr.fw_new_ver[3]);
|
||||
printf("string: \t%s\n\r",upkHdr.user_string);
|
||||
printf("partition: \t%s\n\r", upkHdr.part_name);
|
||||
printf("raw_size: \t%d\n\r", upkHdr.raw_size);
|
||||
printf("pkg_size: \t%d\n\r", upkHdr.pkg_size);
|
||||
printf("timestamp: \t%d\n\r", upkHdr.timestamp);
|
||||
printf("raw_crc: \t%.8X\n\r", upkHdr.raw_crc);
|
||||
printf("pkg_crc: \t%.8X\n\r", upkHdr.pkg_crc);
|
||||
printf("head_crc: \t%.8X\n\r", upkHdr.head_crc);
|
||||
printf("--------------------\n\r");
|
||||
|
||||
if (app_part_flag) {
|
||||
pkg_size = upkHdr.raw_size;
|
||||
} else {
|
||||
pkg_size = upkHdr.pkg_size;
|
||||
}
|
||||
|
||||
/* 校验固件包体的数据正确性 */
|
||||
for (; read_posit < pkg_size; ) {
|
||||
/* 剩余的数据数小于最小处理单位时,按剩余字节数处理 */
|
||||
if ((pkg_size - read_posit) < UPK_LEAST_HANDLE_BYTE) {
|
||||
need_read_size = pkg_size - read_posit;
|
||||
}
|
||||
|
||||
/* 非 APP 分区,需要偏移包头的地址才是包体 */
|
||||
if (app_part_flag) {
|
||||
read_posit_temp = read_posit;
|
||||
} else {
|
||||
read_posit_temp = read_posit + UPK_HEAD_SIZE;
|
||||
}
|
||||
|
||||
read_len = BSP_Flash_Read(part, read_posit_temp, _upk_min_handle_buff, need_read_size);
|
||||
if (read_len < 0) {
|
||||
printf("%s: read error (%d).\r\n", __func__, __LINE__);
|
||||
return ERR_VERIFY_READ_ERR;
|
||||
}
|
||||
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
if (is_auto_fill) {
|
||||
if (first_flag == 0) {
|
||||
first_flag = 1;
|
||||
for (uint8_t i = 0; i < CONFIG_WRITE_BYTES_LEASET; i++) {
|
||||
_upk_min_handle_buff[i] = _fw_first_bytes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
body_crc = crc32_step(body_crc, _upk_min_handle_buff, read_len);
|
||||
read_posit += read_len;
|
||||
}
|
||||
|
||||
if (body_crc != crc32) {
|
||||
printf("%s: '%s' body crc verify failed. (%08X vs %08X)\r\n", __func__, part_name, crc32, body_crc);
|
||||
if (app_part_flag) {
|
||||
return ERR_RAW_BODY_VERIFY_ERR;
|
||||
} else {
|
||||
return ERR_PKG_BODY_VERIFY_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 擦除某个分区的固件
|
||||
* @note
|
||||
* @param[in] part_name: 分区名称
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_EraseFirmware(const char *part_name)
|
||||
{
|
||||
ASSERT(part_name != NULL);
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL)
|
||||
{
|
||||
printf("%s: not found %s part.\r\n", __func__, part_name);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Erase(part, 0, part->len) < 0)
|
||||
{
|
||||
printf("%s: %s part erase failed.\r\n", __func__, part_name);
|
||||
return ERR_ERASE_PART_ERR;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 固件写入分区的最终阶段,将分区首地址的几个字节数据写入 flash
|
||||
* @note 程序调用 _Write_FirmwareSubPackage 函数时已暂存进 _fw_first_bytes
|
||||
* @param[in] part_name: 分区名称
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_WriteFirmwareDone (const char *part_name)
|
||||
{
|
||||
ASSERT(part_name != NULL);
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL) {
|
||||
printf("%s: not found part.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Write(part, 0, _fw_first_bytes, CONFIG_WRITE_BYTES_LEASET) < 0) {
|
||||
printf("%s: write error (%d).\r\n", __func__, __LINE__);
|
||||
return ERR_WRITE_FIRST_ADDR_ERR;
|
||||
}
|
||||
|
||||
_Reset_Write();
|
||||
Firmware_OperateCallback(10000);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 将固件分包按顺序写入分区
|
||||
* @note 由于固件包头已经写入,这里写入的是固件包体,需要注意在 flash 的偏移位置
|
||||
* @param[in] part_name: 分区名称
|
||||
* @param[in] data: 数据包
|
||||
* @param[in] pkg_size: 数据包大小,单位 byte
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_WriteFirmwareSubPackage(const char *part_name, uint8_t *data, uint16_t pkg_size)
|
||||
{
|
||||
ASSERT(part_name != NULL);
|
||||
ASSERT(data != NULL);
|
||||
ASSERT(pkg_size != 0);
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL)
|
||||
{
|
||||
printf("%s: not found %s part.\r\n", __func__, part_name);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
printf(",");
|
||||
|
||||
#if (CONFIG_CHIP_PARTS == USE_SINGLE_PARTITION)
|
||||
uint8_t decrypt = 0;
|
||||
|
||||
/* 读取加密选项 */
|
||||
decrypt = FM_IsEncrypt();
|
||||
|
||||
return _Write_FirmwareSubPackage(part, data, pkg_size, decrypt, FM_DIR_HOST_TO_APP); /* 写入前解密 */
|
||||
#else
|
||||
return _Write_FirmwareSubPackage(part, data, pkg_size, 0, FM_DIR_HOST_TO_DOWNLOAD); /* 写入前不解密 */
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 检查固件的完整性
|
||||
* @note 通过首地址数据最后写入的机制,判断首地址 4 个字节是否有正确的数据
|
||||
* @param[in] addr: 分区首地址
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_CheckFirmwareIntegrity(uint32_t addr)
|
||||
{
|
||||
uint32_t value = *(volatile uint32_t *)addr;
|
||||
eErrCode fw_integrity = ERR_JUMP_TO_APP_ERR;
|
||||
|
||||
printf("\r\nvalue = 0x%08X @ offset 0x%.8X", value, addr);
|
||||
|
||||
if (BASE_APPLICATION == addr) {
|
||||
fw_integrity = ((value & 0x2FF00000) == 0x20000000) ? ERR_OK : ERR_JUMP_TO_APP_ERR;
|
||||
}
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
else if ((BASE_DOWNLOAD == addr)||(BASE_FACTORY == addr)) {
|
||||
if (UPK_IDENTIFIER == value) {
|
||||
fw_integrity = ERR_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return fw_integrity;
|
||||
}
|
||||
|
||||
|
||||
#if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION)
|
||||
/**
|
||||
* @brief 判断是否要进行固件自动更新
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 0: 无须更新。1: 需自动更新
|
||||
*/
|
||||
uint8_t FM_IsNeedAutoUpdate(void)
|
||||
{
|
||||
#if (CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP)
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(NAME_PART_APPLICATION);
|
||||
if (part == NULL) {
|
||||
printf("%s: not found app part.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Read(part, (SIZE_PART_APPLICATION - UPK_VERSION_SIZE), (uint8_t *)&upkHdr.fw_old_ver[0], UPK_VERSION_SIZE) < 0)
|
||||
{
|
||||
printf("%s: read error.\r\n", __func__);
|
||||
return ERR_READ_VER_ERR;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("fw old ver: V%d.%d.%d.%d\r\n", upkHdr.fw_old_ver[0], upkHdr.fw_old_ver[1], upkHdr.fw_old_ver[2], upkHdr.fw_old_ver[3]);
|
||||
printf("fw new ver: V%d.%d.%d.%d\r\n", upkHdr.fw_new_ver[0], upkHdr.fw_new_ver[1], upkHdr.fw_new_ver[2], upkHdr.fw_new_ver[3]);
|
||||
|
||||
if (upkHdr.fw_old_ver[0] != upkHdr.fw_new_ver[0]
|
||||
|| upkHdr.fw_old_ver[1] != upkHdr.fw_new_ver[1]
|
||||
|| upkHdr.fw_old_ver[2] != upkHdr.fw_new_ver[2]
|
||||
|| upkHdr.fw_old_ver[3] != upkHdr.fw_new_ver[3]) {
|
||||
printf("Need to update.\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取当前操作的固件包的分区名称
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 分区名称
|
||||
*/
|
||||
inline char * FM_GetPartName(void)
|
||||
{
|
||||
return upkHdr.part_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取旧的固件版本,即 APP 分区正在运行的固件版本
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 固件旧版本
|
||||
*/
|
||||
inline char * FM_GetOldFirmwareVersion(void)
|
||||
{
|
||||
return upkHdr.fw_old_ver;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 获取打包后固件的 CRC32 值
|
||||
* @note 调用前需确保 upkHdr 已经读入了数据
|
||||
* @retval 打包后固件的CRC32值
|
||||
*/
|
||||
inline uint32_t FM_GetPackageCRC32(void)
|
||||
{
|
||||
return upkHdr.pkg_crc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 将分区内的固件包头读出
|
||||
* @note 读出后的数据将放在 upkHdr 中
|
||||
* @param[in] part_name: 分区名称
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_ReadFirmwareHead(const char *part_name)
|
||||
{
|
||||
ASSERT(part_name != NULL);
|
||||
|
||||
_Reset_Write();
|
||||
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL)
|
||||
{
|
||||
printf("%s: not found.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Read(part, 0, (uint8_t *)&upkHdr, UPK_HEAD_SIZE) < 0)
|
||||
{
|
||||
printf("%s: read error.\r\n", __func__);
|
||||
return ERR_READ_FIRMWARE_HEAD_ERR;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief 从某个分区将固件包更新至 APP 分区
|
||||
* @note 读取 -> 解密 -> 写入
|
||||
* @param[in] from_part_name: 放置需要更新至 APP 分区的固件包的分区
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_UpdateToAPP(const char *from_part_name)
|
||||
{
|
||||
int read_len = 0;
|
||||
uint8_t decrypt = 0;
|
||||
uint32_t read_posit = 0;
|
||||
uint32_t write_posit = 0;
|
||||
uint32_t need_read_size = UPK_LEAST_HANDLE_BYTE;
|
||||
eErrCode result = ERR_OK;
|
||||
|
||||
ASSERT(from_part_name != NULL);
|
||||
|
||||
const struct BSP_FLASH *app_part = NULL;
|
||||
const struct BSP_FLASH *firmware_part = NULL;
|
||||
|
||||
app_part = BSP_Flash_GetHandle(NAME_PART_APPLICATION);
|
||||
if (app_part == NULL) {
|
||||
printf("%s: not found.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
firmware_part = BSP_Flash_GetHandle(from_part_name);
|
||||
if (firmware_part == NULL) {
|
||||
printf("%s: not found %s part.\r\n", __func__, from_part_name);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
_Reset_Write();
|
||||
printf("part '%s' write to 'app'.\r\n", from_part_name);
|
||||
|
||||
/* 读取加密选项 */
|
||||
decrypt = FM_IsEncrypt();
|
||||
|
||||
for (write_posit = 0; write_posit < upkHdr.pkg_size; ) {
|
||||
if ((upkHdr.pkg_size - read_posit) < UPK_LEAST_HANDLE_BYTE) {
|
||||
need_read_size = upkHdr.pkg_size - read_posit;
|
||||
}
|
||||
|
||||
read_len = BSP_Flash_Read(firmware_part, (read_posit + UPK_HEAD_SIZE), _upk_min_handle_buff, need_read_size);
|
||||
if (read_len < 0) {
|
||||
printf("%s: read error (%d).\r\n", __func__, __LINE__);
|
||||
return ERR_UPDATE_READ_ERR;
|
||||
}
|
||||
|
||||
result = _Write_FirmwareSubPackage(app_part, _upk_min_handle_buff, read_len, decrypt, FM_DIR_DOWNLOAD_TO_APP);
|
||||
if (result) {
|
||||
printf("%s: write error (%d).\r\n", __func__, __LINE__);
|
||||
return result;
|
||||
}
|
||||
|
||||
read_posit += read_len;
|
||||
write_posit += read_len;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD)
|
||||
/**
|
||||
* @brief 更新固件包中的版本信息
|
||||
* @note
|
||||
* @param[in] part_name: 分区名称
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_UpdateFirmwareVersion(const char *part_name)
|
||||
{
|
||||
ASSERT(part_name != NULL);
|
||||
|
||||
#if (ONCHIP_FLASH_ERASE_GRANULARITY > UPK_LEAST_HANDLE_BYTE)
|
||||
#error "erase granularity oversize than _upk_min_handle_buff array"
|
||||
#endif
|
||||
/* 将 download 分区首地址的数据读出,长度为片内 flash 最小擦除粒度 */
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(part_name);
|
||||
if (part == NULL)
|
||||
{
|
||||
printf("%s: not found.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
printf("%s: part name: %s\r\n", __func__, part_name);
|
||||
|
||||
if (BSP_Flash_Read(part, 0, &_upk_min_handle_buff[0], ONCHIP_FLASH_ERASE_GRANULARITY) < 0)
|
||||
{
|
||||
printf("%s: read error.\r\n", __func__);
|
||||
return ERR_UPDATE_VER_READ_ERR;
|
||||
}
|
||||
|
||||
/* 修改固件包头中旧版本字段的版本信息为新的固件版本 */
|
||||
struct upk_head_t *p_pkg_head = (struct upk_head_t *)&_upk_min_handle_buff[0];
|
||||
|
||||
p_pkg_head->fw_old_ver[0] = p_pkg_head->fw_new_ver[0];
|
||||
p_pkg_head->fw_old_ver[1] = p_pkg_head->fw_new_ver[1];
|
||||
p_pkg_head->fw_old_ver[2] = p_pkg_head->fw_new_ver[2];
|
||||
p_pkg_head->fw_old_ver[3] = p_pkg_head->fw_new_ver[3];
|
||||
|
||||
/* 将读出数据的区域擦除 */
|
||||
if (BSP_Flash_Erase(part, 0, ONCHIP_FLASH_ERASE_GRANULARITY) < 0)
|
||||
{
|
||||
printf("%s: %s part erase failed.\r\n", __func__, part_name);
|
||||
return ERR_UPDATE_VER_ERASE_ERR;
|
||||
}
|
||||
|
||||
/* 将新的数据写入擦除的区域 */
|
||||
if (BSP_Flash_Write(part, 0, &_upk_min_handle_buff[0], ONCHIP_FLASH_ERASE_GRANULARITY) < 0)
|
||||
{
|
||||
printf("%s: write error (%d).\r\n", __func__, __LINE__);
|
||||
return ERR_UPDATE_VER_WRITE_ERR;
|
||||
}
|
||||
|
||||
memcpy((uint8_t *)&upkHdr, &_upk_min_handle_buff[0], UPK_HEAD_SIZE);
|
||||
printf("fw old ver: V%d.%d.%d.%d\r\n", p_pkg_head->fw_old_ver[0], p_pkg_head->fw_old_ver[1], p_pkg_head->fw_old_ver[2], p_pkg_head->fw_old_ver[3]);
|
||||
printf("fw new ver: V%d.%d.%d.%d\r\n", p_pkg_head->fw_new_ver[0], p_pkg_head->fw_new_ver[1], p_pkg_head->fw_new_ver[2], p_pkg_head->fw_new_ver[3]);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
#elif (CONFIG_AUTO_UPDATE_MODE == MODE_APPEND_TO_APP)
|
||||
/**
|
||||
* @brief 更新固件包中的版本信息
|
||||
* @note
|
||||
* @param[in] part_name: 分区名称
|
||||
* @retval eErrCode
|
||||
*/
|
||||
eErrCode FM_UpdateFirmwareVersion(const char *part_name)
|
||||
{
|
||||
const struct BSP_FLASH *part = NULL;
|
||||
|
||||
part = BSP_Flash_GetHandle(NAME_PART_APPLICATION);
|
||||
if (part == NULL)
|
||||
{
|
||||
printf("%s: not found APP part.\r\n", __func__);
|
||||
return ERR_NO_THIS_PART;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Read(part, (SIZE_PART_APPLICATION - UPK_VERSION_SIZE), (uint8_t *)&upkHdr.fw_old_ver[0], UPK_VERSION_SIZE) < 0)
|
||||
{
|
||||
printf("%s: read error.\r\n", __func__);
|
||||
return ERR_READ_VER_ERR;
|
||||
}
|
||||
|
||||
if (upkHdr.fw_old_ver[0] != 0xFF
|
||||
|| upkHdr.fw_old_ver[1] != 0xFF
|
||||
|| upkHdr.fw_old_ver[2] != 0xFF
|
||||
|| upkHdr.fw_old_ver[3] != 0xFF)
|
||||
{
|
||||
printf("%s: version area no erase.\r\n", __func__);
|
||||
return ERR_VER_AREA_NO_ERASE;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Write(part, (SIZE_PART_APPLICATION - UPK_VERSION_SIZE), (uint8_t *)&upkHdr.fw_new_ver[0], UPK_VERSION_SIZE) < 0)
|
||||
{
|
||||
printf("%s: write error.\r\n", __func__);
|
||||
return ERR_WRITE_VER_ERR;
|
||||
}
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#endif /* #if (CONFIG_AUTO_UPDATE_MODE == MODE_UPDATE_DOWNLOAD_HEAD) */
|
||||
|
||||
#endif /* #if (CONFIG_CHIP_PARTS > USE_SINGLE_PARTITION) */
|
||||
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/**
|
||||
* @brief 复位写固件的一些记录信息
|
||||
* @note
|
||||
* @retval None
|
||||
*/
|
||||
static void _Reset_Write(void)
|
||||
{
|
||||
_fw_start_write_flag = 0; /* 固件开始写入的标志位 */
|
||||
_update_progress = 0; /* 固件更新的进度, 10000 制 */
|
||||
_storage_data_size = 0; /* 固件包写入时记录暂存的固件分包大小,单位 byte */
|
||||
_write_part_addr = 0; /* 固件包写入时记录写入 flash 的相对地址 */
|
||||
_write_last_pkg_size = 0; /* 固件包写入时最后一个分包的大小,单位 byte */
|
||||
}
|
||||
|
||||
uint32_t wcrc32 = 0xFFFFFFFF;
|
||||
uint32_t wlen = 0;
|
||||
/**
|
||||
* @brief 将固件分包按顺序写入某个分区
|
||||
* @note 循环调用本函数,无须指定写入地址,函数内部自行记录已写入的大小
|
||||
* @param[in] part: 分区对象
|
||||
* @param[in] data: 数据
|
||||
* @param[in] pkg_size: 数据大小,单位 byte
|
||||
* @param[in] decrypt: 0: 固件包无加密。1: 固件包有加密
|
||||
* @retval eErrCode
|
||||
*/
|
||||
static eErrCode _Write_FirmwareSubPackage( const struct BSP_FLASH *part,
|
||||
uint8_t *data,
|
||||
uint16_t pkg_size,
|
||||
uint8_t decrypt,
|
||||
FM_FIRMWARE_WRITE_DIR write_dir)
|
||||
{
|
||||
uint8_t *fw_4096byte_buff = data;
|
||||
|
||||
/* 主机直接下发的固件分包不满 UPK_LEAST_HANDLE_BYTE 个字节,需要先暂存至满足后再写入 */
|
||||
if (write_dir == FM_DIR_HOST_TO_APP) {
|
||||
fw_4096byte_buff = &_upk_min_handle_buff[0];
|
||||
|
||||
/* 判断是否是最后一个包 */
|
||||
if (_storage_data_size == 0) {
|
||||
if (upkHdr.pkg_size - _write_part_addr < UPK_LEAST_HANDLE_BYTE)
|
||||
{
|
||||
/* 最后一个固件分包的标志 */
|
||||
_write_last_pkg_size = upkHdr.pkg_size - _write_part_addr;
|
||||
printf("_write_last_pkg_size : %d\r\n", _write_last_pkg_size);
|
||||
}
|
||||
}
|
||||
|
||||
/* 小于最小处理单位时,暂存 */
|
||||
if (_storage_data_size < UPK_LEAST_HANDLE_BYTE) {
|
||||
memcpy(&fw_4096byte_buff[_storage_data_size], data, pkg_size);
|
||||
_storage_data_size += pkg_size;
|
||||
|
||||
if (_write_last_pkg_size) {
|
||||
if (_storage_data_size < _write_last_pkg_size) {
|
||||
return ERR_OK;
|
||||
}
|
||||
} else if (_storage_data_size < UPK_LEAST_HANDLE_BYTE) {
|
||||
return ERR_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* 从 download 或 factory 更新至 APP ,因可以直接读取 UPK_LEAST_HANDLE_BYTE 个字节,所以无须暂存 */
|
||||
else {
|
||||
if (_fw_start_write_flag == 0) {
|
||||
wlen = upkHdr.pkg_size;
|
||||
_storage_data_size = pkg_size;
|
||||
} else {
|
||||
if (wlen >= pkg_size) {
|
||||
wlen -= pkg_size;
|
||||
_storage_data_size = pkg_size;
|
||||
} else {
|
||||
_storage_data_size = wlen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (CONFIG_DECRYPT)
|
||||
if (decrypt) {
|
||||
AES_CBC_decrypt_buffer(&aesCtx, fw_4096byte_buff, _storage_data_size);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 保存首地址的几个字节数据,等待最后写入 */
|
||||
if (_fw_start_write_flag == 0) {
|
||||
for (uint8_t i = 0; i < CONFIG_WRITE_BYTES_LEASET; i++) {
|
||||
_fw_first_bytes[i] = fw_4096byte_buff[i];
|
||||
}
|
||||
|
||||
fw_4096byte_buff += CONFIG_WRITE_BYTES_LEASET;
|
||||
_storage_data_size -= CONFIG_WRITE_BYTES_LEASET;
|
||||
_write_part_addr = CONFIG_WRITE_BYTES_LEASET;
|
||||
}
|
||||
|
||||
if (BSP_Flash_Write(part, _write_part_addr, fw_4096byte_buff, _storage_data_size) < 0) {
|
||||
printf("%s: write error (%d) 0x%08X + 0x%08X, len %d.\r\n", __func__, __LINE__,
|
||||
part->addr,_write_part_addr, _storage_data_size);
|
||||
_Reset_Write();
|
||||
return ERR_WRITE_PART_ERR;
|
||||
}
|
||||
|
||||
if (_storage_data_size!=92) {
|
||||
wcrc32 = crc32_step(wcrc32, fw_4096byte_buff, _storage_data_size);
|
||||
}
|
||||
|
||||
_write_part_addr += _storage_data_size;
|
||||
_storage_data_size = 0;
|
||||
_fw_start_write_flag = 1;
|
||||
|
||||
_update_progress += _update_progress_step_num;
|
||||
Firmware_OperateCallback(_update_progress);
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user