Ver código fonte

add serialX hardware driver for bluetrum gd32 n32 nuc980 renesas (#6952)

 add serialX hardware driver for bluetrum gd32 n32 nuc980 renesas
thewon86 2 anos atrás
pai
commit
e98df69775

+ 4 - 1
bsp/bluetrum/libraries/hal_drivers/SConscript

@@ -12,7 +12,10 @@ if GetDepend('RT_USING_PIN'):
     src += ['drv_gpio.c']
 
 if GetDepend('RT_USING_SERIAL'):
-    src += ['drv_usart.c']
+    if GetDepend(['RT_USING_SERIAL_X']):
+        src += ['drv_usartX.c']
+    else:
+        src += ['drv_usart.c']
 
 if GetDepend('RT_USING_SDIO'):
     src += ['drv_sdio.c']

+ 348 - 0
bsp/bluetrum/libraries/hal_drivers/drv_usartX.c

@@ -0,0 +1,348 @@
+/*
+ * Copyright (c) 2020-2022, Bluetrum Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-11-20     greedyhao         first version
+ * 2022-06-08     THEWON            first version for serialX
+ */
+
+#include "board.h"
+#include <drv_usartX.h>
+
+#ifdef RT_USING_SERIAL
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.usart"
+#include <drv_log.h>
+
+enum
+{
+#ifdef BSP_USING_UART0
+    UART0_INDEX,
+#endif
+#ifdef BSP_USING_UART1
+    UART1_INDEX,
+#endif
+#ifdef BSP_USING_UART2
+    UART2_INDEX,
+#endif
+};
+
+static struct ab32_uart_config uart_config[] =
+{
+#ifdef BSP_USING_UART0
+    {
+        .name = "uart0",
+        .instance = UART0_BASE,
+        .mode = UART_MODE_TX_RX | UART_MODE_1LINE,
+    },
+#endif
+#ifdef BSP_USING_UART1
+    {
+        .name = "uart1",
+        .instance = UART1_BASE,
+        .mode = UART_MODE_TX_RX,
+    },
+#endif
+#ifdef BSP_USING_UART2
+    {
+        .name = "uart2",
+        .instance = UART2_BASE,
+        .mode = UART_MODE_TX_RX,
+    }
+#endif
+};
+
+static struct ab32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
+
+static rt_err_t ab32_init(struct rt_serial_device *serial)
+{
+    struct ab32_uart *uart;
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+    uart->handle.instance           = uart->uart_config->instance;
+    uart->handle.init.baud          = serial->config->baud_rate;
+    uart->handle.init.mode          = uart->uart_config->mode;
+
+    switch (serial->config->data_bits)
+    {
+    case DATA_BITS_8:
+        uart->handle.init.word_len  = UART_WORDLENGTH_8B;
+    break;
+    case DATA_BITS_9:
+        uart->handle.init.word_len  = UART_WORDLENGTH_9B;
+    break;
+    default:
+        uart->handle.init.word_len  = UART_WORDLENGTH_8B;
+    break;
+    }
+
+    switch (serial->config->stop_bits)
+    {
+    case STOP_BITS_1:
+        uart->handle.init.stop_bits = UART_STOPBITS_1;
+    break;
+    case STOP_BITS_2:
+        uart->handle.init.stop_bits = UART_STOPBITS_2;
+    break;
+    default:
+        uart->handle.init.stop_bits = UART_STOPBITS_1;
+    break;
+    }
+
+    hal_uart_init(&uart->handle);
+
+    return RT_EOK;
+}
+
+static rt_err_t ab32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    struct ab32_uart *uart;
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+    uart->handle.instance           = uart->uart_config->instance;
+    uart->handle.init.baud          = cfg->baud_rate;
+    uart->handle.init.mode          = uart->uart_config->mode;
+
+    switch (cfg->data_bits)
+    {
+    case DATA_BITS_8:
+        uart->handle.init.word_len  = UART_WORDLENGTH_8B;
+    break;
+    case DATA_BITS_9:
+        uart->handle.init.word_len  = UART_WORDLENGTH_9B;
+    break;
+    default:
+        uart->handle.init.word_len  = UART_WORDLENGTH_8B;
+    break;
+    }
+
+    switch (cfg->stop_bits)
+    {
+    case STOP_BITS_1:
+        uart->handle.init.stop_bits = UART_STOPBITS_1;
+    break;
+    case STOP_BITS_2:
+        uart->handle.init.stop_bits = UART_STOPBITS_2;
+    break;
+    default:
+        uart->handle.init.stop_bits = UART_STOPBITS_1;
+    break;
+    }
+
+    hal_uart_init(&uart->handle);
+
+    return RT_EOK;
+}
+
+static rt_err_t ab32_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+
+    switch (cmd)
+    {
+    case RT_DEVICE_CTRL_OPEN:
+        uart->intTxing = RT_FALSE;
+    break;
+    /* disable interrupt */
+    case RT_DEVICE_CTRL_CLR_INT:
+        hal_uart_control(uart->handle.instance, UART_RXIT_ENABLE, HAL_DISABLE);
+    break;
+    /* enable interrupt */
+    case RT_DEVICE_CTRL_SET_INT:
+        hal_uart_clrflag(uart->handle.instance, UART_FLAG_RXPND);
+        hal_uart_control(uart->handle.instance, UART_RXIT_ENABLE, HAL_ENABLE);
+    break;
+    case RT_DEVICE_CTRL_CLOSE:
+        hal_uart_deinit(uart->handle.instance);
+    break;
+    }
+
+    return RT_EOK;
+}
+
+static int ab32_putc(struct rt_serial_device *serial, char ch)
+{
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+
+    hal_uart_write(uart->handle.instance, ch);
+
+    return 1;
+}
+
+static int ab32_getc(struct rt_serial_device *serial)
+{
+    int ch;
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+
+    ch = -1;
+    if (hal_uart_getflag(UART0_BASE, UART_FLAG_RXPND)) {
+        ch = hal_uart_read(uart->handle.instance);
+        hal_uart_clrflag(UART0_BASE, UART_FLAG_RXPND);
+    }
+
+    return ch;
+}
+
+static int ab32_flush(struct rt_serial_device *serial)
+{
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+    while(hal_uart_getflag(uart->handle.instance, UART_FLAG_TXPND) == 0);
+}
+
+rt_bool_t ab32_int_txing(struct rt_serial_device *serial)
+{
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+
+    return uart->intTxing;
+}
+
+static void ab32_start_tx(struct rt_serial_device *serial, rt_uint8_t ch)
+{
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+    uart->intTxing = RT_TRUE;
+    hal_uart_control(uart->handle.instance, UART_TXIT_ENABLE, HAL_ENABLE);
+    hal_uart_write(uart->handle.instance, ch);
+}
+
+static void ab32_stop_tx(struct rt_serial_device *serial)
+{
+    struct ab32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ab32_uart, serial);
+    hal_uart_control(uart->handle.instance, UART_TXIT_ENABLE, HAL_DISABLE);
+    uart->intTxing = RT_FALSE;
+}
+
+RT_SECTION(".irq.usart")
+static void uart_isr(int vector, void *param)
+{
+    rt_interrupt_enter();
+
+#ifdef BSP_USING_UART0
+    if(hal_uart_getflag(UART0_BASE, UART_FLAG_RXPND))       //RX one byte finish
+    {
+        rt_hw_serial_isr(&(uart_obj[UART0_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
+        hal_uart_clrflag(UART0_BASE, UART_FLAG_RXPND);
+    }
+    if(hal_uart_getflag(UART0_BASE, UART_FLAG_TXPND))       //TX one byte finish
+    {
+        rt_hw_serial_isr(&(uart_obj[UART0INDEX].serial), RT_SERIAL_EVENT_TX_DONE);
+        hal_uart_clrflag(UART0_BASE, UART_FLAG_TXPND);
+    }
+#endif
+#ifdef BSP_USING_UART1
+    if(hal_uart_getflag(UART1_BASE, UART_FLAG_RXPND))       //RX one byte finish
+    {
+        rt_hw_serial_isr(&(uart_obj[UART1_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
+        hal_uart_clrflag(UART1_BASE, UART_FLAG_RXPND);
+    }
+    if(hal_uart_getflag(UART1_BASE, UART_FLAG_TXPND))       //TX one byte finish
+    {
+        rt_hw_serial_isr(&(uart_obj[UART1_INDEX].serial), RT_SERIAL_EVENT_TX_DONE);
+        hal_uart_clrflag(UART1_BASE, UART_FLAG_TXPND);
+    }
+#endif
+#ifdef BSP_USING_UART2
+    if(hal_uart_getflag(UART2_BASE, UART_FLAG_RXPND))       //RX one byte finish
+    {
+        rt_hw_serial_isr(&(uart_obj[UART2_INDEX].serial), RT_SERIAL_EVENT_RX_IND);
+        hal_uart_clrflag(UART2_BASE, UART_FLAG_RXPND);
+    }
+    if(hal_uart_getflag(UART2_BASE, UART_FLAG_TXPND))       //TX one byte finish
+    {
+        rt_hw_serial_isr(&(uart_obj[UART2_INDEX].serial), RT_SERIAL_EVENT_TX_DONE);
+        hal_uart_clrflag(UART2_BASE, UART_FLAG_TXPND);
+    }
+#endif
+
+    rt_interrupt_leave();
+}
+
+#ifdef HUART_ENABLE
+RT_SECTION(".irq.huart")
+void huart_timer_isr(void)
+{
+    huart_if_rx_ovflow();
+
+    if (0 == huart_get_rxcnt()) {
+        return;
+    }
+}
+#else
+RT_SECTION(".irq.huart")
+void huart_timer_isr(void)
+{
+}
+#endif
+
+static const struct rt_uart_ops ab32_uart_ops =
+{
+    .init = ab32_init,
+    .configure = ab32_configure,
+    .control = ab32_control,
+    .putc = ab32_putc,
+    .getc = ab32_getc,
+    .flush = ab32_flush,
+    .is_int_txing = ab32_int_txing,
+    .start_tx = ab32_start_tx,
+    .stop_tx = ab32_stop_tx,
+};
+
+int rt_hw_usart_init(void)
+{
+    rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct ab32_uart);
+    rt_err_t result = 0;
+
+    rt_hw_interrupt_install(IRQ_UART0_2_VECTOR, uart_isr, RT_NULL, "ut_isr");
+
+    for (int i = 0; i < obj_num; i++)
+    {
+        /* init UART object */
+        uart_obj[i].uart_config     = &uart_config[i];
+        uart_obj[i].serial.ops      = &ab32_uart_ops;
+
+        /* register UART device */
+        result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].uart_config->name,
+                                       RT_DEVICE_FLAG_RDWR
+                                       | RT_DEVICE_FLAG_INT_RX
+                                       | RT_DEVICE_FLAG_INT_TX
+                                       , RT_NULL);
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return result;
+}
+
+#endif

+ 40 - 0
bsp/bluetrum/libraries/hal_drivers/drv_usartX.h

@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2020-2022, Bluetrum Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2020-11-20     greedyhao         first version
+ * 2022-06-08     THEWON            first version for serialX
+ */
+
+#ifndef DRV_USART_H__
+#define DRV_USART_H__
+
+#include "drv_common.h"
+
+#ifdef RT_USING_SERIAL
+
+/* an32 config class */
+struct ab32_uart_config
+{
+    const char *name;
+    hal_sfr_t   instance;
+    uint8_t     mode;
+};
+
+/* ab32 uart driver class */
+struct ab32_uart
+{
+    struct uart_handle handle;
+    struct rt_serial_device serial;
+    struct ab32_uart_config *uart_config;
+    rt_bool_t intTxing;
+};
+
+#endif
+
+int rt_hw_usart_init(void);
+
+#endif

+ 4 - 1
bsp/gd32/arm/libraries/gd32_drivers/SConscript

@@ -14,7 +14,10 @@ if GetDepend('RT_USING_PIN'):
 
 # add usart drivers.
 if GetDepend(['RT_USING_SERIAL']):
-    src += ['drv_usart.c']
+    if GetDepend(['RT_USING_SERIAL_X']):
+        src += ['drv_usartX.c']
+    else:
+        src += ['drv_usart.c']
 
 # add i2c drivers.
 if GetDepend(['RT_USING_I2C', 'RT_USING_I2C_BITOPS']):

+ 848 - 0
bsp/gd32/arm/libraries/gd32_drivers/drv_usartX.c

@@ -0,0 +1,848 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2009-01-05     Bernard      the first version
+ * 2010-03-29     Bernard      remove interrupt Tx and DMA Rx mode
+ * 2012-02-08     aozima       update for F4.
+ * 2012-07-28     aozima       update for ART board.
+ * 2016-05-28     armink       add DMA Rx mode
+ * 2022-06-09     THEWON       first version for serialX
+ */
+
+#include <gd32f4xx.h>
+#include <drv_usartX.h>
+#include <board.h>
+
+#ifdef RT_USING_SERIAL
+
+#if !defined(BSP_USING_UART0) && !defined(BSP_USING_UART1) && \
+    !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && \
+    !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && \
+    !defined(BSP_USING_UART6) && !defined(BSP_USING_UART7)
+#error "Please define at least one UARTx"
+
+#endif
+
+enum
+{
+#ifdef BSP_USING_UART0
+    UART0_INDEX,
+#endif
+#ifdef BSP_USING_UART1
+    UART1_INDEX,
+#endif
+#ifdef BSP_USING_UART2
+    UART2_INDEX,
+#endif
+#ifdef BSP_USING_UART3
+    UART3_INDEX,
+#endif
+#ifdef BSP_USING_UART4
+    UART4_INDEX,
+#endif
+#ifdef BSP_USING_UART5
+    UART5_INDEX,
+#endif
+#ifdef BSP_USING_UART6
+    UART6_INDEX,
+#endif
+#ifdef BSP_USING_UART7
+    UART7_INDEX,
+#endif
+};
+
+/* GD32 uart driver */
+
+static void uart_isr(struct rt_serial_device *serial);
+
+#ifdef RT_SERIAL_USING_DMA
+static void DMA_RX_Configuration(struct rt_serial_device *serial);
+static void DMA_TX_Configuration(struct rt_serial_device *serial);
+#endif
+
+static struct gd32_uart uarts[] = {
+    #ifdef BSP_USING_UART0
+    {
+        .uart_periph = USART0,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart0",
+            .irqn = USART0_IRQn,                            // uart iqrn
+            RCU_USART0, RCU_GPIOA, RCU_GPIOA,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOA, GPIO_AF_7, GPIO_PIN_9,           // tx port, tx alternate, tx pin
+            GPIOA, GPIO_AF_7, GPIO_PIN_10,          // rx port, rx alternate, rx pin
+        },
+#ifdef RT_SERIAL_USING_DMA
+        .dmaTxing = RT_FALSE,
+        .dma_rx = {
+            .dma_periph = DMA1,
+            .dma_channel = DMA_CH2,
+            .dma_subperi = DMA_SUBPERI4,
+            .dma_irq = DMA1_Channel2_IRQn,
+        },
+        .dma_tx = {
+            .dma_periph = DMA1,
+            .dma_channel = DMA_CH7,
+            .dma_subperi = DMA_SUBPERI4,
+            .dma_irq = DMA1_Channel7_IRQn,
+        },
+#endif
+    },
+    #endif
+
+    #ifdef BSP_USING_UART1
+    {
+        .uart_periph = USART1,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart1",
+            .irqn = USART1_IRQn,                            // uart iqrn
+            RCU_USART1, RCU_GPIOA, RCU_GPIOA,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOA, GPIO_AF_7, GPIO_PIN_2,           // tx port, tx alternate, tx pin
+            GPIOA, GPIO_AF_7, GPIO_PIN_3,           // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+
+    #ifdef BSP_USING_UART2
+    {
+        .uart_periph = USART2,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart2",
+            .irqn = USART2_IRQn,                            // uart iqrn
+            RCU_USART2, RCU_GPIOB, RCU_GPIOB,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOB, GPIO_AF_7, GPIO_PIN_10,          // tx port, tx alternate, tx pin
+            GPIOB, GPIO_AF_7, GPIO_PIN_11,          // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+
+    #ifdef BSP_USING_UART3
+    {
+        .uart_periph = UART3,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart3",
+            .irqn = UART3_IRQn,                            // uart iqrn
+            RCU_UART3, RCU_GPIOC, RCU_GPIOC,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOC, GPIO_AF_8, GPIO_PIN_10,         // tx port, tx alternate, tx pin
+            GPIOC, GPIO_AF_8, GPIO_PIN_11,         // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+
+    #ifdef BSP_USING_UART4
+    {
+        .uart_periph = UART4,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart4",
+            .irqn = UART4_IRQn,                            // uart iqrn
+            RCU_UART4, RCU_GPIOC, RCU_GPIOD,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOC, GPIO_AF_8, GPIO_PIN_12,         // tx port, tx alternate, tx pin
+            GPIOD, GPIO_AF_8, GPIO_PIN_2,          // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+
+    #ifdef BSP_USING_UART5
+    {
+        .uart_periph = USART5,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart5",
+            .irqn = USART5_IRQn,                            // uart iqrn
+            RCU_USART5, RCU_GPIOC, RCU_GPIOC,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOC, GPIO_AF_8, GPIO_PIN_6,           // tx port, tx alternate, tx pin
+            GPIOC, GPIO_AF_8, GPIO_PIN_7,           // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+
+    #ifdef BSP_USING_UART6
+    {
+        .uart_periph = UART6,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart6",
+            .irqn = UART6_IRQn,                            // uart iqrn
+            RCU_UART6, RCU_GPIOE, RCU_GPIOE,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOE, GPIO_AF_8, GPIO_PIN_7,          // tx port, tx alternate, tx pin
+            GPIOE, GPIO_AF_8, GPIO_PIN_8,          // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+
+    #ifdef BSP_USING_UART7
+    {
+        .uart_periph = UART7,                                 // uart peripheral index
+        .uart_config = {
+            .name = "uart7",
+            .irqn = UART7_IRQn,                            // uart iqrn
+            RCU_UART7, RCU_GPIOE, RCU_GPIOE,       // periph clock, tx gpio clock, rt gpio clock
+            GPIOE, GPIO_AF_8, GPIO_PIN_0,          // tx port, tx alternate, tx pin
+            GPIOE, GPIO_AF_8, GPIO_PIN_1,          // rx port, rx alternate, rx pin
+        }
+    },
+    #endif
+};
+
+/**
+* @brief UART MSP Initialization
+*        This function configures the hardware resources used in this example:
+*           - Peripheral's clock enable
+*           - Peripheral's GPIO Configuration
+*           - NVIC configuration for UART interrupt request enable
+* @param huart: UART handle pointer
+* @retval None
+*/
+void gd32_uart_gpio_init(struct gd32_uart *uart)
+{
+    /* enable USART clock */
+    rcu_periph_clock_enable(uart->uart_config.tx_gpio_clk);
+    rcu_periph_clock_enable(uart->uart_config.rx_gpio_clk);
+    rcu_periph_clock_enable(uart->uart_config.per_clk);
+
+    /* connect port to USARTx_Tx */
+    gpio_af_set(uart->uart_config.tx_port, uart->uart_config.tx_af, uart->uart_config.tx_pin);
+
+    /* connect port to USARTx_Rx */
+    gpio_af_set(uart->uart_config.rx_port, uart->uart_config.rx_af, uart->uart_config.rx_pin);
+
+    /* configure USART Tx as alternate function push-pull */
+    gpio_mode_set(uart->uart_config.tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, uart->uart_config.tx_pin);
+    gpio_output_options_set(uart->uart_config.tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uart->uart_config.tx_pin);
+
+    /* configure USART Rx as alternate function push-pull */
+    gpio_mode_set(uart->uart_config.rx_port, GPIO_MODE_AF, GPIO_PUPD_NONE, uart->uart_config.rx_pin);
+    gpio_output_options_set(uart->uart_config.rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, uart->uart_config.rx_pin);
+}
+
+static rt_err_t gd32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    usart_baudrate_set(uart->uart_periph, cfg->baud_rate);
+
+    switch (cfg->data_bits)
+    {
+    case DATA_BITS_9:
+        usart_word_length_set(uart->uart_periph, USART_WL_9BIT);
+    break;
+
+    default:
+        usart_word_length_set(uart->uart_periph, USART_WL_8BIT);
+    break;
+    }
+
+    switch (cfg->stop_bits)
+    {
+    case STOP_BITS_2:
+        usart_stop_bit_set(uart->uart_periph, USART_STB_2BIT);
+    break;
+    default:
+        usart_stop_bit_set(uart->uart_periph, USART_STB_1BIT);
+    break;
+    }
+
+    switch (cfg->parity)
+    {
+    case PARITY_ODD:
+        usart_parity_config(uart->uart_periph, USART_PM_ODD);
+    break;
+    case PARITY_EVEN:
+        usart_parity_config(uart->uart_periph, USART_PM_EVEN);
+    break;
+    default:
+        usart_parity_config(uart->uart_periph, USART_PM_NONE);
+    break;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t gd32_init(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    gd32_uart_gpio_init(uart);
+
+    if (gd32_configure(serial, &serial->config) != RT_EOK)
+    {
+        return -RT_ERROR;
+    }
+
+    usart_receive_config(uart->uart_periph, USART_RECEIVE_ENABLE);
+    usart_transmit_config(uart->uart_periph, USART_TRANSMIT_ENABLE);
+
+    return RT_EOK;
+}
+
+static rt_err_t gd32_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct gd32_uart *uart;
+    rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    switch (cmd) {
+    case RT_DEVICE_CTRL_OPEN:
+        usart_interrupt_disable(uart->uart_periph, USART_INT_TBE);
+        usart_interrupt_disable(uart->uart_periph, USART_INT_TC);
+        usart_flag_clear(uart->uart_periph, USART_FLAG_RBNE);
+        usart_flag_clear(uart->uart_periph, USART_FLAG_TBE);
+        usart_flag_clear(uart->uart_periph, USART_FLAG_TC);
+        /* enable rx irq */
+        NVIC_SetPriority(uart->uart_config.irqn, 0);
+        NVIC_EnableIRQ(uart->uart_config.irqn);
+        usart_enable(uart->uart_periph);
+#ifdef RT_SERIAL_USING_DMA
+        uart->dmaTxing = RT_FALSE;
+#endif
+    break;
+    case RT_DEVICE_CTRL_CLOSE:
+        NVIC_DisableIRQ(uart->uart_config.irqn);
+        usart_interrupt_disable(uart->uart_periph, USART_INT_RBNE);
+        usart_interrupt_disable(uart->uart_periph, USART_INT_TBE);
+        usart_interrupt_disable(uart->uart_periph, USART_INT_IDLE);
+        usart_interrupt_disable(uart->uart_periph, USART_INT_TC);
+        usart_disable(uart->uart_periph);
+        usart_deinit(uart->uart_periph);
+#ifdef RT_SERIAL_USING_DMA
+        NVIC_DisableIRQ(uart->dma_rx.dma_irq);
+        dma_interrupt_disable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_CHXCTL_HTFIE);
+        dma_interrupt_disable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_CHXCTL_FTFIE);
+        dma_channel_disable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel);
+        dma_deinit(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel);
+
+        NVIC_DisableIRQ(uart->dma_tx.dma_irq);
+        dma_interrupt_disable(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel, DMA_CHXCTL_FTFIE);
+        dma_channel_disable(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel);
+        dma_deinit(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel);
+#endif
+    break;
+    case RT_DEVICE_CTRL_CLR_INT:
+        /* disable interrupt */
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_RX) {
+            usart_interrupt_disable(uart->uart_periph, USART_INT_RBNE);
+        }
+#ifdef RT_SERIAL_USING_DMA
+        /* disable DMA */
+        if (ctrl_arg & RT_DEVICE_FLAG_DMA_RX) {
+            NVIC_DisableIRQ(uart->dma_rx.dma_irq);
+            dma_interrupt_disable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_CHXCTL_HTFIE);
+            dma_interrupt_disable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_CHXCTL_FTFIE);
+        }
+        if(ctrl_arg & RT_DEVICE_FLAG_DMA_TX) {
+            NVIC_DisableIRQ(uart->dma_tx.dma_irq);
+            dma_interrupt_disable(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel, DMA_CHXCTL_FTFIE);
+        }
+#endif
+    break;
+    case RT_DEVICE_CTRL_SET_INT:
+        /* enable interrupt */
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_RX) {
+            usart_interrupt_enable(uart->uart_periph, USART_INT_RBNE);
+        }
+    break;
+    /* USART config */
+    case RT_DEVICE_CTRL_CONFIG :
+#ifdef RT_SERIAL_USING_DMA
+        if (ctrl_arg & RT_DEVICE_FLAG_DMA_RX) {
+            DMA_RX_Configuration(serial);
+        } else if (ctrl_arg & RT_DEVICE_FLAG_DMA_TX) {
+            DMA_TX_Configuration(serial);
+        }
+#endif
+    break;
+    default :
+    break;
+    }
+
+    return RT_EOK;
+}
+
+static int gd32_putc(struct rt_serial_device *serial, char ch)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    while((usart_flag_get(uart->uart_periph, USART_FLAG_TBE) == RESET));
+    usart_data_transmit(uart->uart_periph, ch);
+
+    return 1;
+}
+
+static int gd32_getc(struct rt_serial_device *serial)
+{
+    int ch;
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    ch = -1;
+    if (usart_flag_get(uart->uart_periph, USART_FLAG_RBNE) != RESET) {
+        ch = usart_data_receive(uart->uart_periph);
+    }
+    return ch;
+}
+
+static int gd32_flush(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+    while (!(usart_flag_get(uart->uart_periph, USART_FLAG_TBE) == SET && usart_flag_get(uart->uart_periph, USART_FLAG_TC) == SET));
+
+    return 1;
+}
+
+static void gd32_start_tx(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+    usart_interrupt_enable(uart->uart_periph, USART_INT_TBE);
+}
+
+static void gd32_stop_tx(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+    usart_interrupt_disable(uart->uart_periph, USART_INT_TBE);
+}
+
+#ifdef RT_SERIAL_USING_DMA
+static rt_bool_t gd32_is_dma_txing(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    return uart->dmaTxing;  //RT_FALSE;
+}
+
+static void gd32_start_dma_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    // TODO: 启用 DMA 发送
+    DMA_CHM0ADDR(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel) = (uint32_t)(buf);
+    DMA_CHCNT(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel) = (uint32_t)(size);
+    dma_channel_enable(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel);
+
+    uart->dmaTxing = RT_TRUE;
+}
+
+static void gd32_stop_dma_tx(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    // TODO: 禁用 DMA 发送
+    dma_channel_disable(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel);
+    uart->dmaTxing = RT_FALSE;
+}
+#endif
+
+static void gd32_enable_interrupt(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    NVIC_EnableIRQ(uart->uart_config.irqn);
+}
+
+static void gd32_disable_interrupt(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    NVIC_DisableIRQ(uart->uart_config.irqn);
+}
+
+#ifdef RT_SERIAL_USING_DMA
+/**
+ * DMA receive done process. This need add to DMA receive done ISR.
+ *
+ * @param serial serial device
+ */
+static void dma_rx_done_isr(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+    rt_size_t dma_cnt;
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    dma_cnt = RT_SERIAL_DMA_BUFSZ - DMA_CHCNT(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel);
+
+    rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (dma_cnt << 8));
+
+    dma_interrupt_flag_clear(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_INT_FLAG_HTF);
+    dma_interrupt_flag_clear(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_INT_FLAG_FTF);
+}
+/**
+ * DMA transmit done process. This need add to DMA transmit done ISR.
+ *
+ * @param serial serial device
+ */
+static void dma_tx_done_isr(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+    rt_size_t dma_cnt;
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    dma_cnt = DMA_CHCNT(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel);
+
+    if (dma_cnt == 0)
+    {
+        rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_TX_DMADONE);
+    }
+    dma_interrupt_flag_clear(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel, DMA_INT_FLAG_FTF);
+}
+#endif
+
+/**
+ * Uart common interrupt process. This need add to uart ISR.
+ *
+ * @param serial serial device
+ */
+static void uart_isr(struct rt_serial_device *serial)
+{
+    struct gd32_uart *uart;
+#ifdef RT_SERIAL_USING_DMA
+    rt_size_t dma_cnt;
+#endif
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    /* UART in mode Receiver -------------------------------------------------*/
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_RBNE) != RESET))
+    {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+        /* Clear RXNE interrupt flag */
+        usart_interrupt_flag_clear(uart->uart_periph, USART_INT_FLAG_RBNE);
+    }
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_RBNE_ORERR) != RESET))
+    {
+        usart_data_receive(uart->uart_periph);
+    }
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_TBE) != RESET))
+    {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
+        usart_interrupt_flag_clear(uart->uart_periph, USART_INT_FLAG_TBE);
+    }
+#ifdef RT_SERIAL_USING_DMA
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_IDLE) != RESET))
+    {
+        usart_data_receive(uart->uart_periph);
+        dma_cnt = RT_SERIAL_DMA_BUFSZ - DMA_CHCNT(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel);
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (dma_cnt << 8));
+    }
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_TC) != RESET))
+    {
+        usart_interrupt_flag_clear(uart->uart_periph, USART_INT_FLAG_TC);
+    }
+#endif
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_PERR) != RESET))
+    {
+        usart_data_receive(uart->uart_periph);
+    }
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_EB) != RESET))
+    {
+        usart_interrupt_flag_clear(uart->uart_periph, USART_INT_FLAG_EB);
+    }
+    if ((usart_interrupt_flag_get(uart->uart_periph, USART_INT_FLAG_RT) != RESET))
+    {
+        usart_interrupt_flag_clear(uart->uart_periph, USART_INT_FLAG_RT);
+    }
+}
+
+#if defined(BSP_USING_UART0)
+
+void USART0_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART0_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#ifdef RT_SERIAL_USING_DMA
+void DMA1_Channel2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_rx_done_isr(&uarts[UART0_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+void DMA1_Channel7_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_tx_done_isr(&uarts[UART0_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+
+#endif /* BSP_USING_UART0 */
+
+#if defined(BSP_USING_UART1)
+
+void USART1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART1_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#endif /* BSP_USING_UART1 */
+
+#if defined(BSP_USING_UART2)
+
+void USART2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART2_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#endif /* BSP_USING_UART2 */
+
+#if defined(BSP_USING_UART3)
+
+void UART3_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART3_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#endif /* BSP_USING_UART3 */
+
+#if defined(BSP_USING_UART4)
+
+void UART4_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART4_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif /* BSP_USING_UART4 */
+
+#if defined(BSP_USING_UART5)
+
+void USART5_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART5_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#endif /* BSP_USING_UART5 */
+
+#if defined(BSP_USING_UART6)
+
+void UART6_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART6_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#endif /* BSP_USING_UART6 */
+
+#if defined(BSP_USING_UART7)
+
+void UART7_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uarts[UART7_INDEX].serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#endif /* BSP_USING_UART7 */
+
+#ifdef RT_SERIAL_USING_DMA
+// TODO: 添加发送 DMA 配置,添加接收 DMA 配置
+static void DMA_RX_Configuration(struct rt_serial_device *serial)
+{
+    dma_single_data_parameter_struct dma_init_struct;
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    /* enable DMA1 */
+    rcu_periph_clock_enable(RCU_DMA1);
+
+    /* deinitialize DMA channel3(USART0 tx) */
+    dma_deinit(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel);
+    dma_init_struct.direction = DMA_PERIPH_TO_MEMORY;
+    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
+    dma_init_struct.memory0_addr = (uint32_t)(serial->serial_dma_rx);
+    dma_init_struct.number = RT_SERIAL_DMA_BUFSZ;
+    dma_init_struct.periph_addr = (uint32_t)(uart->uart_periph + 0x04);
+    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
+    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
+    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
+    dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_ENABLE;
+
+    dma_single_data_mode_init(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, &dma_init_struct);
+    dma_channel_subperipheral_select(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, uart->dma_rx.dma_subperi);
+
+    dma_interrupt_enable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_CHXCTL_HTFIE);
+    dma_interrupt_enable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel, DMA_CHXCTL_FTFIE);
+    NVIC_SetPriority(uart->dma_rx.dma_irq, 0);
+    NVIC_EnableIRQ(uart->dma_rx.dma_irq);
+    dma_channel_enable(uart->dma_rx.dma_periph, uart->dma_rx.dma_channel);
+    usart_dma_receive_config(uart->uart_periph, USART_DENR_ENABLE);
+}
+static void DMA_TX_Configuration(struct rt_serial_device *serial)
+{
+    dma_single_data_parameter_struct dma_init_struct;
+    struct gd32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct gd32_uart, serial);
+
+    /* enable DMA1 */
+    rcu_periph_clock_enable(RCU_DMA1);
+    /* deinitialize DMA channel3(USART0 tx) */
+    dma_deinit(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel);
+    dma_init_struct.direction = DMA_MEMORY_TO_PERIPH;
+    dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
+//    dma_init_struct.memory0_addr = (uint32_t)tx_buffer;
+//    dma_init_struct.number = ARRAYNUM(tx_buffer);
+    dma_init_struct.periph_addr = (uint32_t)(uart->uart_periph + 0x04);
+    dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
+    dma_init_struct.periph_memory_width = DMA_PERIPH_WIDTH_8BIT;
+    dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
+    dma_init_struct.circular_mode = DMA_CIRCULAR_MODE_DISABLE;
+
+    dma_single_data_mode_init(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel, &dma_init_struct);
+    dma_channel_subperipheral_select(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel, uart->dma_tx.dma_subperi);
+
+    dma_interrupt_enable(uart->dma_tx.dma_periph, uart->dma_tx.dma_channel, DMA_CHXCTL_FTFIE);
+    NVIC_SetPriority(uart->dma_tx.dma_irq, 0);
+    NVIC_EnableIRQ(uart->dma_tx.dma_irq);
+
+    usart_interrupt_enable(uart->uart_periph, USART_INT_IDLE);
+    usart_interrupt_enable(uart->uart_periph, USART_INT_TC);
+    usart_dma_transmit_config(uart->uart_periph, USART_DENT_ENABLE);
+}
+#endif
+static const struct rt_uart_ops gd32_uart_ops =
+{
+    .init = gd32_init,
+    .configure = gd32_configure,
+    .control = gd32_control,
+    .putc = gd32_putc,
+    .getc = gd32_getc,
+    .flush = gd32_flush,
+    .start_tx = gd32_start_tx,
+    .stop_tx = gd32_stop_tx,
+#ifdef RT_SERIAL_USING_DMA
+    .is_dma_txing = gd32_is_dma_txing,
+    .start_dma_tx = gd32_start_dma_tx,
+    .stop_dma_tx = gd32_stop_dma_tx,
+#endif
+    .enable_interrupt = gd32_enable_interrupt,
+    .disable_interrupt = gd32_disable_interrupt,
+};
+
+int rt_hw_usart_init(void)
+{
+    int i;
+
+    for (i = 0; i < sizeof(uarts) / sizeof(uarts[0]); i++)
+    {
+        uarts[i].serial.ops    = &gd32_uart_ops;
+
+        /* register UART1 device */
+        rt_hw_serial_register(&uarts[i].serial,
+                              uarts[i].uart_config.name,
+                              RT_DEVICE_FLAG_RDWR |
+                              RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX
+#ifdef RT_SERIAL_USING_DMA
+                            | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX
+#endif
+                              , RT_NULL);
+    }
+
+    return 0;
+}
+#endif // RT_USING_SERIAL

+ 64 - 0
bsp/gd32/arm/libraries/gd32_drivers/drv_usartX.h

@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2006-2021, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2009-01-05     Bernard      the first version
+ * 2022-06-09     THEWON       first version for serialX
+ */
+
+#ifndef __DRV_USARTX_H__
+#define __DRV_USARTX_H__
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <rtdevice.h>
+
+#define UART_ENABLE_IRQ(n)            NVIC_EnableIRQ((n))
+#define UART_DISABLE_IRQ(n)           NVIC_DisableIRQ((n))
+
+/* stm32 config class */
+struct gd32_uart_config
+{
+    const char *name;
+    IRQn_Type irqn;
+
+    rcu_periph_enum per_clk;
+    rcu_periph_enum tx_gpio_clk;
+    rcu_periph_enum rx_gpio_clk;
+    uint32_t tx_port;
+    uint16_t tx_af;
+    uint16_t tx_pin;
+    uint32_t rx_port;
+    uint16_t rx_af;
+    uint16_t rx_pin;
+};
+
+struct gd32_uart_dma
+{
+    /* dma channel */
+    uint32_t dma_periph;
+    dma_channel_enum dma_channel;
+    dma_subperipheral_enum dma_subperi;
+    /* dma irq channel */
+    IRQn_Type dma_irq;
+};
+
+/* gd32 uart driver class */
+struct gd32_uart
+{
+    uint32_t uart_periph;
+    struct rt_serial_device serial;
+    struct gd32_uart_config uart_config;
+#ifdef RT_SERIAL_USING_DMA
+    rt_bool_t dmaTxing;
+    struct gd32_uart_dma dma_rx;
+    struct gd32_uart_dma dma_tx;
+#endif
+};
+
+int rt_hw_usart_init(void);
+
+#endif // __DRV_USARTX_H__

+ 2 - 0
bsp/n32/libraries/n32_drivers/SConscript

@@ -14,6 +14,8 @@ if GetDepend(['RT_USING_PIN']):
 if GetDepend(['RT_USING_SERIAL']):
     if GetDepend(['RT_USING_SERIAL_V2']):
         src += ['drv_usart_v2.c']
+    elif GetDepend(['RT_USING_SERIAL_X']):
+        src += ['drv_usartX.c']
     else:
         src += ['drv_usart.c']
 

+ 839 - 0
bsp/n32/libraries/n32_drivers/drv_usartX.c

@@ -0,0 +1,839 @@
+/*
+ * File      : usart.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006-2022, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2009-01-05     Bernard      the first version
+ * 2010-03-29     Bernard      remove interrupt Tx and DMA Rx mode
+ * 2013-05-13     aozima       update for kehong-lingtai.
+ * 2015-01-31     armink       make sure the serial transmit complete in putc()
+ * 2016-05-13     armink       add DMA Rx mode
+ * 2017-01-19     aubr.cool    add interrupt Tx mode
+ * 2017-04-13     aubr.cool    correct Rx parity err
+ * 2021-08-20     breo.com     first version
+ * 2022-06-01     THEWON       first version for serialX
+ */
+
+#include <rtdevice.h>
+#include <rthw.h>
+#include <board.h>
+#include "drv_usartX.h"
+
+#define UART_ENABLE_IRQ(n)            NVIC_EnableIRQ((n))
+#define UART_DISABLE_IRQ(n)           NVIC_DisableIRQ((n))
+
+#ifdef RT_SERIAL_USING_DMA
+static void DMA_RX_Configuration(struct rt_serial_device *serial);
+static void DMA_TX_Configuration(struct rt_serial_device *serial);
+#endif
+
+static rt_err_t n32_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    struct n32_uart *uart;
+    USART_InitType USART_InitStructure;
+
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    USART_InitStructure.BaudRate = cfg->baud_rate;
+
+    switch (cfg->data_bits)
+    {
+    case DATA_BITS_8 :
+        USART_InitStructure.WordLength = USART_WL_8B;
+    break;
+    case DATA_BITS_9 :
+        USART_InitStructure.WordLength = USART_WL_9B;
+    break;
+    default:
+        USART_InitStructure.WordLength = USART_WL_8B;
+    break;
+    }
+
+    switch (cfg->stop_bits)
+    {
+    case STOP_BITS_1 :
+        USART_InitStructure.StopBits = USART_STPB_1;
+    break;
+    case STOP_BITS_2 :
+        USART_InitStructure.StopBits = USART_STPB_2;
+    break;
+    default:
+        USART_InitStructure.StopBits = USART_STPB_1;
+    break;
+    }
+
+    switch (cfg->parity)
+    case PARITY_NONE :
+        USART_InitStructure.Parity = USART_PE_NO;
+    break;
+    case PARITY_ODD :
+        USART_InitStructure.Parity = USART_PE_ODD;
+    break;
+    case PARITY_EVEN :
+        USART_InitStructure.Parity = USART_PE_EVEN;
+    break;
+    default:
+        USART_InitStructure.Parity = USART_PE_NO;
+    break;
+    }
+
+    USART_InitStructure.HardwareFlowControl = USART_HFCTRL_NONE;
+    USART_InitStructure.Mode = USART_MODE_RX | USART_MODE_TX;
+    USART_Init(uart->uart_device, &USART_InitStructure);
+
+    return RT_EOK;
+}
+
+static rt_err_t n32_uart_init(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+    USART_InitType USART_InitStructure;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    n32_msp_usart_init(uart->uart_device);
+
+    if (n32_uart_configure(serial, &serial->config) != RT_EOK)
+    {
+        return -RT_ERROR;
+    }
+
+    /* Enable USART */
+    USART_Enable(uart->uart_device, ENABLE);
+
+    USART_ClrFlag(uart->uart_device, USART_FLAG_TXDE|USART_FLAG_TXC);
+
+    return RT_EOK;
+}
+
+static rt_err_t n32_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct n32_uart *uart;
+    rt_uint32_t ctrl_arg = (rt_uint32_t)(arg);
+    NVIC_InitType NVIC_InitStructure;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    switch (cmd) {
+    case RT_DEVICE_CTRL_OPEN:
+        USART_ConfigInt(uart->uart_device, USART_INT_TXDE, DISABLE);
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_RXDNE);
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_TXDE);
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_TXC);
+        /* enable rx irq */
+        UART_ENABLE_IRQ(uart->irq);
+#ifdef RT_SERIAL_USING_DMA
+        uart->dmaTxing = RT_FALSE;
+#endif
+    break;
+    case RT_DEVICE_CTRL_CLOSE:
+        /* disable rx irq */
+        UART_DISABLE_IRQ(uart->irq);
+        USART_ConfigInt(uart->uart_device, USART_INT_RXDNE, DISABLE);
+        USART_ConfigInt(uart->uart_device, USART_INT_TXDE, DISABLE);
+        USART_ConfigInt(uart->uart_device, USART_INT_TXC, DISABLE);
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_RXDNE);
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_TXDE);
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_TXC);
+
+#ifdef RT_SERIAL_USING_DMA
+        NVIC_InitStructure.NVIC_IRQChannel = uart->dma_rx.dma_irq;
+        NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+        NVIC_Init(&NVIC_InitStructure);
+        DMA_EnableChannel(uart->dma_rx.dma_ch, DISABLE);
+        DMA_ConfigInt(uart->dma_rx.dma_ch, DMA_INT_HTX, DISABLE);
+        DMA_ConfigInt(uart->dma_rx.dma_ch, DMA_INT_TXC, DISABLE);
+        DMA_DeInit(uart->dma_rx.dma_ch);
+        NVIC_InitStructure.NVIC_IRQChannel = uart->dma_tx.dma_irq;
+        NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+        NVIC_Init(&NVIC_InitStructure);
+        DMA_EnableChannel(uart->dma_tx.dma_ch, DISABLE);
+        DMA_ConfigInt(uart->dma_tx.dma_ch, DMA_INT_TXC, DISABLE);
+        DMA_DeInit(uart->dma_tx.dma_ch);
+#endif
+    break;
+    case RT_DEVICE_CTRL_CLR_INT:
+        /* disable interrupt */
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_RX) {
+            USART_ConfigInt(uart->uart_device, USART_INT_RXDNE, DISABLE);
+        }
+
+#ifdef RT_SERIAL_USING_DMA
+        /* disable DMA */
+        if (ctrl_arg & RT_DEVICE_FLAG_DMA_RX) {
+            NVIC_InitStructure.NVIC_IRQChannel = uart->dma_rx.dma_irq;
+            NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+            NVIC_Init(&NVIC_InitStructure);
+            DMA_ConfigInt(uart->dma_rx.dma_ch, DMA_INT_HTX, DISABLE);
+            DMA_ConfigInt(uart->dma_rx.dma_ch, DMA_INT_TXC, DISABLE);
+        }
+        if(ctrl_arg & RT_DEVICE_FLAG_DMA_TX) {
+            NVIC_InitStructure.NVIC_IRQChannel = uart->dma_tx.dma_irq;
+            NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+            NVIC_Init(&NVIC_InitStructure);
+            DMA_ConfigInt(uart->dma_tx.dma_ch, DMA_INT_TXC, DISABLE);
+        }
+#endif
+    break;
+    case RT_DEVICE_CTRL_SET_INT:
+        /* enable interrupt */
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_RX) {
+            USART_ConfigInt(uart->uart_device, USART_INT_RXDNE, ENABLE);
+        }
+    break;
+    /* USART config */
+    case RT_DEVICE_CTRL_CONFIG :
+#ifdef RT_SERIAL_USING_DMA
+        if (ctrl_arg & RT_DEVICE_FLAG_DMA_RX) {
+            DMA_RX_Configuration(serial);
+        } else if (ctrl_arg & RT_DEVICE_FLAG_DMA_TX) {
+            DMA_TX_Configuration(serial);
+        }
+#endif
+    break;
+    default :
+    break;
+    }
+    return RT_EOK;
+}
+
+static int n32_uart_putc(struct rt_serial_device *serial, char c)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    while (!(uart->uart_device->STS & USART_FLAG_TXDE));
+    uart->uart_device->DAT = c;
+
+    return 1;
+}
+
+static int n32_uart_getc(struct rt_serial_device *serial)
+{
+    int ch;
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    ch = -1;
+    if (uart->uart_device->STS & USART_FLAG_RXDNE)
+    {
+        ch = uart->uart_device->DAT & 0xff;
+    }
+
+    return ch;
+}
+
+static int n32_uart_flush(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+    while(!((uart->uart_device->STS & USART_FLAG_TXDE) && (uart->uart_device->STS & USART_FLAG_TXC)));
+
+    return 0;
+}
+
+static void n32_start_tx(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    USART_ConfigInt(uart->uart_device, USART_INT_TXDE, ENABLE);
+}
+
+static void n32_stop_tx(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    USART_ConfigInt(uart->uart_device, USART_INT_TXDE, DISABLE);
+}
+
+#ifdef RT_SERIAL_USING_DMA
+static rt_bool_t n32_is_dma_txing(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+//    return uart->dmaTxing;  //RT_FALSE;
+    return (DMA_GetFlagStatus(uart->dma_tx.dma_flag, uart->dma_tx.dma_module) == SET);
+}
+
+static void n32_start_dma_tx(struct rt_serial_device *serial, rt_uint8_t *buf, rt_size_t size)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    // TODO: 启用 DMA 发送
+    uart->dma_tx.dma_ch->MADDR = (uint32_t)(buf);
+    uart->dma_tx.dma_ch->TXNUM = (uint32_t)(size);
+    DMA_EnableChannel(uart->dma_tx.dma_ch, ENABLE);
+
+    uart->dmaTxing = RT_TRUE;
+}
+
+static void n32_stop_dma_tx(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    // TODO: 禁用 DMA 发送
+    DMA_EnableChannel(uart->dma_tx.dma_ch, DISABLE);
+    uart->dmaTxing = RT_FALSE;
+}
+#endif
+
+static void n32_enable_interrupt(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    UART_ENABLE_IRQ(uart->irq);
+}
+
+static void n32_disable_interrupt(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    UART_DISABLE_IRQ(uart->irq);
+}
+
+#ifdef RT_SERIAL_USING_DMA
+/**
+ * DMA receive done process. This need add to DMA receive done ISR.
+ *
+ * @param serial serial device
+ */
+static void dma_rx_done_isr(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+    rt_size_t dma_cnt;
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    dma_cnt = RT_SERIAL_DMA_BUFSZ - DMA_GetCurrDataCounter(uart->dma_rx.dma_ch);
+
+    rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (dma_cnt << 8));
+
+    DMA_ClearFlag(uart->dma_rx.dma_flag, uart->dma_rx.dma_module);
+    DMA_ClrIntPendingBit(uart->dma_rx.dma_flag, uart->dma_rx.dma_module);
+}
+/**
+ * DMA transmit done process. This need add to DMA transmit done ISR.
+ *
+ * @param serial serial device
+ */
+static void dma_tx_done_isr(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+    rt_size_t dma_cnt;
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    dma_cnt = DMA_GetCurrDataCounter(uart->dma_tx.dma_ch);
+
+    if (dma_cnt == 0)
+    {
+        rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_TX_DMADONE);
+    }
+    DMA_ClrIntPendingBit(uart->dma_tx.dma_flag, uart->dma_rx.dma_module);
+}
+#endif
+
+/**
+ * Uart common interrupt process. This need add to uart ISR.
+ *
+ * @param serial serial device
+ */
+static void uart_isr(struct rt_serial_device *serial)
+{
+    struct n32_uart *uart;
+#ifdef RT_SERIAL_USING_DMA
+    rt_size_t dma_cnt;
+#endif
+
+    RT_ASSERT(uart != RT_NULL);
+
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    if(USART_GetIntStatus(uart->uart_device, USART_INT_RXDNE) != RESET)
+    {
+        if(USART_GetFlagStatus(uart->uart_device, USART_FLAG_PEF) == RESET)
+        {
+            rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+        }
+        /* clear interrupt */
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_RXDNE);
+    }
+    if(USART_GetIntStatus(uart->uart_device, USART_INT_TXDE) != RESET)
+    {
+        if(USART_GetFlagStatus(uart->uart_device, USART_FLAG_PEF) == RESET)
+        {
+            rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
+        }
+        /* clear interrupt */
+        USART_ClrIntPendingBit(uart->uart_device, USART_INT_TXDE);
+    }
+
+#ifdef RT_SERIAL_USING_DMA
+    if(USART_GetIntStatus(uart->uart_device, USART_INT_IDLEF) != RESET)
+    {
+        /* read a data for clear receive idle interrupt flag */
+        USART_ReceiveData(uart->uart_device);
+
+        dma_cnt = RT_SERIAL_DMA_BUFSZ - DMA_GetCurrDataCounter(uart->dma_rx.dma_ch);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (dma_cnt << 8));
+    }
+#endif
+    if (USART_GetFlagStatus(uart->uart_device, USART_FLAG_OREF) == SET)
+    {
+        n32_uart_getc(serial);
+    }
+}
+
+static const struct rt_uart_ops n32_uart_ops =
+{
+    .configure = n32_uart_configure,
+    .control = n32_uart_control,
+    .putc = n32_uart_putc,
+    .getc = n32_uart_getc,
+    .flush = n32_uart_flush,
+    .start_tx = n32_start_tx,
+    .stop_tx = n32_stop_tx,
+#ifdef RT_SERIAL_USING_DMA
+    .is_dma_txing = n32_is_dma_txing,
+    .start_dma_tx = n32_start_dma_tx,
+    .stop_dma_tx = n32_stop_dma_tx,
+#endif
+    .enable_interrupt = n32_enable_interrupt,
+    .disable_interrupt = n32_disable_interrupt,
+};
+
+#if defined(BSP_USING_UART1)
+/* UART1 device driver structure */
+struct n32_uart uart1 =
+{
+    .uart_device = USART1,
+    .irq = USART1_IRQn,
+#ifdef RT_SERIAL_USING_DMA
+    .dmaTxing = RT_FALSE,
+    .dma_rx = {
+        DMA1_CH5,
+        DMA1,
+        DMA1_FLAG_TC5 | DMA1_FLAG_HT5,
+        DMA1_Channel5_IRQn,
+    },
+    .dma_tx = {
+        DMA1_CH4,
+        DMA1,
+        DMA1_FLAG_TC4,
+        DMA1_Channel4_IRQn,
+    },
+#endif
+};
+
+void USART1_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uart1.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#ifdef RT_SERIAL_USING_DMA
+void DMA1_Channel5_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_rx_done_isr(&uart1.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+void DMA1_Channel4_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_tx_done_isr(&uart1.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#endif /* BSP_USING_UART1 */
+
+#if defined(BSP_USING_UART2)
+/* UART2 device driver structure */
+struct n32_uart uart2 =
+{
+    .uart_device = USART2,
+    .irq = USART2_IRQn,
+#ifdef RT_SERIAL_USING_DMA
+    .dmaTxing = RT_FALSE,
+    .dma_rx = {
+        DMA1_CH6,
+        DMA1,
+        DMA1_FLAG_TC6 | DMA1_FLAG_HT6,
+        DMA1_Channel6_IRQn,
+    },
+    .dma_tx = {
+        DMA1_CH7,
+        DMA1,
+        DMA1_FLAG_TC7,
+        DMA1_Channel7_IRQn,
+    },
+#endif
+};
+
+void USART2_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uart2.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#ifdef RT_SERIAL_USING_DMA
+void DMA1_Channel6_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_rx_done_isr(&uart2.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#endif /* BSP_USING_UART2 */
+
+#if defined(BSP_USING_UART3)
+/* UART3 device driver structure */
+struct n32_uart uart3 =
+{
+    .uart_device = USART3,
+    .irq = USART3_IRQn,
+#ifdef RT_SERIAL_USING_DMA
+    .dmaTxing = RT_FALSE,
+    .dma_rx = {
+        DMA1_CH3,
+        DMA1,
+        DMA1_FLAG_TC3 | DMA1_FLAG_HT3,
+        DMA1_Channel3_IRQn,
+    },
+    .dma_tx = {
+        DMA1_CH2,
+        DMA1,
+        DMA1_FLAG_TC2,
+        DMA1_Channel2_IRQn,
+    },
+#endif
+};
+
+void USART3_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uart3.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#ifdef RT_SERIAL_USING_DMA
+void DMA1_Channel3_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_rx_done_isr(&uart3.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#endif /* BSP_USING_UART3 */
+
+#if defined(BSP_USING_UART4)
+/* UART4 device driver structure */
+struct n32_uart uart4 =
+{
+    .uart_device = UART4,
+    .irq = UART4_IRQn,
+#ifdef RT_SERIAL_USING_DMA
+    .dmaTxing = RT_FALSE,
+    .dma_rx = {
+        DMA2_CH3,
+        DMA2,
+        DMA2_FLAG_TC3 | DMA2_FLAG_HT3,
+        DMA2_Channel3_IRQn,
+    },
+    .dma_tx = {
+        DMA2_CH5,
+        DMA2,
+        DMA2_FLAG_TC5,
+        DMA2_Channel5_IRQn,
+    },
+#endif
+};
+
+void UART4_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    uart_isr(&uart4.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+
+#ifdef RT_SERIAL_USING_DMA
+void DMA2_Channel3_IRQHandler(void)
+{
+    /* enter interrupt */
+    rt_interrupt_enter();
+
+    dma_rx_done_isr(&uart4.serial);
+
+    /* leave interrupt */
+    rt_interrupt_leave();
+}
+#endif
+#endif /* BSP_USING_UART4 */
+
+static void NVIC_Configuration(struct n32_uart *uart)
+{
+    NVIC_InitType NVIC_InitStructure;
+
+    /* Enable the USART1 Interrupt */
+    NVIC_InitStructure.NVIC_IRQChannel = uart->irq;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+    NVIC_Init(&NVIC_InitStructure);
+}
+
+#ifdef RT_SERIAL_USING_DMA
+// TODO: 添加发送 DMA 配置,添加接收 DMA 配置
+static void DMA_RX_Configuration(struct rt_serial_device *serial)
+{
+    DMA_InitType DMA_InitStructure;
+    NVIC_InitType NVIC_InitStructure;
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    /* enable transmit idle interrupt */
+    USART_ConfigInt(uart->uart_device, USART_INT_IDLEF, ENABLE);
+
+    /* DMA clock enable */
+    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
+    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA2, ENABLE);
+
+    /* rx dma config */
+    DMA_InitStructure.PeriphAddr = (uint32_t)&(uart->uart_device->DAT);
+    DMA_InitStructure.MemAddr = (uint32_t)(serial->serial_dma_rx);
+    DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
+    DMA_InitStructure.BufSize = RT_SERIAL_DMA_BUFSZ;
+    DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
+    DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
+    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;
+    DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte;
+    DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
+    DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
+    DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
+
+    DMA_DeInit(uart->dma_rx.dma_ch);
+    DMA_Init(uart->dma_rx.dma_ch, &DMA_InitStructure);
+
+    DMA_ClearFlag(uart->dma_rx.dma_flag, uart->dma_rx.dma_module);
+    DMA_ConfigInt(uart->dma_rx.dma_ch, DMA_INT_HTX, ENABLE);
+    DMA_ConfigInt(uart->dma_rx.dma_ch, DMA_INT_TXC, ENABLE);
+
+    USART_EnableDMA(uart->uart_device, USART_DMAREQ_RX, ENABLE);
+    DMA_EnableChannel(uart->dma_rx.dma_ch, ENABLE);
+
+    /* rx dma interrupt config */
+    NVIC_InitStructure.NVIC_IRQChannel = uart->dma_rx.dma_irq;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+}
+static void DMA_TX_Configuration(struct rt_serial_device *serial)
+{
+    DMA_InitType DMA_InitStructure;
+    NVIC_InitType NVIC_InitStructure;
+    struct n32_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+    uart = rt_container_of(serial, struct n32_uart, serial);
+
+    /* enable transmit idle interrupt */
+//    USART_ConfigInt(uart->uart_device, USART_INT_IDLEF, ENABLE);
+
+    /* DMA clock enable */
+    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA1, ENABLE);
+    RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA2, ENABLE);
+
+    /* tx dma config */
+    DMA_InitStructure.PeriphAddr = (uint32_t)&(uart->uart_device->DAT);
+//    DMA_InitStructure.MemAddr = (uint32_t)(serial->serial_dma_tx);
+    DMA_InitStructure.Direction = DMA_DIR_PERIPH_DST;
+//    DMA_InitStructure.BufSize = serial->config.bufsz;
+    DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
+    DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
+    DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_BYTE;
+    DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Byte;
+    DMA_InitStructure.CircularMode = DMA_MODE_NORMAL;
+    DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
+    DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
+
+    DMA_DeInit(uart->dma_tx.dma_ch);
+    DMA_Init(uart->dma_tx.dma_ch, &DMA_InitStructure);
+
+    DMA_ClearFlag(uart->dma_tx.dma_flag, uart->dma_tx.dma_module);
+    DMA_ConfigInt(uart->dma_tx.dma_ch, DMA_INT_TXC, ENABLE);
+    USART_EnableDMA(uart->uart_device, USART_DMAREQ_TX, ENABLE);
+//    DMA_EnableChannel(uart->dma_tx.dma_ch, ENABLE);
+
+    /* rx dma interrupt config */
+    NVIC_InitStructure.NVIC_IRQChannel = uart->dma_tx.dma_irq;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+}
+#endif
+
+int rt_hw_usart_init(void)
+{
+    struct n32_uart *uart;
+
+#if defined(BSP_USING_UART1)
+    uart = &uart1;
+
+    uart->serial.ops = &n32_uart_ops;
+
+    NVIC_Configuration(uart);
+
+    /* register UART1 device */
+    rt_hw_serial_register(&uart->serial, "uart1",
+                          RT_DEVICE_FLAG_RDWR |
+                          RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX
+#ifdef RT_SERIAL_USING_DMA
+                          | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX
+#endif
+                          , uart);
+#endif /* BSP_USING_UART1 */
+
+#if defined(BSP_USING_UART2)
+    uart = &uart2;
+
+    uart->serial.ops    = &n32_uart_ops;
+
+    NVIC_Configuration(uart);
+
+    /* register UART2 device */
+    rt_hw_serial_register(&uart->serial, "uart2",
+                          RT_DEVICE_FLAG_RDWR |
+                          RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX
+#ifdef RT_SERIAL_USING_DMA
+                          | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX
+#endif
+                          , uart);
+#endif /* BSP_USING_UART2 */
+
+#if defined(BSP_USING_UART3)
+    uart = &uart3;
+
+    uart->serial.ops    = &n32_uart_ops;
+
+    NVIC_Configuration(uart);
+
+    /* register UART3 device */
+    rt_hw_serial_register(&uart->serial, "uart3",
+                          RT_DEVICE_FLAG_RDWR |
+                          RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX
+#ifdef RT_SERIAL_USING_DMA
+                          | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX
+#endif
+                          , uart);
+#endif /* BSP_USING_UART3 */
+
+#if defined(BSP_USING_UART4)
+    uart = &uart4;
+
+    uart->serial.ops    = &n32_uart_ops;
+
+    NVIC_Configuration(uart);
+
+    /* register UART4 device */
+    rt_hw_serial_register(&uart->serial, "uart4",
+                          RT_DEVICE_FLAG_RDWR |
+                          RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX
+#ifdef RT_SERIAL_USING_DMA
+                          | RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX
+#endif
+                          , uart);
+#endif /* BSP_USING_UART4 */
+
+    return RT_EOK;
+}
+INIT_BOARD_EXPORT(rt_hw_usart_init);
+

+ 39 - 0
bsp/n32/libraries/n32_drivers/drv_usartX.h

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2022-06-06     THEWON       first version for serialX
+ */
+
+#ifndef __DRV_USARTX_H__
+#define __DRV_USARTX_H__
+
+#include "rtdevice.h"
+
+struct n32_uart_dma
+{
+    /* dma channel */
+    DMA_ChannelType *dma_ch;
+    DMA_Module *dma_module;
+    /* dma global flag */
+    uint32_t dma_flag;
+    /* dma irq channel */
+    uint8_t dma_irq;
+};
+
+struct n32_uart
+{
+    USART_Module *uart_device;
+    struct rt_serial_device serial;
+    IRQn_Type irq;
+#ifdef RT_SERIAL_USING_DMA
+    rt_bool_t dmaTxing;
+    struct n32_uart_dma dma_rx;
+    struct n32_uart_dma dma_tx;
+#endif
+};
+
+#endif  /* __DRV_USART_H__ */

+ 4 - 0
bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c

@@ -13,7 +13,11 @@
 #include <rtthread.h>
 #include <rthw.h>
 #include "board.h"
+#ifdef RT_USING_SERIAL_X
+#include "drv_uartX.h"
+#else
 #include "drv_uart.h"
+#endif
 #include "drv_sys.h"
 
 #if defined(BSP_USING_MMU)

+ 390 - 0
bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.c

@@ -0,0 +1,390 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-01     THEWON       first version for serialX
+ */
+
+#include <rtconfig.h>
+
+#ifdef RT_USING_SERIAL
+
+#include <rtdevice.h>
+#include "drv_uartX.h"
+#include "drv_sys.h"
+
+//#define DRV_DEBUG
+#define LOG_TAG             "drv.uart"
+// #include <drv_log.h>
+
+#if !defined(BSP_USING_UART1) && !defined(BSP_USING_UART2) && !defined(BSP_USING_UART3) && \
+    !defined(BSP_USING_UART4) && !defined(BSP_USING_UART5) && !defined(BSP_USING_UART6) && \
+    !defined(BSP_USING_UART7) && !defined(BSP_USING_UART8) && !defined(BSP_USING_UART9) && \
+    !defined(BSP_USING_UARTA)
+#error "Please define at least one BSP_USING_UARTx"
+/* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */
+#endif
+
+static int nu_uart_flush(struct rt_serial_device *serial);
+
+static void nu_uart_isr(int vector, void *param);
+
+static struct nu_uart nu_uart_arr[] =
+{
+#ifdef BSP_USING_UART0
+    UART0_CONFIG,
+#endif
+#ifdef BSP_USING_UART1
+    UART1_CONFIG,
+#endif
+#ifdef BSP_USING_UART2
+    UART2_CONFIG,
+#endif
+#ifdef BSP_USING_UART3
+    UART3_CONFIG,
+#endif
+#ifdef BSP_USING_UART4
+    UART4_CONFIG,
+#endif
+#ifdef BSP_USING_UART5
+    UART5_CONFIG,
+#endif
+#ifdef BSP_USING_UART6
+    UART6_CONFIG,
+#endif
+#ifdef BSP_USING_UART7
+    UART7_CONFIG,
+#endif
+#ifdef BSP_USING_UART8
+    UART8_CONFIG,
+#endif
+#ifdef BSP_USING_UART9
+    UART9_CONFIG,
+#endif
+#ifdef BSP_USING_UARTA
+    UARTA_CONFIG,
+#endif
+};
+
+// for ALL uarts
+static void nu_uart_isr(int vector, void *param)
+{
+    /* Get base address of uart register */
+    nu_uart_t serial = (nu_uart_t)param;
+    UART_T *uart_base = ((nu_uart_t)serial)->uart_base;
+
+    /* Get interrupt event */
+    uint32_t u32IntSts = uart_base->INTSTS;
+    uint32_t u32FIFOSts = uart_base->FIFOSTS;
+
+    if (u32IntSts & (UART_INTSTS_RDAINT_Msk | UART_INTSTS_RXTOINT_Msk)) {   // Received Data Available interrupt
+        rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    if (u32IntSts & UART_INTSTS_THREINT_Msk) {                            // Transmit Holding Register Empty interrupt
+        rt_hw_serial_isr(&serial->dev, RT_SERIAL_EVENT_TX_DONE | (16<<8));
+    }
+
+    // if (uRegISR & UART_INTSTS_MODEMINT_Msk) {
+        // uRegMSR = huart->Instance->MSR;
+        // uRegMSR |= UART_MSR_DCTSF_Msk;
+        // huart->Instance->MSR = uRegMSR;
+    // }
+
+    // if (uRegISR & UART_ISR_BUF_ERR_INT_Msk) {
+        // if (uRegFSR & (UART_FSR_TX_OVER_IF_Msk)) {
+            // huart->Instance->FSR = UART_FSR_TX_OVER_IF_Msk;
+        // }
+        // if (uRegFSR & (UART_FSR_RX_OVER_IF_Msk)) {
+            // huart->Instance->FSR = UART_FSR_RX_OVER_IF_Msk;
+        // }
+    // }
+
+    // if (uRegFSR & (UART_FSR_BIF_Msk | UART_FSR_FEF_Msk | UART_FSR_PEF_Msk | UART_FSR_RX_OVER_IF_Msk | UART_FSR_TX_OVER_IF_Msk)) {
+        // huart->Instance->FSR = (UART_FSR_BIF_Msk | UART_FSR_FEF_Msk | UART_FSR_PEF_Msk | UART_FSR_RX_OVER_IF_Msk | UART_FSR_TX_OVER_IF_Msk);
+    // }
+    uart_base->INTSTS = u32IntSts;
+    uart_base->FIFOSTS = u32FIFOSts;
+}
+
+/**
+ * Configure uart port
+ */
+static rt_err_t nu_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    rt_err_t ret = RT_EOK;
+    uint32_t uart_word_len = 0;
+    uint32_t uart_stop_bit = 0;
+    uint32_t uart_parity = 0;
+
+    /* Get base address of uart register */
+    UART_T *uart_base = ((nu_uart_t)serial)->uart_base;
+
+    /* Check baudrate */
+    RT_ASSERT(cfg->baud_rate != 0);
+
+    /* Check word len */
+    switch (cfg->data_bits) {
+    case DATA_BITS_5:
+        uart_word_len = UART_WORD_LEN_5;
+    break;
+    case DATA_BITS_6:
+        uart_word_len = UART_WORD_LEN_6;
+    break;
+    case DATA_BITS_7:
+        uart_word_len = UART_WORD_LEN_7;
+    break;
+    case DATA_BITS_8:
+        uart_word_len = UART_WORD_LEN_8;
+    break;
+    default:
+        uart_word_len = UART_WORD_LEN_8;
+    break;
+    }
+
+    /* Check stop bit */
+    switch (cfg->stop_bits) {
+    case STOP_BITS_1:
+        uart_stop_bit = UART_STOP_BIT_1;
+    break;
+    case STOP_BITS_2:
+        uart_stop_bit = UART_STOP_BIT_2;
+    break;
+    default:
+        uart_stop_bit = UART_STOP_BIT_1;
+    break;
+    }
+
+    /* Check parity */
+    switch (cfg->parity)
+    {
+    case PARITY_NONE:
+        uart_parity = UART_PARITY_NONE;
+    break;
+    case PARITY_ODD:
+        uart_parity = UART_PARITY_ODD;
+    break;
+    case PARITY_EVEN:
+        uart_parity = UART_PARITY_EVEN;
+    break;
+    default:
+        uart_parity = UART_PARITY_NONE;
+    break;
+    }
+
+    /* Set line configuration. */
+    UART_SetLineConfig(uart_base, cfg->baud_rate, uart_word_len, uart_parity, uart_stop_bit);
+
+    return RT_EOK;
+}
+
+/**
+ * Initialize uart port
+ */
+static rt_err_t nu_uart_init(struct rt_serial_device *serial)
+{
+    /* Get base address of uart register */
+    UART_T *uart_base = ((nu_uart_t)serial)->uart_base;
+
+//    nu_sys_ip_reset(((nu_uart_t)serial)->rstidx);
+
+    /* Open Uart and set UART Baudrate */
+    UART_Open(uart_base, serial->config->baud_rate);
+
+    if (nu_uart_configure(serial, &serial->config) != RT_EOK)
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t nu_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    nu_uart_t psNuUart = (nu_uart_t)serial;
+    rt_err_t result = RT_EOK;
+    rt_uint32_t flag;
+    rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    /* Get base address of uart register */
+    UART_T *uart_base = psNuUart->uart_base;
+
+    switch (cmd) {
+    case RT_DEVICE_CTRL_OPEN:
+        /* Enable interrupt. */
+        rt_hw_interrupt_umask(((nu_uart_t)serial)->irqn);
+    break;
+    case RT_DEVICE_CTRL_CLR_INT:
+        /* disable interrupt */
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_TX) {
+            UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
+        }
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_RX) {
+            flag = UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_TOCNTEN_Msk;
+            UART_DISABLE_INT(uart_base, flag);
+        }
+
+#ifdef RT_SERIAL_USING_DMA
+        /* disable DMA */
+#endif
+    break;
+    case RT_DEVICE_CTRL_SET_INT:
+        /* enable interrupt */
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_TX) {
+            UART_ENABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
+        }
+        if (ctrl_arg & RT_DEVICE_FLAG_INT_RX) {
+            flag = UART_INTEN_RDAIEN_Msk | UART_INTEN_RXTOIEN_Msk | UART_INTEN_TOCNTEN_Msk;
+            UART_ENABLE_INT(uart_base, flag);
+        }
+    break;
+    case RT_DEVICE_CTRL_CONFIG:
+#ifdef RT_SERIAL_USING_DMA
+#endif
+    break;
+    case RT_DEVICE_CTRL_CLOSE:
+        /* disable interrupt */
+        rt_hw_interrupt_mask(psNuUart->irqn);
+
+        /* Close UART port */
+        UART_Close(uart_base);
+    break;
+    default :
+    break;
+    }
+    return RT_EOK;
+}
+
+static int nu_uart_putc(struct rt_serial_device *serial, char c)
+{
+    UART_T *uart_base;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    /* Get base address of uart register */
+    uart_base = ((nu_uart_t)serial)->uart_base;
+    /* Waiting if TX-FIFO is full. */
+    while (UART_IS_TX_FULL(uart_base));
+    /* Put char into TX-FIFO */
+    UART_WRITE(uart_base, c);
+    return 1;
+}
+
+static int nu_uart_getc(struct rt_serial_device *serial)
+{
+    int ch;
+    UART_T *uart_base;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    /* Get base address of uart register */
+    uart_base = ((nu_uart_t)serial)->uart_base;
+
+    /* Return failure if RX-FIFO is empty. */
+    if (UART_GET_RX_EMPTY(uart_base)) {
+        return -1;
+    }
+    /* Get char from RX-FIFO */
+    ch = UART_READ(uart_base);
+
+    return ch;
+}
+
+static int nu_uart_flush(struct rt_serial_device *serial)
+{
+    UART_T *uart_base;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    /* Get base address of uart register */
+    uart_base = ((nu_uart_t)serial)->uart_base;
+    while(!UART_IS_TX_EMPTY(uart_base)){;}
+
+    return 1;
+}
+
+static void nu_start_tx(struct rt_serial_device *serial)
+{
+    UART_T *uart_base;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart_base = ((nu_uart_t)serial)->uart_base;
+
+    /* enable interrupt */
+    UART_ENABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
+}
+
+static void nu_stop_tx(struct rt_serial_device *serial)
+{
+    UART_T *uart_base;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart_base = ((nu_uart_t)serial)->uart_base;
+
+    /* disable interrupt */
+    UART_DISABLE_INT(uart_base, UART_INTEN_THREIEN_Msk);
+}
+
+static void nu_enable_interrupt(struct rt_serial_device *serial)
+{
+    RT_ASSERT(serial != RT_NULL);
+
+    rt_hw_interrupt_umask(((nu_uart_t)serial)->irqn);
+}
+
+static void nu_disable_interrupt(struct rt_serial_device *serial)
+{
+    RT_ASSERT(serial != RT_NULL);
+
+    rt_hw_interrupt_mask(((nu_uart_t)serial)->irqn);
+}
+
+static const struct rt_uart_ops nu_uart_ops =
+{
+    .init = nu_uart_init,
+    .configure = nu_uart_configure,
+    .control = nu_uart_control,
+    .putc = nu_uart_putc,
+    .getc = nu_uart_getc,
+    .flush = nu_uart_flush,
+    .start_tx = nu_start_tx,
+    .stop_tx = nu_stop_tx,
+    .enable_interrupt = nu_enable_interrupt,
+    .disable_interrupt = nu_disable_interrupt,
+};
+
+int rt_hw_uart_init(void)
+{
+    rt_size_t obj_num = sizeof(nu_uart_arr) / sizeof(struct nu_uart);
+    rt_err_t result = 0;
+    int i;
+
+    for (i = 0; i < obj_num; i++)
+    {
+        /* init UART object */
+        nu_uart_arr[i].dev.ops    = &nu_uart_ops;
+
+        rt_hw_interrupt_install(nu_uart_arr[i].irqn, nu_uart_isr, &nu_uart_arr[i], nu_uart_arr[i].name);
+
+        nu_sys_ipclk_enable(nu_uart_arr[i].clkidx);
+
+        /* register UART device */
+        result = rt_hw_serial_register(&nu_uart_arr[i].dev, nu_uart_arr[i].name,
+                                       RT_DEVICE_FLAG_RDWR
+                                       | RT_DEVICE_FLAG_INT_RX
+                                       | RT_DEVICE_FLAG_INT_TX
+                                       , NULL);
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return result;
+}
+
+#endif /* RT_USING_SERIAL */

+ 79 - 0
bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.h

@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-02-01     THEWON       first version for serialX
+ */
+
+#ifndef __DRV_UART_H__
+#define __DRV_UART_H__
+
+#include <rtthread.h>
+#include "rtdevice.h"
+#include <rthw.h>
+#include <drv_common.h>
+#include "NuMicro.h"
+#include <drv_sys.h>
+
+typedef void(*uart_isr_cb)(int, void*);
+
+/* Private typedef --------------------------------------------------------------*/
+struct nu_uart
+{
+    struct rt_serial_device dev;
+    char *name;
+    UART_T *uart_base;
+    IRQn_Type irqn;
+    E_SYS_IPRST rstidx;
+    E_SYS_IPCLK clkidx;
+
+#if defined(RT_SERIAL_USING_DMA)
+    uint32_t dma_flag;
+    int16_t pdma_perp_tx;
+    int8_t  pdma_chanid_tx;
+
+    int16_t pdma_perp_rx;
+    int8_t  pdma_chanid_rx;
+    int32_t rx_write_offset;
+    int32_t rxdma_trigger_len;
+
+    nu_pdma_desc_t pdma_rx_desc;
+#endif
+
+};
+typedef struct nu_uart *nu_uart_t;
+
+#if defined(BSP_USING_UART0)
+#ifndef UART0_CONFIG
+#define UART0_CONFIG                                                \
+    {                                                               \
+        .name = "uart0",                                            \
+        .uart_base = UART0,                                         \
+        .irqn = IRQ_UART0,                                          \
+        .rstidx = UART0RST,                                         \
+        .clkidx = UART0CKEN,                                        \
+    }
+#endif /* UART0_CONFIG */
+
+#endif /* BSP_USING_UART0 */
+
+#if defined(BSP_USING_UART1)
+#ifndef UART1_CONFIG
+#define UART1_CONFIG                                                \
+    {                                                               \
+        .name = "uart1",                                            \
+        .uart_base = UART1,                                         \
+        .irqn = IRQ_UART1,                                          \
+        .rstidx = UART1RST,                                         \
+        .clkidx = UART1CKEN,                                        \
+    }
+#endif /* UART1_CONFIG */
+
+#endif /* BSP_USING_UART1 */
+
+int rt_hw_uart_init(void);
+
+#endif  /* __DRV_UART_H__ */

+ 2 - 0
bsp/renesas/libraries/HAL_Drivers/SConscript

@@ -12,6 +12,8 @@ src = Split("""
 if GetDepend(['BSP_USING_UART']):
     if GetDepend(['RT_USING_SERIAL_V2']):
         src += ['drv_usart_v2.c']
+    elif GetDepend(['RT_USING_SERIAL_X']):
+        src += ['drv_usartX.c']
     else:
         print("\nThe current project does not support serial-v1\n")
         Return('group')

+ 625 - 0
bsp/renesas/libraries/HAL_Drivers/drv_usartX.c

@@ -0,0 +1,625 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2021-07-29     KyleChan          first version
+ * 2022-06-08     THEWON            first version for serialX
+ */
+
+#include <drv_usartX.h>
+
+#ifdef RT_USING_SERIAL_X
+
+//#define DRV_DEBUG
+#define DBG_TAG              "drv.usart"
+#ifdef DRV_DEBUG
+    #define DBG_LVL               DBG_LOG
+#else
+    #define DBG_LVL               DBG_INFO
+#endif /* DRV_DEBUG */
+#include <rtdbg.h>
+
+/* SCI SCR register bit masks */
+#define SCI_SCR_TEIE_MASK                       (0x04U) ///< Transmit End Interrupt Enable
+#define SCI_SCR_RE_MASK                         (0x10U) ///< Receive Enable
+#define SCI_SCR_TE_MASK                         (0x20U) ///< Transmit Enable
+#define SCI_SCR_RIE_MASK                        (0x40U) ///< Receive Interrupt Enable
+#define SCI_SCR_TIE_MASK                        (0x80U) ///< Transmit Interrupt Enable
+
+static struct ra_uart_config uart_config[] =
+{
+#ifdef BSP_USING_UART0
+    UART0_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART1
+    UART1_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART2
+    UART2_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART3
+    UART3_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART4
+    UART4_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART5
+    UART5_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART6
+    UART6_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART7
+    UART7_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART8
+    UART8_CONFIG,
+#endif
+
+#ifdef BSP_USING_UART9
+    UART9_CONFIG,
+#endif
+};
+
+enum
+{
+#ifdef BSP_USING_UART0
+    UART0_INDEX,
+#endif
+
+#ifdef BSP_USING_UART1
+    UART1_INDEX,
+#endif
+
+#ifdef BSP_USING_UART2
+    UART2_INDEX,
+#endif
+
+#ifdef BSP_USING_UART3
+    UART3_INDEX,
+#endif
+
+#ifdef BSP_USING_UART4
+    UART4_INDEX,
+#endif
+
+#ifdef BSP_USING_UART5
+    UART5_INDEX,
+#endif
+
+#ifdef BSP_USING_UART6
+    UART6_INDEX,
+#endif
+
+#ifdef BSP_USING_UART7
+    UART7_INDEX,
+#endif
+
+#ifdef BSP_USING_UART8
+    UART8_INDEX,
+#endif
+
+#ifdef BSP_USING_UART9
+    UART9_INDEX,
+#endif
+};
+
+static struct ra_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0};
+
+static void ra_uart_get_config(void)
+{
+    struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
+
+#ifdef BSP_USING_UART0
+    uart_obj[UART0_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART1
+    uart_obj[UART1_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART2
+    uart_obj[UART2_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART3
+    uart_obj[UART3_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART4
+    uart_obj[UART4_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART6
+    uart_obj[UART6_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART7
+    uart_obj[UART7_INDEX].serial.config = config;
+    uart_config[UART7_INDEX].uart_cfg = g_uart7_cfg;
+#endif
+
+#ifdef BSP_USING_UART8
+    uart_obj[UART8_INDEX].serial.config = config;
+#endif
+
+#ifdef BSP_USING_UART9
+    uart_obj[UART9_INDEX].serial.config = config;
+#endif
+}
+
+/*
+ * UART interface
+ */
+static rt_err_t ra_uart_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
+{
+    struct ra_uart *uart;
+    RT_ASSERT(serial != RT_NULL);
+    RT_ASSERT(cfg != RT_NULL);
+
+    fsp_err_t err = FSP_SUCCESS;
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+    RT_ASSERT(uart != RT_NULL);
+
+    if (cfg->data_bits == DATA_BITS_7)
+    {
+        uart->uart_config->uart_cfg.data_bits = UART_DATA_BITS_7;
+    }
+    else if (cfg->data_bits == DATA_BITS_8)
+    {
+        uart->uart_config->uart_cfg.data_bits = UART_DATA_BITS_8;
+    }
+    else if (cfg->data_bits == DATA_BITS_9)
+    {
+        uart->uart_config->uart_cfg.data_bits = UART_DATA_BITS_9;
+    }
+
+    if (cfg->stop_bits == STOP_BITS_1)
+    {
+        uart->uart_config->uart_cfg.stop_bits = UART_STOP_BITS_1;
+    }
+    else if (cfg->stop_bits == STOP_BITS_2)
+    {
+        uart->uart_config->uart_cfg.stop_bits = UART_STOP_BITS_2;
+    }
+
+    if (cfg->parity == PARITY_NONE)
+    {
+        uart->uart_config->uart_cfg.parity = UART_PARITY_OFF;
+    }
+    else if (cfg->parity == PARITY_ODD)
+    {
+        uart->uart_config->uart_cfg.parity = UART_PARITY_ODD;
+    }
+    else if (cfg->parity == PARITY_EVEN)
+    {
+        uart->uart_config->uart_cfg.parity = UART_PARITY_EVEN;
+    }
+
+    err = R_SCI_UART_Open(uart->uart_config->p_api_ctrl, &uart->uart_config->uart_cfg);
+    if (FSP_SUCCESS != err)
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+/*
+ * Initialize UART interface
+ */
+static rt_err_t ra_uart_init(struct rt_serial_device *serial)
+{
+    if (ra_uart_configure(serial, &serial->config) != RT_EOK)
+    {
+        return -RT_ERROR;
+    }
+
+    return RT_EOK;
+}
+
+static rt_err_t ra_uart_control(struct rt_serial_device *serial, int cmd, void *arg)
+{
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    switch (cmd) {
+    case RT_DEVICE_CTRL_OPEN:
+        uart->intTxing = RT_FALSE;
+    break;
+    case RT_DEVICE_CTRL_CLOSE:
+        R_SCI_UART_Close(uart->uart_config->p_api_ctrl);
+    break;
+    case RT_DEVICE_CTRL_CLR_INT:
+        /* disable interrupt */
+    break;
+    case RT_DEVICE_CTRL_SET_INT:
+        /* enable interrupt */
+    break;
+    /* USART config */
+    case RT_DEVICE_CTRL_CONFIG :
+    break;
+    default :
+    break;
+    }
+    return RT_EOK;
+}
+
+static int ra_uart_putc(struct rt_serial_device *serial, char c, rt_bool_t useint)
+{
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    sci_uart_instance_ctrl_t *p_ctrl = (sci_uart_instance_ctrl_t *)uart->uart_config->p_api_ctrl;
+
+    while ((p_ctrl->p_reg->SSR_b.TDRE) == 0);
+    p_ctrl->p_reg->TDR = c;
+    if (useint) {
+        p_ctrl->p_reg->SCR |= SCI_SCR_TE_MASK;
+        p_ctrl->p_reg->SCR |= SCI_SCR_TIE_MASK;
+    }
+
+    return RT_EOK;
+}
+
+static int ra_uart_getc(struct rt_serial_device *serial)
+{
+    int ch;
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    sci_uart_instance_ctrl_t *p_ctrl = (sci_uart_instance_ctrl_t *)uart->uart_config->p_api_ctrl;
+
+    ch = -1;
+    if ((p_ctrl->p_reg->SSR_b.RDRF) == 1) {
+        ch = p_ctrl->p_reg->RDR & 0xFF;
+        p_ctrl->p_reg->SSR_b.RDRF = 0;
+    }
+
+    return ch;
+}
+
+static int ra_uart_flush(struct rt_serial_device *serial)
+{
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    sci_uart_instance_ctrl_t *p_ctrl = (sci_uart_instance_ctrl_t *)uart->uart_config->p_api_ctrl;
+
+    while (!((p_ctrl->p_reg->SSR_b.TEND) == 1 && (p_ctrl->p_reg->SSR_b.TDRE) == 1));
+
+    return 0;
+}
+
+rt_bool_t ra_int_txing(struct rt_serial_device *serial)
+{
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    return uart->intTxing;
+}
+
+static void ra_start_tx(struct rt_serial_device *serial, rt_uint8_t ch)
+{
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    sci_uart_instance_ctrl_t *p_ctrl = (sci_uart_instance_ctrl_t *)uart->uart_config->p_api_ctrl;
+
+    uart->intTxing = RT_TRUE;
+    p_ctrl->p_reg->SCR &= ~(SCI_SCR_TIE_MASK | SCI_SCR_TEIE_MASK);
+    p_ctrl->p_reg->TDR = ch;
+    p_ctrl->p_reg->SCR |= SCI_SCR_TE_MASK;
+    /* Trigger a TXI interrupt. This triggers the transfer instance or a TXI interrupt if the transfer instance is
+     * not used. */
+    p_ctrl->p_reg->SCR |= SCI_SCR_TIE_MASK;
+}
+
+static void ra_stop_tx(struct rt_serial_device *serial)
+{
+    struct ra_uart *uart;
+
+    RT_ASSERT(serial != RT_NULL);
+
+    uart = rt_container_of(serial, struct ra_uart, serial);
+
+    sci_uart_instance_ctrl_t *p_ctrl = (sci_uart_instance_ctrl_t *)uart->uart_config->p_api_ctrl;
+
+    p_ctrl->p_reg->SCR &= ~(SCI_SCR_TIE_MASK | SCI_SCR_TEIE_MASK);
+    uart->intTxing = RT_FALSE;
+}
+
+#ifdef BSP_USING_UART0
+void user_uart0_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART0_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART1
+void user_uart1_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART1_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART2
+void user_uart2_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART2_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART3
+void user_uart3_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART3_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART4
+void user_uart4_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART4_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART5
+void user_uart5_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART5_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART6
+void user_uart6_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART6_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART7
+void user_uart7_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART7_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    } else if (UART_EVENT_TX_COMPLETE == p_args->event) {
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART8
+void user_uart8_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART8_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+#ifdef BSP_USING_UART9
+void user_uart9_callback(uart_callback_args_t *p_args)
+{
+    rt_interrupt_enter();
+
+    struct rt_serial_device *serial = &uart_obj[UART9_INDEX].serial;
+    RT_ASSERT(serial != RT_NULL);
+
+    if (UART_EVENT_RX_CHAR == p_args->event)
+    {
+        struct rt_serial_rx_fifo *rx_fifo;
+        rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx;
+        RT_ASSERT(rx_fifo != RT_NULL);
+
+        rt_ringbuffer_putchar(&(rx_fifo->rb), (rt_uint8_t)p_args->data);
+
+        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
+    }
+
+    rt_interrupt_leave();
+}
+#endif
+
+static const struct rt_uart_ops ra_uart_ops =
+{
+    .init = ra_uart_init,
+    .configure = ra_uart_configure,
+    .control = ra_uart_control,
+    .putc = ra_uart_putc,
+    .getc = ra_uart_getc,
+    .flush = ra_uart_flush,
+    .is_int_txing = ra_int_txing,
+    .start_tx = ra_start_tx,
+    .stop_tx = ra_stop_tx,
+};
+
+
+int rt_hw_usart_init(void)
+{
+    rt_err_t result = 0;
+    rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct ra_uart);
+
+    ra_uart_get_config();
+    for (int i = 0; i < obj_num; i++)
+    {
+        /* init UART object */
+        uart_obj[i].uart_config = &uart_config[i];
+        uart_obj[i].serial.ops = &ra_uart_ops;
+        /* register UART device */
+        result = rt_hw_serial_register(&uart_obj[i].serial,
+                                       uart_obj[i].uart_config->name,
+                                       RT_DEVICE_FLAG_RDWR |
+                                       RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_INT_TX,
+                                       NULL);
+        RT_ASSERT(result == RT_EOK);
+    }
+
+    return result;
+}
+
+#endif /* RT_USING_SERIAL_X */

+ 39 - 0
bsp/renesas/libraries/HAL_Drivers/drv_usartX.h

@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author            Notes
+ * 2021-07-29     KyleChan          first version
+ * 2022-06-08     THEWON            first version for serialX
+ */
+
+#ifndef __DRV_USART_V2_H__
+#define __DRV_USART_V2_H__
+
+#include <rtthread.h>
+#include <rtdevice.h>
+#include <rthw.h>
+#include <drv_common.h>
+#include <drv_config.h>
+#include <hal_data.h>
+
+/* renesas config class */
+struct ra_uart_config
+{
+    const char *name;
+    uart_ctrl_t * p_api_ctrl;
+    uart_cfg_t  uart_cfg;
+};
+
+struct ra_uart
+{
+    struct rt_serial_device serial;
+    struct ra_uart_config *uart_config;
+    rt_bool_t intTxing;
+};
+
+int rt_hw_usart_init(void);
+
+#endif  /* __DRV_USART_H__ */

+ 3 - 3
src/device.c

@@ -509,13 +509,13 @@ rt_err_t rt_device_bind_driver(rt_device_t device, rt_driver_t driver, void *nod
     }
 
     device->drv = driver;
-#ifdef RT_USING_DEVICE_OPS    
+#ifdef RT_USING_DEVICE_OPS
     device->ops = driver->dev_ops;
-#endif    
+#endif
     device->dtb_node = node;
 
     return RT_EOK;
-} 
+}
 RTM_EXPORT(rt_device_bind_driver);
 
 /**