diff options
Diffstat (limited to 'bsp/n32')
| -rw-r--r-- | bsp/n32/libraries/n32_drivers/SConscript | 2 | ||||
| -rw-r--r-- | bsp/n32/libraries/n32_drivers/drv_usartX.c | 839 | ||||
| -rw-r--r-- | bsp/n32/libraries/n32_drivers/drv_usartX.h | 39 |
3 files changed, 880 insertions, 0 deletions
diff --git a/bsp/n32/libraries/n32_drivers/SConscript b/bsp/n32/libraries/n32_drivers/SConscript index 107e4d1b33..8b2f3a26b7 100644 --- a/bsp/n32/libraries/n32_drivers/SConscript +++ b/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'] diff --git a/bsp/n32/libraries/n32_drivers/drv_usartX.c b/bsp/n32/libraries/n32_drivers/drv_usartX.c new file mode 100644 index 0000000000..cc025080fc --- /dev/null +++ b/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); + diff --git a/bsp/n32/libraries/n32_drivers/drv_usartX.h b/bsp/n32/libraries/n32_drivers/drv_usartX.h new file mode 100644 index 0000000000..c383b6d55a --- /dev/null +++ b/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__ */ |
