#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; }