forked from gary/BCU
2
0
Fork 0
BCU/library/bsp/bsp_boot.c

264 lines
8.4 KiB
C
Raw Permalink 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.

#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中
*升级模式3中1.不升级,直接跳到应用程序
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;
}