Files
AC707N/SDK/apps/common/update/testbox_uart_update.c
2025-12-03 11:12:34 +08:00

354 lines
10 KiB
C

#ifdef SUPPORT_MS_EXTENSIONS
#pragma bss_seg(".testbox_uart_update.data.bss")
#pragma data_seg(".testbox_uart_update.data")
#pragma const_seg(".testbox_uart_update.text.const")
#pragma code_seg(".testbox_uart_update.text")
#endif
#include "init.h"
#include "app_config.h"
#include "system/includes.h"
#include "asm/chargestore.h"
#include "asm/charge.h"
#include "app_charge.h"
#include "user_cfg.h"
#include "app_chargestore.h"
#include "app_testbox.h"
#include "device/vm.h"
#include "btstack/avctp_user.h"
#include "app_action.h"
#include "app_main.h"
#include "app_charge.h"
#include "classic/tws_api.h"
#include "update.h"
#include "bt_ble.h"
#include "bt_tws.h"
#include "app_action.h"
#include "app_power_manage.h"
#include "bt_common.h"
#include "uart_update.h"
#include "update/update_loader_download.h"
#if TCFG_TEST_BOX_ENABLE
#define LOG_TAG "[TEST-UART-UPDATE]"
#define LOG_INFO_ENABLE
#define LOG_ERROR_ENABLE
#include "debug.h"
#define FIXED_LOADER_BAUDRATE (100000)
#define RETRY_TIME 4//重试n次
#define PACKET_TIMEOUT 200//ms
//命令
#define CMD_UPDATE_START 0x01
#define CMD_UPDATE_READ 0x02
#define CMD_UPDATE_END 0x03
#define CMD_SEND_UPDATE_LEN 0x04
#define CMD_KEEP_ALIVE 0x05
extern void chargestore_set_baudrate(u32 baudrate);
static void app_testbox_loader_update_recv(u8 cmd, u8 *buf, u32 len);
extern const char updata_file_name[];
static protocal_frame_t protocal_frame __attribute__((aligned(4)));
static OS_SEM loader_sem;
static u32 uart_file_offset = 0;
static u32 update_baudrate = 0;
static bool app_testbox_loader_send_packet(u8 *buf, u16 length)
{
bool ret = TRUE;
u16 crc;
u8 *buffer;
buffer = (u8 *)&protocal_frame;
protocal_frame.data.mark0 = SYNC_MARK0;
protocal_frame.data.mark1 = SYNC_MARK1;
protocal_frame.data.length = length;
memcpy((char *)&buffer[4], buf, length);
crc = CRC16(buffer, length + SYNC_SIZE - 2);
memcpy(buffer + 4 + length, &crc, 2);
/* put_buf((u8 *)&protocal_frame, length + SYNC_SIZE); */
os_sem_set(&loader_sem, 0);
loader_uart_write((u8 *)&protocal_frame, length + SYNC_SIZE);
chargestore_api_wait_complete();
/* chargestore_api_set_mode(0); // 设置为接收 */
if (OS_TIMEOUT == os_sem_pend(&loader_sem, 35)) {
puts("loader send packet timeout err\n");
return FALSE;
}
return ret;
}
static u32 app_testbox_loader_receive_data(void *buf, u32 relen, u32 addr)
{
u8 i;
struct file_info file_cmd;
for (i = 0; i < RETRY_TIME; i++) {
if (i > 0) {
putchar('r');
}
file_cmd.cmd = CMD_UPDATE_READ;
file_cmd.addr = addr;
file_cmd.len = relen;
if (app_testbox_loader_send_packet((u8 *)&file_cmd, sizeof(file_cmd)) == FALSE) {
continue;
}
memcpy(&file_cmd, protocal_frame.data.data, sizeof(file_cmd));
if ((file_cmd.cmd != CMD_UPDATE_READ) || (file_cmd.addr != addr) || (file_cmd.len != relen)) {
continue;
}
memcpy(buf, &protocal_frame.data.data[sizeof(file_cmd)], protocal_frame.data.length - sizeof(file_cmd));
return (protocal_frame.data.length - sizeof(file_cmd));
}
putchar('R');
return relen;
}
static bool app_testbox_loader_send_cmd(u8 cmd, u8 *buf, u32 len)
{
u8 *pbuf, i;
for (i = 0; i < RETRY_TIME; i++) {
pbuf = protocal_frame.data.data;
pbuf[0] = cmd;
memcpy(pbuf + 1, buf, len);
if (app_testbox_loader_send_packet(pbuf, len + 1) == FALSE) {
continue;
}
if (cmd == protocal_frame.data.data[0]) {
app_testbox_loader_update_recv(cmd, &protocal_frame.data.data[1], protocal_frame.data.length - 1);
return TRUE;
}
}
putchar('F');
return FALSE;
}
static u16 uart_f_open(void)
{
return 1;
}
static u16 uart_f_read(void *handle, u8 *buf, u16 relen)
{
u32 len;
/* printf("%s\n", __func__); */
len = app_testbox_loader_receive_data(buf, relen, uart_file_offset);
if (len == -1) {
log_info("uart_f_read err\n");
return -1;
}
uart_file_offset += len;
return len;
}
static int uart_f_seek(void *fp, u8 type, u32 offset)
{
if (type == SEEK_SET) {
uart_file_offset = offset;
} else if (type == SEEK_CUR) {
uart_file_offset += offset;
}
return 0;//FR_OK;
}
static u16 uart_f_stop(u8 err)
{
app_testbox_loader_send_cmd(CMD_UPDATE_END, &err, 1);
return 0;
}
static const update_op_api_t app_testbox_uart_ch_update_op = {
.ch_init = NULL,
.f_open = uart_f_open,
.f_read = uart_f_read,
.f_seek = uart_f_seek,
.f_stop = uart_f_stop,
};
static void app_testbox_loader_ufw_update_before_jump_handle(int type)
{
printf("soft reset to update >>>");
cpu_reset(); //复位让主控进入升级内置flash
}
static void app_testbox_loader_ufw_update_private_param_fill(UPDATA_PARM *p)
{
memcpy(p->parm_priv, &update_baudrate, sizeof(update_baudrate));
memcpy(p->file_patch, updata_file_name, strlen(updata_file_name));
}
static void app_testbox_loader_update_state_cbk(int type, u32 state, void *priv)
{
update_ret_code_t *ret_code = (update_ret_code_t *)priv;
if (ret_code) {
printf("state:%x err:%x\n", ret_code->stu, ret_code->err_code);
}
switch (state) {
case UPDATE_CH_EXIT:
if ((0 == ret_code->stu) && (0 == ret_code->err_code)) {
//update_mode_api(BT_UPDATA);
update_mode_api_v2(type,
app_testbox_loader_ufw_update_private_param_fill,
app_testbox_loader_ufw_update_before_jump_handle);
}
break;
default:
break;
}
}
static void app_testbox_loader_update_recv(u8 cmd, u8 *buf, u32 len)
{
u32 baudrate = 9600;
switch (cmd) {
case CMD_UPDATE_START:
memcpy(&baudrate, buf, 4);
g_printf("CMD_UPDATE_START:%d\n", baudrate);
if (update_baudrate != baudrate) {
update_baudrate = baudrate;
chargestore_set_baudrate(baudrate);
/* app_testbox_loader_send_cmd(CMD_UPDATE_START, (u8 *)&update_baudrate, 4); */
} else {
update_mode_info_t info = {
.type = TESTBOX_UART_UPDATA,
.state_cbk = app_testbox_loader_update_state_cbk,
.p_op_api = &app_testbox_uart_ch_update_op,
.task_en = 1,
};
app_active_update_task_init(&info);
}
break;
case CMD_UPDATE_END:
break;
case CMD_SEND_UPDATE_LEN:
break;
default:
break;
}
}
static bool app_testbox_loader_start(void)
{
return app_testbox_loader_send_cmd(CMD_UPDATE_START, NULL, 0);
}
static void app_testbox_loader_data_decode(u8 *buf, u32 len)
{
u16 crc, crc0, i, ch;
static u16 rx_cnt = 0;
/* printf("decode_len:%d\n", len); */
/* put_buf(buf, len); */
for (i = 0; i < len; i++) {
ch = buf[i];
__recheck:
if (rx_cnt == 0) {
if (ch == SYNC_MARK0) {
protocal_frame.raw_data[rx_cnt++] = ch;
}
} else if (rx_cnt == 1) {
protocal_frame.raw_data[rx_cnt++] = ch;
if (ch != SYNC_MARK1) {
rx_cnt = 0;
goto __recheck;
}
} else if (rx_cnt < 4) {
protocal_frame.raw_data[rx_cnt++] = ch;
} else {
protocal_frame.raw_data[rx_cnt++] = ch;
if (rx_cnt == (protocal_frame.data.length + SYNC_SIZE)) {
rx_cnt = 0;
crc = CRC16(protocal_frame.raw_data, protocal_frame.data.length + SYNC_SIZE - 2);
memcpy(&crc0, &protocal_frame.raw_data[protocal_frame.data.length + SYNC_SIZE - 2], 2);
if (crc0 == crc) {
os_sem_post(&loader_sem);
#if 0/*{{{*/
switch (protocal_frame.data.data[0]) {
case CMD_UART_UPDATE_START:
log_info("CMD_UART_UPDATE_START\n");
os_taskq_post_msg(THIS_TASK_NAME, 1, MSG_UART_UPDATE_START_RSP);
break;
case CMD_UART_UPDATE_READ:
log_info("CMD_UART_UPDATE_READ\n");
if (uart_update_resume_hdl) {
uart_update_resume_hdl(NULL);
}
break;
case CMD_UART_UPDATE_END:
log_info("CMD_UART_UPDATE_END\n");
break;
case CMD_UART_UPDATE_UPDATE_LEN:
log_info("CMD_UART_UPDATE_LEN\n");
break;
case CMD_UART_JEEP_ALIVE:
log_info("CMD_UART_KEEP_ALIVE\n");
break;
case CMD_UART_UPDATE_READY:
log_info("CMD_UART_UPDATE_READY\n");
os_taskq_post_msg(THIS_TASK_NAME, 1, MSG_UART_UPDATE_READY);
break;
default:
log_info("unkown cmd...\n");
break;
}
#endif/*}}}*/
} else {
rx_cnt = 0;
}
}
}
}
}
static void app_testbox_loader_data_deal(void *p, void *buf, u32 len)
{
app_testbox_loader_data_decode(buf, len);
}
u8 app_testbox_enter_loader_update(void)
{
#if 1 // 使能sdk测试盒串口升级功能
os_sem_create(&loader_sem, 0);
// 设置波特率
chargestore_set_baudrate(FIXED_LOADER_BAUDRATE);
// 设置协议为loader
chargestore_set_protocal(1); // PROTOCAL_LOADER
// 设置回调函数
chargestore_set_loader_update_callback(app_testbox_loader_data_deal);
// 启动start
if (app_testbox_loader_start() == FALSE) {
return 0;
}
if (app_testbox_loader_start() == FALSE) {
return 0;
}
return 1;
#else
return 0;
#endif
}
#else // TCFG_TEST_BOX_ENABLE
u8 app_testbox_enter_loader_update(void)
{
return -1;
}
#endif // TCFG_TEST_BOX_ENABLE