/*================================================================ Copyright (c) 2018 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Quectel Wireless Solution Proprietary and Confidential. =================================================================*/ #include #include #include "quec_rtos.h" #include "quec_ring_buffer.h" #include "UART.h" #include "quec_uart.h" #include "cgpio.h" #include "UART_CommonControl.h" #include "quec_debug.h" #define uart_dbg_log(fmt, args...) quec_debug_print_uart("[%s][%d]"fmt, __FUNCTION__, __LINE__, ##args) #define QUEC_CHECK_UART_PORT_VALID(port_num) do { \ if(port_num >= NUMBER_OF_PORTS) { \ uart_dbg_log("port_num =%d is invalid! \n", port_num); \ return -4; \ } \ }while(0) #define QUEC_CHECK_UART_PORT_VALID_VOID(port_num) do { \ if(port_num >= NUMBER_OF_PORTS) { \ uart_dbg_log("port_num =%d is invalid! \n", port_num); \ return; \ } \ }while(0) extern void UARTClearRxTxFIFO(UART_Port portNumber); extern int quec_uart_dma_init(UART_Port portNumber); extern int quec_uart_power_on(void); #define QUEC_DEBUGUART_TX_BUFF_SIZE (1024*8) #define QUEC_DEBUGUART_RX_BUFF_SIZE (1024*8) #define QUEC_DEBUGUART_FC_HIGH_THRESHOLD (1024*6) #define QUEC_DEBUGUART_FC_LOW_THRESHOLD (1024*3) #define QUEC_BTUART_TX_BUFF_SIZE (1024*8) #define QUEC_BTUART_RX_BUFF_SIZE (1024*8) #define QUEC_BTUART_FC_HIGH_THRESHOLD (1024*6) #define QUEC_BTUART_FC_LOW_THRESHOLD (1024*3) #define QUEC_MAINUART_TX_BUFF_SIZE (1024*8) #define QUEC_MAINUART_RX_BUFF_SIZE (1024*16) #define QUEC_UART_U4_TX_BUFF_SIZE (1024*8) #define QUEC_UART_U4_RX_BUFF_SIZE (1024*8) /*此处rb总大小减流控上限得到的剩余大小必须大于dma缓冲块大小(8k)加上uart fifo大小(64byte)*/ #define QUEC_MAINUART_FC_HIGH_THRESHOLD (1024*7) #define QUEC_MAINUART_FC_LOW_THRESHOLD (1024*4) #define QUEC_MAINUART_TXRB_FC_HIGH_THRESHOLD (1024*7) #define QUEC_MAINUART_TXRB_FC_LOW_THRESHOLD (1024*4) /*主串口流控标志*/ char g_stop_main_uart_f = 0; quec_queue_t quec_debuguart_tx_msg_ref; quec_queue_t quec_btuart_tx_msg_ref; quec_queue_t quec_mainuart_tx_msg_ref; quec_queue_t quec_uart_u4_tx_msg_ref; quec_queue_t quec_uart_rx_msg_ref; quec_task_t quec_debuguart_tx_task; quec_task_t quec_btuart_tx_task; quec_task_t quec_mainuart_tx_task; quec_task_t quec_uart_u4_tx_task; quec_task_t quec_uart_rx_task; //20230525 用于标记设置是否选择非默认uart pin脚的复用功能,该标记置位,则不会对相应port口默认pin脚进行配置 quec_uart_pin_select_t quec_uart_pin_select = {0,0,0,0}; quec_uart_data_t quec_uart_data[NUMBER_OF_SUPPORT_PORTS] = {{0}, {0}, {0},{0}}; char uart_wakeup_mode_open[NUMBER_OF_PORTS]={0}; extern uart_mode_info UartModeInfo; extern void enable_uart_print(void); extern void disable_uart_print(void); static unsigned int quec_selfadatpt_baud_array[] = { 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600 }; // Default configuration in all UART ports static UARTConfiguration uart_default_config[NUMBER_OF_SUPPORT_PORTS] = { { UART_FIFO_CTL, UART_INT_TRIGGER_L32, UART_BAUD_115200, UART_WORD_LEN_8, UART_ONE_STOP_BIT, UART_NO_PARITY_BITS, UART_BASIC_INTERFACE,//UART_L2_INTERFACE; FALSE, FALSE }, { UART_FIFO_CTL, UART_INT_TRIGGER_L32, UART_BAUD_115200, UART_WORD_LEN_8, UART_ONE_STOP_BIT, UART_NO_PARITY_BITS, UART_BASIC_INTERFACE,//UART_L1_INTERFACE; FALSE, FALSE }, { UART_FIFO_CTL, UART_INT_TRIGGER_L32, UART_BAUD_115200, UART_WORD_LEN_8, UART_ONE_STOP_BIT, UART_NO_PARITY_BITS, UART_BASIC_INTERFACE, FALSE, FALSE }, { //port = QL_U4_UART_PORT; UART_FIFO_CTL, UART_INT_TRIGGER_L32, UART_BAUD_115200, UART_WORD_LEN_8, UART_ONE_STOP_BIT, UART_NO_PARITY_BITS, UART_BASIC_INTERFACE, FALSE, FALSE } }; static void quec_uart_gpio_config(UART_Port port, unsigned int flag) { unsigned long mfpr_reg_data = 0; switch (port) { case UART_PORT_FFUART: break; case UART_PORT_BTUART: if(!quec_uart_pin_select.bt_uart_pin_select) { #if defined(__QUECTEL_PROJECT_EC200MCN_GB__)/*asr gps*/ mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(14)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x7; *(volatile unsigned long *)(GPIO_MFPR_ADDR(14)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(15)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x7; *(volatile unsigned long *)(GPIO_MFPR_ADDR(15)) = mfpr_reg_data; #elif defined(__QUECTEL_PROJECT_EG800KCN_GC__) || defined(__QUECTEL_PROJECT_EG915KEU_LA__)\ || defined(__QUECTEL_PROJECT_EG915KEU_LC__)|| defined(__QUECTEL_PROJECT_EG915KEU_LG__)\ || defined (__QUECTEL_PROJECT_EG915KLA_LG__)\ || defined (__QUECTEL_PROJECT_EG800AKCN_11LG__)|| defined(__QUECTEL_PROJECT_EG800AKCN_91LC__)\ || defined (__QUECTEL_PROJECT_EG915KLA_LC__) || defined (__QUECTEL_PROJECT_EG915KLA_LA__)\ || defined(__QUECTEL_PROJECT_EG800AKCN_90LC__) ||defined (__QUECTEL_PROJECT_EG600AKCN_90LC__) \ || defined (__QUECTEL_PROJECT_EG600AKCN_91LC__)||defined (__QUECTEL_PROJECT_EG600AKCN_00LC__) \ || defined (__QUECTEL_PROJECT_EG600AKCN_11LC__)|| defined (__QUECTEL_PROJECT_EG800AKEU_11LC__)\ || defined (__QUECTEL_PROJECT_EG800AKEU_11LG__)|| defined (__QUECTEL_PROJECT_EG800AKLA_11LC__)\ || defined (__QUECTEL_PROJECT_EG800AKLA_00LC__) || defined (__QUECTEL_PROJECT_EG800AKCN_11LN__)\ || defined(ASR_PLATFORM_CRANELR) || defined (__QUECTEL_PROJECT_EG800AKEU_00LC__)\ || defined (__QUECTEL_PROJECT_EG800AKLA_11LG__) || defined (__QUECTEL_PROJECT_EG600AKCN_11LG__) mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(2)); //GPIO3--pin28 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c02; *(volatile unsigned long *)(GPIO_MFPR_ADDR(2)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(3)); //GPIO3--pin29 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c02; *(volatile unsigned long *)(GPIO_MFPR_ADDR(3)) = mfpr_reg_data; #elif defined (__QUECTEL_PROJECT_EC800MCN_GA__) || defined (__QUECTEL_PROJECT_EC800MCN_GC__) \ || defined (__QUECTEL_PROJECT_EC800MCN_GM__) || defined (__QUECTEL_PROJECT_EG810MCN_GA__)\ || defined (__QUECTEL_PROJECT_EC800MCN_GD__) || defined (__QUECTEL_PROJECT_EG810MCN_LA__)\ || defined (__QUECTEL_PROJECT_EG800PCN_LA__) mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(73)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x3; *(volatile unsigned long *)(GPIO_MFPR_ADDR(73)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(74)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x3; *(volatile unsigned long *)(GPIO_MFPR_ADDR(74)) = mfpr_reg_data; #else if (flag) { //QUEC_FC_HW mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(53)); //GPIO53 mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x2; *(volatile unsigned long *)(GPIO_MFPR_ADDR(53)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(54)); //GPIO54 mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x2; *(volatile unsigned long *)(GPIO_MFPR_ADDR(54)) = mfpr_reg_data; } else { mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(35)); //GPIO35 mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x3; *(volatile unsigned long *)(GPIO_MFPR_ADDR(35)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(36)); //GPIO36 mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x3; *(volatile unsigned long *)(GPIO_MFPR_ADDR(36)) = mfpr_reg_data; } #endif } break; case UART_PORT_STUART: if(!quec_uart_pin_select.st_uart_pin_select) { if(uart_wakeup_mode_open[port]) { mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(51)); //GPIO51 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c31; *(volatile unsigned long *)(GPIO_MFPR_ADDR(51)) = mfpr_reg_data; } else { mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(51)); //GPIO51 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c01; *(volatile unsigned long *)(GPIO_MFPR_ADDR(51)) = mfpr_reg_data; } mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(52)); //GPIO52 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c01; *(volatile unsigned long *)(GPIO_MFPR_ADDR(52)) = mfpr_reg_data; if (flag) { //QUEC_FC_HW #if defined(__QUECTEL_PROJECT_EG800WCN_11LG__)/*asr gps*/ mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(4)); //GPIO4 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c03; *(volatile unsigned long *)(GPIO_MFPR_ADDR(4)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(5)); //GPIO5 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c03; *(volatile unsigned long *)(GPIO_MFPR_ADDR(5)) = mfpr_reg_data; #else mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(53)); //GPIO53 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c01; *(volatile unsigned long *)(GPIO_MFPR_ADDR(53)) = mfpr_reg_data; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(54)); //GPIO54 mfpr_reg_data = mfpr_reg_data & ~(0x1fff) | 0x1c01; *(volatile unsigned long *)(GPIO_MFPR_ADDR(54)) = mfpr_reg_data; #endif } } break; case UART_PORT_U4UART: if(!quec_uart_pin_select.u4_uart_pin_select) { #if defined(QUEC_CRANEM_U4_CONFIG) //rx mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(4)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x4; *(volatile unsigned long *)(GPIO_MFPR_ADDR(4)) = mfpr_reg_data; //tx mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(5)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x4; *(volatile unsigned long *)(GPIO_MFPR_ADDR(5)) = mfpr_reg_data; #else //rx mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(2)); //GPIO2--pin28 mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x4; *(volatile unsigned long *)(GPIO_MFPR_ADDR(2)) = mfpr_reg_data; //tx mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(3)); //GPIO3--pin29 mfpr_reg_data = mfpr_reg_data & ~(0x7) | 0x4; *(volatile unsigned long *)(GPIO_MFPR_ADDR(3)) = mfpr_reg_data; #endif } break; default: break; } } static char uart_power_on =0; static int quec_uart_config(UART_Port port, UARTConfiguration uart_config) { int ret = 0; QUEC_CHECK_UART_PORT_VALID(port); //UARTInitializePortAddress((UART_Port)UART_PORT_FFUART); /* Close UART port. */ UARTClose(port); /* Confige the STUART port */ UARTConfigure(port, &uart_config); /* Open UART port. */ ret = UARTOpen(port); /*register dma isr cb*/ quec_uart_dma_init(port); /*Open UART power*/ if(!uart_power_on){ quec_uart_power_on(); uart_power_on = 1; } if (ret != 1) { uart_dbg_log("open uart failed, port:%d, ret:%d \n", port, ret); return -1; } return 0; } //因为STD项目需要默认打开Main_Uart作为AT的收发 int quec_stdproj_uart_init(UART_Port port,QUEC_UART_BAUD_E baudrate, QUEC_UART_FLOWCTRL_E flow_ctrl) { int ret = 0; UARTConfiguration *UART_CONFIG = NULL; if (quec_uart_data[port].uart_state) { uart_dbg_log("The serial port has been opened \r\n"); return QUEC_UART_ALREAD_OPEN; } quec_uart_gpio_config(port, flow_ctrl); UART_CONFIG = &uart_default_config[port]; UART_CONFIG->baudRate = (UART_BaudRates)baudrate; if(UART_PORT_STUART == port)//Only Main UART support flow_ctrl UART_CONFIG->flowControl = (unsigned char)flow_ctrl; else UART_CONFIG->flowControl = (unsigned char)QUEC_FC_NONE; ret = quec_uart_config(port, uart_default_config[port]); if (ret) { uart_dbg_log("config uart failed \n"); return QUEC_UART_OPEN_FAILED; } UARTPhase2Init(); //STD项目暂时不使用OPEN的ring buffer先不进行申请 return ret; } int quec_uart_pin_set_func(UART_Port port, UINT32 PIN_NUM,unsigned int func_num) { unsigned long mfpr_reg_data = 0; switch (port){ case UART_PORT_FFUART: quec_uart_pin_select.ff_uart_pin_select = 1; break; case UART_PORT_BTUART: quec_uart_pin_select.bt_uart_pin_select = 1; break; case UART_PORT_STUART: quec_uart_pin_select.st_uart_pin_select = 1; break; case UART_PORT_U4UART: quec_uart_pin_select.u4_uart_pin_select = 1; break; default: break; } mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(PIN_NUM)); mfpr_reg_data = mfpr_reg_data & ~(0x7) | func_num; *(volatile unsigned long *)(GPIO_MFPR_ADDR(PIN_NUM)) = mfpr_reg_data; return 0; } int quec_uart_pin_get_func( UINT32 PIN_NUM) { int func; unsigned long mfpr_reg_data = 0; mfpr_reg_data = *(volatile unsigned long *)(GPIO_MFPR_ADDR(PIN_NUM)); func = (int)(mfpr_reg_data & 0x7); return func; } int quec_uart_wakeup_mode_enable(UART_Port port) { uart_wakeup_mode_open[port]=1; return 0; } int quec_uart_wakeup_mode_disable(UART_Port port) { uart_wakeup_mode_open[port]=0; return 0; } char quec_uart_get_wakeup_mode_flag(UART_Port port) { return uart_wakeup_mode_open[port]; } int quec_uart_rx_dma_size_set(UART_Port port, UINT32 size) { return uart_rx_dma_size_set(port, size); } int quec_uart_rx_dma_size_get(UART_Port port) { return uart_rx_dma_size_get(port); } //Open项目使用此接口 int quec_uart_open(UART_Port port, QUEC_UART_BAUD_E baudrate, QUEC_UART_FLOWCTRL_E flow_ctrl) { int ret = 0; UARTConfiguration *UART_CONFIG = NULL; QUEC_CHECK_UART_PORT_VALID(port); if (quec_uart_data[port].uart_state) { uart_dbg_log("The serial port has been opened \r\n"); return QUEC_UART_ALREAD_OPEN; } if (port == UART_PORT_FFUART) { UartModeInfo.Type[UART_PORT_FFUART] = UART_INT_ENABLE; // 关闭DEBUG UART使能输出,反正后续重新使能DEBUG 口初始化失败 disable_uart_print(); } quec_uart_gpio_config(port, flow_ctrl); UART_CONFIG = &uart_default_config[port]; UART_CONFIG->baudRate = (UART_BaudRates)baudrate; if(UART_PORT_STUART == port)//Only Main UART support flow_ctrl UART_CONFIG->flowControl = (unsigned char)flow_ctrl; else UART_CONFIG->flowControl = (unsigned char)QUEC_FC_NONE; ret = quec_uart_config(port, uart_default_config[port]); if (ret) { uart_dbg_log("config uart failed \n"); return QUEC_UART_OPEN_FAILED; } switch (port) { case UART_PORT_FFUART: quec_uart_data[port].tx_rb = __kfifo_rb_create(QUEC_DEBUGUART_TX_BUFF_SIZE); quec_uart_data[port].rx_rb = __kfifo_rb_create(QUEC_DEBUGUART_RX_BUFF_SIZE); break; case UART_PORT_BTUART: quec_uart_data[port].tx_rb = __kfifo_rb_create(QUEC_BTUART_TX_BUFF_SIZE); quec_uart_data[port].rx_rb = __kfifo_rb_create(QUEC_BTUART_RX_BUFF_SIZE); break; case UART_PORT_STUART: quec_uart_data[port].tx_rb = __kfifo_rb_create(QUEC_MAINUART_TX_BUFF_SIZE); quec_uart_data[port].rx_rb = __kfifo_rb_create(QUEC_MAINUART_RX_BUFF_SIZE); break; case UART_PORT_U4UART: quec_uart_data[port].tx_rb = __kfifo_rb_create(QUEC_UART_U4_TX_BUFF_SIZE); quec_uart_data[port].rx_rb = __kfifo_rb_create(QUEC_UART_U4_RX_BUFF_SIZE); break; default: return QUEC_UART_ILLEGAL_PORT; } if(quec_uart_data[port].tx_rb !=NULL && quec_uart_data[port].rx_rb != NULL) { quec_uart_data[port].IsSendingStatus=FALSE; quec_uart_data[port].uart_state = TRUE; uart_dbg_log("uart open port=%d,success",port); quec_uart_data[port].uart_state = 1; return QUEC_UART_SUCCESS; } else { uart_dbg_log("uart open port=%d,fail",port); if(quec_uart_data[port].tx_rb !=NULL) __kfifo_rb_destroy(&quec_uart_data[port].tx_rb); if(quec_uart_data[port].rx_rb !=NULL) __kfifo_rb_destroy(&quec_uart_data[port].rx_rb); return QUEC_UART_RB_CFG_FAILED; } } int quec_uart_close(UART_Port port) { QUEC_CHECK_UART_PORT_VALID(port); if (port == UART_PORT_FFUART) { UartModeInfo.Type[UART_PORT_FFUART] = UART_INT_DISABLE; enable_uart_print(); } if (quec_uart_data[port].uart_state) { /* Close UART port. */ UARTClose(port); quec_uart_data[port].uart_state = 0; __kfifo_rb_destroy(&quec_uart_data[port].tx_rb); __kfifo_rb_destroy(&quec_uart_data[port].rx_rb); } switch (port){ case UART_PORT_FFUART: quec_uart_pin_select.ff_uart_pin_select = 0; break; case UART_PORT_BTUART: quec_uart_pin_select.bt_uart_pin_select = 0; break; case UART_PORT_STUART: quec_uart_pin_select.st_uart_pin_select = 0; break; case UART_PORT_U4UART: quec_uart_pin_select.u4_uart_pin_select = 0; break; default: break; } return QUEC_UART_SUCCESS; } void quec_uart_register_cb(UART_Port port, uart_callback uart_cb) { QUEC_CHECK_UART_PORT_VALID_VOID(port); quec_uart_data[port].uart_cb = uart_cb; quec_uart_data[port].uart_cb_ex = NULL; } void quec_uart_register_cb_ex(UART_Port port, uart_callback_ex uart_cb, void *priavte) { QUEC_CHECK_UART_PORT_VALID_VOID(port); quec_uart_data[port].uart_cb_ex = uart_cb; quec_uart_data[port].callback_private_argv = priavte; quec_uart_data[port].uart_cb = NULL; } void quec_uart_register_TxFwctrl_cb(UART_Port port, uart_tx_fwctrl_callback uart_cb) { QUEC_CHECK_UART_PORT_VALID_VOID(port); quec_uart_data[port].uart_fwctrl_cb = uart_cb; } int quec_uart_get_dcbconfig(UART_Port port, quec_uart_config_t *dcb) { QUEC_CHECK_UART_PORT_VALID(port); if (NULL == dcb) { uart_dbg_log("set dcbconfig failed, the dcb is NULL \n"); return -1; } if (!_UARTPorts[port].config.baudRate) { _UARTPorts[port].config = uart_default_config[port]; } dcb->baudrate = (QUEC_UART_BAUD_E)(_UARTPorts[port].config.baudRate); dcb->data_bit = (QUEC_UART_DATABIT_E)(_UARTPorts[port].config.numDataBits); dcb->stop_bit = (QUEC_UART_STOPBIT_E)(_UARTPorts[port].config.stopBits); dcb->parity_bit = (QUEC_UART_PARITYBIT_E)(_UARTPorts[port].config.parityBitType); dcb->flow_ctrl = (QUEC_UART_FLOWCTRL_E)(_UARTPorts[port].config.flowControl); return 0; } int quec_uart_set_dcbconfig(UART_Port port, quec_uart_config_t *dcb) { int ret = 0; UARTConfiguration *UART_CONFIG = NULL; QUEC_CHECK_UART_PORT_VALID(port); if (NULL == dcb) { uart_dbg_log("set dcbconfig failed, the dcb is NULL \n"); return QUEC_UART_DCB_PRAM_ERR; } UART_CONFIG = &uart_default_config[port]; UART_CONFIG->baudRate = (UART_BaudRates)dcb->baudrate; UART_CONFIG->numDataBits = (UART_WordLen)dcb->data_bit; UART_CONFIG->stopBits = (UART_StopBits)dcb->stop_bit; UART_CONFIG->parityBitType = (UART_ParityTBits)dcb->parity_bit; if(port == UART_PORT_STUART){ UART_CONFIG->flowControl = (unsigned char)dcb->flow_ctrl; }else{ UART_CONFIG->flowControl = (unsigned char )QUEC_FC_NONE; } quec_uart_gpio_config(port, dcb->flow_ctrl); ret = quec_uart_config(port, uart_default_config[port]); if (ret) { uart_dbg_log("config uart failed \n"); return QUEC_UART_DCB_CFG_ERR; } return QUEC_UART_SUCCESS; } /*同步发送接口,此接口数据未发送完成会阻塞线程*/ int quec_uart_write_sync(UART_Port port, unsigned char *data, int len) { int send_len = 0; unsigned short unsend_len = len; while(send_len < len) { /*若对端流控被拉起,此函数将一直阻塞直到流控被去使能*/ QUEC_UART_DMAWrite(port, (data+send_len), &unsend_len); send_len = len - unsend_len; } return len; } void quec_uart_flush_fifo(UART_Port port) { if(port >= NUMBER_OF_PORTS) { uart_dbg_log("port_num =%d is invalid! \n", port); return ; } /*step1 清除软件fifo*/ if (quec_uart_data[port].tx_rb) { switch (port) { case UART_PORT_FFUART: quec_uart_data[port].tx_rb->size = QUEC_DEBUGUART_TX_BUFF_SIZE; quec_uart_data[port].tx_rb->wpos = 0; quec_uart_data[port].tx_rb->rpos = 0; if (quec_uart_data[port].tx_rb->data) { memset(quec_uart_data[port].tx_rb->data, 0, QUEC_DEBUGUART_TX_BUFF_SIZE); } break; case UART_PORT_BTUART: quec_uart_data[port].tx_rb->size = QUEC_BTUART_TX_BUFF_SIZE; quec_uart_data[port].tx_rb->wpos = 0; quec_uart_data[port].tx_rb->rpos = 0; if (quec_uart_data[port].tx_rb->data) { memset(quec_uart_data[port].tx_rb->data, 0, QUEC_BTUART_TX_BUFF_SIZE); } break; case UART_PORT_STUART: quec_uart_data[port].tx_rb->size = QUEC_MAINUART_TX_BUFF_SIZE; quec_uart_data[port].tx_rb->wpos = 0; quec_uart_data[port].tx_rb->rpos = 0; if (quec_uart_data[port].tx_rb->data) { memset(quec_uart_data[port].tx_rb->data, 0, QUEC_MAINUART_TX_BUFF_SIZE); } break; case UART_PORT_U4UART: quec_uart_data[port].tx_rb->size = QUEC_UART_U4_TX_BUFF_SIZE; quec_uart_data[port].tx_rb->wpos = 0; quec_uart_data[port].tx_rb->rpos = 0; if (quec_uart_data[port].tx_rb->data) { memset(quec_uart_data[port].tx_rb->data, 0, QUEC_UART_U4_TX_BUFF_SIZE); } break; } } if (quec_uart_data[port].rx_rb) { switch (port) { case UART_PORT_FFUART: quec_uart_data[port].rx_rb->size = QUEC_DEBUGUART_RX_BUFF_SIZE; quec_uart_data[port].rx_rb->wpos = 0; quec_uart_data[port].rx_rb->rpos = 0; if (quec_uart_data[port].rx_rb->data) { memset(quec_uart_data[port].rx_rb->data, 0, QUEC_DEBUGUART_RX_BUFF_SIZE); } break; case UART_PORT_BTUART: quec_uart_data[port].rx_rb->size = QUEC_BTUART_RX_BUFF_SIZE; quec_uart_data[port].rx_rb->wpos = 0; quec_uart_data[port].rx_rb->rpos = 0; if (quec_uart_data[port].rx_rb->data) { memset(quec_uart_data[port].rx_rb->data, 0, QUEC_BTUART_RX_BUFF_SIZE); } break; case UART_PORT_STUART: quec_uart_data[port].rx_rb->size = QUEC_MAINUART_RX_BUFF_SIZE; quec_uart_data[port].rx_rb->wpos = 0; quec_uart_data[port].rx_rb->rpos = 0; if (quec_uart_data[port].rx_rb->data) { memset(quec_uart_data[port].rx_rb->data, 0, QUEC_MAINUART_RX_BUFF_SIZE); } break; case UART_PORT_U4UART: quec_uart_data[port].rx_rb->size = QUEC_UART_U4_RX_BUFF_SIZE; quec_uart_data[port].rx_rb->wpos = 0; quec_uart_data[port].rx_rb->rpos = 0; if (quec_uart_data[port].rx_rb->data) { memset(quec_uart_data[port].rx_rb->data, 0, QUEC_UART_U4_RX_BUFF_SIZE); } break; } } /* step2 清除硬件fifo */ UARTClearRxTxFIFO(port); } void quec_aotu_flow_enable(UART_Port portNumber) { UINT32 address = _UARTHwAddresses[portNumber]; if((quec_check_uart_is_open(portNumber))&&(_UARTPorts[portNumber].config.flowControl == 1)) { HW_UART_WRITE_MCR(address,(MCR_AFE|MCR_FORCE_RTS|MCR_ENABLE_INTS)); } } void quec_aotu_flow_Disable(UART_Port portNumber) { UINT32 address = _UARTHwAddresses[portNumber]; unsigned long val = 0; if((quec_check_uart_is_open(portNumber))&&(_UARTPorts[portNumber].config.flowControl == 1)) { HW_UART_READ_MCR(address,val); val &= ~(MCR_AFE|MCR_FORCE_RTS|MCR_ENABLE_INTS); HW_UART_WRITE_MCR(address,val); } } unsigned char quec_check_uart_tx_fifo_empty(UART_Port portNumber) { unsigned int lineStatus; unsigned int address = _UARTHwAddresses[portNumber]; HW_UART_READ_LSR(address, lineStatus); //wait for tx fifo and shift register empty if ( lineStatus & LSR_EMP_DATA ) // 64 byte in the FIFO are free return 1;//TBD!!!// fifo empty else return 0; } unsigned char quec_check_uart_rx_fifo_busy(UART_Port portNumber) { unsigned int lineStatus; unsigned int address = _UARTHwAddresses[portNumber]; if((quec_uart_data[portNumber].uart_state)&&(_UARTPorts[portNumber].config.flowControl == (unsigned char)QUEC_FC_HW)) { /* Read Line Status. */ HW_UART_READ_LSR(address, lineStatus); if (lineStatus & LSR_DATA_READY) // LSR_DATA_READY == 0x01 return 1;//rx fifo have data else { if(__kfifo_rb_is_empty(quec_uart_data[portNumber].rx_rb)) return 0; else return 1;//rx rb have data } } else return 0;//UART not open,think rx not busy } int quec_uart_write(UART_Port port, unsigned char *data, int len) { int send_len = QUEC_UART_SUCCESS; quec_uart_msg_t uart_msg={0}; unsigned int reg = 0; unsigned int address =0; QUEC_CHECK_UART_PORT_VALID(port); if ((NULL == data) || (len <= 0) || (NULL==quec_uart_data[port].tx_rb)) { uart_dbg_log("write uart data, invalid param, len=%d,rb=%#x,port=%d\n", len,quec_uart_data[port].tx_rb,port); return QUEC_UART_WRITE_PRAM_ERR; } if (quec_debuguart_tx_msg_ref == NULL || quec_btuart_tx_msg_ref == NULL || quec_mainuart_tx_msg_ref == NULL) { return QUEC_UART_OPEN_FAILED; } /*只有设置了硬件流控会去判断流控脚状态*/ if(uart_default_config[port].flowControl == QUEC_FC_HW) { if(__kfifo_rb_data_len(quec_uart_data[port].tx_rb) > QUEC_MAINUART_TXRB_FC_HIGH_THRESHOLD) { send_len = QUEC_UART_CTS_HIGH ; if(quec_uart_data[port].uart_fwctrl_cb) { quec_uart_data[port].uart_fwctrl_cb(port,1); } } } if(send_len == QUEC_UART_SUCCESS) { uart_msg.direction = quec_uart_tx; uart_msg.uart_port = port; send_len = __kfifo_rb_write(quec_uart_data[port].tx_rb, data, len); uart_msg.data_len = send_len; //uart_dbg_log("%s,port=%d,send_len=%d;",__func__,port,send_len); if(send_len > 0) switch (port) { case UART_PORT_FFUART: quec_rtos_queue_release(quec_debuguart_tx_msg_ref, sizeof(quec_uart_msg_t), (unsigned char *)&uart_msg, 10); break; case UART_PORT_BTUART: quec_rtos_queue_release(quec_btuart_tx_msg_ref, sizeof(quec_uart_msg_t), (unsigned char *)&uart_msg, 10); break; case UART_PORT_STUART: quec_rtos_queue_release(quec_mainuart_tx_msg_ref, sizeof(quec_uart_msg_t), (unsigned char *)&uart_msg, 10); break; case UART_PORT_U4UART: quec_rtos_queue_release(quec_uart_u4_tx_msg_ref, sizeof(quec_uart_msg_t), (u8 *)&uart_msg, 10); break; default: send_len = QUEC_UART_ILLEGAL_PORT; break; } else send_len = QUEC_UART_WRITE_ERR; } return send_len; } int quec_uart_read_fifo_to_rb(UART_Port port, unsigned char *data, int len) { unsigned int read_len = 0; QUEC_CHECK_UART_PORT_VALID(port); if ((NULL == data) || (len <= 0)) { uart_dbg_log("read uart fifo data, uart data is null or len is less 0, len=%d \n", len); return -1; } if (quec_uart_data[port].rx_rb && quec_uart_data[port].rx_rb->data) { read_len = __kfifo_rb_write(quec_uart_data[port].rx_rb, data, len); } return read_len; } int quec_uart_fc_high_threshold(UART_Port port) { int ret=0; switch (port) { case UART_PORT_FFUART: ret=QUEC_DEBUGUART_FC_HIGH_THRESHOLD; break; case UART_PORT_BTUART: ret=QUEC_BTUART_FC_HIGH_THRESHOLD; break; case UART_PORT_STUART: ret=QUEC_MAINUART_FC_HIGH_THRESHOLD; break; default: ret=QUEC_UART_ILLEGAL_PORT; break; } return ret; } int quec_uart_fc_low_threshold(UART_Port port) { int ret=0; switch (port) { case UART_PORT_FFUART: ret=QUEC_DEBUGUART_FC_LOW_THRESHOLD; break; case UART_PORT_BTUART: ret=QUEC_BTUART_FC_LOW_THRESHOLD; break; case UART_PORT_STUART: ret=QUEC_MAINUART_FC_LOW_THRESHOLD; break; default: ret=QUEC_UART_ILLEGAL_PORT; break; } return ret; } void quec_uart_baud_selfadatpt_enable(UART_Port port) { UINT32 address= _UARTHwAddresses[port] ; HW_UART_WRITE_ABR(address, UART_ABR_ABE|UART_ABR_ABUP|UART_ABR_ABLIE|UART_ABR_ABT); } void quec_uart_baud_selfadatpt_disable(UART_Port port,unsigned int *bandrate) { unsigned int real_band = QUEC_UART_BAUD_300; UINT32 address= _UARTHwAddresses[port] ; unsigned int div = 0,i; unsigned int current_band = 0; unsigned int deviation_band=0; unsigned int min_deviation_band=0xFFFFFFFF; HW_UART_READ_ACR(address,div); current_band=UART_CLOCK/(div&0XFFFF); for(i = 0; i < sizeof(quec_selfadatpt_baud_array)/sizeof(unsigned int); i++) { if(current_band > quec_selfadatpt_baud_array[i]) { deviation_band = current_band - quec_selfadatpt_baud_array[i]; } else { deviation_band = quec_selfadatpt_baud_array[i] - current_band; } if(deviation_band quec_uart_fc_high_threshold(port))//到达流控阈值 { switch(port) { /*目前仅主串口支持流控机制*/ case UART_PORT_STUART : g_stop_main_uart_f = 1 ; ret = 1; break; case UART_PORT_FFUART : case UART_PORT_BTUART : default: ret = 0; break; } } } else ret = 0; err: return ret; } int quec_get_uart_rb_state(UART_Port port) { int ret = 0; if((_UARTPorts[port].config.flowControl==(unsigned char)QUEC_FC_HW)) { switch(port) { case UART_PORT_STUART : ret=g_stop_main_uart_f; break; case UART_PORT_FFUART : case UART_PORT_BTUART : default: ret = 0; break; } } else ret = 0; return ret; } int quec_uart_read(UART_Port port, unsigned char *data, int len) { int read_len = 0; unsigned int rb_data_len = 0; QUEC_CHECK_UART_PORT_VALID(port); if (quec_uart_data[port].rx_rb && data && (len>0)) { read_len = __kfifo_rb_read(quec_uart_data[port].rx_rb, data, len); rb_data_len = __kfifo_rb_data_len(quec_uart_data[port].rx_rb);; /*如果高限位流控被拉起接收中断会被关闭,此处检测rb到达低限值重新打开接收中断*/ if((_UARTPorts[port].config.flowControl==(unsigned char)QUEC_FC_HW) &&(quec_get_uart_rb_state(port) == 1)) { if(rb_data_len <= quec_uart_fc_low_threshold( port))//到达流控下限值 { switch(port) { case UART_PORT_STUART : //目前只有主串口支持流控机制 g_stop_main_uart_f = 0 ; ENABLE_UART_INT(port, IER_TIME_OUT|IER_RCV_DATA_AVAILABLE); //start interrupt break; case UART_PORT_FFUART : case UART_PORT_BTUART : case UART_PORT_U4UART : default: break; } } } return read_len; } return QUEC_UART_READ_ERR; } unsigned char quec_uart_is_sending(UART_Port port) { if((quec_uart_data[port].IsSendingStatus ) || (!__kfifo_rb_is_empty(quec_uart_data[port].tx_rb)) || (!quec_check_uart_tx_fifo_empty(port))) return QUEC_UART_IS_SENDING; else return QUEC_UART_NOT_SENDING; } unsigned int quec_rb_free_space(UART_Port port) { return __kfifo_rb_free_space(quec_uart_data[port].rx_rb); } unsigned char quec_check_uart_is_open(UART_Port port) { return quec_uart_data[port].uart_state; } unsigned int quec_uart_get_rxrb_data_len(UART_Port port) { if (quec_uart_data[port].rx_rb) { return __kfifo_rb_data_len(quec_uart_data[port].rx_rb); } return 0; } void quec_uart_send_msg(UART_Port port) { quec_uart_msg_t uart_msg; uart_msg.direction = 1; uart_msg.uart_port = port; uart_msg.data_len = __kfifo_rb_data_len(quec_uart_data[port].rx_rb); if (quec_uart_rx_msg_ref && (quec_uart_data[port].uart_cb || quec_uart_data[port].uart_cb_ex) && (uart_msg.data_len > 0)) { quec_rtos_queue_release(quec_uart_rx_msg_ref, sizeof(quec_uart_msg_t), (unsigned char *)&uart_msg, QUEC_NO_WAIT); } return; } static void quec_uart_rx_msg_process(void * argv) { int ret = -1; unsigned int transfer_len = 0; quec_uart_msg_t main_uart_msg; quec_uart_msg_t uart2_uart_msg; quec_uart_msg_t debug_uart_msg; quec_uart_msg_t uart_msg; unsigned char *data = NULL; unsigned char ql_uart_port = 0; while (1) { ret = quec_rtos_queue_wait(quec_uart_rx_msg_ref, (unsigned char *)&uart_msg, sizeof(quec_uart_msg_t), (unsigned int)QUEC_WAIT_FOREVER); if (ret) { return; } //miles.ma 20221121将CB传递给APP测试的port参数,由kernel侧UART_PORT_U4UART(3)转换为app侧的QL_U4_UART_PORT(4) if(UART_PORT_U4UART == uart_msg.uart_port) { ql_uart_port = QUEC2QL_U4_UART_PORT; } else { ql_uart_port = uart_msg.uart_port; } switch (uart_msg.direction) { case quec_uart_rx: //rx if (NULL != quec_uart_data[uart_msg.uart_port].uart_cb) { quec_uart_data[uart_msg.uart_port].uart_cb((UART_Port)ql_uart_port, (void *)&uart_msg.data_len); } if (NULL != quec_uart_data[uart_msg.uart_port].uart_cb_ex) { quec_uart_data[uart_msg.uart_port].uart_cb_ex((UART_Port)ql_uart_port, uart_msg.data_len, quec_uart_data[uart_msg.uart_port].callback_private_argv); } default: break; } } } /*因为串口cts流控会阻塞dma 导致此线程会被阻塞,所以在dma模式下每个串口tx需要单独的线程去处理*/ static void quec_debuguart_tx_msg_process(void * argv) { int ret = -1; unsigned int transfer_len = 0; unsigned int send_len = 0; unsigned short unsend_len = 0; quec_uart_msg_t uart_msg; unsigned char *usb_data = NULL; unsigned char *tx_data = NULL; while (1) { ret = quec_rtos_queue_wait(quec_debuguart_tx_msg_ref, (unsigned char *)&uart_msg, sizeof(quec_uart_msg_t), (unsigned int)QUEC_WAIT_FOREVER); if (ret) { return; } quec_uart_data[uart_msg.uart_port].IsSendingStatus=TRUE; tx_data = malloc(uart_msg.data_len); switch (uart_msg.direction) { case quec_uart_tx: { transfer_len = __kfifo_rb_read(quec_uart_data[uart_msg.uart_port].tx_rb, tx_data,uart_msg.data_len); send_len = 0; unsend_len = (unsigned short)transfer_len; /*如果tx_fifo为空直接退出不发数据*/ if(transfer_len <= 0) break; while(send_len < transfer_len) { //uart_dbg_log("#b%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); #ifdef QUEC_UART_DMA_TX_ENABLE QUEC_UART_DMAWrite((UART_Port)(uart_msg.uart_port), (tx_data+send_len), &unsend_len); #endif //uart_dbg_log("##QUEC_UART_DMAWrite,ret=%d;",ret); send_len = transfer_len - unsend_len; //uart_dbg_log("#c%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); } quec_uart_data[uart_msg.uart_port].IsSendingStatus=FALSE; } break; default: break; } free(tx_data); } } /*因为串口cts流控会阻塞dma 进而导致此线程会被阻塞,所以在dma模式下每个串口tx需要单独的线程去处理*/ static void quec_btuart_tx_msg_process(void * argv) { int ret = -1; unsigned int transfer_len = 0; unsigned int send_len = 0; unsigned short unsend_len = 0; quec_uart_msg_t uart_msg; unsigned char *usb_data = NULL; unsigned char *tx_data = NULL; while (1) { ret = quec_rtos_queue_wait(quec_btuart_tx_msg_ref, (unsigned char *)&uart_msg, sizeof(quec_uart_msg_t), (unsigned int)QUEC_WAIT_FOREVER); if (ret) { return; } quec_uart_data[uart_msg.uart_port].IsSendingStatus=TRUE; tx_data = malloc(uart_msg.data_len); switch (uart_msg.direction) { case quec_uart_tx: { transfer_len = __kfifo_rb_read(quec_uart_data[uart_msg.uart_port].tx_rb, tx_data,uart_msg.data_len); send_len = 0; unsend_len = (unsigned short)transfer_len; /*如果tx_fifo为空直接退出不发数据*/ if(transfer_len <= 0) break; while(send_len < transfer_len) { //uart_dbg_log("#b%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); #ifdef QUEC_UART_DMA_TX_ENABLE QUEC_UART_DMAWrite((UART_Port)(uart_msg.uart_port), (tx_data+send_len), &unsend_len); #endif //uart_dbg_log("##QUEC_UART_DMAWrite,ret=%d;",ret); send_len = transfer_len - unsend_len; //uart_dbg_log("#c%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); } quec_uart_data[uart_msg.uart_port].IsSendingStatus=FALSE; } break; default: break; } free(tx_data); } } /*因为串口cts流控会阻塞dma 导致此线程会被阻塞,所以在dma模式下每个串口tx需要单独的线程去处理*/ static void quec_mainuart_tx_msg_process(void * argv) { int ret = -1; unsigned int transfer_len = 0; unsigned int send_len = 0; unsigned short unsend_len = 0; quec_uart_msg_t uart_msg; unsigned char *usb_data = NULL; unsigned char *tx_data = NULL; while (1) { ret = quec_rtos_queue_wait(quec_mainuart_tx_msg_ref, (unsigned char *)&uart_msg, sizeof(quec_uart_msg_t), (unsigned int)QUEC_WAIT_FOREVER); if (ret) { return; } quec_uart_data[uart_msg.uart_port].IsSendingStatus=TRUE; tx_data = malloc(uart_msg.data_len); switch (uart_msg.direction) { case quec_uart_tx: { transfer_len = __kfifo_rb_read(quec_uart_data[uart_msg.uart_port].tx_rb, tx_data,uart_msg.data_len); send_len = 0; unsend_len = (unsigned short)transfer_len; //uart_dbg_log("%s",tx_data); /*如果tx_fifo为空直接退出不发数据*/ if(transfer_len <= 0) break; while(send_len < transfer_len) { //uart_dbg_log("#b%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); #ifdef QUEC_UART_DMA_TX_ENABLE ret = QUEC_UART_DMAWrite((UART_Port)(uart_msg.uart_port), (tx_data+send_len), &unsend_len); #endif //uart_dbg_log("##QUEC_UART_DMAWrite,ret=%d;",ret); send_len = transfer_len - unsend_len; //uart_dbg_log("#c%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); if(__kfifo_rb_data_len(quec_uart_data[uart_msg.uart_port].tx_rb) < QUEC_MAINUART_TXRB_FC_LOW_THRESHOLD) { if(quec_uart_data[uart_msg.uart_port].uart_fwctrl_cb) { quec_uart_data[uart_msg.uart_port].uart_fwctrl_cb(uart_msg.uart_port,0); } } } quec_uart_data[uart_msg.uart_port].IsSendingStatus=FALSE; } break; default: break; } free(tx_data); } } static void quec_uart_u4_tx_msg_process(void * argv) { int ret = -1; unsigned int transfer_len = 0; unsigned int send_len = 0; unsigned short unsend_len = 0; quec_uart_msg_t uart_msg; unsigned char *tx_data = NULL; while (1) { ret = quec_rtos_queue_wait(quec_uart_u4_tx_msg_ref, (unsigned char *)&uart_msg, sizeof(quec_uart_msg_t), (unsigned int)QUEC_WAIT_FOREVER); if (ret) { return; } quec_uart_data[uart_msg.uart_port].IsSendingStatus=TRUE; tx_data = malloc(uart_msg.data_len); switch (uart_msg.direction) { case quec_uart_tx: { transfer_len = __kfifo_rb_read(quec_uart_data[uart_msg.uart_port].tx_rb, tx_data,uart_msg.data_len); send_len = 0; unsend_len = (unsigned short)transfer_len; //uart_dbg_log("%s",tx_data); /*如果tx_fifo为空直接退出不发数据*/ if(transfer_len <= 0) break; while(send_len < transfer_len) { //uart_dbg_log("#b%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); #ifdef QUEC_UART_DMA_TX_ENABLE QUEC_UART_DMAWrite((UART_Port)(uart_msg.uart_port), (tx_data+send_len), &unsend_len); #endif //uart_dbg_log("##QUEC_UART_DMAWrite,ret=%d;",ret); send_len = transfer_len - unsend_len; //uart_dbg_log("#c%s port=%d,trs=%u,sdl=%u,unst=%u\r\n",__func__,uart_msg.uart_port,transfer_len,send_len,unsend_len); } quec_uart_data[uart_msg.uart_port].IsSendingStatus=FALSE; } break; default: break; } free(tx_data); } } int quec_uart_driver_init(void) { OSA_STATUS status = OS_SUCCESS; status = quec_rtos_queue_create(&quec_uart_rx_msg_ref, sizeof(quec_uart_msg_t), 256); ASSERT(status == OS_SUCCESS); status = quec_rtos_queue_create(&quec_debuguart_tx_msg_ref, sizeof(quec_uart_msg_t), 256); ASSERT(status == OS_SUCCESS); status = quec_rtos_queue_create(&quec_btuart_tx_msg_ref, sizeof(quec_uart_msg_t), 256); ASSERT(status == OS_SUCCESS); status = quec_rtos_queue_create(&quec_mainuart_tx_msg_ref, sizeof(quec_uart_msg_t), 256); ASSERT(status == OS_SUCCESS); /* quec_rtos_task_create */ status = quec_rtos_task_create(&quec_uart_rx_task, 2048, 40, "QUARTRx", quec_uart_rx_msg_process, NULL); ASSERT(status == OS_SUCCESS); status = quec_rtos_task_create(&quec_debuguart_tx_task, 2048, 90, "QUART1Tx", quec_debuguart_tx_msg_process, NULL); ASSERT(status == OS_SUCCESS); status = quec_rtos_task_create(&quec_btuart_tx_task, 2048, 90, "QUART2Tx", quec_btuart_tx_msg_process, NULL); ASSERT(status == OS_SUCCESS); status = quec_rtos_task_create(&quec_mainuart_tx_task, 2048, 90, "QUART3Tx", quec_mainuart_tx_msg_process, NULL); ASSERT(status == OS_SUCCESS); status = quec_rtos_queue_create(&quec_uart_u4_tx_msg_ref, sizeof(quec_uart_msg_t), 256); ASSERT(status == OS_SUCCESS); status = quec_rtos_task_create(&quec_uart_u4_tx_task, 2048, 90, "QUART4Tx", quec_uart_u4_tx_msg_process, NULL); ASSERT(status == OS_SUCCESS); return 0; }