Docker-Build mit gcc-arm-none-eabi 4.9-2014q4 (statt Homebrew-Cask) verwendet, Dockerfile/tools/docker.sh dafür aus Task 13 vorgezogen. cmake/sdk.cmake schont gcc 4.9 (kennt -fcommon/-Wno-error=... nicht). Zwei zusätzliche SDK-Stubs (EarlyInit, pre_gpio_config) in src/sys/sdk_stubs.c ergänzt, siehe sdk/PATCHES.md.
1601 lines
46 KiB
C
1601 lines
46 KiB
C
/**
|
||
* @file wm_uart.c
|
||
*
|
||
* @brief uart Driver Module
|
||
*
|
||
* @author dave
|
||
*
|
||
* Copyright (c) 2015 Winner Microelectronics Co., Ltd.
|
||
*/
|
||
|
||
#include <string.h>
|
||
#include "wm_regs.h"
|
||
#include "wm_uart.h"
|
||
#include "wm_debug.h"
|
||
#include "wm_irq.h"
|
||
#include "wm_config.h"
|
||
#include "wm_mem.h"
|
||
#include "wm_dma.h"
|
||
#include "wm_cpu.h"
|
||
#include "wm_pmu.h"
|
||
#include "wm_wifi.h"
|
||
|
||
#include "misc.h"
|
||
|
||
#if TLS_CONFIG_UART
|
||
|
||
#define DEBUG_RX_LEN 0
|
||
#define RX_CACHE_LIMIT 128
|
||
|
||
struct tls_uart_port uart_port[3];
|
||
//void (*tx_sent_callback)(struct tls_uart_port *port) = NULL;
|
||
static void tls_uart_tx_chars(struct tls_uart_port *port);
|
||
extern s16 uart_tx_sent_callback(struct tls_uart_port *port);
|
||
void tls_uart_tx_callback_register(u16 uart_no,
|
||
s16(*tx_callback) (struct tls_uart_port *
|
||
port));
|
||
|
||
const u32 baud_rates[] = {
|
||
2000000, 1500000, 1250000,
|
||
1000000, 921600, 460800,
|
||
230400, 115200, 57600, 38400,
|
||
19200, 9600, 4800, 2400,
|
||
1800, 1200, 600
|
||
};
|
||
|
||
static void tls_uart_tx_enable(struct tls_uart_port *port);
|
||
static void tls_uart_tx_chars(struct tls_uart_port *port);
|
||
|
||
void Debug_UartInit(void)
|
||
{
|
||
u32 bd;
|
||
|
||
u32 apbclk;
|
||
tls_sys_clk sysclk;
|
||
|
||
tls_sys_clk_get(&sysclk);
|
||
apbclk = sysclk.apbclk * 1000000;
|
||
|
||
/* baud rate register value = apb_clk/(16*115200) */
|
||
/* ���APBʱ����40MHz�� */
|
||
/* �����ʼĴ�����ֵ����Ϊ 115200 : 21 */
|
||
/* 9600bps : 260 */
|
||
bd = (apbclk / (16 * 115200) -
|
||
1) | (((apbclk % (115200 * 16)) * 16 / (115200 * 16)) << 16);
|
||
#if WM_CONFIG_DEBUG_UART1
|
||
{
|
||
tls_reg_write32(HR_UART1_BAUD_RATE_CTRL, bd);
|
||
/* Line control register : Normal,No parity,1 stop,8 bits, only use tx */
|
||
tls_reg_write32(HR_UART1_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN);
|
||
}
|
||
|
||
#elif WM_CONFIG_DEBUG_UART2
|
||
{
|
||
tls_reg_write32(HR_UART2_BAUD_RATE_CTRL, bd);
|
||
/* Line control register : Normal,No parity,1 stop,8 bits, only use tx */
|
||
tls_reg_write32(HR_UART2_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN);
|
||
}
|
||
#else
|
||
{
|
||
tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd);
|
||
/* Line control register : Normal,No parity,1 stop,8 bits, only use tx */
|
||
tls_reg_write32(HR_UART0_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN);
|
||
|
||
}
|
||
|
||
#endif
|
||
}
|
||
|
||
void UartRegInit(int uart_no)
|
||
{
|
||
u32 bd;
|
||
u32 apbclk;
|
||
tls_sys_clk sysclk;
|
||
|
||
tls_sys_clk_get(&sysclk);
|
||
apbclk = sysclk.apbclk * 1000000;
|
||
|
||
/* baud rate register value = apb_clk/(16*115200) */
|
||
/* ���APBʱ����40MHz�� */
|
||
/* �����ʼĴ�����ֵ����Ϊ 115200 : 21 */
|
||
/* 9600bps : 260 */
|
||
if (TLS_UART_0 == uart_no)
|
||
{
|
||
bd = (apbclk / (16 * 115200) - 1) | (((apbclk % (115200 * 16)) * 16 / (115200 * 16)) << 16);
|
||
tls_reg_write32(HR_UART0_BAUD_RATE_CTRL, bd);
|
||
/* Line control register : Normal,No parity,1 stop,8 bits, only use tx */
|
||
tls_reg_write32(HR_UART0_LINE_CTRL, ULCON_WL8 | ULCON_TX_EN);
|
||
|
||
/* disable auto flow control */
|
||
tls_reg_write32(HR_UART0_FLOW_CTRL, 0);
|
||
/* disable dma */
|
||
tls_reg_write32(HR_UART0_DMA_CTRL, 0);
|
||
/* one byte tx */
|
||
tls_reg_write32(HR_UART0_FIFO_CTRL, 0);
|
||
/* disable interrupt */
|
||
tls_reg_write32(HR_UART0_INT_MASK, 0xFF);
|
||
}
|
||
|
||
if (TLS_UART_1 == uart_no)
|
||
{
|
||
/* 4 byte tx, 8 bytes rx */
|
||
tls_reg_write32(HR_UART1_FIFO_CTRL, (0x01 << 2) | (0x02 << 4));
|
||
/* enable rx timeout, disable rx dma, disable tx dma */
|
||
tls_reg_write32(HR_UART1_DMA_CTRL, (8 << 3) | (1 << 2));
|
||
/* enable rx/timeout interrupt */
|
||
tls_reg_write32(HR_UART1_INT_MASK, ~(3 << 2));
|
||
|
||
// uart1
|
||
}
|
||
if (TLS_UART_2 == uart_no)
|
||
{
|
||
/* 4 byte tx, 8 bytes rx */
|
||
tls_reg_write32(HR_UART2_FIFO_CTRL, (0x01 << 2) | (0x02 << 4));
|
||
/* enable rx timeout, disable rx dma, disable tx dma */
|
||
tls_reg_write32(HR_UART2_DMA_CTRL, (8 << 3) | (1 << 2));
|
||
/* enable rx/timeout interrupt */
|
||
tls_reg_write32(HR_UART2_INT_MASK, ~(3 << 2));
|
||
}
|
||
}
|
||
|
||
int tls_uart_check_baudrate(u32 baudrate)
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < sizeof(baud_rates) / sizeof(u32); i++)
|
||
{
|
||
if (baudrate == baud_rates[i])
|
||
return 1;
|
||
}
|
||
/* not found match baudrate */
|
||
return -1;
|
||
}
|
||
|
||
u32 tls_uart_get_baud_rate(struct tls_uart_port * port)
|
||
{
|
||
if ((port != NULL) && (port->regs != NULL))
|
||
return port->opts.baudrate;
|
||
else
|
||
return 0;
|
||
}
|
||
|
||
int tls_uart_set_baud_rate_inside(struct tls_uart_port *port, u32 baudrate)
|
||
{
|
||
int index;
|
||
u32 value;
|
||
u32 apbclk;
|
||
tls_sys_clk sysclk;
|
||
|
||
|
||
index = tls_uart_check_baudrate(baudrate);
|
||
if (index < 0)
|
||
return WM_FAILED;
|
||
port->regs->UR_FIFOC &= ~0x3;
|
||
port->regs->UR_FIFOC |= UFC_TX_FIFO_RESET|UFC_RX_FIFO_RESET;
|
||
tls_sys_clk_get(&sysclk);
|
||
apbclk = sysclk.apbclk * 1000000;
|
||
value = (apbclk / (16 * baudrate) - 1) |
|
||
(((apbclk % (baudrate * 16)) * 16 / (baudrate * 16)) << 16);
|
||
TLS_DBGPRT_INFO("value = 0x%x\n", value);
|
||
port->regs->UR_BD = value;
|
||
port->regs->UR_FIFOC &= ~0x3;
|
||
port->regs->UR_FIFOC |= UFC_TX_FIFO_RESET|UFC_RX_FIFO_RESET;
|
||
|
||
port->opts.baudrate = baudrate;
|
||
TLS_DBGPRT_INFO("UR_BR = 0x%x\n", port->regs->UR_BD);
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
|
||
int tls_uart_set_parity_inside(struct tls_uart_port *port,
|
||
TLS_UART_PMODE_T paritytype)
|
||
{
|
||
if (port == NULL)
|
||
return WM_FAILED;
|
||
|
||
port->opts.paritytype = paritytype;
|
||
|
||
if (paritytype == TLS_UART_PMODE_DISABLED)
|
||
port->regs->UR_LC &= ~ULCON_PMD_EN;
|
||
else if (paritytype == TLS_UART_PMODE_EVEN)
|
||
{
|
||
port->regs->UR_LC &= ~ULCON_PMD_MASK;
|
||
port->regs->UR_LC |= ULCON_PMD_EVEN;
|
||
}
|
||
else if (paritytype == TLS_UART_PMODE_ODD)
|
||
{
|
||
port->regs->UR_LC &= ~ULCON_PMD_MASK;
|
||
port->regs->UR_LC |= ULCON_PMD_ODD;
|
||
}
|
||
else
|
||
return WM_FAILED;
|
||
|
||
return WM_SUCCESS;
|
||
|
||
}
|
||
|
||
TLS_UART_PMODE_T tls_uart_get_parity(struct tls_uart_port * port)
|
||
{
|
||
return port->opts.paritytype;
|
||
}
|
||
|
||
int tls_uart_set_data_bits(struct tls_uart_port *port,
|
||
TLS_UART_CHSIZE_T charlength)
|
||
{
|
||
if (!port)
|
||
return WM_FAILED;
|
||
|
||
port->opts.charlength = charlength;
|
||
|
||
port->regs->UR_LC &= ~ULCON_WL_MASK;
|
||
|
||
if (charlength == TLS_UART_CHSIZE_5BIT)
|
||
port->regs->UR_LC |= ULCON_WL5;
|
||
else if (charlength == TLS_UART_CHSIZE_6BIT)
|
||
port->regs->UR_LC |= ULCON_WL6;
|
||
else if (charlength == TLS_UART_CHSIZE_7BIT)
|
||
port->regs->UR_LC |= ULCON_WL7;
|
||
else if (charlength == TLS_UART_CHSIZE_8BIT)
|
||
port->regs->UR_LC |= ULCON_WL8;
|
||
else
|
||
return WM_FAILED;
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
TLS_UART_CHSIZE_T tls_uart_get_data_bits(struct tls_uart_port * port)
|
||
{
|
||
return port->opts.charlength;
|
||
}
|
||
|
||
int tls_uart_set_stop_bits_inside(struct tls_uart_port *port,
|
||
TLS_UART_STOPBITS_T stopbits)
|
||
{
|
||
if (!port)
|
||
return WM_FAILED;
|
||
|
||
port->opts.stopbits = stopbits;
|
||
|
||
if (stopbits == TLS_UART_TWO_STOPBITS)
|
||
port->regs->UR_LC |= ULCON_STOP_2;
|
||
else
|
||
port->regs->UR_LC &= ~ULCON_STOP_2;
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
TLS_UART_STOPBITS_T tls_uart_get_stop_bits(struct tls_uart_port * port)
|
||
{
|
||
return port->opts.stopbits;
|
||
}
|
||
|
||
TLS_UART_STATUS_T tls_uart_set_flow_ctrl(struct tls_uart_port * port,
|
||
TLS_UART_FLOW_CTRL_MODE_T flow_ctrl)
|
||
{
|
||
TLS_UART_STATUS_T status = TLS_UART_STATUS_OK;
|
||
|
||
if (!port)
|
||
return TLS_UART_STATUS_ERROR;
|
||
|
||
// port->opts.flow_ctrl = flow_ctrl;
|
||
// //�����������ģ�Ϊ���������ATָ��������Լ���flowctrl���ã����Dz������ǹ̶������
|
||
//printf("\nport %d flow ctrl==%d\n",port->uart_no,flow_ctrl);
|
||
switch (flow_ctrl)
|
||
{
|
||
case TLS_UART_FLOW_CTRL_NONE:
|
||
port->regs->UR_FC = 0;
|
||
break;
|
||
case TLS_UART_FLOW_CTRL_HARDWARE:
|
||
if (TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl)
|
||
{
|
||
port->regs->UR_FC = (1UL << 0) | (6UL << 2);
|
||
}
|
||
break;
|
||
default:
|
||
return TLS_UART_STATUS_ERROR;
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
void tls_uart_set_fc_status(int uart_no, TLS_UART_FLOW_CTRL_MODE_T status)
|
||
{
|
||
struct tls_uart_port *port;
|
||
|
||
if (TLS_UART_0 == uart_no)
|
||
{
|
||
port = &uart_port[0];
|
||
}
|
||
else if (TLS_UART_1 == uart_no)
|
||
{
|
||
port = &uart_port[1];
|
||
}
|
||
else
|
||
{
|
||
port = &uart_port[2];
|
||
}
|
||
|
||
port->fcStatus = status;
|
||
//printf("\nset fc status=%d\n",status);
|
||
tls_uart_set_flow_ctrl(port, status);
|
||
if (TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl && 0 == status && port->hw_stopped) // ���ر�����ʱ������tx�Ѿ�ֹͣ����Ҫ�ٴ�tx
|
||
{
|
||
tls_uart_tx_enable(port);
|
||
tls_uart_tx_chars(port);
|
||
port->hw_stopped = 0;
|
||
}
|
||
}
|
||
|
||
void tls_uart_rx_disable(struct tls_uart_port *port)
|
||
{
|
||
u32 ucon;
|
||
|
||
ucon = port->regs->UR_LC;
|
||
ucon &= ~ULCON_RX_EN;
|
||
port->regs->UR_LC = ucon;
|
||
}
|
||
|
||
void tls_uart_rx_enable(struct tls_uart_port *port)
|
||
{
|
||
port->regs->UR_LC |= ULCON_RX_EN;
|
||
}
|
||
|
||
static void tls_uart_tx_enable(struct tls_uart_port *port)
|
||
{
|
||
u32 ucon;
|
||
|
||
// printf("tx e\n");
|
||
ucon = port->regs->UR_LC;
|
||
ucon |= ULCON_TX_EN;
|
||
port->regs->UR_LC = ucon;
|
||
}
|
||
|
||
static void tls_uart_tx_disable(struct tls_uart_port *port)
|
||
{
|
||
u32 ucon;
|
||
|
||
// printf("tx d\n");
|
||
ucon = port->regs->UR_LC;
|
||
ucon &= ~ULCON_TX_EN;
|
||
port->regs->UR_LC = ucon;
|
||
}
|
||
|
||
|
||
int tls_uart_config(struct tls_uart_port *port, struct tls_uart_options *opts)
|
||
{
|
||
if (NULL == port || NULL == opts)
|
||
return WM_FAILED;
|
||
/* set the baud rate */
|
||
tls_uart_set_baud_rate_inside(port, opts->baudrate);
|
||
/* set the parity */
|
||
tls_uart_set_parity_inside(port, opts->paritytype);
|
||
/* set the number of data bits */
|
||
tls_uart_set_data_bits(port, opts->charlength);
|
||
/* set the number of stop bits */
|
||
tls_uart_set_stop_bits_inside(port, opts->stopbits);
|
||
/* Set flow control */
|
||
port->opts.flow_ctrl = opts->flow_ctrl;
|
||
tls_uart_set_flow_ctrl(port, opts->flow_ctrl);
|
||
|
||
/* config uart interrupt register */
|
||
/* if (port->uart_mode == TLS_UART_MODE_INT) */// Ĭ��ʹ���жϵķ�ʽ
|
||
{
|
||
/* clear interrupt */
|
||
port->regs->UR_INTS = 0xFFFFFFFF;
|
||
/* enable interupt */
|
||
port->regs->UR_INTM = 0x0;
|
||
port->regs->UR_DMAC =
|
||
(4UL << UDMA_RX_FIFO_TIMEOUT_SHIFT) | UDMA_RX_FIFO_TIMEOUT;
|
||
}
|
||
|
||
/* config FIFO control */
|
||
port->regs->UR_FIFOC = UFC_TX_FIFO_LVL_16_BYTE | UFC_RX_FIFO_LVL_16_BYTE |
|
||
UFC_TX_FIFO_RESET | UFC_RX_FIFO_RESET;
|
||
port->regs->UR_LC &= ~(ULCON_TX_EN | ULCON_RX_EN);
|
||
port->regs->UR_LC |= ULCON_RX_EN | ULCON_TX_EN;
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief handle a change of clear-to-send state
|
||
* @param[in] port: uart_port structure for the open port
|
||
* @param[in] status: new clear to send status, nonzero if active
|
||
*/
|
||
static void uart_handle_cts_change(struct tls_uart_port *port,
|
||
unsigned int status)
|
||
{
|
||
//printf("\ncts change port->fcStatus=%d,port->opts.flow_ctrl=%d,status=%d\n",port->fcStatus,port->opts.flow_ctrl,status);
|
||
if (((1 == port->fcStatus)
|
||
&& (port->opts.flow_ctrl == TLS_UART_FLOW_CTRL_HARDWARE))
|
||
&& (port->uart_no == TLS_UART_1))
|
||
{
|
||
if (port->hw_stopped)
|
||
{
|
||
if (status)
|
||
{
|
||
port->hw_stopped = 0;
|
||
tls_uart_tx_enable(port);
|
||
tls_uart_tx_chars(port);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
if (!status)
|
||
{
|
||
port->hw_stopped = 1;
|
||
tls_uart_tx_disable(port);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
int tls_uart_poll_put_char(struct tls_uart_port *port, int ch)
|
||
{
|
||
if (ch == '\n')
|
||
{
|
||
while (port->regs->UR_FIFOS & 0x3F) /* wait THR is empty */
|
||
;
|
||
port->regs->UR_TXW = '\r'; /* output CR */
|
||
}
|
||
while (port->regs->UR_FIFOS & 0x3F) /* wait THR is empty */
|
||
;
|
||
port->regs->UR_TXW = (char) ch;
|
||
|
||
return ch;
|
||
}
|
||
|
||
int tls_uart_poll_get_char(struct tls_uart_port *port)
|
||
{
|
||
while ((port->regs->UR_FIFOS & UFS_RX_FIFO_CNT_MASK) >> 6)
|
||
return (int) port->regs->UR_RXW;
|
||
return 0;
|
||
}
|
||
|
||
static void uart_tx_finish_callback(void *arg)
|
||
{
|
||
if (arg)
|
||
{
|
||
tls_mem_free(arg);
|
||
}
|
||
}
|
||
|
||
int tls_uart_tx_remain_len(struct tls_uart_port *port)
|
||
{
|
||
tls_uart_tx_msg_t *tx_msg = NULL;
|
||
u16 buf_len = 0;
|
||
u32 cpu_sr;
|
||
cpu_sr = tls_os_set_critical();
|
||
dl_list_for_each(tx_msg, &port->tx_msg_pending_list, tls_uart_tx_msg_t,
|
||
list)
|
||
{
|
||
buf_len += tx_msg->buflen;
|
||
}
|
||
tls_os_release_critical(cpu_sr);
|
||
return TLS_UART_TX_BUF_SIZE - buf_len;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to fill tx buffer.
|
||
* @param[in] port: is the uart port.
|
||
* @param[in] buf: is the user buffer.
|
||
* @param[in] count: is the user data length
|
||
* @retval
|
||
*/
|
||
int tls_uart_fill_buf(struct tls_uart_port *port, char *buf, u32 count)
|
||
{
|
||
tls_uart_tx_msg_t *uart_tx_msg;
|
||
// int c;
|
||
int ret = 0;
|
||
u32 cpu_sr;
|
||
|
||
uart_tx_msg = tls_mem_alloc(sizeof(tls_uart_tx_msg_t));
|
||
if (uart_tx_msg == NULL)
|
||
{
|
||
TLS_DBGPRT_ERR("mem err\n");
|
||
return -1;
|
||
}
|
||
dl_list_init(&uart_tx_msg->list);
|
||
uart_tx_msg->buf = tls_mem_alloc(count);
|
||
if (uart_tx_msg->buf == NULL)
|
||
{
|
||
tls_mem_free(uart_tx_msg);
|
||
TLS_DBGPRT_ERR("mem err 1 count=%d\n", count);
|
||
return -1;
|
||
}
|
||
memcpy(uart_tx_msg->buf, buf, count);
|
||
uart_tx_msg->buflen = count;
|
||
uart_tx_msg->offset = 0;
|
||
uart_tx_msg->finish_callback = uart_tx_finish_callback;
|
||
uart_tx_msg->callback_arg = uart_tx_msg->buf;
|
||
cpu_sr = tls_os_set_critical();
|
||
dl_list_add_tail(&port->tx_msg_pending_list, &uart_tx_msg->list);
|
||
tls_os_release_critical(cpu_sr);
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* @brief free the data buffer has been transmitted.
|
||
* @param[in] port: is the uart port.
|
||
* @retval
|
||
*/
|
||
s16 tls_uart_free_tx_sent_data(struct tls_uart_port *port)
|
||
{
|
||
tls_uart_tx_msg_t *tx_msg = NULL;
|
||
u32 cpu_sr = tls_os_set_critical();
|
||
while (!dl_list_empty(&port->tx_msg_to_be_freed_list))
|
||
{
|
||
tx_msg = dl_list_first(&port->tx_msg_to_be_freed_list, tls_uart_tx_msg_t, list);
|
||
dl_list_del(&tx_msg->list);
|
||
tls_os_release_critical(cpu_sr);
|
||
// printf("tx_msg=%p\n", tx_msg);
|
||
if (tx_msg->buf != NULL)
|
||
{
|
||
tx_msg->buf = NULL;
|
||
if (tx_msg->finish_callback)
|
||
tx_msg->finish_callback(tx_msg->callback_arg);
|
||
tls_mem_free(tx_msg);
|
||
}
|
||
cpu_sr = tls_os_set_critical();
|
||
}
|
||
tls_os_release_critical(cpu_sr);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to start transfer data.
|
||
* @param[in] port: is the uart port.
|
||
* @retval
|
||
*/
|
||
void tls_uart_tx_chars_start(struct tls_uart_port *port)
|
||
{
|
||
struct dl_list *pending_list = &port->tx_msg_pending_list;
|
||
tls_uart_tx_msg_t *tx_msg = NULL;
|
||
int tx_count;
|
||
u32 cpu_sr;
|
||
|
||
/* send some chars */
|
||
tx_count = 32;
|
||
cpu_sr = tls_os_set_critical();
|
||
if (!dl_list_empty(pending_list))
|
||
{
|
||
|
||
tx_msg = dl_list_first(pending_list, tls_uart_tx_msg_t, list);
|
||
while (tx_count-- > 0 && tx_msg->offset < tx_msg->buflen)
|
||
{
|
||
/* ���tx fifo�Ƿ����� */
|
||
if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) ==
|
||
port->tx_fifofull)
|
||
{
|
||
break;
|
||
}
|
||
port->regs->UR_TXW = tx_msg->buf[tx_msg->offset];
|
||
tx_msg->offset++;
|
||
port->icount.tx++;
|
||
}
|
||
|
||
if (tx_msg->offset >= tx_msg->buflen)
|
||
{
|
||
dl_list_del(&tx_msg->list);
|
||
dl_list_add_tail(&port->tx_msg_to_be_freed_list, &tx_msg->list);
|
||
tls_os_release_critical(cpu_sr);
|
||
|
||
// if(tx_sent_callback)
|
||
// tx_sent_callback(port);
|
||
if (port->tx_callback)
|
||
port->tx_callback(port);
|
||
}else{
|
||
tls_os_release_critical(cpu_sr);
|
||
}
|
||
}else{
|
||
tls_os_release_critical(cpu_sr);
|
||
|
||
if (port->tx_sem)
|
||
tls_os_sem_release(port->tx_sem);
|
||
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to continue transfer data.
|
||
* @param[in] port: is the uart port.
|
||
* @retval
|
||
*/
|
||
static void tls_uart_tx_chars(struct tls_uart_port *port)
|
||
{
|
||
struct dl_list *pending_list = &port->tx_msg_pending_list;
|
||
tls_uart_tx_msg_t *tx_msg = NULL;
|
||
int tx_count = 64;
|
||
// int len;
|
||
// u32 cpu_sr;
|
||
u8 fifofull = 0;
|
||
|
||
if (dl_list_empty(pending_list))
|
||
{
|
||
// tls_uart_tx_disable(port);
|
||
|
||
if (port->tx_sem)
|
||
tls_os_sem_release(port->tx_sem);
|
||
|
||
return;
|
||
}
|
||
|
||
// cpu_sr = tls_os_set_critical();
|
||
while (!dl_list_empty(pending_list) && !fifofull)
|
||
{
|
||
tx_msg = dl_list_first(pending_list, tls_uart_tx_msg_t, list);
|
||
while (tx_count-- > 0 && tx_msg->offset < tx_msg->buflen)
|
||
{
|
||
/* ���tx fifo�Ƿ����� */
|
||
if ((port->regs->UR_FIFOS & UFS_TX_FIFO_CNT_MASK) ==
|
||
port->tx_fifofull)
|
||
{
|
||
fifofull = 1;
|
||
break;
|
||
}
|
||
port->regs->UR_TXW = tx_msg->buf[tx_msg->offset];
|
||
tx_msg->offset++;
|
||
port->icount.tx++;
|
||
}
|
||
if (tx_msg->offset >= tx_msg->buflen)
|
||
{
|
||
// cpu_sr = tls_os_set_critical();
|
||
dl_list_del(&tx_msg->list);
|
||
dl_list_add_tail(&port->tx_msg_to_be_freed_list, &tx_msg->list);
|
||
// tls_os_release_critical(cpu_sr);
|
||
// if(tx_sent_callback)
|
||
// tx_sent_callback(port);
|
||
|
||
if (port->tx_callback)
|
||
port->tx_callback(port);
|
||
}
|
||
}
|
||
// tls_os_release_critical(cpu_sr);
|
||
#if 0
|
||
len = uart_circ_chars_pending(xmit);
|
||
if (len < WAKEUP_CHARS)
|
||
{
|
||
if (port->tx_callback)
|
||
port->tx_callback(port);
|
||
}
|
||
|
||
|
||
if (uart_circ_empty(xmit))
|
||
tls_uart_tx_disable(port);
|
||
#endif
|
||
}
|
||
|
||
#if DEBUG_RX_LEN
|
||
static int tls_rx_len = 0;
|
||
|
||
int get_rx_len(void)
|
||
{
|
||
return tls_rx_len;
|
||
}
|
||
|
||
void clear_rx_len(void)
|
||
{
|
||
tls_rx_len = 0;
|
||
}
|
||
#endif
|
||
|
||
void tls_set_uart_rx_status(int uart_no, int status)
|
||
{
|
||
u32 cpu_sr;
|
||
struct tls_uart_port *port;
|
||
|
||
if (TLS_UART_1 == uart_no)
|
||
{
|
||
port = &uart_port[1];
|
||
// TLS_DBGPRT_INFO("port%d set rx status=%d,prev
|
||
// rxstatus=%d\n",uart_no,status,port->rxstatus);
|
||
if ((TLS_UART_RX_DISABLE == port->rxstatus
|
||
&& TLS_UART_RX_DISABLE == status)
|
||
|| (TLS_UART_RX_ENABLE == port->rxstatus
|
||
&& TLS_UART_RX_ENABLE == status))
|
||
return;
|
||
|
||
if (TLS_UART_RX_DISABLE == status)
|
||
{
|
||
// TLS_DBGPRT_INFO("\nopts
|
||
// flowctrl=%d,fcstatus=%d\n",port->opts.flow_ctrl,port->fcStatus);
|
||
if ((TLS_UART_FLOW_CTRL_HARDWARE == port->opts.flow_ctrl)
|
||
&& (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus))
|
||
{
|
||
cpu_sr = tls_os_set_critical();
|
||
// ��rxfifo trigger level interrupt��overrun error
|
||
port->regs->UR_INTM |= ((0x1 << 2) | (0x01 << 8));
|
||
port->rxstatus = TLS_UART_RX_DISABLE;
|
||
tls_os_release_critical(cpu_sr);
|
||
// TLS_DBGPRT_INFO(" rx int mask status=%d\n",port->rxstatus);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// TLS_DBGPRT_INFO("start unmask\n");
|
||
cpu_sr = tls_os_set_critical();
|
||
uart_port[1].regs->UR_INTM &= ~((0x1 << 2) | (0x01 << 8));
|
||
port->rxstatus = TLS_UART_RX_ENABLE;
|
||
tls_os_release_critical(cpu_sr);
|
||
// TLS_DBGPRT_INFO("rx int unmask status=%d\n",port->rxstatus);
|
||
}
|
||
}
|
||
}
|
||
|
||
void UART0_IRQHandler(void)
|
||
{
|
||
struct tls_uart_port *port = &uart_port[0];
|
||
struct tls_uart_circ_buf *recv = &port->recv;
|
||
u32 intr_src;
|
||
u32 rx_fifocnt;
|
||
u32 fifos;
|
||
u8 ch;
|
||
u32 rxlen = 0;
|
||
|
||
/* check interrupt status */
|
||
intr_src = port->regs->UR_INTS;
|
||
port->regs->UR_INTS = intr_src;
|
||
|
||
if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO)))
|
||
{
|
||
rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F;
|
||
#if DEBUG_RX_LEN
|
||
tls_rx_len += rx_fifocnt;
|
||
#endif
|
||
while (rx_fifocnt-- > 0)
|
||
{
|
||
ch = (u8) port->regs->UR_RXW;
|
||
if (intr_src & UART_RX_ERR_INT_FLAG)
|
||
{
|
||
port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG;
|
||
TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch);
|
||
/* not insert to buffer */
|
||
continue;
|
||
}
|
||
if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= 2)
|
||
{
|
||
TLS_DBGPRT_INFO("\nrx buf overrun int_src=%x\n", intr_src);
|
||
if (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus)
|
||
{
|
||
tls_set_uart_rx_status(port->uart_no, TLS_UART_RX_DISABLE);
|
||
rx_fifocnt = 0; // �����Ӳ�����أ��رս��գ������һ���ַ��Ž�����buffer��
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
|
||
/* insert the character into the buffer */
|
||
recv->buf[recv->head] = ch;
|
||
recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1);
|
||
rxlen++;
|
||
}
|
||
if (port->rx_callback != NULL)
|
||
{
|
||
port->rx_callback((u16) rxlen);
|
||
}
|
||
}
|
||
|
||
if (intr_src & UART_TX_INT_FLAG)
|
||
{
|
||
tls_uart_tx_chars(port);
|
||
}
|
||
|
||
if (intr_src & UIS_CTS_CHNG)
|
||
{
|
||
fifos = port->regs->UR_FIFOS;
|
||
uart_handle_cts_change(port, fifos & UFS_CST_STS);
|
||
}
|
||
return;
|
||
}
|
||
|
||
void UART1_IRQHandler(void)
|
||
{
|
||
struct tls_uart_port *port = &uart_port[1];
|
||
struct tls_uart_circ_buf *recv = &port->recv;
|
||
u32 intr_src;
|
||
u32 rx_fifocnt;
|
||
u32 fifos;
|
||
u8 ch = 0;
|
||
u8 escapefifocnt = 0;
|
||
u32 rxlen = 0;
|
||
|
||
/* check interrupt status */
|
||
intr_src = port->regs->UR_INTS;
|
||
port->regs->UR_INTS = intr_src;
|
||
|
||
if (intr_src & UIS_OVERRUN)
|
||
{
|
||
port->regs->UR_INTS |= UIS_OVERRUN;
|
||
if(port->tx_dma_on)
|
||
{
|
||
tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01));
|
||
tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01));
|
||
}
|
||
}
|
||
if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO)))
|
||
{
|
||
rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F;
|
||
#if DEBUG_RX_LEN
|
||
tls_rx_len += rx_fifocnt;
|
||
#endif
|
||
escapefifocnt = rx_fifocnt;
|
||
port->plus_char_cnt = 0;
|
||
rxlen = rx_fifocnt;
|
||
|
||
if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= RX_CACHE_LIMIT)
|
||
{
|
||
recv->tail = (recv->tail + RX_CACHE_LIMIT) & (TLS_UART_RX_BUF_SIZE - 1);
|
||
}
|
||
|
||
while (rx_fifocnt-- > 0)
|
||
{
|
||
ch = (u8) port->regs->UR_RXW;
|
||
if (intr_src & UART_RX_ERR_INT_FLAG)
|
||
{
|
||
port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG;
|
||
TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch);
|
||
continue;
|
||
}
|
||
recv->buf[recv->head] = ch;
|
||
recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1);
|
||
}
|
||
|
||
if( escapefifocnt==3 && ch=='+')
|
||
{
|
||
switch(recv->head-1)
|
||
{
|
||
case 0:
|
||
if(recv->buf[TLS_UART_RX_BUF_SIZE-1]=='+' && recv->buf[TLS_UART_RX_BUF_SIZE-2]=='+')
|
||
port->plus_char_cnt = 3;
|
||
break;
|
||
case 1:
|
||
if(recv->buf[0]=='+' && recv->buf[TLS_UART_RX_BUF_SIZE-1]=='+')
|
||
port->plus_char_cnt = 3;
|
||
break;
|
||
default:
|
||
if(recv->buf[recv->head-2]=='+' && recv->buf[recv->head-3]=='+')
|
||
port->plus_char_cnt = 3;
|
||
break;
|
||
}
|
||
}
|
||
if (port->rx_callback!=NULL)
|
||
{
|
||
port->rx_callback((u16) rxlen);
|
||
}
|
||
}
|
||
if (intr_src & UART_TX_INT_FLAG)
|
||
{
|
||
tls_uart_tx_chars(port);
|
||
}
|
||
if (intr_src & UIS_CTS_CHNG)
|
||
{
|
||
fifos = port->regs->UR_FIFOS;
|
||
uart_handle_cts_change(port, fifos & UFS_CST_STS);
|
||
}
|
||
return;
|
||
}
|
||
|
||
void UART2_IRQHandler(void)
|
||
{
|
||
struct tls_uart_port *port = &uart_port[2];
|
||
struct tls_uart_circ_buf *recv = &port->recv;
|
||
u32 intr_src;
|
||
u32 rx_fifocnt;
|
||
u32 fifos;
|
||
u8 ch;
|
||
u32 rxlen = 0;
|
||
|
||
/* check interrupt status */
|
||
intr_src = port->regs->UR_INTS;
|
||
port->regs->UR_INTS = intr_src;
|
||
|
||
if (intr_src & UIS_OVERRUN)
|
||
{
|
||
port->regs->UR_INTS |= UIS_OVERRUN;
|
||
if(port->tx_dma_on)
|
||
{
|
||
tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01));
|
||
tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01));
|
||
}
|
||
}
|
||
if ((intr_src & UART_RX_INT_FLAG) && (0 == (port->regs->UR_INTM & UIS_RX_FIFO)))
|
||
{
|
||
rx_fifocnt = (port->regs->UR_FIFOS >> 6) & 0x3F;
|
||
#if DEBUG_RX_LEN
|
||
tls_rx_len += rx_fifocnt;
|
||
#endif
|
||
while (rx_fifocnt-- > 0)
|
||
{
|
||
ch = (u8) port->regs->UR_RXW;
|
||
/* break, stop bit error parity error, not include overrun err */
|
||
if (intr_src & UART_RX_ERR_INT_FLAG)
|
||
{
|
||
port->regs->UR_INTS |= UART_RX_ERR_INT_FLAG;
|
||
TLS_DBGPRT_INFO("\nrx err=%x,c=%d,ch=%x\n", intr_src, rx_fifocnt, ch);
|
||
/* not insert to buffer */
|
||
continue;
|
||
}
|
||
// if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) == 0)
|
||
if (CIRC_SPACE(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE) <= 2)
|
||
{
|
||
TLS_DBGPRT_INFO("\nrx buf overrun int_src=%x\n", intr_src);
|
||
if (TLS_UART_FLOW_CTRL_HARDWARE == port->fcStatus)
|
||
{
|
||
tls_set_uart_rx_status(port->uart_no, TLS_UART_RX_DISABLE);
|
||
rx_fifocnt = 0; // �����Ӳ�����أ��رս��գ������һ���ַ��Ž�����buffer��
|
||
}
|
||
else
|
||
break;
|
||
}
|
||
|
||
/* insert the character into the buffer */
|
||
recv->buf[recv->head] = ch;
|
||
recv->head = (recv->head + 1) & (TLS_UART_RX_BUF_SIZE - 1);
|
||
rxlen++;
|
||
}
|
||
if(port->rx_callback != NULL && rxlen)
|
||
{
|
||
port->rx_callback((u16) rxlen);
|
||
}
|
||
|
||
}
|
||
|
||
if (intr_src & UART_TX_INT_FLAG)
|
||
{
|
||
tls_uart_tx_chars(port);
|
||
}
|
||
|
||
if (intr_src & UIS_CTS_CHNG)
|
||
{
|
||
fifos = port->regs->UR_FIFOS;
|
||
uart_handle_cts_change(port, fifos & UFS_CST_STS);
|
||
}
|
||
return;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to initial uart port.
|
||
*
|
||
* @param[in] uart_no: is the uart number.
|
||
* - \ref TLS_UART_0
|
||
* - \ref TLS_UART_1
|
||
* - \ref TLS_UART_2
|
||
* @param[in] opts: is the uart setting options,if this param is NULL,this function will use the default options.
|
||
* @param[in] modeChoose:; choose uart2 mode or 7816 mode when uart_no is TLS_UART_2, 0 for uart2 mode and 1 for 7816 mode.
|
||
*
|
||
* @retval
|
||
* - \ref WM_SUCCESS
|
||
* - \ref WM_FAILED
|
||
*
|
||
* @note When the system is initialized, the function has been called, so users can not call the function.
|
||
*/
|
||
int tls_uart_port_init(u16 uart_no, tls_uart_options_t * opts, u8 modeChoose)
|
||
{
|
||
struct tls_uart_port *port;
|
||
int ret;
|
||
char *bufrx; // ,*buftx
|
||
tls_uart_options_t opt;
|
||
|
||
|
||
|
||
UartRegInit(uart_no);
|
||
if (uart_no > TLS_UART_2)
|
||
{
|
||
return WM_FAILED;
|
||
}
|
||
|
||
if (uart_port[uart_no].recv.buf)
|
||
{
|
||
tls_mem_free(uart_port[uart_no].recv.buf);
|
||
uart_port[uart_no].recv.buf = NULL;
|
||
}
|
||
|
||
memset(&uart_port[uart_no], 0, sizeof(struct tls_uart_port));
|
||
port = &uart_port[uart_no];
|
||
|
||
if (TLS_UART_0 == uart_no)
|
||
{
|
||
port->regs = (TLS_UART_REGS_T *) HR_UART0_BASE_ADDR;
|
||
}
|
||
else if (TLS_UART_1 == uart_no)
|
||
{
|
||
port->regs = (TLS_UART_REGS_T *) HR_UART1_BASE_ADDR;
|
||
}
|
||
else if (TLS_UART_2 == uart_no)
|
||
{
|
||
port->regs = (TLS_UART_REGS_T *) HR_UART2_BASE_ADDR;
|
||
(modeChoose == 1)?(port->regs->UR_LC |= (1 << 24)):(port->regs->UR_LC &= ~(0x1000000));
|
||
}
|
||
|
||
port->uart_no = uart_no;
|
||
|
||
if (NULL == opts)
|
||
{
|
||
opt.baudrate = UART_BAUDRATE_B115200;
|
||
opt.charlength = TLS_UART_CHSIZE_8BIT;
|
||
opt.flow_ctrl = TLS_UART_FLOW_CTRL_NONE;
|
||
opt.paritytype = TLS_UART_PMODE_DISABLED;
|
||
opt.stopbits = TLS_UART_ONE_STOPBITS;
|
||
ret = tls_uart_config(port, &opt);
|
||
}
|
||
else
|
||
{
|
||
ret = tls_uart_config(port, opts);
|
||
}
|
||
|
||
if (ret != WM_SUCCESS)
|
||
return WM_FAILED;
|
||
port->rxstatus = TLS_UART_RX_ENABLE;
|
||
port->uart_irq_no = (uart_no == TLS_UART_0) ? UART0_INT : ((uart_no == TLS_UART_1) ? UART1_INT : UART2_INT);
|
||
tls_irq_disable(port->uart_irq_no);
|
||
|
||
if (port->recv.buf == NULL){
|
||
bufrx = tls_mem_alloc(TLS_UART_RX_BUF_SIZE);
|
||
if (!bufrx)
|
||
return WM_FAILED;
|
||
memset(bufrx, 0, TLS_UART_RX_BUF_SIZE);
|
||
port->recv.buf = (u8 *) bufrx;
|
||
}
|
||
port->recv.head = 0;
|
||
port->recv.tail = 0;
|
||
port->tx_fifofull = 16;
|
||
dl_list_init(&port->tx_msg_pending_list);
|
||
dl_list_init(&port->tx_msg_to_be_freed_list);
|
||
tls_uart_tx_callback_register(uart_no, tls_uart_free_tx_sent_data);
|
||
|
||
/* enable uart interrupt */
|
||
tls_irq_enable(port->uart_irq_no);
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to register uart rx interrupt.
|
||
*
|
||
* @param[in] uart_no: is the uart numer.
|
||
* @param[in] callback: is the uart rx interrupt call back function.
|
||
*
|
||
* @retval
|
||
*
|
||
* @note This function should be called after the fucntion tls_uart_port_init() or it won't work.
|
||
*/
|
||
void tls_uart_rx_callback_register(u16 uart_no, s16(*rx_callback) (u16 len))
|
||
{
|
||
if (TLS_UART_0 == uart_no)
|
||
uart_port[0].rx_callback = rx_callback;
|
||
else if (TLS_UART_1 == uart_no)
|
||
uart_port[1].rx_callback = rx_callback;
|
||
else if (TLS_UART_2 == uart_no)
|
||
uart_port[2].rx_callback = rx_callback;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to register uart tx interrupt.
|
||
*
|
||
* @param[in] uart_no: is the uart numer.
|
||
* @param[in] callback: is the uart tx interrupt call back function.
|
||
*
|
||
* @retval
|
||
*/
|
||
void tls_uart_tx_callback_register(u16 uart_no,
|
||
s16(*tx_callback) (struct tls_uart_port *
|
||
port))
|
||
{
|
||
if (TLS_UART_0 == uart_no)
|
||
uart_port[0].tx_callback = tx_callback;
|
||
else if (TLS_UART_1 == uart_no)
|
||
uart_port[1].tx_callback = tx_callback;
|
||
else if (TLS_UART_2 == uart_no)
|
||
uart_port[2].tx_callback = tx_callback;
|
||
}
|
||
|
||
//void tls_uart_tx_sent_register(void (*tx_sent_callbk)(struct tls_uart_port *port))
|
||
//{
|
||
// tx_sent_callback = tx_sent_callbk;
|
||
//}
|
||
|
||
/**
|
||
* @brief This function is used to copy circular buffer data to user buffer.
|
||
* @param[in] uart_no: is the uart numer.
|
||
* @param[in] buf: is the user buffer.
|
||
* @param[in] readsize: is the user read size.
|
||
* @retval -1:failed
|
||
* other:real length to written in buf
|
||
*/
|
||
int tls_uart_read(u16 uart_no, u8 * buf, u16 readsize)
|
||
{
|
||
int data_cnt, buflen, bufcopylen;
|
||
struct tls_uart_port *port = NULL;
|
||
struct tls_uart_circ_buf *recv;
|
||
|
||
if (NULL == buf || readsize < 1)
|
||
return WM_FAILED;
|
||
|
||
if (TLS_UART_0 == uart_no)
|
||
port = &uart_port[0];
|
||
else if (TLS_UART_1 == uart_no)
|
||
port = &uart_port[1];
|
||
else if (TLS_UART_2 == uart_no)
|
||
port = &uart_port[2];
|
||
|
||
recv = &port->recv;
|
||
data_cnt = CIRC_CNT(recv->head, recv->tail, TLS_UART_RX_BUF_SIZE);
|
||
if (data_cnt >= readsize)
|
||
{
|
||
buflen = readsize;
|
||
}
|
||
else // ������ݲ�����ֱ�ӷ���0
|
||
{
|
||
buflen = data_cnt;
|
||
}
|
||
if ((recv->tail + buflen) > TLS_UART_RX_BUF_SIZE)
|
||
{
|
||
bufcopylen = (TLS_UART_RX_BUF_SIZE - recv->tail);
|
||
MEMCPY(buf, recv->buf + recv->tail, bufcopylen);
|
||
MEMCPY(buf + bufcopylen, recv->buf, buflen - bufcopylen);
|
||
}
|
||
else
|
||
{
|
||
MEMCPY(buf, recv->buf + recv->tail, buflen);
|
||
}
|
||
recv->tail = (recv->tail + buflen) & (TLS_UART_RX_BUF_SIZE - 1);
|
||
return buflen;
|
||
}
|
||
|
||
|
||
u8 *testbuf;
|
||
u16 flag = 0;
|
||
u16 datalen = 0;
|
||
|
||
#ifdef TEST_UART
|
||
/**********************************************************************************************************
|
||
* Description: This function is used to receive uart data.
|
||
*
|
||
* Arguments : buf is a buf for saving received data.
|
||
*
|
||
* Returns : Return received data length.
|
||
* Notes :
|
||
**********************************************************************************************************/
|
||
s16 tls_uart_rx_test(u16 len)
|
||
{
|
||
|
||
if (datalen < (4096 - len))
|
||
{
|
||
// MEMCPY(testbuf + datalen, buf, len);
|
||
tls_uart_read(TLS_UART_1, testbuf + datalen, len);
|
||
flag = 1;
|
||
datalen += len;
|
||
}
|
||
else
|
||
{
|
||
TLS_DBGPRT_INFO("\rx buffer over\n");
|
||
}
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
|
||
void tls_uart_test(void)
|
||
{
|
||
int len = 0;
|
||
|
||
TLS_DBGPRT_INFO("\nentry tls_uart_test\n");
|
||
testbuf = tls_mem_alloc(4096);
|
||
if (!testbuf)
|
||
return;
|
||
memset(testbuf, 0, 4096);
|
||
// tls_uart_cfg_user_mode();
|
||
tls_uart_rx_callback_register(TLS_UART_1, tls_uart_rx_test);
|
||
#if 0
|
||
tls_user_uart_set_baud_rate(UART_BAUDRATE_B38400);
|
||
tls_user_uart_set_stop_bits(TLS_UART_ONE_STOPBITS);
|
||
tls_user_uart_set_parity(TLS_UART_PMODE_DISABLED);
|
||
#endif
|
||
TLS_DBGPRT_INFO("\nentry while\n");
|
||
while (1)
|
||
{
|
||
// TLS_DBGPRT_INFO("\n==============flag=%d\n",flag);
|
||
|
||
OSTimeDly(0x100);
|
||
if (flag)
|
||
{
|
||
TLS_DBGPRT_INFO("\n\rrx data len = %d\n%s\n\r", datalen, testbuf);
|
||
// tls_uart_tx("\n\r",2);
|
||
tls_uart_write_sync(TLS_UART_1, testbuf, datalen);
|
||
len = tls_uart_tx_length(TLS_UART_1);
|
||
printf("\ntx len=%d\n", len);
|
||
|
||
len = tls_uart_tx_length();
|
||
printf("\ntx len 0=%d\n", len);
|
||
// tls_uart_tx("\n\r",2);
|
||
tls_uart_write(TLS_UART_1, "abcde", 5);
|
||
len = tls_uart_tx_length(TLS_UART_1);
|
||
printf("\ntx len 1=%d\n", len);
|
||
flag = 0;
|
||
datalen = 0;
|
||
}
|
||
// len = tls_uart_tx_length();
|
||
// printf("\ntx len 2=%d\n",len);
|
||
|
||
}
|
||
|
||
}
|
||
|
||
#endif
|
||
/**********************************************************************************************************
|
||
* Description: This function is used to config uart port for user mode.
|
||
*
|
||
* Arguments :
|
||
*
|
||
* Returns :
|
||
* Notes : If user want to use uart function,must call this function.
|
||
**********************************************************************************************************/
|
||
#if 0
|
||
void tls_uart_cfg_user_mode(void)
|
||
{
|
||
struct tls_uart_port *port = &uart_port[1];
|
||
|
||
port->ifusermode = 1;
|
||
memset(port->recv.buf, 0, TLS_UART_RX_BUF_SIZE);
|
||
port->recv.head = 0;
|
||
port->recv.tail = 0;
|
||
port->icount.rx = 0;
|
||
|
||
port->rx_callback_bk = port->rx_callback;
|
||
port->rx_callback = NULL;
|
||
|
||
port->tx_callback_bk = port->tx_callback;
|
||
port->tx_callback = NULL;
|
||
}
|
||
#endif
|
||
/**********************************************************************************************************
|
||
* Description: This function is used to disable uart user mode.
|
||
*
|
||
* Arguments :
|
||
*
|
||
* Returns :
|
||
* Notes : If user want to resume uart old function for AT commond,must call this function.
|
||
**********************************************************************************************************/
|
||
#if 0
|
||
void tls_uart_disable_user_mode(void)
|
||
{
|
||
struct tls_uart_port *port = &uart_port[1];
|
||
|
||
port->ifusermode = 0;
|
||
memset(port->recv.buf, 0, TLS_UART_RX_BUF_SIZE);
|
||
port->recv.head = 0;
|
||
port->recv.tail = 0;
|
||
|
||
port->rx_callback = port->rx_callback_bk;
|
||
port->rx_callback_bk = NULL;
|
||
|
||
port->tx_callback = port->tx_callback_bk;
|
||
port->tx_callback_bk = NULL;
|
||
}
|
||
#endif
|
||
|
||
#if 0
|
||
static s16 tls_uart_tx_cb(struct tls_uart_port *port)
|
||
{
|
||
int ret_len = 0;
|
||
|
||
if (NULL == port)
|
||
return WM_FAILED;
|
||
if (port->buf_len > 0) // uart1,���������ݴ������֮��ʣ��Ĵ����������ٷ��뻺����
|
||
{
|
||
ret_len = tls_uart_fill_buf(port, port->buf_ptr, port->buf_len);
|
||
// TLS_DBGPRT_INFO("\ntx cb write len=%d",ret_len);
|
||
|
||
if (ret_len >= 0)
|
||
{
|
||
if (port->buf_len >= ret_len)
|
||
{
|
||
port->buf_len -= ret_len;
|
||
port->buf_ptr += ret_len;
|
||
}
|
||
}
|
||
}
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
#endif
|
||
|
||
|
||
/**
|
||
* @brief This function is used to transfer data throuth DMA.
|
||
*
|
||
* @param[in] buf is a buf for saving user data
|
||
* @param[in] writesize is the user data length
|
||
* @param[in] cmpl_callback function point,when the transfer is completed, the function will be called.
|
||
* @param[in] uart_no is the uart number
|
||
*
|
||
* @retval WM_SUCCESS success
|
||
* @retval WM_FAILED failed
|
||
*
|
||
* @note Only uart1 support DMA transfer.
|
||
*/
|
||
int tls_uart_dma_write(char *buf, u16 writesize, void (*cmpl_callback) (void *p), u16 uart_no)
|
||
{
|
||
unsigned char dmaCh = 0;
|
||
struct tls_dma_descriptor DmaDesc;
|
||
struct tls_uart_port *port = &uart_port[uart_no];
|
||
|
||
if (NULL == buf || writesize < 1 || writesize >= 4096)
|
||
{
|
||
TLS_DBGPRT_ERR("param err\n");
|
||
return WM_FAILED;
|
||
}
|
||
if (port->tx_dma_on)
|
||
{
|
||
TLS_DBGPRT_ERR("transmiting,wait\n");
|
||
return WM_FAILED;
|
||
}
|
||
// port->tx_dma_cmpl_callbk = cmpl_callback;
|
||
|
||
tls_reg_write32(HR_DMA_CHNL_SEL, uart_no);
|
||
|
||
/* Request DMA Channel */
|
||
dmaCh = tls_dma_request(2,
|
||
TLS_DMA_FLAGS_CHANNEL_SEL(TLS_DMA_SEL_UART_TX) | TLS_DMA_FLAGS_HARD_MODE);
|
||
if (dmaCh != 2)
|
||
{
|
||
TLS_DBGPRT_ERR("dma request err\n");
|
||
return WM_FAILED;
|
||
}
|
||
tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) & ~0x01));
|
||
tls_dma_irq_register(dmaCh, cmpl_callback, (void *)(uintptr_t)uart_no, TLS_DMA_IRQ_TRANSFER_DONE);
|
||
DmaDesc.src_addr = (int) buf;
|
||
DmaDesc.dest_addr = (int)&port->regs->UR_TXW;
|
||
DmaDesc.dma_ctrl = TLS_DMA_DESC_CTRL_SRC_ADD_INC | TLS_DMA_DESC_CTRL_DATA_SIZE_BYTE |
|
||
(writesize << 7);
|
||
DmaDesc.valid = TLS_DMA_DESC_VALID;
|
||
DmaDesc.next = NULL;
|
||
tls_dma_start(dmaCh, &DmaDesc, 0);
|
||
/* Enable uart TX DMA */
|
||
port->tx_dma_on = TRUE;
|
||
tls_reg_write32((int)&port->regs->UR_DMAC, (tls_reg_read32((int)&port->regs->UR_DMAC) | 0x01));
|
||
tls_reg_write32(HR_DMA_INT_MASK,
|
||
(tls_reg_read32(HR_DMA_INT_MASK) & ~(0x01 << 5)));
|
||
|
||
/* enable dma interrupt */
|
||
tls_irq_enable(DMA2_INT);
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to transfer data asynchronous.
|
||
*
|
||
* @param[in] uart_no is the uart number
|
||
* @param[in] buf is a buf for saving user data.
|
||
* @param[in] writesize is the data length
|
||
*
|
||
* @retval WM_SUCCESS success
|
||
* @retval WM_FAILED failed
|
||
*
|
||
* @note The function only start transmission, fill buffer in the callback function.
|
||
*/
|
||
int tls_uart_write_async(u16 uart_no, char *buf, u16 writesize)
|
||
{
|
||
struct tls_uart_port *port = NULL;
|
||
int ret;
|
||
|
||
if (NULL == buf || writesize < 1)
|
||
{
|
||
TLS_DBGPRT_ERR("param err\n");
|
||
return WM_FAILED;
|
||
}
|
||
|
||
if (TLS_UART_1 == uart_no)
|
||
port = &uart_port[1];
|
||
else if (TLS_UART_0 == uart_no)
|
||
port = &uart_port[0];
|
||
else if (TLS_UART_2 == uart_no)
|
||
port = &uart_port[2];
|
||
|
||
ret = tls_uart_fill_buf(port, buf, writesize);
|
||
|
||
if (0 == ret)
|
||
{
|
||
tls_uart_tx_chars_start(port);
|
||
}
|
||
|
||
return ret;
|
||
}
|
||
|
||
/**
|
||
* @brief get the data length has been transmitted.
|
||
*
|
||
* @param[in] uart_no is the uart number
|
||
*
|
||
* @retval the length has been transmitted
|
||
*
|
||
*/
|
||
int tls_uart_tx_length(u16 uart_no)
|
||
{
|
||
struct tls_uart_port *port = &uart_port[uart_no];
|
||
|
||
return port->icount.tx;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to transfer data synchronous.
|
||
*
|
||
* @param[in] uart_no is the uart number
|
||
* @param[in] buf is a buf for saving user data.
|
||
* @param[in] writesize is the data length
|
||
*
|
||
* @retval WM_SUCCESS success
|
||
* @retval WM_FAILED failed
|
||
*
|
||
* @note The function only start transmission, fill buffer in the callback function.
|
||
*/
|
||
int tls_uart_write(u16 uart_no, char *buf, u16 writesize)
|
||
{
|
||
struct tls_uart_port *port = NULL;
|
||
u8 err;
|
||
int ret = 0;
|
||
|
||
if (TLS_UART_1 == uart_no)
|
||
port = &uart_port[1];
|
||
else if (TLS_UART_0 == uart_no)
|
||
port = &uart_port[0];
|
||
else if (TLS_UART_2 == uart_no)
|
||
port = &uart_port[2];
|
||
|
||
err = tls_os_sem_create(&port->tx_sem, 0);
|
||
if (err != TLS_OS_SUCCESS)
|
||
{
|
||
TLS_DBGPRT_ERR("\ntx sem create fail\n");
|
||
return WM_FAILED;
|
||
}
|
||
|
||
ret = tls_uart_write_async(uart_no, buf, writesize);
|
||
if (0 == ret)
|
||
{
|
||
tls_os_sem_acquire(port->tx_sem, 0);
|
||
}
|
||
tls_os_sem_delete(port->tx_sem);
|
||
port->tx_sem = NULL;
|
||
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
|
||
/**********************************************************************************************************
|
||
* Description: This function is used to register uart rx interrupt.
|
||
*
|
||
* Arguments : callback is the uart rx interrupt call back function.
|
||
*
|
||
* Returns :
|
||
*
|
||
**********************************************************************************************************/
|
||
#if 0
|
||
void tls_user_uart_rx_register(s16(*rx_callback) (char *buf, u16 len))
|
||
{
|
||
tls_uart_rx_callback_register(TLS_UART_1, rx_callback);
|
||
}
|
||
#endif
|
||
/**********************************************************************************************************
|
||
* Description: This function is used to register uart tx interrupt.
|
||
*
|
||
* Arguments : callback is the uart tx interrupt call back function.
|
||
*
|
||
* Returns :
|
||
*
|
||
**********************************************************************************************************/
|
||
#if 0
|
||
void tls_user_uart_tx_register(s16(*tx_callback) (struct tls_uart_port * port))
|
||
{
|
||
tls_uart_tx_callback_register(TLS_UART_1, tx_callback);
|
||
}
|
||
#endif
|
||
/**
|
||
* @brief This function is used to set uart parity.
|
||
*
|
||
* @param[in] paritytype is a parity type defined in TLS_UART_PMODE_T
|
||
*
|
||
* @retval WM_SUCCESS success
|
||
* @retval WM_FAILED failed
|
||
*
|
||
*/
|
||
int tls_uart_set_parity(u16 uart_no, TLS_UART_PMODE_T paritytype)
|
||
{
|
||
if (TLS_UART_1 == uart_no)
|
||
return tls_uart_set_parity_inside(&uart_port[1], paritytype);
|
||
else if (TLS_UART_0 == uart_no)
|
||
return tls_uart_set_parity_inside(&uart_port[0], paritytype);
|
||
else if (TLS_UART_2 == uart_no)
|
||
return tls_uart_set_parity_inside(&uart_port[2], paritytype);
|
||
return WM_FAILED;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to set uart baudrate.
|
||
*
|
||
* @param[in] uart_no is the uart number
|
||
* @param[in] baudrate is the baudrate user want used,the unit is HZ.
|
||
*
|
||
* @retval WM_SUCCESS success
|
||
* @retval WM_FAILED failed
|
||
*
|
||
*/
|
||
int tls_uart_set_baud_rate(u16 uart_no, u32 baudrate)
|
||
{
|
||
if (TLS_UART_1 == uart_no)
|
||
return tls_uart_set_baud_rate_inside(&uart_port[1], baudrate);
|
||
else if (TLS_UART_0 == uart_no)
|
||
return tls_uart_set_baud_rate_inside(&uart_port[0], baudrate);
|
||
else if (TLS_UART_2 == uart_no)
|
||
return tls_uart_set_baud_rate_inside(&uart_port[2], baudrate);
|
||
return WM_FAILED;
|
||
}
|
||
|
||
/**
|
||
* @brief This function is used to set uart stop bits.
|
||
*
|
||
* @param[in] uart_no is the uart number
|
||
* @param[in] stopbits is a stop bit type defined in TLS_UART_STOPBITS_T.
|
||
*
|
||
* @retval WM_SUCCESS success
|
||
* @retval WM_FAILED failed
|
||
*
|
||
*/
|
||
int tls_uart_set_stop_bits(u16 uart_no, TLS_UART_STOPBITS_T stopbits)
|
||
{
|
||
if (TLS_UART_1 == uart_no)
|
||
return tls_uart_set_stop_bits_inside(&uart_port[1], stopbits);
|
||
else if (TLS_UART_0 == uart_no)
|
||
return tls_uart_set_stop_bits_inside(&uart_port[0], stopbits);
|
||
else if (TLS_UART_2 == uart_no)
|
||
return tls_uart_set_stop_bits_inside(&uart_port[2], stopbits);
|
||
return WM_FAILED;
|
||
}
|
||
|
||
int tls_uart_dma_off(u16 uart_no)
|
||
{
|
||
uart_port[uart_no].tx_dma_on = FALSE;
|
||
return WM_SUCCESS;
|
||
}
|
||
|
||
int tls_uart_output_char(int ch)
|
||
{
|
||
#if WM_CONFIG_DEBUG_UART1
|
||
tls_reg_write32(HR_UART1_INT_MASK, 0x3);
|
||
if(ch == '\n')
|
||
{
|
||
while (tls_reg_read32(HR_UART1_FIFO_STATUS)&0x3F);
|
||
tls_reg_write32(HR_UART1_TX_WIN, '\r');
|
||
}
|
||
while(tls_reg_read32(HR_UART1_FIFO_STATUS)&0x3F);
|
||
tls_reg_write32(HR_UART1_TX_WIN, (char)ch);
|
||
tls_reg_write32(HR_UART1_INT_MASK, 0x0);
|
||
#elif WM_CONFIG_DEBUG_UART2
|
||
tls_reg_write32(HR_UART2_INT_MASK, 0x3);
|
||
if(ch == '\n')
|
||
{
|
||
while (tls_reg_read32(HR_UART2_FIFO_STATUS)&0x3F);
|
||
tls_reg_write32(HR_UART2_TX_WIN, '\r');
|
||
}
|
||
while(tls_reg_read32(HR_UART2_FIFO_STATUS)&0x3F);
|
||
tls_reg_write32(HR_UART2_TX_WIN, (char)ch);
|
||
tls_reg_write32(HR_UART2_INT_MASK, 0x0);
|
||
#else
|
||
tls_reg_write32(HR_UART0_INT_MASK, 0x3);
|
||
if(ch == '\n')
|
||
{
|
||
while (tls_reg_read32(HR_UART0_FIFO_STATUS)&0x3F);
|
||
tls_reg_write32(HR_UART0_TX_WIN, '\r');
|
||
}
|
||
while(tls_reg_read32(HR_UART0_FIFO_STATUS)&0x3F);
|
||
tls_reg_write32(HR_UART0_TX_WIN, (char)ch);
|
||
tls_reg_write32(HR_UART0_INT_MASK, 0x0);
|
||
#endif
|
||
|
||
return ch;
|
||
}
|
||
#endif
|
||
//TLS_CONFIG_UART
|