1375 lines
48 KiB
C
1375 lines
48 KiB
C
/*================================================================
|
|
Copyright (c) 2018 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
|
|
Quectel Wireless Solution Proprietary and Confidential.
|
|
=================================================================*/
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#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<min_deviation_band)
|
|
{
|
|
min_deviation_band = deviation_band;
|
|
real_band = quec_selfadatpt_baud_array[i];
|
|
}
|
|
}
|
|
HW_UART_WRITE_ABR(address, 0);
|
|
*bandrate = real_band;
|
|
uart_default_config[port].baudRate = (UART_BaudRates)real_band;
|
|
_UARTPorts[port].config.baudRate =(UART_BaudRates)real_band;
|
|
}
|
|
|
|
//返回值: -1,rb可能溢出数据搬运不到rb里;1:UART rb流控;0:一切正常
|
|
//
|
|
int quec_move_uart_buffer_to_rb(UART_Port port, unsigned char *dma_buffer, unsigned int move_len)
|
|
{
|
|
int trans_len = 0;
|
|
int ret = 0;
|
|
unsigned int rb_data_len = 0;
|
|
trans_len = quec_uart_read_fifo_to_rb(port, (unsigned char *)dma_buffer,move_len);
|
|
rb_data_len = __kfifo_rb_data_len(quec_uart_data[port].rx_rb);
|
|
if(trans_len != move_len)
|
|
{
|
|
ret = -1;
|
|
goto err;
|
|
}
|
|
|
|
//If the flow control function is not enabled and the amount of data in a packet is very large, the serial port is stuck //pony@2021-07-23
|
|
if((_UARTPorts[port].config.flowControl==(unsigned char)QUEC_FC_HW))
|
|
{
|
|
if(rb_data_len > 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;
|
|
}
|
|
|