BCU/library/bsp/bsp_boot.c

264 lines
8.4 KiB
C
Raw Permalink Normal View History

2025-02-06 15:08:48 +08:00
#include "drv_misc.h"
#include "bsp_boot.h"
#include "bsp_head.h"
#include "bsp_flash.h"
#include "kit_data.h"
#include "kit_time.h"
#include "kit_debug.h"
/********************************************************************************
*
*
*n次复位异常boot中
*31.
2.app升级
3.OTA模式需要写备份区
*********************************************************************************/
/***********备份区起始开辟32字节空间**********
+-------+-------+----------+----------+--------+
| head1 | head2 | | | |
| 4B | 4B | 4B | 4B | 16B |
+-------+-------+----------+----------+--------+
**********************************************/
#define APP_CFG_BOOT_FW_LENGTH_OFFSET 8u
#define APP_CFG_BOOT_FW_UPDATE_TIME_OFFSET 12u
#define APP_CFG_BOOT_FW_DATA_OFFSET 32u
static kit_ret_e boot_write_data(BootItem *item);
static kit_ret_e boot_write_data(BootItem *item)
{
uint8_t tmp;
uint16_t data_len;
uint32_t start_addr = 0;
kit_ret_e res = kKit_Ret_Ok;
//校验不过重新请求改包,不算错误
if((item != NULL) && (kit_check_crc16(item->buf_addr, item->buf_len) == 0))
{
//校验第一包数据的产品编号和地址
if(item->pack_idx == 0)
{
if((*((uint32_t *)item->buf_addr) != item->app_start_addr)
|| (*((uint16_t *)&item->buf_addr[2 + 4 + item->product_num_offset]) != item->product_num))
{
return kKit_Ret_Error;
}
}
data_len = item->buf_len - 4 - 2 - 2; // 减去地址 数据长度 CRC
//数据先写入备份区
start_addr = item->back_up_addr + APP_CFG_BOOT_FW_DATA_OFFSET + item->rcv_firmware_len;
item->rcv_firmware_len += data_len;
//每一包数据必须4字节对齐,TODO必须是最后一包
tmp = data_len % 4;
if(tmp != 0)
{
data_len += (4 - tmp);
}
res = bsp_flash_write_data_u32(item->flash_item, start_addr, item->buf_addr + 6, data_len);
//校验写入flash数据是否正确
if((res == kKit_Ret_Ok) && (kit_is_buf_same((void *)start_addr, (void *)(item->buf_addr + 6), data_len) == false))
{
//如果写入失败,擦除从新开始升级
res = bsp_flash_erase_page(item->flash_item, item->back_up_addr, item->firmware_len + APP_CFG_BOOT_FW_DATA_OFFSET);
item->pack_idx = 0;
}
else
{
item->pack_idx++;
}
}
return res;
}
uint16_t bsp_boot_get_pack_idx(BootItem *item)
{
uint16_t res = 0;
if(item != NULL)
{
res = item->pack_idx;
}
return res;
}
void bsp_boot_set_cmd(BootItem *item, BootCmd cmd, uint8_t* buf, uint16_t len)
{
KIT_ASSERT_PARAM(cmd < kBootCmd_End);
if((item != NULL) && (cmd < kBootCmd_End))
{
item->cmd = cmd;
if(item->cmd == kBootCmd_Erase)
{
item->firmware_len = READ_LT_INT32U_BY_CONST_POS(buf, 0);
}
else if(item->cmd == kBootCmd_SndFrame)
{
item->buf_len = len;
item->buf_addr = buf;
}
else if(item->cmd == kBootCmd_UpdateRes)
{
item->update_time = READ_LT_INT32U_BY_CONST_POS(buf, 0);
}
}
}
void bsp_boot_poll(BootItem *item)
{
kit_ret_e res;
if((item != NULL) && (item->ans_call != NULL))
{
if(item->cmd == kBootCmd_Reboot)
{
item->buf_len = 0;
item->pack_idx = 0;
item->is_token = false;
item->rcv_firmware_len = 0;
item->cmd = kBootCmd_None;
item->step = kBootStep_WaitErase;
item->ans_call(item, kBootCmd_Reboot, kKit_Ret_Ok);
}
else if(item->cmd == kBootCmd_Quit)
{
item->step = kBootStep_None;
item->ans_call(item, kBootCmd_Quit, kKit_Ret_Ok);
}
else if(item->cmd == kBootCmd_Token)
{
item->is_token = true;
item->ans_call(item, kBootCmd_Token, kKit_Ret_Ok);
}
switch (item->step)
{
case kBootStep_None:
break;
case kBootStep_WaitErase:
if(item->cmd == kBootCmd_Erase)
{
res = bsp_flash_erase_page(item->flash_item, item->back_up_addr, item->firmware_len + APP_CFG_BOOT_FW_DATA_OFFSET);
if (res == kKit_Ret_Ok)
{
item->step = kBootStep_RvdData;
}
if(item->is_token == true)
{
item->ans_call(item, kBootCmd_Erase, res);
}
}
break;
case kBootStep_RvdData:
if(item->cmd == kBootCmd_SndFrame)
{
res = boot_write_data(item);
if(item->is_token == true)
{
kit_time_dly_ms(10);
item->ans_call(item, kBootCmd_SndFrame, res);
}
}
else if(item->cmd == kBootCmd_UpdateRes)
{
if((item->rcv_firmware_len == item->firmware_len)
&& (kit_check_crc16((uint8_t *)(item->back_up_addr + APP_CFG_BOOT_FW_DATA_OFFSET), item->rcv_firmware_len) == 0))
{
res = kKit_Ret_Ok;
drv_flash_write_u32(item->flash_item, item->back_up_addr + APP_CFG_BOOT_FW_LENGTH_OFFSET, item->rcv_firmware_len);
drv_flash_write_u32(item->flash_item, item->back_up_addr + APP_CFG_BOOT_FW_UPDATE_TIME_OFFSET, item->update_time);
bsp_head_set_status(item->flash_item, item->back_up_addr, kHeadStatus_Start);
item->step = kBootStep_UpdateEnd;
}
else
{
res = kKit_Ret_CheckErr;
}
kit_time_dly_ms(10);
item->ans_call(item, kBootCmd_UpdateRes, res);
}
break;
case kBootStep_UpdateEnd:
if(item->cmd == kBootCmd_UpdateEnd)
{
//必须复位直接跳转后使用的堆栈是PSP导致软件复位
drv_misc_reset_mcu();
}
break;
default:
break;
}
item->cmd = kBootCmd_None;
}
}
//固件长度> BOOT_SPACE_SIZE - 16 异常
//固件长度为0xFFFFFFFF表示未下载完成断电无需搬运直接跳到应用程序
//固件长度不为0xFFFFFFFF表示固件已经下载到备份区可能未搬运、可能搬运未完成
bool bsp_boot_move_firmware(BootItem *item, uint32_t start_addr, uint32_t max_len)
{
bool res = false;
uint16_t crc;
uint32_t tmp, data = 0xFFFFFFFF;
if(item != NULL)
{
drv_flash_read_u32(item->flash_item, item->back_up_addr + APP_CFG_BOOT_FW_LENGTH_OFFSET, &data);
KIT_ASSERT_PARAM(data < (max_len - APP_CFG_BOOT_FW_DATA_OFFSET));
KIT_DEBUG_PRINTF("GUIDE:need update\r\n");
if((data < (max_len - APP_CFG_BOOT_FW_DATA_OFFSET)) && (kit_check_crc16((uint8_t *)(item->back_up_addr + APP_CFG_BOOT_FW_DATA_OFFSET), data) == 0))
{
bsp_flash_erase_page(item->flash_item, start_addr, data);
tmp = data;
if(data % 4 != 0)
{
tmp += 4 - (data % 4);
}
bsp_flash_write_data_u32(item->flash_item, start_addr, (uint8_t *)(item->back_up_addr + APP_CFG_BOOT_FW_DATA_OFFSET), tmp);
crc = kit_check_crc16((uint8_t *)start_addr, data);
KIT_ASSERT_PARAM(crc == 0);
//todo
if(crc == 0)
{
bsp_head_set_status(item->flash_item, item->back_up_addr, kHeadStatus_Finsih);
res = true;
}
else
{
KIT_DEBUG_PRINTF("GUIDE:crc err\r\n");
}
}
}
return res;
}
uint32_t bsp_boot_get_update_time(BootItem *item)
{
uint32_t tmp = 0;
if((drv_flash_read_u32(item->flash_item, item->back_up_addr + APP_CFG_BOOT_FW_UPDATE_TIME_OFFSET, &tmp) != kKit_Ret_Ok)
|| (tmp == 0xFFFFFFFF))
{
tmp = 0;
}
return tmp;
}