435 lines
13 KiB
C
435 lines
13 KiB
C
|
#include "app_config.h"
|
||
|
#if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_SLAVE)
|
||
|
#include "typedef.h"
|
||
|
#include "update_loader_download.h"
|
||
|
#include "os/os_api.h"
|
||
|
#include "system/task.h"
|
||
|
#include "update.h"
|
||
|
#include "gpio.h"
|
||
|
#include "uart_update.h"
|
||
|
#include "asm/uart_dev.h"
|
||
|
#include "asm/clock.h"
|
||
|
|
||
|
static volatile u32 uart_to_cnt = 0;
|
||
|
static volatile u32 uart_file_offset = 0;
|
||
|
static volatile u16 rx_cnt; //收数据计数
|
||
|
static void (*uart_update_resume_hdl)(void *priv) = NULL;
|
||
|
static int (*uart_update_sleep_hdl)(void *priv) = NULL;
|
||
|
|
||
|
#define LOG_TAG "[UART_UPDATE]"
|
||
|
#define LOG_ERROR_ENABLE
|
||
|
#define LOG_DEBUG_ENABLE
|
||
|
#define LOG_INFO_ENABLE
|
||
|
#define LOG_CLI_ENABLE
|
||
|
#include "debug.h"
|
||
|
|
||
|
#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
|
||
|
|
||
|
|
||
|
#define READ_LIT_U16(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8))
|
||
|
#define READ_LIT_U32(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8) + (*((u8*)(a)+2)<<16) + (*((u8*)(a)+3)<<24))
|
||
|
|
||
|
#define WRITE_LIT_U16(a,src) {*((u8*)(a)+1) = (u8)(src>>8); *((u8*)(a)+0) = (u8)(src&0xff); }
|
||
|
#define WRITE_LIT_U32(a,src) {*((u8*)(a)+3) = (u8)((src)>>24); *((u8*)(a)+2) = (u8)(((src)>>16)&0xff);*((u8*)(a)+1) = (u8)(((src)>>8)&0xff);*((u8*)(a)+0) = (u8)((src)&0xff);}
|
||
|
|
||
|
#define THIS_TASK_NAME "uart_update"
|
||
|
|
||
|
|
||
|
static protocal_frame_t protocal_frame __attribute__((aligned(4)));
|
||
|
u32 update_baudrate = 9600; //初始波特率
|
||
|
static uart_update_cfg update_cfg;
|
||
|
|
||
|
u32 uart_dev_receive_data(void *buf, u32 relen, u32 addr);
|
||
|
void uart_set_dir(u8 mode);
|
||
|
void uart_update_write(u8 *data, u32 len);
|
||
|
void uart_update_set_baud(u32 baudrate);
|
||
|
void uart_close_deal(void);
|
||
|
void uart_hw_init(uart_update_cfg update_cfg, void (*cb)(void *, u32));
|
||
|
void uart_data_decode(u8 *buf, u16 len);
|
||
|
void updata_parm_set(UPDATA_TYPE up_type, void *priv, u32 len);
|
||
|
|
||
|
enum {
|
||
|
SEEK_SET = 0x0,
|
||
|
SEEK_CUR = 0x1,
|
||
|
SEEK_END = 0X2,
|
||
|
};
|
||
|
|
||
|
enum {
|
||
|
CMD_UART_UPDATE_START = 0x1,
|
||
|
CMD_UART_UPDATE_READ,
|
||
|
CMD_UART_UPDATE_END,
|
||
|
CMD_UART_UPDATE_UPDATE_LEN,
|
||
|
CMD_UART_JEEP_ALIVE,
|
||
|
CMD_UART_UPDATE_READY,
|
||
|
};
|
||
|
|
||
|
|
||
|
static void uart_update_hdl_register(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv))
|
||
|
{
|
||
|
uart_update_resume_hdl = resume_hdl;
|
||
|
uart_update_sleep_hdl = sleep_hdl;
|
||
|
}
|
||
|
|
||
|
void sava_uart_update_param(void)
|
||
|
{
|
||
|
UPDATA_UART uart_param = {.control_baud = update_baudrate, .control_io_tx = update_cfg.tx, .control_io_rx = update_cfg.rx};
|
||
|
updata_parm_set(UART_UPDATA, (u8 *)&uart_param, sizeof(UPDATA_UART));
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 填充升级结构体私有参数
|
||
|
@param p: 升级结构体指针(UPDATA_PARM)
|
||
|
@return void
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void uart_ufw_update_private_param_fill(UPDATA_PARM *p)
|
||
|
{
|
||
|
UPDATA_UART uart_param = {.control_baud = update_baudrate, .control_io_tx = update_cfg.tx, .control_io_rx = update_cfg.rx};
|
||
|
memcpy(p->parm_priv, &uart_param, sizeof(uart_param));
|
||
|
}
|
||
|
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
/**@brief 固件升级校验流程完成, cpu reset跳转升级新的固件
|
||
|
@param type: 升级类型
|
||
|
@return void
|
||
|
@note
|
||
|
*/
|
||
|
/*----------------------------------------------------------------------------*/
|
||
|
static void uart_ufw_update_before_jump_handle(int type)
|
||
|
{
|
||
|
printf("soft reset to update >>>");
|
||
|
cpu_reset(); //复位让主控进入升级内置flash
|
||
|
}
|
||
|
|
||
|
static void uart_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(UART_UPDATA,
|
||
|
uart_ufw_update_private_param_fill,
|
||
|
uart_ufw_update_before_jump_handle);
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
static void uart_update_callback(void *priv, u8 type, u8 cmd)
|
||
|
{
|
||
|
/* printf("cmd:%x\n", cmd); */
|
||
|
/* if (cmd == UPDATE_LOADER_OK) { */
|
||
|
/* update_mode_api(type, update_baudrate, update_cfg.tx, update_cfg.rx); */
|
||
|
/* } else { */
|
||
|
/* //失败将波特率设置回初始,并重置变量 */
|
||
|
/* rx_cnt = 0; */
|
||
|
/* update_baudrate = 9600; */
|
||
|
/* uart_file_offset = 0; */
|
||
|
/* uart_update_set_baud(update_baudrate); */
|
||
|
/* //uart_hw_init(update_cfg, uart_data_decode); */
|
||
|
/* } */
|
||
|
}
|
||
|
|
||
|
void uart_data_decode(u8 *buf, u16 len)
|
||
|
{
|
||
|
u16 crc, crc0, i, ch;
|
||
|
/* 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;
|
||
|
extern u16 CRC16(void *ptr, u32 len);
|
||
|
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) {
|
||
|
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;
|
||
|
}
|
||
|
} else {
|
||
|
rx_cnt = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static bool uart_send_packet(u8 *buf, u16 length)
|
||
|
{
|
||
|
bool ret;
|
||
|
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);
|
||
|
uart_set_dir(0);//设为输出
|
||
|
put_buf((u8 *)&protocal_frame, length + SYNC_SIZE);
|
||
|
uart_update_write((u8 *)&protocal_frame, length + SYNC_SIZE);
|
||
|
uart_set_dir(1);
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
u32 uart_dev_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;
|
||
|
uart_send_packet(&file_cmd, sizeof(file_cmd));
|
||
|
if (uart_update_sleep_hdl) {
|
||
|
if (uart_update_sleep_hdl(NULL) == OS_TIMEOUT) {
|
||
|
printf("uart_sleep\n");
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
bool uart_update_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;
|
||
|
if (buf) {
|
||
|
memcpy(pbuf + 1, buf, len);
|
||
|
}
|
||
|
uart_send_packet(pbuf, len + 1);
|
||
|
}
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
extern const update_op_api_t uart_ch_update_op;
|
||
|
void uart_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;
|
||
|
uart_update_set_baud(baudrate);
|
||
|
uart_update_cmd(CMD_UPDATE_START, &update_baudrate, 4);
|
||
|
} else {
|
||
|
update_mode_info_t info = {
|
||
|
.type = UART_UPDATA,
|
||
|
.state_cbk = uart_update_state_cbk,
|
||
|
.p_op_api = &uart_ch_update_op,
|
||
|
.task_en = 1,
|
||
|
};
|
||
|
app_active_update_task_init(&info);
|
||
|
/* app_update_loader_downloader_init( //设置完波特率后开始升级 */
|
||
|
/* UART_UPDATA, */
|
||
|
/* uart_update_callback, */
|
||
|
/* NULL, */
|
||
|
/* &uart_ch_update_op); */
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case CMD_UPDATE_END:
|
||
|
break;
|
||
|
|
||
|
case CMD_SEND_UPDATE_LEN:
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
bool uart_send_update_len(u32 update_len)
|
||
|
{
|
||
|
u8 cmd[4];
|
||
|
WRITE_LIT_U32(&cmd[0], update_len);
|
||
|
return uart_update_cmd(CMD_SEND_UPDATE_LEN, cmd, 4);
|
||
|
}
|
||
|
|
||
|
|
||
|
u16 uart_f_open(void)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
u16 uart_f_read(void *handle, void *buf, u32 relen)
|
||
|
{
|
||
|
u32 len;
|
||
|
printf("%s\n", __func__);
|
||
|
len = uart_dev_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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
u16 uart_f_stop(u8 err)
|
||
|
{
|
||
|
uart_update_cmd(CMD_UPDATE_END, &err, 1);
|
||
|
update_baudrate = 9600; //把波特率设置回9600
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
const update_op_api_t uart_ch_update_op = {
|
||
|
.ch_init = uart_update_hdl_register,
|
||
|
.f_open = uart_f_open,
|
||
|
.f_read = uart_f_read,
|
||
|
.f_seek = uart_f_seek,
|
||
|
.f_stop = uart_f_stop,
|
||
|
};
|
||
|
|
||
|
static void update_loader_download_task(void *p)
|
||
|
{
|
||
|
int ret;
|
||
|
int msg[8];
|
||
|
static u8 update_start = 0;
|
||
|
const uart_bus_t *uart_bus;
|
||
|
u32 uart_rxcnt = 0;
|
||
|
|
||
|
while (1) {
|
||
|
ret = os_task_pend("taskq", msg, ARRAY_SIZE(msg));
|
||
|
if (ret != OS_TASKQ) {
|
||
|
continue;
|
||
|
}
|
||
|
if (msg[0] != Q_MSG) {
|
||
|
continue;
|
||
|
}
|
||
|
switch (msg[1]) {
|
||
|
case MSG_UART_UPDATE_READY:
|
||
|
uart_update_cmd(CMD_UPDATE_START, NULL, 0);
|
||
|
break;
|
||
|
|
||
|
case MSG_UART_UPDATE_START_RSP: //收到START_RSP 进行波特率设置设置
|
||
|
log_info("MSG_UART_UPDATE_START_RSP\n");
|
||
|
uart_update_recv(protocal_frame.data.data[0], &protocal_frame.data.data[1], protocal_frame.data.length - 1);
|
||
|
break;
|
||
|
|
||
|
case MSG_UART_UPDATE_READ_RSP:
|
||
|
log_info("MSG_UART_UPDATE_READ_RSP\n");
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
log_info("unkown msg..............\n");
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void uart_update_init(uart_update_cfg *cfg)
|
||
|
{
|
||
|
memcpy(&update_cfg, cfg, sizeof(uart_update_cfg));
|
||
|
task_create(update_loader_download_task, NULL, THIS_TASK_NAME);
|
||
|
uart_hw_init(update_cfg, uart_data_decode);
|
||
|
printf(">>>%s\n", __func__);
|
||
|
}
|
||
|
|
||
|
|
||
|
static void clock_critical_enter(void)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
static void clock_critical_exit(void)
|
||
|
{
|
||
|
uart_update_set_baud(update_baudrate);
|
||
|
}
|
||
|
CLOCK_CRITICAL_HANDLE_REG(uart_update, clock_critical_enter, clock_critical_exit)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#endif
|