#include "app_config.h" #if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_MASTER) #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" #include "timer.h" #include "system/fs/fs.h" static volatile u32 uart_to_cnt = 0; static volatile u32 uart_file_offset = 0; static volatile u16 rx_cnt; //收数据计数 typedef struct _uart_updte_ctl_t { OS_SEM sem; OS_SEM rx_sem; OS_SEM sd_sem; volatile u16 timemax; volatile u16 timeout; volatile u8 flag; volatile u8 err_code; u8 update_sta; u8 update_percent; u32 update_total_size; u32 update_send_size; u8 rx_cmd[0x30]; u16 cmd_len; u16 uart_timer_hdl; u32 offset_addr; } uart_update_ctl_t; static uart_update_ctl_t uart_update_ctl; #define __this (&uart_update_ctl) #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 FILE_READ_UNIT 512 // #define UART_DEFAULT_BAUD 9600 #define UART_UPDATE_BAUD (50*10000L) #define TIME_TICK_UNIT (10) //unit: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 UART_DEFALT_SEND_DATA_LEN 256 #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; void *fd = NULL; 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); /* enum { */ /* SEEK_SET = 0x0, */ /* SEEK_CUR = 0x1, */ /* SEEK_END = 0X2, */ /* }; */ enum { RX_DATA_READY = 0, RX_DATA_TIMEOUT, RX_DATA_SUCC, }; void uart_update_set_offset_addr(u32 offset) { __this->offset_addr = offset; } 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) { __this->timemax = 0; if (protocal_frame.data.length <= sizeof(__this->rx_cmd)) { memcpy(__this->rx_cmd, &(protocal_frame.data.data), protocal_frame.data.length); __this->flag = RX_DATA_SUCC; os_sem_post(&__this->rx_sem); } } } } } } 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);//设为输出 uart_update_write((u8 *)&protocal_frame, length + SYNC_SIZE); uart_set_dir(1); return ret; } //read file by file operation handle u32 ufw_data_read_api(u8 *buff, u32 addr, u32 size) { //To do... if (fd) { addr += __this->offset_addr; //多芯片ufw偏移 fseek(fd, addr, SEEK_SET); return fread(fd, buff, size); } return 0; } //open file and get file operation handle bool ufw_file_op_init(char *update_path) { if (fd) { fclose(fd); } //To do fd = fopen(update_path, "r"); if (!fd) { return false; } return true; } //close the file and release resource void ufw_file_op_close(void) { if (fd) { fclose(fd); fd = NULL; } //To do } static u32 update_data_read_from_file(void *p, u32 addr, u32 len) { u8 *buffer; struct file_info *p_file_info; u32 read_len = 0; if (len > FILE_READ_UNIT) { return (u32) - 1; } buffer = malloc(len + sizeof(struct file_info)); if (buffer) { p_file_info = (struct file_info *)buffer; p_file_info->cmd = CMD_UART_UPDATE_READ; p_file_info->addr = addr; p_file_info->len = len; read_len = ufw_data_read_api(buffer + sizeof(struct file_info), addr, len); } else { return (u32) - 2; } uart_send_packet(buffer, len + sizeof(struct file_info)); if (buffer) { free(buffer); } return read_len; } static u32 update_data_read_and_send(u32 addr, u32 len, u8 wait_ack) { u8 *buffer; struct file_info *p_file_info; u32 read_len = 0; if (len > FILE_READ_UNIT) { return (u32) - 1; } buffer = malloc(len + sizeof(struct file_info)); if (buffer) { p_file_info = (struct file_info *)buffer; p_file_info->cmd = CMD_UART_SEND_DATA; p_file_info->addr = addr; p_file_info->len = len; read_len = ufw_data_read_api(buffer + sizeof(struct file_info), addr, len); } else { return (u32) - 2; } uart_send_packet(buffer, len + sizeof(struct file_info)); if (buffer) { free(buffer); } return read_len; } enum { UPDATE_STA_NONE = 0, UPDATE_STA_READY, UPDATE_STA_START, UPDATE_STA_TIMEOUT, UPDATE_STA_LOADER_DOWNLOAD_FINISH, UPDATE_STA_SUCC, UPDATE_STA_FAIL, }; enum { UPDATE_ERR_NONE = 0, UPDATE_ERR_KEY, UPDATE_ERR_VERIFY, UPDATE_ERR_LOADER_DOWNLOAD_SUCC = 0x80, }; static void uart_update_err_code_handle(u8 code) { if (code) { if (UPDATE_ERR_LOADER_DOWNLOAD_SUCC == code) { __this->update_percent = 100; __this->update_send_size = 0; __this->update_total_size = 0; __this->update_sta = UPDATE_STA_LOADER_DOWNLOAD_FINISH; log_info("loader dn succ\n"); } else { __this->update_sta = UPDATE_STA_FAIL; log_error("update_err:%x\n", code); } } else { __this->update_percent = 100; __this->update_sta = UPDATE_STA_SUCC; log_info("update all succ\n"); } } static int uart_update_wait_rev_data(timeout) { u32 err; __this->flag = RX_DATA_READY; __this->timeout = 0; __this->timemax = (timeout + 1) / TIME_TICK_UNIT; err = os_sem_pend(&__this->rx_sem, 2000); if (OS_NO_ERR != err) { log_info("wait tm out\n"); } __this->timemax = __this->timeout = 0; if (__this->flag == RX_DATA_SUCC) { return TRUE; } return FALSE; } int uart_update_api_write_then_read(u8 *buf, u8 length, u8 timeout) { int ret = FALSE; uart_send_packet(buf, length); if (timeout) { ret = uart_update_wait_rev_data(timeout); } return ret; } bool uart_update_send_update_ready(char *file_update_path) { u8 ut_cmd[1]; ut_cmd[0] = CMD_UART_UPDATE_READY; if (ufw_file_op_init(file_update_path)) { __this->update_sta = UPDATE_STA_READY; uart_send_packet(ut_cmd, sizeof(ut_cmd)); log_info("uart_update_send_update_ready\n"); return TRUE; } return FALSE; } bool get_uart_update_sta(void) { return (__this->update_sta == UPDATE_STA_READY || __this->update_sta == UPDATE_STA_START) ? TRUE : FALSE; } static void update_process_run(void) { update_baudrate = UART_DEFAULT_BAUD; uart_update_set_baud(update_baudrate); __this->update_total_size = 0; __this->update_percent = 0; __this->update_send_size = 0; __this->offset_addr = 0; //多芯片升级ufw偏移 u8 *pbuf = &__this->rx_cmd; while (1) { if (OS_NO_ERR != os_sem_pend(&__this->rx_sem, 800)) { log_info("uart_timeout\n"); __this->update_sta = UPDATE_STA_TIMEOUT; update_baudrate = 9600; uart_update_set_baud(update_baudrate); continue; } //os_time_dly(1); switch (pbuf[0]) { case CMD_UPDATE_START: log_info("CMD_UPDATE_START\n"); __this->update_sta = UPDATE_STA_START; update_baudrate = UART_UPDATE_BAUD; WRITE_LIT_U32(pbuf + 1, update_baudrate); uart_send_packet(pbuf, 1 + sizeof(u32)); log_info("use baud:%x\n", update_baudrate); uart_update_set_baud(update_baudrate); break; case CMD_UPDATE_READ: { u32 addr = READ_LIT_U32(&pbuf[1]); u32 len = READ_LIT_U32(&pbuf[1 + sizeof(u32)]); if (__this->update_total_size) { __this->update_send_size += len; __this->update_percent = (__this->update_send_size * 100) / __this->update_total_size; if (__this->update_percent >= 99) { __this->update_percent = 99; } log_info("send data process:%x\n", __this->update_percent); } log_info("CMD_UPDATE_READ\n"); update_data_read_from_file(NULL, addr, len); } break; case CMD_UPDATE_END: log_info("CMD_UPDATE_END\n"); uart_update_err_code_handle(pbuf[1]); uart_send_packet(pbuf, 1); break; case CMD_SEND_UPDATE_LEN: __this->update_total_size = READ_LIT_U32(&pbuf[1]); __this->update_percent = 0; __this->update_send_size = 0; log_info("update_total_size:%x\n", __this->update_total_size); uart_send_packet(pbuf, 1); break; case CMD_KEEP_ALIVE: uart_send_packet(pbuf, 1); break; case CMD_UART_ACK: log_info("CMD_UART_ACK -> CMD_UART_SEND_DATA\n"); os_sem_post(&__this->sd_sem); break; } } } static void uart_timeout_handler(void *priv) { if (__this->timemax) { __this->timeout++; if (__this->timeout > __this->timemax) { __this->timemax = 0; __this->flag = RX_DATA_TIMEOUT; os_sem_post(&__this->rx_sem); } } } static void update_loader_download_task(void *p) { log_info("create %s task\n", THIS_TASK_NAME); os_sem_create(&__this->sem, 0); os_sem_create(&__this->rx_sem, 0); os_sem_create(&__this->sd_sem, 0); while (1) { update_process_run(); } } 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); } void uart_update_exit(void) { log_info("uart update exit\n"); if (__this->uart_timer_hdl) { sys_timer_del(__this->uart_timer_hdl); } os_sem_del(&__this->sem, 0); os_sem_del(&__this->rx_sem, 0); ufw_file_op_close(); uart_close_deal(); task_kill(THIS_TASK_NAME); } 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 #if MUTIL_CPU_UART_UPDATE_ENABLE #include "app_config.h" #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 "system/fs/fs.h" #include "avctp_user.h" #define UART_UPDATE_DATA_LEN 256 static uart_bus_t *uart_update_hdl = NULL; static u8 uart_update_cbuf[UART_UPDATE_DATA_LEN * 2] __attribute__((aligned(4))); #define UART_UPDATE_TX_PORT IO_PORTA_03 #define UART_UPDATE_RX_PORT IO_PORTA_03 #define UART_UPDATE_BAUDRATE 500 * 1000 //115200 static protocal_frame_t protocal_frame __attribute__((aligned(4))); static u32 send_len = 0; static OS_MUTEX uart_mutex; static u32 ot_time = 100; static update_op_api_t *uart_op = NULL; static u8 uart_init_flag = 1; static u8 uart_init() { u8 ret = 0; struct uart_platform_data_t u_arg = {0}; u_arg.tx_pin = UART_UPDATE_TX_PORT; u_arg.rx_pin = UART_UPDATE_RX_PORT; u_arg.rx_cbuf = uart_update_cbuf; u_arg.rx_cbuf_size = UART_UPDATE_DATA_LEN * 2; u_arg.frame_length = UART_UPDATE_DATA_LEN * 2; u_arg.rx_timeout = 5; /* u_arg.isr_cbfun = uart_isr_hook; */ u_arg.baud = UART_UPDATE_BAUDRATE; u_arg.is_9bit = 0; r_printf("uart_dev_open() ...\n"); uart_update_hdl = uart_dev_open(&u_arg); if (uart_update_hdl != NULL) { r_printf("success\n"); ret = 0; } else { ret = 1; r_printf("false\n"); } return ret; } static u8 uart_update_packet_data(u8 cmd, u8 *buf, u32 addr, u16 len) { u8 ret = 0; u16 crc; u8 *buffer; u8 *data_buffer; u16 length = len; struct file_info *p_file_info; data_buffer = malloc(len + sizeof(struct file_info)); if (data_buffer) { switch (cmd) { case CMD_UART_SEND_DATA: p_file_info = (struct file_info *)data_buffer; p_file_info->cmd = cmd; p_file_info->addr = addr; p_file_info->len = len; memcpy(data_buffer + sizeof(struct file_info), buf, len); length = len + sizeof(struct file_info); break; case CMD_UART_UPDATE_END: default: memcpy(data_buffer, buf, len); length = len; break; } } else { ret = 1; goto __exit; } buffer = (u8 *)&protocal_frame; memset(buffer, 0, sizeof(protocal_frame_t)); protocal_frame.data.mark0 = SYNC_MARK0; protocal_frame.data.mark1 = SYNC_MARK1; protocal_frame.data.length = length; memcpy((char *)&buffer[4], data_buffer, length); crc = CRC16(buffer, length + SYNC_SIZE - 2); memcpy(buffer + 4 + length, &crc, 2); send_len = length + SYNC_SIZE; __exit: if (data_buffer) { free(data_buffer); data_buffer = NULL; } return ret; } static u8 uart_update_check_ack(u8 cmd, u8 *buf, u32 rx_len) { u16 crc, crc0, i, ch; u32 ut_rx_cnt = 0; u8 ret = 0xff; /* printf("decode_len:%d\n", rx_len); */ /* put_buf(buf, rx_len); */ for (i = 0; i < rx_len; i++) { ch = buf[i]; __recheck: if (ut_rx_cnt == 0) { if (ch == SYNC_MARK0) { protocal_frame.raw_data[ut_rx_cnt++] = ch; } } else if (ut_rx_cnt == 1) { protocal_frame.raw_data[ut_rx_cnt++] = ch; if (ch != SYNC_MARK1) { ut_rx_cnt = 0; goto __recheck; } } else if (ut_rx_cnt < 4) { protocal_frame.raw_data[ut_rx_cnt++] = ch; } else { protocal_frame.raw_data[ut_rx_cnt++] = ch; if (ut_rx_cnt == (protocal_frame.data.length + SYNC_SIZE)) { ut_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) { u8 *buffer = (u8 *)&protocal_frame; if (buffer[4] == cmd) { ret = buffer[5]; break; } } } } } return ret; } static u32 uart_update_read(u8 *rx_buf, u32 total_len) { u32 start_time = timer_get_ms(); u32 rlen = total_len; u32 rx_len = 0; while (1) { rlen = uart_update_hdl->read(rx_buf, rlen, ot_time); rx_len += rlen; if (rx_len == total_len || rx_len >= 9) { break; } else { rx_buf += rlen; rlen = total_len - rx_len; } if ((timer_get_ms() - start_time) >= ot_time) { break; } } return rx_len; } u8 uart_update_tx_packet(u8 cmd, void *data, u32 addr, u16 len, u8 wait_ack) { u8 ret = 0; os_mutex_pend(&uart_mutex, 0); ret = uart_update_packet_data(cmd, data, addr, len); if (ret) { y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); return 1; } putchar('W'); uart_update_hdl->write((u8 *)&protocal_frame, send_len); /* printf(">>>[test]:len = %d\n", send_len); */ /* put_buf((u8 *)&protocal_frame, send_len); */ if (wait_ack) { u8 *rx_buf = malloc(UART_UPDATE_DATA_LEN); ASSERT(rx_buf); u32 rx_len = uart_update_read(rx_buf, UART_UPDATE_DATA_LEN); ret = uart_update_check_ack(cmd, rx_buf, rx_len); if (rx_buf) { free(rx_buf); rx_buf = NULL; } } /* y_printf(">>>[test]:ret = %d\n", ret); */ os_mutex_post(&uart_mutex); return ret; } u8 uart_update_init_uart_type() { u8 ret = 0; if (uart_init_flag) { os_mutex_create(&uart_mutex); ret = uart_init(); uart_init_flag = 0; } return ret; } void uart_update_change_ot_time(u32 new_time) { ot_time = new_time; } int uart_update_send_data(void *op_hdl, void *info) { /* clk_set("sys", 96000000); */ if (!info || !op_hdl) { y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); return -1; } uart_op = (update_op_api_t *)op_hdl; int ret = 0; mutil_ufw_info *p = (mutil_ufw_info *)info; ot_time = (p->ufw_len + 64 * 1024 - 1) / (64 * 1024) * 500; //AD100那边每64K需要等待时间是300ms。 ot_time += 500; y_printf(">>>[test]:ot_time = %dms, p->ufw_len = %d\n", ot_time, p->ufw_len); u32 send_addr = 0;//p->ufw_addr; u32 send_len = UART_UPDATE_DATA_LEN; u8 *send_buf = malloc(UART_UPDATE_DATA_LEN); uart_op->f_seek(NULL, SEEK_SET, send_addr); uart_op->f_read(NULL, send_buf, send_len); ret = uart_update_tx_packet(CMD_UART_SEND_DATA, send_buf, send_addr, send_len, 1); //先发一包数据 if (ret) { y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); goto __exit; } #if (LED_LYRICS_ENABLE && TCFG_LRC_LYRICS_ENABLE) user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); #endif ot_time = 50; //第一次交互之后都比较快 send_addr += send_len; while (1) { putchar('a'); if ((send_addr + send_len) > p->ufw_len) { send_len = p->ufw_len - send_addr; } uart_op->f_seek(NULL, SEEK_SET, send_addr); uart_op->f_read(NULL, send_buf, send_len); ret = uart_update_tx_packet(CMD_UART_SEND_DATA, send_buf, send_addr, send_len, 1); if (ret) { goto __exit; } send_addr += send_len; if (send_addr == p->ufw_len) { ret = 0; break; } } __exit: if (send_buf) { free(send_buf); send_buf = NULL; } u8 end_buf[2]; end_buf[0] = CMD_UART_UPDATE_END; end_buf[1] = ret; ot_time = (p->ufw_len + 64 * 1024 - 1) / (64 * 1024) * 500; //AD100那边每64K需要等待时间是300ms。 ret = uart_update_tx_packet(CMD_UART_UPDATE_END, end_buf, 0, 2, 1); y_printf(">>>[test]:update over ret = %d\n", ret); return ret; } #endif