1333 lines
48 KiB
C
1333 lines
48 KiB
C
/*----------------------------------------------------------------------------
|
||
* Copyright (c) Fenda Technologies Co., Ltd. 2021. All rights reserved.
|
||
*
|
||
* Description: 蓝牙文件传输中间层,供蓝牙调用
|
||
*
|
||
* Author: george
|
||
*
|
||
* Create: 2022-10-10
|
||
*--------------------------------------------------------------------------*/
|
||
|
||
#include <string.h>
|
||
|
||
#include "FreeRTOS.h"
|
||
#include "task.h"
|
||
#include "timers.h"
|
||
|
||
#include "am_util_debug.h"
|
||
#include "am_bootloader.h"
|
||
#include "am_multi_boot.h"
|
||
#include "crc32.h"
|
||
#include "amotas_api.h"
|
||
|
||
#include "sys_config.h"
|
||
#include "sys_memory.h"
|
||
#include "ble_data_transmission.h"
|
||
#include "ble_ota_execute.h"
|
||
#include "ble_file_trans.h"
|
||
#include "task_ble.h"
|
||
#include "watchdog_api.h"
|
||
#include "rom_api.h"
|
||
#include "flash_api.h"
|
||
//#include "fs_adapt.h"
|
||
//#include "fs_user_app.h"
|
||
#include "fs_api.h"
|
||
#include "fs_user_init.h"
|
||
#include "user_pack_analysis.h"
|
||
#include "ui_event.h"
|
||
#include "task_ui.h"
|
||
#include "ui_port_resource.h"
|
||
|
||
|
||
#define ENABLE_STATIC_PRINT 0
|
||
extern uint32_t am_util_stdio_printf(const char *pcFmt, ...);
|
||
#define static_print_remind(...) am_util_stdio_printf(__VA_ARGS__)
|
||
#if ENABLE_STATIC_PRINT
|
||
#define static_print_info(...) am_util_stdio_printf(__VA_ARGS__)
|
||
#else
|
||
#define static_print_info(...)
|
||
#endif
|
||
|
||
#define ENABLE_MALLOC_BUFF 0
|
||
|
||
FileTransCtrlBlock_t g_fileTransCtrlBlock;
|
||
|
||
static volatile bool g_file_trans_busy = false;
|
||
//static bool g_file_trans_use_diff = true; //差分传输的标志,false表示不使用差分升级
|
||
static bool g_file_trans_use_diff = false;
|
||
static uint32_t g_file_trans_percent_count = 0;
|
||
static TimerHandle_t g_fileTransOverTimer = NULL;
|
||
static head_desc_parm g_file_trans_head_param = {0};
|
||
static head_struct_parm g_file_trans_head_struct = {0};
|
||
static lfs_file_t g_lfs_file_trans = {0};
|
||
static am_multiboot_flash_info_t *g_file_trans_pFlash = NULL;
|
||
static am_multiboot_flash_info_t g_file_trans_ext_flash = {0};
|
||
|
||
//
|
||
// Data structure for flash operation
|
||
//
|
||
typedef struct
|
||
{
|
||
uint8_t* write_buffer; // needs to be 32-bit word aligned.
|
||
uint16_t buffer_index;
|
||
}file_trans_flash_op_t;
|
||
|
||
file_trans_flash_op_t file_trans_flash_op = {
|
||
.write_buffer = NULL,
|
||
.buffer_index = 0,
|
||
};
|
||
|
||
|
||
static void FileTransOverTimerCallback(TimerHandle_t xTimer);
|
||
static void SaveFileTransFile(void);
|
||
static void LoadFileTransFile(void);
|
||
static OtaUiMsgType GetTransTypeByAction(FileActionType action);
|
||
void switch_to_unix_path(char *path);
|
||
void delete_all_complete_ota_files(void);
|
||
int32_t copy_file_to_rom(void);
|
||
|
||
|
||
/********** 片外flash操作接口 ***********/
|
||
int file_trans_flash_read_func(uint32_t ui32DestAddr, uint32_t *pSrc, uint32_t ui32Length)
|
||
{
|
||
return flash_api_read(ui32DestAddr, pSrc, ui32Length);
|
||
}
|
||
|
||
int file_trans_flash_write_func(uint32_t ui32DestAddr, uint32_t *pSrc, uint32_t ui32Length)
|
||
{
|
||
return flash_api_write(ui32DestAddr, pSrc, ui32Length);
|
||
}
|
||
|
||
int file_trans_flash_erase_func(uint32_t ui32Addr)
|
||
{
|
||
return flash_api_erase(ui32Addr);
|
||
}
|
||
|
||
int file_trans_ext_flash_info_init(am_multiboot_flash_info_t *pFlash)
|
||
{
|
||
pFlash->flashPageSize = flash_api_get_erase_unit_size();
|
||
pFlash->flashSectorSize = flash_api_get_erase_unit_size();
|
||
pFlash->flash_init = NULL;
|
||
pFlash->flash_deinit = NULL;
|
||
pFlash->flash_enable = NULL;
|
||
pFlash->flash_disable = NULL;
|
||
pFlash->flash_read_page = file_trans_flash_read_func;
|
||
pFlash->flash_write_page = file_trans_flash_write_func;
|
||
pFlash->flash_erase_sector = file_trans_flash_erase_func;
|
||
return true;
|
||
}
|
||
/********** 片外flash操作接口 ***********/
|
||
|
||
void FileTransInit(void)
|
||
{
|
||
if (g_fileTransOverTimer == NULL)
|
||
{
|
||
g_fileTransOverTimer = xTimerCreate("fileTransOverTimer", (1000 * 15), false, NULL, FileTransOverTimerCallback);
|
||
}
|
||
LoadFileTransFile();
|
||
}
|
||
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 获取文件传输状态,是否繁忙.
|
||
* @retval true-正在传输文件,false-空闲.
|
||
*****************************************************************************************
|
||
*/
|
||
bool file_trans_busy(void)
|
||
{
|
||
return g_file_trans_busy;
|
||
}
|
||
|
||
void file_trans_start(uint32_t id, char *name, uint32_t size, FileActionType action)
|
||
{
|
||
// g_file_trans_use_diff = false; //for test -- 默认为true, 在此强行赋值为false,用于禁止差分升级
|
||
// memset(&g_fileTransCtrlBlock, 0, sizeof(FileTransCtrlBlock_t));
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_START;
|
||
g_fileTransCtrlBlock.fileId = id;
|
||
// strcpy(g_fileTransCtrlBlock.fileName, name);
|
||
snprintf(g_fileTransCtrlBlock.fileName, sizeof(g_fileTransCtrlBlock.fileName), "%s/%s", DIR_RECEIVED, name);
|
||
switch_to_unix_path(g_fileTransCtrlBlock.fileName);
|
||
g_fileTransCtrlBlock.fileSize = size;
|
||
g_fileTransCtrlBlock.offset = 0;
|
||
g_fileTransCtrlBlock.fileAction = action;
|
||
if (g_file_trans_use_diff == false)
|
||
{
|
||
g_fileTransCtrlBlock.nextPkgSize = FILE_HEAD_INFO_IEN; //必须整除一个flash擦除单元
|
||
}
|
||
else
|
||
{
|
||
// g_fileTransCtrlBlock.nextPkgSize = HEAD_DESC_LEN + HEAD_STRUCT_LEN;
|
||
g_fileTransCtrlBlock.nextPkgSize = flash_api_get_erase_unit_size();
|
||
/* if (g_fileTransCtrlBlock.nextPkgSize < 4096)
|
||
{
|
||
g_fileTransCtrlBlock.nextPkgSize = 4096;
|
||
} */
|
||
}
|
||
g_fileTransCtrlBlock.fsfd = -1;
|
||
g_fileTransCtrlBlock.type = GetTransTypeByAction(action);
|
||
|
||
g_file_trans_percent_count = 101;
|
||
|
||
amota_conn_param_update(CONN_PARAM_OTA); // 使用OTA连接参数
|
||
|
||
if (g_fileTransOverTimer != NULL)
|
||
{
|
||
xTimerStart(g_fileTransOverTimer, 0);
|
||
}
|
||
|
||
task_ui_notify(EVENT_OTA_TRANS_START, 0, NULL, 0);
|
||
}
|
||
|
||
void FileTransSetCrc(uint32_t crc)
|
||
{
|
||
static_print_info("file trans crc=0x%08X\r\n", crc);
|
||
g_fileTransCtrlBlock.crc32 = crc;
|
||
}
|
||
|
||
|
||
void FileTransSetMd5(uint8_t *md5)
|
||
{
|
||
if(memcmp(md5, g_fileTransCtrlBlock.md5, 16) != 0) {
|
||
g_fileTransCtrlBlock.offset = 0;
|
||
g_fileTransCtrlBlock.fsfd = -1;
|
||
static_print_info("different md5\r\n");
|
||
static_print_info("this time md5:");
|
||
for(uint32_t i = 0; i < 16; i++) {
|
||
static_print_info(" %02X", md5[i]);
|
||
}
|
||
static_print_info("\r\n");
|
||
static_print_info("last time md5:");
|
||
for(uint32_t i = 0; i < 16; i++) {
|
||
static_print_info(" %02X", g_fileTransCtrlBlock.md5[i]);
|
||
}
|
||
static_print_info("\r\n");
|
||
}
|
||
memcpy(g_fileTransCtrlBlock.md5, md5, 16);
|
||
static_print_info("file trans md5:");
|
||
for(uint32_t i = 0; i < 16; i++) {
|
||
static_print_info(" %02X", g_fileTransCtrlBlock.md5[i]);
|
||
}
|
||
static_print_info("\r\n");
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 刷新进度条
|
||
*****************************************************************************************
|
||
*/
|
||
static void file_trans_refresh_percent(void)
|
||
{
|
||
uint32_t percent;
|
||
|
||
percent = (g_fileTransCtrlBlock.offset * 100) / g_fileTransCtrlBlock.fileSize;
|
||
if (percent != g_file_trans_percent_count) {
|
||
g_file_trans_percent_count = percent;
|
||
static_print_info("file trans pct=%d%%, %d\r\n", percent, g_fileTransCtrlBlock.offset);
|
||
if ((FileActionType)g_fileTransCtrlBlock.fileAction != FILE_ACTION_WATCHFACE) {
|
||
task_ui_notify(EVENT_OTA_TRANSMITTING, g_file_trans_percent_count, NULL, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 根据固件头信息判断是否需要续传
|
||
*****************************************************************************************
|
||
*/
|
||
static int32_t file_trans_handle_resume(const uint8_t *data, uint32_t length, const char *file_name)
|
||
{
|
||
const char *path = NULL;
|
||
int32_t file_size = 0;
|
||
char *buffer = NULL;
|
||
uint32_t read_len = 0;
|
||
int ret = 0;
|
||
bool is_dir = false;
|
||
head_desc_parm head_desc_temp;
|
||
head_struct_parm head_struct_temp;
|
||
|
||
if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_FILE)
|
||
{
|
||
// path = pvPortMalloc(128);
|
||
// snprintf(path, 128, "%s/%s", DIR_RECEIVED, g_fileTransCtrlBlock.fileName);
|
||
path = file_name;
|
||
file_size = fs_api_stat(path, &is_dir);
|
||
if (file_size <= 0 || is_dir)
|
||
{
|
||
static_print_info("No need to resume because NO THIS FILE.\r\n");
|
||
// vPortFree(path);
|
||
return 0;
|
||
}
|
||
read_len = HEAD_DESC_LEN + HEAD_STRUCT_LEN;
|
||
static_print_info("FSStat(%s)=%d\r\n", path, file_size);
|
||
if(file_size < (read_len + MCU_ROM_PAGE_SIZE))
|
||
{
|
||
static_print_info("No need to resume trans because the size.\r\n");
|
||
// vPortFree(path);
|
||
return 0;
|
||
}
|
||
else
|
||
{
|
||
static_print_info("file_size=%d\r\n", file_size);
|
||
buffer = pvPortMalloc(read_len + 1);
|
||
if(buffer==NULL)
|
||
{
|
||
static_print_remind("pvPortMalloc fail.%s\r\n", path);
|
||
return 0;
|
||
}
|
||
fs_api_file_load(path, 0, buffer, read_len);
|
||
buffer[read_len] = 0;
|
||
}
|
||
if(user_pack_json_head(buffer, &head_desc_temp, &head_struct_temp)==false)
|
||
{
|
||
ret = 0;
|
||
}
|
||
else if(head_desc_temp.pack_len == g_file_trans_head_param.pack_len
|
||
&& head_struct_temp.file_crc32 == g_file_trans_head_struct.file_crc32
|
||
)
|
||
{
|
||
g_fileTransCtrlBlock.fileSize = head_desc_temp.pack_len;
|
||
ret = file_size;
|
||
}
|
||
static_print_info("pack_len = %d.crc32_desc = %d.crc32_detail = %d\r\n",
|
||
head_desc_temp.pack_len,head_struct_temp.file_crc32,head_desc_temp.crc32_detail);
|
||
// vPortFree(path);
|
||
vPortFree(buffer);
|
||
}
|
||
else if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_ADDR)
|
||
{
|
||
static_print_info("resume crc32 = %x, fileSize = %x\r\n", g_fileTransCtrlBlock.file_resume_crc32, g_fileTransCtrlBlock.file_resume_size);
|
||
static_print_info("file crc32 = %x, fileSize = %x\r\n", g_file_trans_head_struct.file_crc32, g_file_trans_head_struct.file_size);
|
||
if(g_file_trans_head_param.pack_len == g_fileTransCtrlBlock.file_resume_size
|
||
&& g_file_trans_head_struct.file_crc32 == g_fileTransCtrlBlock.file_resume_crc32)
|
||
{
|
||
g_fileTransCtrlBlock.fileSize = g_file_trans_head_param.pack_len;
|
||
if(g_fileTransCtrlBlock.file_resume_offset > MCU_ROM_PAGE_SIZE)
|
||
{
|
||
ret = g_fileTransCtrlBlock.file_resume_offset;
|
||
}
|
||
}
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
static int process_file_head(uint8_t* data, uint32_t length)
|
||
{
|
||
int ret = 0;
|
||
|
||
ret = user_pack_json_head((char *)data, &g_file_trans_head_param, &g_file_trans_head_struct);
|
||
am_util_stdio_printf("process file head dest_addr = %x - %d, h_len = %d - %d - %d, struct_len = %d- %d - %x\r\n",
|
||
g_file_trans_head_struct.dest_addr, length,
|
||
g_file_trans_head_param.h_len, g_file_trans_head_param.pack_len, g_file_trans_head_param.ext_offset,
|
||
g_file_trans_head_param.struct_len, g_file_trans_head_param.struct_offset, g_file_trans_head_struct.file_crc32);
|
||
if(ret == false)
|
||
{
|
||
return FILE_ILLEGAL_ERR; // 非法固件
|
||
}
|
||
|
||
if(g_file_trans_head_param.mark != MARK_ALL_IN_ONE
|
||
&& g_file_trans_head_param.mark != MARK_MORE_THAN_ONE
|
||
&& g_file_trans_head_struct.dest_cs != FILE_SOUR_CS_FS)
|
||
{// 固件不以文件的形式存储,须初始化flash操作接口
|
||
g_fileTransCtrlBlock.file_storage_cs = STORAGE_IN_ADDR;
|
||
if(g_file_trans_head_struct.dest_cs == FILE_SOUR_CS_FLASH)
|
||
{// 片外升级
|
||
static_print_info("FILE_SOUR_CS_FLASH\r\n");
|
||
if(g_file_trans_head_param.mark == MARK_MCU_FW_BIN) // is a run image
|
||
{
|
||
if(g_file_trans_head_struct.file_size > MAX_IMAGE_SIZE)
|
||
{
|
||
return FILE_ILLEGAL_ERR;
|
||
}
|
||
}
|
||
file_trans_ext_flash_info_init(&g_file_trans_ext_flash);
|
||
g_file_trans_pFlash = &g_file_trans_ext_flash;
|
||
static_print_info("flashPageSize = %d\r\n", g_file_trans_pFlash->flashPageSize);
|
||
}
|
||
else if(g_file_trans_head_struct.dest_cs == FILE_SOUR_CS_ROM)
|
||
{// 片内升级
|
||
static_print_info("FILE_SOUR_CS_ROM\r\n");
|
||
// Check to make sure the incoming image will fit in the space allocated for OTA
|
||
if (g_file_trans_head_struct.file_size > AMOTA_INT_FLASH_OTA_MAX_SIZE)
|
||
{
|
||
return FILE_ILLEGAL_ERR;
|
||
}
|
||
g_file_trans_pFlash = &g_intFlash;
|
||
static_print_info("flashPageSize = %d\r\n", g_file_trans_pFlash->flashPageSize);
|
||
}
|
||
else
|
||
{// 其他存储模式暂不支持
|
||
return FILE_ILLEGAL_ERR;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
g_fileTransCtrlBlock.file_storage_cs = STORAGE_IN_FILE;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static uint8_t _file_trans_temp_buff[4096 + 16] = {0}; //必须要比4096多加8个字节或以上
|
||
static int check_file_crc32_and_init_crc16_area(void) //add by hes.hezhao -- 差分升级增加的代码
|
||
{
|
||
return FILE_NO_DIFF_CONTENT_TRANS;
|
||
}
|
||
|
||
static int check_file_crc16_area_and_redirect_offset(void) //add by hes.hezhao -- 差分升级增加的代码
|
||
{
|
||
return FILE_NO_DIFF_CONTENT_TRANS;
|
||
}
|
||
|
||
static int check_file_trans_succ_crc32(const char *path, uint8_t type, uint8_t cs) //add by hes.hezhao -- 差分升级增加的代码
|
||
{
|
||
// const char *path = g_fileTransCtrlBlock.fileName;
|
||
uint32_t base_addr = g_file_trans_head_struct.dest_addr;
|
||
|
||
if (g_file_trans_use_diff == false)
|
||
{
|
||
#if 0
|
||
void ate_user_function_test(uint8_t *factory_data, uint16_t len);
|
||
uint8_t ate_param[14] = {0xFD, 0x01, 0x0, 0x27, 0x01, 0x07, 0x10, 0x02, 0x05, 0x0, 0x0, 0x0, 0x0, 0x0};
|
||
uint32_t file_size = g_file_trans_head_struct.file_size + (HEAD_DESC_LEN + HEAD_STRUCT_LEN);
|
||
ate_param[9] = file_size >> 24;
|
||
ate_param[10] = file_size >> 16;
|
||
ate_param[11] = file_size >> 8;
|
||
ate_param[12] = file_size;
|
||
ate_user_function_test(ate_param, sizeof(ate_param));
|
||
#endif
|
||
|
||
return FILE_NO_DIFF_CONTENT_TRANS;
|
||
}
|
||
|
||
if (type == OTA_UI_TRANS_IMAGE) //图片资源
|
||
{
|
||
int32_t ret;
|
||
uint8_t *temp_buff = _file_trans_temp_buff;
|
||
uint16_t temp_len = 4096;
|
||
uint16_t head_size = HEAD_DESC_LEN + HEAD_STRUCT_LEN;
|
||
uint32_t temp_crc32 = 0;
|
||
uint32_t proc_size = 0;
|
||
uint32_t ctx_len = g_file_trans_head_struct.file_size; //(g_fileTransCtrlBlock.fileSize - head_size) == g_file_trans_head_struct.file_size
|
||
|
||
am_util_stdio_printf("start calc file crc32, base_addr = %x -- file size = %d \r\n", base_addr, ctx_len);
|
||
watchdog_api_feed();
|
||
while (proc_size < ctx_len)
|
||
{
|
||
if ((ctx_len - proc_size) < temp_len)
|
||
{
|
||
temp_len = ctx_len - proc_size;
|
||
}
|
||
if (cs == STORAGE_IN_FILE)
|
||
{
|
||
ret = fs_api_file_load(path, head_size + proc_size, temp_buff, temp_len);
|
||
}
|
||
else //STORAGE_IN_ADDR
|
||
{
|
||
// ret = g_file_trans_pFlash->flash_read_page(base_addr + head_size + proc_size, (uint32_t *)temp_buff, temp_len);
|
||
ret = flash_api_read(base_addr + head_size + proc_size, temp_buff, temp_len); //目前只针对保存片外的文件作差分升级处理
|
||
}
|
||
if (ret < 0)
|
||
{
|
||
// break;
|
||
}
|
||
temp_crc32 = crc32_ex(temp_crc32, temp_buff, temp_len);
|
||
proc_size += temp_len;
|
||
if (proc_size % (128 * 1024) == 0) //喂狗
|
||
{
|
||
watchdog_api_feed();
|
||
}
|
||
}
|
||
am_util_stdio_printf("base_addr: 0x%x -- temp_crc32: 0x%x \r\n", base_addr, temp_crc32);
|
||
if (temp_crc32 != g_file_trans_head_struct.file_crc32)
|
||
{
|
||
am_util_stdio_printf("calc crc32 != g_file_trans_head_struct.file_crc32\n");
|
||
return FILE_WRITE_PKG_FILE_ERR;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
void file_trans_set_diff_content_trans_flag(bool flag)
|
||
{
|
||
g_file_trans_use_diff = flag;
|
||
}
|
||
|
||
bool file_trans_get_diff_content_trans_flag(void)
|
||
{
|
||
return g_file_trans_use_diff;
|
||
}
|
||
|
||
uint8_t* file_trans_get_temp_buff_para(uint16_t* buff_size_p)
|
||
{
|
||
if (buff_size_p != NULL)
|
||
{
|
||
*buff_size_p = sizeof(_file_trans_temp_buff) - 4;
|
||
}
|
||
return _file_trans_temp_buff;
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief Verify the currently written data
|
||
*****************************************************************************************
|
||
*/
|
||
static int file_trans_verify_flash_content(uint32_t flashAddr, uint8_t *source, uint32_t len, am_multiboot_flash_info_t *pFlash)
|
||
{
|
||
// read back and check
|
||
uint32_t remaining = len;
|
||
int ret = 0;
|
||
|
||
if(remaining < g_file_trans_pFlash->flashPageSize)
|
||
{
|
||
remaining = g_file_trans_pFlash->flashPageSize;
|
||
}
|
||
|
||
uint8_t* verify_buff = pvPortMalloc(remaining);
|
||
if(verify_buff == NULL)
|
||
{
|
||
return -1;
|
||
}
|
||
|
||
ret = pFlash->flash_read_page(flashAddr, (uint32_t *)verify_buff, remaining);
|
||
|
||
ret = memcmp(verify_buff, source, remaining);
|
||
if ( ret != 0 )
|
||
{
|
||
// there is write failure happened.
|
||
static_print_info("\r\n??????flash write verify failed. address = 0x%x. length = %d????? \r\n", flashAddr, len);
|
||
}
|
||
vPortFree(verify_buff);
|
||
return ret;
|
||
}
|
||
|
||
static int file_write_to_flash(uint8_t *buf, uint16_t len, uint32_t addr)
|
||
{
|
||
if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_FILE)
|
||
{
|
||
int ret = 0;
|
||
/* 若后续解决flash擦写失败问题,不用每次都打开文件再写入 */
|
||
const char *path = g_fileTransCtrlBlock.fileName;
|
||
uint8_t num = 10;
|
||
do{
|
||
//ret = fs_api_file_oft_write(&g_lfs_file_trans, g_fileTransCtrlBlock.offset, buf, len);// 由于出现文件写失败后,无法再操作文件,暂不使用fs_api_file_oft_write接口
|
||
ret = fs_api_file_store(path, g_fileTransCtrlBlock.offset, buf, len);
|
||
if (ret != len)
|
||
{
|
||
vTaskDelay(100);
|
||
num --;
|
||
static_print_info("\r\n write failed occur!!!! ret = %d. num = %d \r\n", ret, num);
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}while(num > 0);
|
||
if(num == 0)
|
||
{
|
||
static_print_info("\r\n\r\n ?????? try 9 times file_trans_write_pkg -> write failed!!! ?????\r\n\r\n");
|
||
return FILE_WRITE_PKG_FILE_ERR;
|
||
}
|
||
}
|
||
else if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_ADDR)
|
||
{
|
||
uint16_t bytes_remaining = len;
|
||
uint32_t target_address = 0;
|
||
uint16_t bytes_to_write = 0;
|
||
uint8_t page_count = 0;
|
||
uint8_t indx = 0;
|
||
|
||
addr -= file_trans_flash_op.buffer_index;
|
||
if (addr & (g_file_trans_pFlash->flashPageSize - 1))
|
||
{
|
||
static_print_info(" application is trying to write to wrong address addr = %x\n",addr);
|
||
return FILE_ILLEGAL_ERR;
|
||
}
|
||
|
||
while (bytes_remaining)
|
||
{
|
||
bytes_to_write = g_file_trans_pFlash->flashPageSize - file_trans_flash_op.buffer_index;
|
||
if (bytes_to_write > bytes_remaining)
|
||
{
|
||
bytes_to_write = bytes_remaining;
|
||
}
|
||
|
||
// move data into buffer
|
||
memcpy(file_trans_flash_op.write_buffer, buf, bytes_to_write);
|
||
file_trans_flash_op.buffer_index += bytes_to_write;
|
||
|
||
bytes_remaining -= bytes_to_write;
|
||
buf += bytes_to_write;
|
||
//
|
||
// Write to flash when there is data more than 1 page size
|
||
// For last fragment write even if it is less than one page.
|
||
//
|
||
if((g_fileTransCtrlBlock.fileSize == (g_fileTransCtrlBlock.offset + len))
|
||
|| (file_trans_flash_op.buffer_index == g_file_trans_pFlash->flashPageSize))
|
||
{
|
||
target_address = addr + (page_count * g_file_trans_pFlash->flashPageSize);
|
||
for(indx = 0; indx < 3; indx++)
|
||
{
|
||
if(g_file_trans_pFlash->flash_erase_sector(target_address) == 0)
|
||
{
|
||
g_file_trans_pFlash->flash_write_page(target_address, (uint32_t *)file_trans_flash_op.write_buffer, g_file_trans_pFlash->flashPageSize);
|
||
if(file_trans_verify_flash_content(target_address, file_trans_flash_op.write_buffer, file_trans_flash_op.buffer_index, g_file_trans_pFlash) == 0)
|
||
{
|
||
static_print_info("Flash write succeeded to address 0x%x. length %d\n", target_address, file_trans_flash_op.buffer_index);
|
||
page_count++;
|
||
file_trans_flash_op.buffer_index = 0;
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
static_print_remind("\r\n\r\n\n\nFlash verify failed to address: 0x%x. indx = %d\r \n", target_address, indx);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
static_print_remind("\r\n\r\n\n\nFlash erase sector failed to address: 0x%x. indx = %d\r\n", target_address, indx);
|
||
}
|
||
vTaskDelay(100);
|
||
}
|
||
if(indx >= 3)
|
||
{
|
||
static_print_remind("try 3 times to write flash, but all failed\r\n");
|
||
return FILE_WRITE_PKG_FILE_ERR;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int file_write_to_storage(uint8_t *buf, uint16_t len, uint32_t addr)
|
||
{
|
||
if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_FILE)
|
||
{
|
||
int32_t ret = 0;
|
||
/* 若后续解决flash擦写失败问题,不用每次都打开文件再写入 */
|
||
const char *path = g_fileTransCtrlBlock.fileName;
|
||
uint8_t num = 10;
|
||
|
||
do{
|
||
//ret = fs_api_file_oft_write(&g_lfs_file_trans, g_fileTransCtrlBlock.offset, buf, len);// 由于出现文件写失败后,无法再操作文件,暂不使用fs_api_file_oft_write接口
|
||
ret = fs_api_file_store(path, g_fileTransCtrlBlock.offset, buf, len);
|
||
if (ret != len)
|
||
{
|
||
vTaskDelay(100);
|
||
num --;
|
||
static_print_info("\r\n write failed occur!!!! ret = %d. num = %d \r\n\r\n", ret, num);
|
||
}
|
||
else
|
||
{
|
||
break;
|
||
}
|
||
}while(num > 0);
|
||
if(num == 0)
|
||
{
|
||
static_print_info("\r\n ?????? try 9 times file_trans_write_pkg -> write failed!!! ????? \r\n\r\n");
|
||
return FILE_WRITE_PKG_FILE_ERR;
|
||
}
|
||
}
|
||
else if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_ADDR)
|
||
{
|
||
int32_t ret = 0;
|
||
uint16_t bytes_remaining = len;
|
||
uint32_t target_address = 0;
|
||
uint16_t bytes_to_write = 0;
|
||
uint16_t write_count = 0;
|
||
uint8_t indx = 0;
|
||
|
||
if (addr & (g_file_trans_pFlash->flashPageSize - 1))
|
||
{
|
||
am_util_stdio_printf(" application is trying to write to wrong address addr = %x\r\n", addr);
|
||
return FILE_ILLEGAL_ERR;
|
||
}
|
||
|
||
while (bytes_remaining)
|
||
{
|
||
target_address = addr + write_count;
|
||
// if ((len > g_file_trans_pFlash->flashPageSize) && (target_address == 0) && (target_address % g_file_trans_pFlash->flashPageSize) != 0)
|
||
if ((target_address % g_file_trans_pFlash->flashPageSize) != 0)
|
||
{
|
||
// static_print_info("target_address = %x\r\n", target_address);
|
||
bytes_to_write = g_file_trans_pFlash->flashPageSize - (target_address % g_file_trans_pFlash->flashPageSize);
|
||
// static_print_info("bytes_to_write = %x\r\n", bytes_to_write);
|
||
}
|
||
else if (bytes_remaining >= g_file_trans_pFlash->flashPageSize)
|
||
{
|
||
bytes_to_write = g_file_trans_pFlash->flashPageSize;
|
||
}
|
||
else
|
||
{
|
||
bytes_to_write = bytes_remaining;
|
||
// static_print_info("bytes_to_write = %x\r\n", bytes_to_write);
|
||
#if 1 //后一半数据将被擦掉,先读取出来暂存
|
||
if (write_count > 0)
|
||
{
|
||
g_file_trans_pFlash->flash_read_page(target_address + bytes_to_write,
|
||
(uint32_t *)_file_trans_temp_buff, g_file_trans_pFlash->flashPageSize - bytes_to_write);
|
||
}
|
||
#endif
|
||
}
|
||
ret = 0;
|
||
// for(indx = 0; indx < 2; indx++)
|
||
for(indx = 0; indx < 1; indx++)
|
||
{
|
||
if ((target_address % g_file_trans_pFlash->flashPageSize) == 0)
|
||
{
|
||
ret = g_file_trans_pFlash->flash_erase_sector(target_address);
|
||
}
|
||
if (ret == 0)
|
||
{
|
||
ret = g_file_trans_pFlash->flash_write_page(target_address, (uint32_t *)buf, bytes_to_write);
|
||
if (ret >= 0)
|
||
{
|
||
#if 1 //擦除操作后,将暂存的数据写回去
|
||
if (bytes_to_write == bytes_remaining && write_count > 0)
|
||
{
|
||
g_file_trans_pFlash->flash_write_page(target_address + bytes_to_write,
|
||
(uint32_t *)_file_trans_temp_buff, g_file_trans_pFlash->flashPageSize - bytes_to_write);
|
||
}
|
||
#endif
|
||
break;
|
||
}
|
||
am_util_stdio_printf("\r\nFlash write failed to address: 0x%x. indx = %d\r\n\r\n", target_address, indx);
|
||
}
|
||
else
|
||
{
|
||
am_util_stdio_printf("\r\nFlash erase failed to address: 0x%x. indx = %d\r\n\r\n", target_address, indx);
|
||
}
|
||
vTaskDelay(100);
|
||
}
|
||
// if(indx >= 2)
|
||
if(indx >= 1)
|
||
{
|
||
am_util_stdio_printf("try 3 times to write flash, but all failed\r\n\r\n");
|
||
return FILE_WRITE_PKG_FILE_ERR;
|
||
}
|
||
write_count += bytes_to_write;
|
||
buf += bytes_to_write;
|
||
bytes_remaining -= bytes_to_write;
|
||
}
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 写入一包数据,返回下一包请求大小
|
||
*****************************************************************************************
|
||
*/
|
||
int32_t file_trans_write_pkg(uint8_t *data, uint32_t length)
|
||
{
|
||
uint16_t psn = 0;
|
||
int ret = 0;
|
||
int32_t resume_file_size = 0;
|
||
|
||
//判断重复包。如果是重复包,参数不变重新请求
|
||
psn = (data[1] << 8) + data[2];
|
||
if (psn != g_fileTransCtrlBlock.psn)
|
||
{
|
||
static_print_info("rcv psn=%d,expected psn=%d\r\n", psn, g_fileTransCtrlBlock.psn);
|
||
return FILE_WRITE_PKG_NO_REQUEST;
|
||
}
|
||
|
||
g_fileTransCtrlBlock.nextPkgSize = FILE_TRANS_PKG_SIZE;
|
||
if (g_fileTransCtrlBlock.offset > g_fileTransCtrlBlock.fileSize)
|
||
{
|
||
static_print_info("file trans offset error,offset=%d,fileSize=%d\r\n", g_fileTransCtrlBlock.offset, g_fileTransCtrlBlock.fileSize);
|
||
return FILE_WRITE_PKG_NO_REQUEST;
|
||
}
|
||
|
||
if (g_fileTransCtrlBlock.state == FILE_TRANS_STATE_CANCEL)
|
||
{
|
||
static_print_info("file trans canceled,do not request anymore\r\n");
|
||
return FILE_WRITE_PKG_NO_REQUEST;
|
||
}
|
||
|
||
if (g_fileTransCtrlBlock.state == FILE_TRANS_STATE_IDLE)
|
||
{
|
||
static_print_info("file trans idle,invalid request\r\n");
|
||
return FILE_WRITE_PKG_NO_REQUEST;
|
||
}
|
||
if (g_fileTransCtrlBlock.state == FILE_TRANS_STATE_START)
|
||
{
|
||
ret = process_file_head(data + 3, length - 3);
|
||
if (ret != 0) {
|
||
static_print_info("process_file_head error ret=%d\r\n", ret);
|
||
return ret;
|
||
}
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_TRANS;
|
||
|
||
/* 判断设备是否已有此固件 */
|
||
//根据相应固件名的crc以及版本号判断,后续添加
|
||
#if 1 //add by hes.hezhao -- 差分升级增加的代码
|
||
ret = check_file_crc32_and_init_crc16_area();
|
||
if (ret == FILE_WRITE_PKG_COMPLETE)
|
||
{
|
||
g_fileTransCtrlBlock.nextPkgSize = 0;
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_IDLE;
|
||
}
|
||
#endif
|
||
|
||
/* 判断是否需要续传 */
|
||
if (g_fileTransCtrlBlock.psn > 0 && g_fileTransCtrlBlock.nextPkgSize > 0)
|
||
{
|
||
resume_file_size = file_trans_handle_resume(data, length, g_fileTransCtrlBlock.fileName);
|
||
}
|
||
if (resume_file_size > 0 && resume_file_size == g_fileTransCtrlBlock.fileSize)
|
||
{
|
||
static_print_info("file already exists\r\n");
|
||
if (g_fileTransCtrlBlock.fsfd >= 0) {
|
||
fs_api_file_close(&g_lfs_file_trans);
|
||
static_print_info("trans file closed\r\n");
|
||
}
|
||
g_fileTransCtrlBlock.nextPkgSize = 0;
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_IDLE;
|
||
}
|
||
else if (resume_file_size > 0 && resume_file_size < g_fileTransCtrlBlock.fileSize)
|
||
{
|
||
static_print_info("rusume file trans,size=%d,total=%d\r\n", resume_file_size, g_fileTransCtrlBlock.fileSize);
|
||
g_fileTransCtrlBlock.offset = resume_file_size;
|
||
g_fileTransCtrlBlock.lastOffset = g_fileTransCtrlBlock.offset;
|
||
// if (g_fileTransCtrlBlock.fileSize - g_fileTransCtrlBlock.offset < FILE_TRANS_PKG_SIZE) {
|
||
// g_fileTransCtrlBlock.nextPkgSize = g_fileTransCtrlBlock.fileSize - g_fileTransCtrlBlock.offset;
|
||
// }
|
||
g_fileTransCtrlBlock.fsfd = -2;
|
||
// g_fileTransCtrlBlock.psn++;
|
||
// g_fileTransCtrlBlock.state = FILE_TRANS_STATE_TRANS;
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_WAIT;
|
||
}
|
||
else
|
||
{
|
||
static_print_info("Block.fileSize=%d,pack_len=%d\r\n", g_fileTransCtrlBlock.fileSize, g_file_trans_head_param.pack_len);
|
||
if (g_fileTransCtrlBlock.fileSize > 256 && g_fileTransCtrlBlock.fileSize != g_file_trans_head_param.pack_len)
|
||
{
|
||
static_print_info("new file\r\n");
|
||
#if 0
|
||
delete_all_complete_ota_files();
|
||
#else
|
||
if (g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_FILE) {
|
||
delete_all_complete_ota_files();
|
||
}
|
||
#endif
|
||
}
|
||
g_fileTransCtrlBlock.fileSize = g_file_trans_head_param.pack_len;
|
||
}
|
||
|
||
// 申请8kflash操作缓存
|
||
if (g_file_trans_use_diff == false)
|
||
{
|
||
#if (ENABLE_MALLOC_BUFF)
|
||
if (file_trans_flash_op.write_buffer == NULL)
|
||
{
|
||
file_trans_flash_op.write_buffer = pvPortMalloc(MCU_ROM_PAGE_SIZE);
|
||
}
|
||
#else
|
||
file_trans_flash_op.write_buffer = otaFlashOp.writeBuffer; //8KB
|
||
#endif
|
||
file_trans_flash_op.buffer_index = 0;
|
||
if (file_trans_flash_op.write_buffer == NULL)
|
||
{
|
||
return FILE_TEMP_MEM_APY_ERR;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if(file_trans_flash_op.write_buffer != NULL)
|
||
{
|
||
#if (ENABLE_MALLOC_BUFF)
|
||
vPortFree(file_trans_flash_op.write_buffer);
|
||
#endif
|
||
file_trans_flash_op.write_buffer = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (g_fileTransCtrlBlock.state == FILE_TRANS_STATE_TRANS)
|
||
{
|
||
if (g_file_trans_use_diff == false)
|
||
{
|
||
ret = file_write_to_flash(data + 3, length - 3, g_file_trans_head_struct.dest_addr + g_fileTransCtrlBlock.offset);
|
||
}
|
||
else
|
||
{
|
||
ret = file_write_to_storage(data + 3, length - 3, g_file_trans_head_struct.dest_addr + g_fileTransCtrlBlock.offset);
|
||
}
|
||
if (ret != 0)
|
||
{
|
||
static_print_info("file_write_to_flash error ret=%d\r\n", ret);
|
||
return ret;
|
||
}
|
||
g_fileTransCtrlBlock.offset += (length - 3);
|
||
g_fileTransCtrlBlock.lastOffset = g_fileTransCtrlBlock.offset;
|
||
if(g_fileTransCtrlBlock.fileSize - g_fileTransCtrlBlock.offset < FILE_TRANS_PKG_SIZE)
|
||
{
|
||
g_fileTransCtrlBlock.nextPkgSize = g_fileTransCtrlBlock.fileSize - g_fileTransCtrlBlock.offset;
|
||
}
|
||
|
||
#if 1 //add by hes.hezhao -- 差分升级增加的代码
|
||
ret = check_file_crc16_area_and_redirect_offset();
|
||
if (ret == FILE_WRITE_PKG_COMPLETE)
|
||
{
|
||
g_fileTransCtrlBlock.nextPkgSize = 0;
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_IDLE;
|
||
}
|
||
#endif
|
||
}
|
||
|
||
file_trans_refresh_percent();
|
||
|
||
if (g_fileTransOverTimer != NULL)
|
||
{
|
||
xTimerReset(g_fileTransOverTimer, 0);
|
||
}
|
||
|
||
if (g_fileTransCtrlBlock.nextPkgSize == 0)
|
||
{ //文件已传输完毕
|
||
static_print_info("trans file finish\r\n");
|
||
if (g_fileTransCtrlBlock.fsfd >= 0)
|
||
{
|
||
fs_api_file_close(&g_lfs_file_trans);
|
||
g_fileTransCtrlBlock.fsfd = -1;
|
||
static_print_info("trans file closed\r\n");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
g_fileTransCtrlBlock.psn++;
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_TRANS;
|
||
}
|
||
|
||
return g_fileTransCtrlBlock.nextPkgSize;
|
||
}
|
||
|
||
FileTransCtrlBlock_t* file_trans_get_ctrl_block_ptr(void)
|
||
{
|
||
return &g_fileTransCtrlBlock;
|
||
}
|
||
|
||
void file_trans_get_ctrl_block(FileTransCtrlBlock_t *ctrl)
|
||
{
|
||
memcpy(ctrl, &g_fileTransCtrlBlock, sizeof(FileTransCtrlBlock_t));
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 该文件传输成功
|
||
* @note 若后续支持拆分升级,须在此函数中保存此文件的偏移,以及多文件的总大小等参数
|
||
*****************************************************************************************
|
||
*/
|
||
void file_trans_succ(void)
|
||
{
|
||
char path_filename[128] = {0};
|
||
// uint16_t file_action = 0;
|
||
uint8_t storage_cs = 0;
|
||
uint8_t file_type = 0;
|
||
|
||
if (g_fileTransOverTimer != NULL)
|
||
{
|
||
xTimerStop(g_fileTransOverTimer, 0);
|
||
}
|
||
|
||
g_file_trans_busy = false;
|
||
|
||
static_print_info("FileTransSucc\n");
|
||
strncpy(path_filename, g_fileTransCtrlBlock.fileName, sizeof(path_filename) - 2);
|
||
// file_action = g_fileTransCtrlBlock.fileAction;
|
||
storage_cs = g_fileTransCtrlBlock.file_storage_cs;
|
||
file_type = g_fileTransCtrlBlock.type;
|
||
memset(&g_fileTransCtrlBlock, 0, sizeof(FileTransCtrlBlock_t));
|
||
SaveFileTransFile(); //清空并保存文件传输参数
|
||
|
||
if(file_trans_flash_op.write_buffer != NULL)
|
||
{
|
||
#if (ENABLE_MALLOC_BUFF)
|
||
vPortFree(file_trans_flash_op.write_buffer);
|
||
#endif
|
||
file_trans_flash_op.write_buffer = NULL;
|
||
}
|
||
|
||
if(storage_cs == STORAGE_IN_FILE)
|
||
{
|
||
//task_ui_notify(EVENT_OTA_INSTALLING, 0, NULL, 0);
|
||
user_pack_analysis_dir(DIR_PACK);
|
||
}
|
||
else if(g_file_trans_head_param.mark == MARK_MCU_FW_BIN)
|
||
{
|
||
user_update_ota_info(&g_file_trans_head_struct, &g_file_trans_head_param);
|
||
// task_ble_notify(BLE_RESET_AFTER_OTA_MSG, 0);
|
||
}
|
||
else if(g_file_trans_head_param.mark == MARK_PASS_THROUGH_BIN)
|
||
{
|
||
if(g_file_trans_head_struct.sour_cs == FILE_SOUR_CS_ROM)
|
||
{
|
||
copy_file_to_rom();
|
||
}
|
||
}
|
||
|
||
amota_conn_param_update(CONN_PARAM_LOW_POWER);
|
||
|
||
#if 0 //add by hes.hezhao -- 差分升级增加的代码
|
||
int32_t ret = check_file_trans_succ_crc32(path_filename, file_type, storage_cs);
|
||
if(ret < 0)
|
||
{
|
||
static_print_info("EVENT_OTA_FAIL\n");
|
||
}
|
||
/* if (file_action != FILE_ACTION_WATCHFACE)
|
||
{
|
||
task_ui_notify(EVENT_OTA_TRANSMITTING, 100, NULL, 0);
|
||
} */
|
||
#endif
|
||
task_ui_notify(EVENT_OTA_SUCCESS, 0, NULL, 0);
|
||
task_ble_notify(BLE_RESET_AFTER_OTA_MSG, 0);
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 文件传输异常处理
|
||
*****************************************************************************************
|
||
*/
|
||
void file_trans_break(bool save_flag)
|
||
{
|
||
static_print_info("file trans break\r\n");
|
||
task_ui_notify(EVENT_OTA_FAIL, 0, NULL, 0);
|
||
if(file_trans_flash_op.write_buffer != NULL)
|
||
{
|
||
#if (ENABLE_MALLOC_BUFF)
|
||
vPortFree(file_trans_flash_op.write_buffer);
|
||
#endif
|
||
file_trans_flash_op.write_buffer = NULL;
|
||
}
|
||
if (g_fileTransCtrlBlock.fsfd >= 0)
|
||
{
|
||
fs_api_file_close(&g_lfs_file_trans);
|
||
g_fileTransCtrlBlock.fsfd = -2;
|
||
static_print_info("trans file closed\r\n");
|
||
}
|
||
//处理此情形:文件接收完毕,但未接收到APP发送的4.11.9指令,导致原因可能为蓝牙断连或者APP程序奔溃等
|
||
if ((g_fileTransCtrlBlock.nextPkgSize == 0 && g_fileTransCtrlBlock.lastOffset == g_fileTransCtrlBlock.fileSize) || !save_flag) {
|
||
// char path[128] = {0};
|
||
// snprintf(path, 128, "%s/%s", DIR_RECEIVED, g_fileTransCtrlBlock.fileName);
|
||
const char *path = g_fileTransCtrlBlock.fileName;
|
||
fs_api_unlink(path);
|
||
memset(&g_fileTransCtrlBlock, 0, sizeof(FileTransCtrlBlock_t));
|
||
}
|
||
//memset(&g_fileTransCtrlBlock, 0, sizeof(FileTransCtrlBlock_t));
|
||
if(g_fileTransCtrlBlock.state == FILE_TRANS_STATE_TRANS && g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_ADDR)
|
||
{
|
||
g_fileTransCtrlBlock.file_resume_crc32 = g_file_trans_head_struct.file_crc32;
|
||
g_fileTransCtrlBlock.file_resume_offset = g_fileTransCtrlBlock.offset;
|
||
g_fileTransCtrlBlock.file_resume_size = g_file_trans_head_param.pack_len;
|
||
static_print_info("crc32 = %x, offset = %x, fileSize = %x\r\n",g_file_trans_head_struct.file_crc32,
|
||
g_fileTransCtrlBlock.offset, g_file_trans_head_struct.file_size);
|
||
}
|
||
g_fileTransCtrlBlock.state = FILE_TRANS_STATE_IDLE;
|
||
SaveFileTransFile();
|
||
g_file_trans_busy = false;
|
||
task_ui_notify(EVENT_OTA_FAIL, 0, NULL, 0);
|
||
if(g_fileTransCtrlBlock.file_storage_cs == STORAGE_IN_FILE)
|
||
{// 目前由于flash bug原因,文件传输失败后,不能再操作文件,古重启解决
|
||
task_ble_notify(BLE_RESET_AFTER_OTA_MSG, 0);
|
||
}
|
||
}
|
||
|
||
void FileTransDisconn(void)
|
||
{
|
||
if (g_fileTransOverTimer != NULL)
|
||
{
|
||
if(!xTimerIsTimerActive(g_fileTransOverTimer))
|
||
{
|
||
return;
|
||
}
|
||
xTimerStop(g_fileTransOverTimer, 0);
|
||
}
|
||
task_ble_notify(BLE_SAVE_TRANS_FILE_INFO, 0);
|
||
}
|
||
|
||
//文件传输结束,关闭超时定时器
|
||
void FileTransOver(void)
|
||
{
|
||
static_print_info("FileTransOver\n");
|
||
}
|
||
|
||
static void FileTransOverTimerCallback(TimerHandle_t xTimer)
|
||
{
|
||
static_print_info("FileTransOverTimerCallback\n");
|
||
amota_conn_param_update(CONN_PARAM_LOW_POWER);
|
||
task_ble_notify(BLE_SAVE_TRANS_FILE_INFO, 0);
|
||
}
|
||
|
||
static int delete_all_complete_files_cb(bool flag, const char *path, int32_t size, void* arg)
|
||
{
|
||
bool isDir = false;
|
||
int fileSize = 0;
|
||
|
||
fileSize = fs_api_stat(path, &isDir);
|
||
if (fileSize <= 0) {
|
||
return 0;
|
||
}
|
||
if (isDir) {
|
||
return 0;
|
||
}
|
||
static_print_info("unlink %s \r\n", path);
|
||
fs_api_unlink(path);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 删除全部在 DIR_RECEIVED 目录下的文件
|
||
* @note 在APP下发一个新文件时调用,目的是删除未处理或未升级成功的文件
|
||
*****************************************************************************************
|
||
*/
|
||
void delete_all_complete_ota_files(void)
|
||
{
|
||
fs_api_dir_scan(DIR_RECEIVED, delete_all_complete_files_cb, NULL);
|
||
}
|
||
|
||
|
||
//用于续传,蓝牙中断等导致的升级失败时,调用该函数进行续传记录
|
||
static void SaveFileTransFile(void)
|
||
{
|
||
fs_api_file_store(FILE_FILE_TRANS_INFO, 0, &g_fileTransCtrlBlock, sizeof(FileTransCtrlBlock_t));
|
||
}
|
||
|
||
static void LoadFileTransFile(void)
|
||
{
|
||
char path[64];
|
||
|
||
fs_user_get_dir_by_full_path(FILE_FILE_TRANS_INFO, path); // 创建文件断点 续传目录,后续可能不在此处创建
|
||
if(fs_api_file_exist(path) == false) {
|
||
fs_user_create_dir(path);
|
||
}
|
||
if(fs_api_file_exist(DIR_RECEIVED) == false) { // 创建文件接收的目录,后续可能不在此处创建
|
||
fs_user_create_dir(DIR_RECEIVED);
|
||
}
|
||
if(fs_api_file_exist(FILE_FILE_TRANS_INFO) == sizeof(FileTransCtrlBlock_t)) {// FSFileExist ---> get file size
|
||
fs_api_file_load(FILE_FILE_TRANS_INFO, 0, &g_fileTransCtrlBlock, sizeof(FileTransCtrlBlock_t));
|
||
}
|
||
}
|
||
|
||
static OtaUiMsgType GetTransTypeByAction(FileActionType action)
|
||
{
|
||
OtaUiMsgType msgType;
|
||
switch(action) {
|
||
case FILE_ACTION_WATCHFACE: {
|
||
msgType = OTA_UI_TRANS_WATCHFACE;
|
||
}
|
||
break;
|
||
case FILE_ACTION_IMAGE: {
|
||
msgType = OTA_UI_TRANS_IMAGE;
|
||
}
|
||
break;
|
||
case FILE_ACTION_FONT: {
|
||
msgType = OTA_UI_TRANS_FONT;
|
||
}
|
||
break;
|
||
case FILE_ACTION_MCU_FIRMWARE:
|
||
case FILE_ACTION_NXP_FIRMWARE:
|
||
case FILE_ACTION_GPS_FIRMWARE:
|
||
case FILE_ACTION_NFC_FIRMWARE:
|
||
case FILE_ACTION_TP_FIRMWARE:
|
||
case FILE_ACTION_BTL_FIRMWARE: {
|
||
msgType = OTA_UI_TRANS_FIRMWARE;
|
||
}
|
||
break;
|
||
default: {
|
||
msgType = OTA_UI_UNKNOWN_TYPE;
|
||
}
|
||
break;
|
||
}
|
||
|
||
return msgType;
|
||
}
|
||
|
||
/**
|
||
*****************************************************************************************
|
||
* @brief 将收到的文件(写入固定地址的透传包),复制到指定片内空间
|
||
*****************************************************************************************
|
||
*/
|
||
int32_t copy_file_to_rom(void)
|
||
{
|
||
uint8_t *buffer = pvPortMalloc(AM_HAL_FLASH_PAGE_SIZE);
|
||
uint32_t ui32_crc;
|
||
uint8_t rw_times = 3;
|
||
uint32_t r_addr = 0;
|
||
uint32_t w_addr = 0;
|
||
uint32_t rw_len = 0;
|
||
uint32_t op_len = 0;
|
||
|
||
if(g_file_trans_head_struct.sour_addr >= APP_CODE_BASE_ADDR
|
||
&& g_file_trans_head_struct.sour_addr < APP_CODE_END_ADDR)
|
||
{/* 试图写入代码区 */
|
||
return -1;
|
||
}
|
||
if(g_file_trans_head_struct.sour_addr % MCU_ROM_PAGE_SIZE)
|
||
{/* 地址未页对齐 */
|
||
return -1;
|
||
}
|
||
|
||
while(rw_times--)
|
||
{
|
||
r_addr = g_file_trans_head_struct.dest_addr + g_file_trans_head_param.h_len;
|
||
w_addr = g_file_trans_head_struct.sour_addr;
|
||
ui32_crc = 0;
|
||
for(rw_len = g_file_trans_head_param.h_len; rw_len < g_file_trans_head_struct.file_size + g_file_trans_head_param.h_len; )
|
||
{
|
||
op_len = (g_file_trans_head_struct.file_size > MCU_ROM_PAGE_SIZE)? MCU_ROM_PAGE_SIZE:(g_file_trans_head_struct.file_size);
|
||
static_print_info("r_addr=0x%x,w_addr=0x%x,op_len=0x%x\n",r_addr,w_addr,op_len);
|
||
flash_api_read(r_addr, buffer, op_len);
|
||
rom_api_erase(w_addr);
|
||
rom_api_write(w_addr, buffer, op_len);
|
||
r_addr += op_len;
|
||
w_addr += op_len;
|
||
rw_len += op_len;
|
||
}
|
||
ui32_crc = crc32_ex(ui32_crc, (uint8_t *)g_file_trans_head_struct.sour_addr, g_file_trans_head_struct.file_size);
|
||
if(ui32_crc == g_file_trans_head_struct.file_crc32)
|
||
{
|
||
break;
|
||
}
|
||
static_print_info("error:obj_crc=0x%x,temp_crc=0x%x\n", g_file_trans_head_struct.file_crc32,ui32_crc);
|
||
}
|
||
vPortFree(buffer);
|
||
static_print_info("copy_file_to_rom succ\r\n");
|
||
return 0;
|
||
}
|
||
|
||
|
||
///////////以下为文件上传部分的代码///////////
|
||
|
||
typedef struct {
|
||
FileTransUploadFileInfo_t *pFileList;
|
||
uint32_t index;
|
||
uint32_t fileNum;
|
||
} FileListInfo_t;
|
||
|
||
static int GetFileNumCb(bool isDir, const char *path, int32_t size, void* arg)
|
||
{
|
||
if (fs_api_stat(path, &isDir) <= 0) {
|
||
return 0;
|
||
}
|
||
if (isDir) {
|
||
return 0;
|
||
}
|
||
FileListInfo_t *fileListInfo = arg;
|
||
|
||
fileListInfo->fileNum++;
|
||
return 0;
|
||
}
|
||
|
||
|
||
static int GetFileInfoCb(bool isDir, const char *path, int32_t size, void* arg)
|
||
{
|
||
FileListInfo_t *fileListInfo = arg;
|
||
if (fileListInfo->index >= fileListInfo->fileNum) {
|
||
return 0;
|
||
}
|
||
if (fs_api_stat(path, &isDir) <= 0) {
|
||
return 0;
|
||
}
|
||
if (isDir) {
|
||
return 0;
|
||
}
|
||
|
||
if(fileListInfo->index >= fileListInfo->fileNum) {
|
||
return 0;
|
||
}
|
||
strcpy(fileListInfo->pFileList[fileListInfo->index].filePathName, path);
|
||
fileListInfo->pFileList[fileListInfo->index].fileSize = size;
|
||
if(size > 0) {
|
||
fileListInfo->pFileList[fileListInfo->index].fileFrames = (size - 1) / FILE_UPLOAD_FRAME_SIZE + 1;
|
||
} else {
|
||
fileListInfo->pFileList[fileListInfo->index].fileFrames = 0;
|
||
}
|
||
fileListInfo->pFileList[fileListInfo->index].fileId = fileListInfo->index;
|
||
ble_printf("file path = %s\n", fileListInfo->pFileList[fileListInfo->index].filePathName);
|
||
ble_printf("file fileId = %d\n", fileListInfo->pFileList[fileListInfo->index].fileId);
|
||
ble_printf("file fileFrames = %d\n", fileListInfo->pFileList[fileListInfo->index].fileFrames);
|
||
fileListInfo->index++;
|
||
return 0;
|
||
}
|
||
|
||
extern int log_api_save_at_power_off(void);
|
||
uint8_t GetFileListByAction(FileActionType action, FileTransUploadFileInfo_t **pFileList)
|
||
{
|
||
uint32_t ret;
|
||
FileListInfo_t fileListInfo = {0};
|
||
char *FilePath = NULL;
|
||
|
||
memset(&fileListInfo, 0, sizeof(FileListInfo_t));
|
||
switch(action) {
|
||
case FILE_ACTION_LOG:
|
||
case FILE_ACTION_DATA_EXERCISE:
|
||
case FILE_ACTION_DATA_SLEEP:
|
||
case FILE_ACTION_DATA_MIN:
|
||
case FILE_ACTION_DATA_DAY:
|
||
case FILE_ALL: {
|
||
if(action == FILE_ACTION_LOG) {
|
||
FilePath = (char *)DIR_DATA_LOG;
|
||
//flush log buf to file
|
||
log_api_save_at_power_off();
|
||
}
|
||
else if(action == FILE_ACTION_DATA_EXERCISE) {
|
||
FilePath = (char *)DIR_DATA_EXERCISE;
|
||
}
|
||
else if(action == FILE_ACTION_DATA_SLEEP) {
|
||
FilePath = (char *)DIR_DATA_SLEEP;
|
||
}
|
||
else if(action == FILE_ACTION_DATA_MIN) {
|
||
FilePath = (char *)DIR_DATA_MIN;
|
||
} else if(action == FILE_ACTION_DATA_DAY) {
|
||
FilePath = (char *)DIR_DATA_DAY;
|
||
}
|
||
else if(action == FILE_ALL) {
|
||
FilePath = (char *)DIR_FD;
|
||
}
|
||
|
||
ble_printf("get file list\r\n");
|
||
fs_api_dir_scan(FilePath, GetFileNumCb, &fileListInfo);
|
||
|
||
if(fileListInfo.fileNum > 255) {
|
||
fileListInfo.fileNum = 255;
|
||
}
|
||
ble_printf("get fileNum=%d\r\n", fileListInfo.fileNum);
|
||
*pFileList = pvPortMalloc(sizeof(FileTransUploadFileInfo_t) * fileListInfo.fileNum);
|
||
fileListInfo.pFileList = *pFileList;
|
||
ret = fileListInfo.fileNum;
|
||
fs_api_dir_scan(FilePath, GetFileInfoCb, &fileListInfo);
|
||
}
|
||
break;
|
||
|
||
default: {
|
||
ret = 0;
|
||
}
|
||
break;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
/* 将'\'转换为'/',将空格' '转换为'_' */
|
||
void switch_to_unix_path(char *path)
|
||
{
|
||
if (path == NULL) {
|
||
return;
|
||
}
|
||
for (int i = 0; path[i] != 0; i++) {
|
||
if (path[i] == '\\') {
|
||
path[i] = '/';
|
||
} else if (path[i] == ' ') {
|
||
path[i] = '_';
|
||
}
|
||
}
|
||
}
|
||
|
||
|