Files
luban-lite-t3e-pro/bsp/artinchip/drv/uart/aic_drv_uart.c

704 lines
21 KiB
C
Raw Normal View History

2023-08-30 16:21:18 +08:00
/*
2024-09-03 11:16:08 +08:00
* Copyright (c) 2022-2024, Artinchip Technology Co., Ltd
2023-08-30 16:21:18 +08:00
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <rtthread.h>
#include <rtdevice.h>
#include <aic_core.h>
#include <aic_drv.h>
#include "aic_hal_uart.h"
#include "aic_drv_uart.h"
#ifndef AIC_CLK_UART0_FREQ
#define AIC_CLK_UART0_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART1_FREQ
#define AIC_CLK_UART1_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART2_FREQ
#define AIC_CLK_UART2_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART3_FREQ
#define AIC_CLK_UART3_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART4_FREQ
#define AIC_CLK_UART4_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART5_FREQ
#define AIC_CLK_UART5_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART6_FREQ
#define AIC_CLK_UART6_FREQ 48000000 /* default 48M*/
#endif
#ifndef AIC_CLK_UART7_FREQ
#define AIC_CLK_UART7_FREQ 48000000 /* default 48M*/
#endif
2024-04-03 16:40:57 +08:00
#ifndef AIC_UART0_CTS_NAME
#define AIC_UART0_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART1_CTS_NAME
#define AIC_UART1_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART2_CTS_NAME
#define AIC_UART2_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART3_CTS_NAME
#define AIC_UART3_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART4_CTS_NAME
#define AIC_UART4_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART5_CTS_NAME
#define AIC_UART5_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART6_CTS_NAME
#define AIC_UART6_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART7_CTS_NAME
#define AIC_UART7_CTS_NAME "no_pin"
#endif
#ifndef AIC_UART0_RTS_NAME
#define AIC_UART0_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART1_RTS_NAME
#define AIC_UART1_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART2_RTS_NAME
#define AIC_UART2_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART3_RTS_NAME
#define AIC_UART3_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART4_RTS_NAME
#define AIC_UART4_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART5_RTS_NAME
#define AIC_UART5_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART6_RTS_NAME
#define AIC_UART6_RTS_NAME "no_pin"
#endif
#ifndef AIC_UART7_RTS_NAME
#define AIC_UART7_RTS_NAME "no_pin"
#endif
struct aic_uart_rts_cts_dev
{
unsigned int uart_rts_pin;
unsigned int uart_cts_pin;
usart_handle_t handle;
};
struct aic_uart_rts_cts_dev uart_rts_dev[AIC_UART_DEV_NUM];
struct aic_uart_rts_cts_dev uart_cts_dev[AIC_UART_DEV_NUM];
2023-08-30 16:21:18 +08:00
void drv_usart_irqhandler(int irq, void * data);
2024-09-03 11:16:08 +08:00
void drv_usart_set_freq(uint32_t baudrate, int u);
2024-04-03 16:40:57 +08:00
static rt_err_t drv_uart_control(struct rt_serial_device *serial, int cmd, void *arg);
2023-08-30 16:21:18 +08:00
struct
{
uint32_t base;
uint32_t irq;
void *handler;
}
const drv_usart_config[AIC_UART_DEV_NUM] =
{
#if (AIC_UART_DEV_NUM >= 4)
{UART0_BASE, UART0_IRQn, drv_usart_irqhandler},
{UART1_BASE, UART1_IRQn, drv_usart_irqhandler},
{UART2_BASE, UART2_IRQn, drv_usart_irqhandler},
{UART3_BASE, UART3_IRQn, drv_usart_irqhandler},
#endif
#if (AIC_UART_DEV_NUM >= 8)
{UART4_BASE, UART4_IRQn, drv_usart_irqhandler},
{UART5_BASE, UART5_IRQn, drv_usart_irqhandler},
{UART6_BASE, UART6_IRQn, drv_usart_irqhandler},
{UART7_BASE, UART7_IRQn, drv_usart_irqhandler},
#endif
};
static usart_handle_t uart_handle[AIC_UART_DEV_NUM];
2024-04-03 16:40:57 +08:00
static struct rt_serial_device g_serial[AIC_UART_DEV_NUM];
2024-06-04 19:00:30 +08:00
#if defined (AIC_SERIAL_USING_DMA)
2024-04-03 16:40:57 +08:00
static uint32_t uart_rx_fifo[AIC_UART_RX_FIFO_SIZE] __attribute__((aligned(64)));
static uint32_t uart_tx_fifo[AIC_UART_TX_FIFO_SIZE] __attribute__((aligned(64)));
static uint32_t rx_size = 0;
2024-06-04 19:00:30 +08:00
#endif
struct uart_freq_baud
{
uint32_t baud;
uint32_t freq;
}uart_freq_baud;
struct uart_freq_baud uart_freq_baud_list[] =
{
#if defined(AIC_CHIP_D13X) || defined(AIC_CHIP_D21X)
{300, 48000000},
{1200, 48000000},
{2400, 48000000},
{4800, 48000000},
{9600, 48000000},
{19200, 48000000},
{38400, 48000000},
{57600, 48000000},
{115200, 48000000},
{230400, 48000000},
{460800, 44444444},
{921600, 44444444},
{1000000, 48000000},
{1152000, 54545454},
{1500000, 48000000},
#elif defined(AIC_CHIP_D12X)
{300, 53454545},
{1200, 53454545},
{2400, 53454545},
{4800, 53454545},
{9600, 53454545},
{19200, 53454545},
{38400, 53454545},
{57600, 53454545},
{115200, 53454545},
{230400, 58800000},
{460800, 58800000},
{921600, 58800000},
{1000000, 49000000},
{1152000, 36750000},
{1500000, 49000000},
{2000000, 65333333},
#else
{0, 0},
#endif
};
2023-08-30 16:21:18 +08:00
int32_t drv_usart_target_init(int32_t idx, uint32_t *base, uint32_t *irq, void **handler)
{
if (idx >= AIC_UART_DEV_NUM)
{
return -1;
}
if (base != NULL)
{
*base = drv_usart_config[idx].base;
}
if (irq != NULL)
{
*irq = drv_usart_config[idx].irq;
}
if (handler != NULL)
{
*handler = drv_usart_config[idx].handler;
}
return idx;
}
2024-09-03 11:16:08 +08:00
void drv_usart_cb_event(int32_t index, usart_event_e event)
{
usart_handle_t uart;
RT_ASSERT(g_serial != RT_NULL);
uart = (usart_handle_t)g_serial[index].parent.user_data;
switch (event)
{
case USART_EVENT_RX_BREAK:
case USART_EVENT_RX_FRAMING_ERROR:
case USART_EVENT_RX_PARITY_ERROR:
hal_usart_clear_rxfifo(uart);
break;
default:
break;
}
return;
}
2024-04-03 16:40:57 +08:00
void drv_usart_irqhandler(int irq, void * data)
{
int index = irq - UART0_IRQn;
uint8_t status= 0;
2024-09-03 11:16:08 +08:00
usart_handle_t uart;
RT_ASSERT(g_serial != RT_NULL);
uart = (usart_handle_t)g_serial[index].parent.user_data;
2024-04-03 16:40:57 +08:00
if (index >= AIC_UART_DEV_NUM)
return;
status = hal_usart_get_irqstatus(index);
if (g_serial[index].config.flag == AIC_UART_DMA_FLAG) {
2024-06-04 19:00:30 +08:00
#if defined (AIC_SERIAL_USING_DMA)
2024-04-03 16:40:57 +08:00
RT_ASSERT(uart != RT_NULL);
2024-09-03 11:16:08 +08:00
hal_usart_set_interrupt(uart, USART_INTR_READ, 0);
2024-04-03 16:40:57 +08:00
switch (status)
{
case AIC_IIR_RECV_DATA:
case AIC_IIR_CHAR_TIMEOUT:
rx_size = hal_usart_get_rx_fifo_num(uart);
// rt_kprintf("%d,%d\n",rx_size,status);
hal_uart_rx_dma_config(uart, (uint8_t *)uart_rx_fifo, rx_size);
break;
default:
break;
}
2024-06-04 19:00:30 +08:00
#endif
2024-04-03 16:40:57 +08:00
} else {
switch (status)
{
case AIC_IIR_RECV_DATA:
case AIC_IIR_CHAR_TIMEOUT:
rt_hw_serial_isr(&g_serial[index], RT_SERIAL_EVENT_RX_IND);
break;
2024-09-03 11:16:08 +08:00
case AIC_IIR_RECV_LINE:
hal_usart_set_interrupt(uart, USART_INTR_READ, 0);
hal_usart_intr_recv_line(index, (aic_usart_priv_t *)g_serial[index].parent.user_data);
hal_usart_set_interrupt(uart, USART_INTR_READ, 1);
break;
2024-04-03 16:40:57 +08:00
default:
break;
}
}
2023-08-30 16:21:18 +08:00
}
/*
* UART interface
*/
static rt_err_t drv_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
int ret;
usart_handle_t uart;
uint32_t bauds;
usart_mode_e mode;
usart_parity_e parity;
usart_stop_bits_e stopbits;
usart_data_bits_e databits;
RT_ASSERT(serial != RT_NULL);
uart = (usart_handle_t)serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
/* set baudrate parity...*/
bauds = cfg->baud_rate;
mode = USART_MODE_ASYNCHRONOUS;
if (cfg->parity == PARITY_EVEN)
parity = USART_PARITY_EVEN;
else if (cfg->parity == PARITY_ODD)
parity = USART_PARITY_ODD;
else
parity = USART_PARITY_NONE;
2024-04-03 16:40:57 +08:00
if (cfg->stop_bits == STOP_BITS_1)
2023-11-30 19:48:02 +08:00
stopbits = USART_STOP_BITS_1;
2024-04-03 16:40:57 +08:00
else if (cfg->stop_bits == STOP_BITS_2)
2023-11-30 19:48:02 +08:00
stopbits = USART_STOP_BITS_2;
2024-04-03 16:40:57 +08:00
else if (cfg->stop_bits == STOP_BITS_3)
2023-11-30 19:48:02 +08:00
stopbits = USART_STOP_BITS_1_5;
2023-08-30 16:21:18 +08:00
else
2023-11-30 19:48:02 +08:00
stopbits = USART_STOP_BITS_0_5;
2023-08-30 16:21:18 +08:00
if (cfg->data_bits == 5)
databits = USART_DATA_BITS_5;
else if (cfg->data_bits == 6)
databits = USART_DATA_BITS_6;
else if (cfg->data_bits == 7)
databits = USART_DATA_BITS_7;
else if (cfg->data_bits == 8)
databits = USART_DATA_BITS_8;
else if (cfg->data_bits == 9)
databits = USART_DATA_BITS_9;
else
databits = USART_DATA_BITS_8;
ret = hal_usart_config(uart, bauds, mode, parity, stopbits, databits, cfg->function);
if (ret < 0)
{
return -RT_ERROR;
}
return RT_EOK;
}
2024-04-03 16:40:57 +08:00
rt_err_t aic_uart_configure(u32 index, struct serial_configure *cfg)
{
if (index >= AIC_UART_DEV_NUM) {
pr_err("Invalid UART port NO. %d\n", index);
return RT_EINVAL;
}
if (!cfg) {
pr_err("Invalid serial_configure\n");
return RT_EINVAL;
}
return drv_uart_configure(&g_serial[index], cfg);
}
2023-08-30 16:21:18 +08:00
static rt_err_t drv_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
{
usart_handle_t uart;
2024-04-03 16:40:57 +08:00
aic_usart_priv_t *uart_data;
unsigned int group, pin;
2023-08-30 16:21:18 +08:00
2024-09-03 11:16:08 +08:00
2023-08-30 16:21:18 +08:00
RT_ASSERT(serial != RT_NULL);
uart = (usart_handle_t)serial->parent.user_data;
2024-04-03 16:40:57 +08:00
uart_data = serial->parent.user_data;
2023-08-30 16:21:18 +08:00
RT_ASSERT(uart != RT_NULL);
2024-04-03 16:40:57 +08:00
char off = AIC_UART_XOFF;
char on = AIC_UART_XON;
2023-08-30 16:21:18 +08:00
switch (cmd)
{
case RT_DEVICE_CTRL_CLR_INT:
/* Disable the UART Interrupt */
2024-01-27 08:47:24 +08:00
if ((uintptr_t)arg == RT_DEVICE_FLAG_INT_RX)
hal_usart_set_interrupt(uart, USART_INTR_READ, 0);
2023-08-30 16:21:18 +08:00
break;
case RT_DEVICE_CTRL_SET_INT:
/* Enable the UART Interrupt */
2024-01-27 08:47:24 +08:00
if ((uintptr_t)arg == RT_DEVICE_FLAG_INT_RX)
hal_usart_set_interrupt(uart, USART_INTR_READ, 1);
2023-08-30 16:21:18 +08:00
break;
2024-04-03 16:40:57 +08:00
case AIC_UART_485_CTL_SOFT_MODE0:
hal_usart_rts_ctl_soft_mode_clr(uart);
group = GPIO_GROUP(uart_rts_dev[uart_data->idx].uart_rts_pin);
pin = GPIO_GROUP_PIN(uart_rts_dev[uart_data->idx].uart_rts_pin);
hal_gpio_clr_output(group, pin);
break;
case AIC_UART_485_CTL_SOFT_MODE1:
hal_usart_rts_ctl_soft_mode_set(uart);
group = GPIO_GROUP(uart_rts_dev[uart_data->idx].uart_rts_pin);
pin = GPIO_GROUP_PIN(uart_rts_dev[uart_data->idx].uart_rts_pin);
hal_gpio_set_output(group, pin);
break;
case AIC_UART_232_RESUME_DATA:
if (serial->config.function == USART_MODE_RS232_UNAUTO_FLOW_CTRL ||
serial->config.function == USART_MODE_RS232_SW_HW_FLOW_CTRL) {
2024-06-04 19:00:30 +08:00
rt_pin_write(uart_rts_dev[uart_data->idx].uart_rts_pin, PIN_LOW);
2024-04-03 16:40:57 +08:00
}
if (serial->config.function == USART_MODE_RS232_SW_FLOW_CTRL ||
serial->config.function == USART_MODE_RS232_SW_HW_FLOW_CTRL) {
#ifdef RT_USING_DEVICE_OPS
serial->parent.ops->write(&serial->parent, 0, &on, 1);
#else
serial->parent.write(&serial->parent, 0, &on, 1);
#endif
}
break;
case AIC_UART_232_SUSPEND_DATA:
if (serial->config.function == USART_MODE_RS232_UNAUTO_FLOW_CTRL ||
serial->config.function == USART_MODE_RS232_SW_HW_FLOW_CTRL) {
2024-06-04 19:00:30 +08:00
rt_pin_write(uart_rts_dev[uart_data->idx].uart_rts_pin, PIN_HIGH);
2024-04-03 16:40:57 +08:00
}
if (serial->config.function == USART_MODE_RS232_SW_FLOW_CTRL ||
serial->config.function == USART_MODE_RS232_SW_HW_FLOW_CTRL) {
#ifdef RT_USING_DEVICE_OPS
serial->parent.ops->write(&serial->parent, 0, &off, 1);
#else
serial->parent.write(&serial->parent, 0, &off, 1);
#endif
}
break;
2024-06-04 19:00:30 +08:00
case AIC_UART_SW_RECEIVE_ON_OFF:
if (*(char *)arg == AIC_UART_XOFF) {
hal_usart_halt_tx_enable(uart, HALT_TX_ENABLE);
} else if (*(char *)arg == AIC_UART_XON) {
hal_usart_halt_tx_enable(uart, HALT_TX_DISABLE);
}
break;
2024-09-03 11:16:08 +08:00
case AIC_UART_SET_BAUDRATE:
hal_clk_disable(CLK_UART0 + serial->config.uart_index);
drv_usart_set_freq(*(uint32_t *)arg, serial->config.uart_index);
hal_clk_enable(CLK_UART0 + serial->config.uart_index);
aic_udelay(1000);
hal_usart_config_baudrate(uart, *(uint32_t *)arg);
break;
2023-08-30 16:21:18 +08:00
}
return (RT_EOK);
}
static int drv_uart_putc(struct rt_serial_device *serial, char c)
{
usart_handle_t uart;
RT_ASSERT(serial != RT_NULL);
uart = (usart_handle_t)serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
2024-09-03 11:16:08 +08:00
hal_usart_putchar(uart, c);
2023-08-30 16:21:18 +08:00
return (1);
}
static int drv_uart_getc(struct rt_serial_device *serial)
{
int ch;
usart_handle_t uart;
RT_ASSERT(serial != RT_NULL);
uart = (usart_handle_t)serial->parent.user_data;
RT_ASSERT(uart != RT_NULL);
ch = hal_uart_getchar(uart);
return ch;
}
2024-06-04 19:00:30 +08:00
#if defined (AIC_SERIAL_USING_DMA)
2024-04-03 16:40:57 +08:00
#include <string.h>
static void drv_uart_callback(aic_usart_priv_t *uart, void *arg)
{
unsigned long event = (unsigned long)arg;
struct rt_serial_rx_fifo *rx_fifo;
switch(event)
{
case AIC_UART_TX_INT:
rt_hw_serial_isr(&g_serial[uart->idx], RT_SERIAL_EVENT_TX_DMADONE);
break;
case AIC_UART_RX_INT:
rx_fifo = (struct rt_serial_rx_fifo *)g_serial[uart->idx].serial_rx;
if (rx_fifo->put_index + rx_size < g_serial[uart->idx].config.bufsz) {
memcpy((rx_fifo->buffer + rx_fifo->put_index), (rt_uint8_t *)uart_rx_fifo, rx_size);
} else {
memcpy((rx_fifo->buffer + rx_fifo->put_index), (rt_uint8_t *)uart_rx_fifo,
g_serial->config.bufsz - rx_fifo->put_index);
memcpy((rx_fifo->buffer), ((rt_uint8_t *)uart_rx_fifo + g_serial->config.bufsz -
rx_fifo->put_index), rx_size + rx_fifo->put_index - g_serial->config.bufsz);
}
2024-09-03 11:16:08 +08:00
hal_usart_set_interrupt(uart, USART_INTR_READ, 1);
2024-04-03 16:40:57 +08:00
rt_hw_serial_isr(&g_serial[uart->idx], RT_SERIAL_EVENT_RX_DMADONE | (rx_size << 8));
break;
default:
hal_log_err("not support event\n");
break;
}
}
static rt_size_t drv_uart_dma_transmit(struct rt_serial_device *serial, rt_uint8_t *buf,
rt_size_t size, int direction)
{
usart_handle_t uart;
RT_ASSERT(serial != RT_NULL);
uart = (usart_handle_t)serial->parent.user_data;
if (direction == RT_SERIAL_DMA_TX) {
memcpy((rt_uint8_t *)uart_tx_fifo, buf, size);
2024-09-03 11:16:08 +08:00
if (hal_uart_send_by_dma(uart, (rt_uint8_t *)uart_tx_fifo, size) == 0) {
2024-04-03 16:40:57 +08:00
return size;
}
}
return 0;
}
#endif
2023-08-30 16:21:18 +08:00
const struct rt_uart_ops drv_uart_ops =
{
drv_uart_configure,
drv_uart_control,
drv_uart_putc,
drv_uart_getc,
2024-06-04 19:00:30 +08:00
#if defined (AIC_SERIAL_USING_DMA)
2024-04-03 16:40:57 +08:00
drv_uart_dma_transmit,
#endif
2023-08-30 16:21:18 +08:00
};
struct drv_uart_dev_para
{
uint32_t index :4;
uint32_t data_bits :4;
uint32_t stop_bits :2;
uint32_t parity :2;
2024-04-03 16:40:57 +08:00
uint32_t flag;
2023-08-30 16:21:18 +08:00
uint32_t baud_rate;
uint32_t clk_freq;
uint32_t function;
char * name;
2024-04-03 16:40:57 +08:00
char * uart_rts_name;
char * uart_cts_name;
2023-08-30 16:21:18 +08:00
};
const struct drv_uart_dev_para uart_dev_paras[] =
{
#ifdef AIC_USING_UART0
2024-04-03 16:40:57 +08:00
{0, AIC_DEV_UART0_DATABITS, AIC_DEV_UART0_STOPBITS, AIC_DEV_UART0_PARITY, AIC_UART0_FLAG,
AIC_DEV_UART0_BAUDRATE, AIC_CLK_UART0_FREQ, AIC_DEV_UART0_MODE, "uart0", AIC_UART0_RTS_NAME, AIC_UART0_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART1
2024-04-03 16:40:57 +08:00
{1, AIC_DEV_UART1_DATABITS, AIC_DEV_UART1_STOPBITS, AIC_DEV_UART1_PARITY, AIC_UART1_FLAG,
AIC_DEV_UART1_BAUDRATE, AIC_CLK_UART1_FREQ, AIC_DEV_UART1_MODE, "uart1", AIC_UART1_RTS_NAME, AIC_UART1_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART2
2024-04-03 16:40:57 +08:00
{2, AIC_DEV_UART2_DATABITS, AIC_DEV_UART2_STOPBITS, AIC_DEV_UART2_PARITY, AIC_UART2_FLAG,
AIC_DEV_UART2_BAUDRATE, AIC_CLK_UART2_FREQ, AIC_DEV_UART2_MODE, "uart2", AIC_UART2_RTS_NAME, AIC_UART2_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART3
2024-04-03 16:40:57 +08:00
{3, AIC_DEV_UART3_DATABITS, AIC_DEV_UART3_STOPBITS, AIC_DEV_UART3_PARITY, AIC_UART3_FLAG,
AIC_DEV_UART3_BAUDRATE, AIC_CLK_UART3_FREQ, AIC_DEV_UART3_MODE, "uart3", AIC_UART3_RTS_NAME, AIC_UART3_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART4
2024-04-03 16:40:57 +08:00
{4, AIC_DEV_UART4_DATABITS, AIC_DEV_UART4_STOPBITS, AIC_DEV_UART4_PARITY, AIC_UART4_FLAG,
AIC_DEV_UART4_BAUDRATE, AIC_CLK_UART4_FREQ, AIC_DEV_UART4_MODE, "uart4", AIC_UART4_RTS_NAME, AIC_UART4_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART5
2024-04-03 16:40:57 +08:00
{5, AIC_DEV_UART5_DATABITS, AIC_DEV_UART5_STOPBITS, AIC_DEV_UART5_PARITY, AIC_UART5_FLAG,
AIC_DEV_UART5_BAUDRATE, AIC_CLK_UART5_FREQ, AIC_DEV_UART5_MODE, "uart5", AIC_UART5_RTS_NAME, AIC_UART5_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART6
2024-04-03 16:40:57 +08:00
{6, AIC_DEV_UART6_DATABITS, AIC_DEV_UART6_STOPBITS, AIC_DEV_UART6_PARITY, AIC_UART6_FLAG,
AIC_DEV_UART6_BAUDRATE, AIC_CLK_UART6_FREQ, AIC_DEV_UART6_MODE, "uart6", AIC_UART6_RTS_NAME, AIC_UART6_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
#ifdef AIC_USING_UART7
2024-04-03 16:40:57 +08:00
{7, AIC_DEV_UART7_DATABITS, AIC_DEV_UART7_STOPBITS, AIC_DEV_UART7_PARITY, AIC_UART7_FLAG,
AIC_DEV_UART7_BAUDRATE, AIC_CLK_UART7_FREQ, AIC_DEV_UART7_MODE, "uart7", AIC_UART7_RTS_NAME, AIC_UART7_CTS_NAME},
2023-08-30 16:21:18 +08:00
#endif
};
2024-06-04 19:00:30 +08:00
static void uart_halt_tx_irq_handler(void *args)
2024-04-03 16:40:57 +08:00
{
usart_handle_t uart;
2024-06-04 19:00:30 +08:00
unsigned int pin, value = PIN_LOW;
2024-04-03 16:40:57 +08:00
struct rt_serial_device *serial = args;
uart = (usart_handle_t)serial->parent.user_data;
2024-06-04 19:00:30 +08:00
2024-09-03 11:16:08 +08:00
pin = rt_pin_get(uart_dev_paras[serial->config.uart_index].uart_cts_name);
2024-06-04 19:00:30 +08:00
value = rt_pin_read(pin);
2024-04-03 16:40:57 +08:00
if (value == PIN_HIGH) {
2024-06-04 19:00:30 +08:00
hal_usart_halt_tx_enable(uart, HALT_TX_ENABLE);
2024-04-03 16:40:57 +08:00
} else {
2024-06-04 19:00:30 +08:00
hal_usart_halt_tx_enable(uart, HALT_TX_DISABLE);
2024-04-03 16:40:57 +08:00
}
}
void drv_usart_function_init(int i, int u)
{
2024-06-04 19:00:30 +08:00
if ((rt_strcmp(uart_dev_paras[i].uart_rts_name, "no_pin") != 0) &&
(uart_dev_paras[i].function == USART_FUNC_RS485_SIMULATION ||
2024-04-03 16:40:57 +08:00
uart_dev_paras[i].function == USART_MODE_RS232_UNAUTO_FLOW_CTRL ||
uart_dev_paras[i].function == USART_MODE_RS232_SW_HW_FLOW_CTRL)) {
2024-09-03 11:16:08 +08:00
uart_rts_dev[u].uart_rts_pin = rt_pin_get(uart_dev_paras[i].uart_rts_name);
2024-06-04 19:00:30 +08:00
rt_pin_mode(uart_rts_dev[u].uart_rts_pin, PIN_MODE_OUTPUT);
rt_pin_write(uart_rts_dev[u].uart_rts_pin, PIN_LOW);
g_serial[u].config.flowctrl_rts_enable = 1;
2024-04-03 16:40:57 +08:00
}
2024-06-04 19:00:30 +08:00
if ((rt_strcmp(uart_dev_paras[i].uart_cts_name, "no_pin") != 0) &&
2024-04-03 16:40:57 +08:00
(uart_dev_paras[i].function == USART_MODE_RS232_UNAUTO_FLOW_CTRL ||
uart_dev_paras[i].function == USART_MODE_RS232_SW_HW_FLOW_CTRL)) {
2024-09-03 11:16:08 +08:00
uart_cts_dev[u].uart_cts_pin = rt_pin_get(uart_dev_paras[i].uart_cts_name);
2024-06-04 19:00:30 +08:00
rt_pin_mode(uart_cts_dev[u].uart_cts_pin, PIN_MODE_INPUT);
rt_pin_attach_irq(uart_cts_dev[u].uart_cts_pin, PIN_IRQ_MODE_RISING_FALLING,
uart_halt_tx_irq_handler, &(g_serial[u]));
rt_pin_irq_enable(uart_cts_dev[u].uart_cts_pin, PIN_IRQ_ENABLE);
g_serial[u].config.flowctrl_cts_enable = 1;
}
2024-04-03 16:40:57 +08:00
2024-06-04 19:00:30 +08:00
if (uart_dev_paras[i].function == USART_MODE_RS232_SW_FLOW_CTRL) {
g_serial[u].config.flowctrl_cts_enable = 1;
g_serial[u].config.flowctrl_rts_enable = 1;
2024-04-03 16:40:57 +08:00
}
2024-06-04 19:00:30 +08:00
}
2024-04-03 16:40:57 +08:00
2024-09-03 11:16:08 +08:00
void drv_usart_set_freq(uint32_t baudrate, int u)
2024-06-04 19:00:30 +08:00
{
int uart_freq;
int config_num = sizeof(uart_freq_baud_list)/sizeof(uart_freq_baud);
for (int x = 0; x < config_num; x++) {
if (baudrate == uart_freq_baud_list[x].baud) {
uart_freq = uart_freq_baud_list[x].freq;
hal_clk_set_freq(CLK_UART0 + u, uart_freq);
return;
}
2024-04-03 16:40:57 +08:00
}
2024-06-04 19:00:30 +08:00
/* Use the menuconfig freq when the baud dose not match in the list */
2024-09-03 11:16:08 +08:00
hal_clk_set_freq(CLK_UART0 + u, g_serial[u].config.uart_freq);
2024-04-03 16:40:57 +08:00
}
2023-08-30 16:21:18 +08:00
int drv_usart_init(void)
{
struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
int u = 0;
int i = 0;
2023-11-30 19:48:02 +08:00
for (i=0; i<sizeof(uart_dev_paras)/sizeof(struct drv_uart_dev_para); i++) {
2023-08-30 16:21:18 +08:00
u = uart_dev_paras[i].index;
2024-04-03 16:40:57 +08:00
g_serial[u].ops = & drv_uart_ops;
g_serial[u].config = config;
g_serial[u].config.bufsz = 2048;
g_serial[u].config.baud_rate = uart_dev_paras[i].baud_rate;
g_serial[u].config.data_bits = uart_dev_paras[i].data_bits;
g_serial[u].config.stop_bits = uart_dev_paras[i].stop_bits - 1;
g_serial[u].config.parity = uart_dev_paras[i].parity;
g_serial[u].config.function = uart_dev_paras[i].function;
g_serial[u].config.flag = uart_dev_paras[i].flag;
g_serial[u].config.uart_index = uart_dev_paras[i].index;
2024-09-03 11:16:08 +08:00
g_serial[u].config.uart_freq = uart_dev_paras[i].clk_freq;
2023-08-30 16:21:18 +08:00
2024-09-03 11:16:08 +08:00
drv_usart_set_freq(uart_dev_paras[i].baud_rate, u);
2023-08-30 16:21:18 +08:00
hal_clk_enable(CLK_UART0 + u);
hal_reset_assert(RESET_UART0 + u);
aic_udelay(10000);
hal_reset_deassert(RESET_UART0 + u);
2024-04-03 16:40:57 +08:00
2023-11-30 19:48:02 +08:00
#ifdef FINSH_POLL_MODE
uart_handle[u] = hal_usart_initialize(u, NULL, NULL);
#else
2024-09-03 11:16:08 +08:00
uart_handle[u] = hal_usart_initialize(u, drv_usart_cb_event, drv_usart_irqhandler);
2023-11-30 19:48:02 +08:00
#endif
2024-04-03 16:40:57 +08:00
rt_hw_serial_register(&g_serial[u],
2023-08-30 16:21:18 +08:00
uart_dev_paras[i].name,
2023-11-30 19:48:02 +08:00
#ifdef FINSH_POLL_MODE
RT_DEVICE_FLAG_RDWR,
#else
2024-04-03 16:40:57 +08:00
uart_dev_paras[i].flag,
2023-11-30 19:48:02 +08:00
#endif
2023-08-30 16:21:18 +08:00
uart_handle[u]);
2024-06-04 19:00:30 +08:00
#if defined (AIC_SERIAL_USING_DMA)
2024-04-03 16:40:57 +08:00
if (uart_dev_paras[i].flag == AIC_UART_DMA_FLAG) {
hal_uart_set_fifo((aic_usart_priv_t *)g_serial[u].parent.user_data);
hal_uart_attach_callback((aic_usart_priv_t *)g_serial[u].parent.user_data,
drv_uart_callback, NULL);
2024-09-03 11:16:08 +08:00
hal_usart_set_interrupt((aic_usart_priv_t *)g_serial[u].parent.user_data,
USART_INTR_READ, 1);
2024-04-03 16:40:57 +08:00
}
2024-06-04 19:00:30 +08:00
#endif
2024-04-03 16:40:57 +08:00
drv_usart_function_init(i, u);
2023-08-30 16:21:18 +08:00
}
return 0;
}
INIT_BOARD_EXPORT(drv_usart_init);