summaryrefslogtreecommitdiff
path: root/bsp/nuvoton/libraries
diff options
context:
space:
mode:
Diffstat (limited to 'bsp/nuvoton/libraries')
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c4
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.c390
-rw-r--r--bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.h79
3 files changed, 473 insertions, 0 deletions
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c
index 11790226e5..415ff6ca35 100644
--- a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_common.c
+++ b/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)
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.c b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.c
new file mode 100644
index 0000000000..1f17d89fbb
--- /dev/null
+++ b/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 */
diff --git a/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.h b/bsp/nuvoton/libraries/nuc980/rtt_port/drv_uartX.h
new file mode 100644
index 0000000000..98cea487fa
--- /dev/null
+++ b/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__ */