diff --git a/bsp/stm32/libraries/HAL_Drivers/SConscript b/bsp/stm32/libraries/HAL_Drivers/SConscript index e41a1f01412d7616d1168b32b002dde5f72d9589..dabcc7002cf8fe59fbcbd7329e8d158e3154fb2b 100644 --- a/bsp/stm32/libraries/HAL_Drivers/SConscript +++ b/bsp/stm32/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_V2']): + src += ['drv_usart_v2.c'] + else: + src += ['drv_usart.c'] if GetDepend(['RT_USING_HWTIMER']): src += ['drv_hwtimer.c'] diff --git a/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h b/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h index 0762f9048db00e5d761b429440b6859876ab484a..0064309f2ed137a843f4d2846492ebd11610eb3d 100644 --- a/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h +++ b/bsp/stm32/libraries/HAL_Drivers/config/l4/dma_config.h @@ -127,6 +127,17 @@ extern "C" { #endif /* DMA1 channel7 */ +#if defined(BSP_UART2_TX_USING_DMA) && !defined(UART2_TX_DMA_INSTANCE) +#define UART2_DMA_TX_IRQHandler DMA1_Channel7_IRQHandler +#define UART2_TX_DMA_RCC RCC_AHB1ENR_DMA1EN +#define UART2_TX_DMA_INSTANCE DMA1_Channel7 +#if defined(DMAMUX1) /* for L4+ */ +#define UART2_TX_DMA_REQUEST DMA_REQUEST_USART2_TX +#else /* for L4 */ +#define UART2_TX_DMA_REQUEST DMA_REQUEST_2 +#endif /* DMAMUX1 */ +#define UART2_TX_DMA_IRQ DMA1_Channel7_IRQn +#endif /* DMA2 channel1 */ #if defined(BSP_UART5_TX_USING_DMA) && !defined(UART5_TX_DMA_INSTANCE) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_common.c b/bsp/stm32/libraries/HAL_Drivers/drv_common.c index 74007b6e881d866a2e59c9edfdcd28178f9c4e5a..134eb7b3df39e99ecf14126de44c9ac9c9f01896 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_common.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_common.c @@ -12,8 +12,12 @@ #include "board.h" #ifdef RT_USING_SERIAL +#ifdef RT_USING_SERIAL_V2 +#include "drv_usart_v2.h" +#else #include "drv_usart.h" #endif +#endif #ifdef RT_USING_FINSH #include diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c new file mode 100644 index 0000000000000000000000000000000000000000..51dfc425c417def4170963c9ae31a4142f84d4c0 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.c @@ -0,0 +1,1137 @@ +/* + * Copyright (c) 2006-2020, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#include "board.h" +#include "drv_usart_v2.h" + +#ifdef RT_USING_SERIAL_V2 + +//#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 + +#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_LPUART1) + #error "Please define at least one BSP_USING_UARTx" + /* this driver can be disabled at menuconfig -> RT-Thread Components -> Device Drivers */ +#endif + +#ifdef RT_SERIAL_USING_DMA + static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag); +#endif + +enum +{ +#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_LPUART1 + LPUART1_INDEX, +#endif +}; + +static struct stm32_uart_config uart_config[] = +{ +#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_LPUART1 + LPUART1_CONFIG, +#endif +}; + + +static struct stm32_uart uart_obj[sizeof(uart_config) / sizeof(uart_config[0])] = {0}; + +static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg) +{ + struct stm32_uart *uart; + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(cfg != RT_NULL); + + uart = rt_container_of(serial, struct stm32_uart, serial); + + uart->handle.Instance = uart->config->Instance; + uart->handle.Init.BaudRate = cfg->baud_rate; + uart->handle.Init.HwFlowCtl = UART_HWCONTROL_NONE; + uart->handle.Init.Mode = UART_MODE_TX_RX; + uart->handle.Init.OverSampling = UART_OVERSAMPLING_16; + + if(uart->handle.Instance == USART3) + { + uart->handle.Init.HwFlowCtl = UART_HWCONTROL_RTS_CTS; + } + + switch (cfg->data_bits) + { + case DATA_BITS_8: + if (cfg->parity == PARITY_ODD || cfg->parity == PARITY_EVEN) + uart->handle.Init.WordLength = UART_WORDLENGTH_9B; + else + uart->handle.Init.WordLength = UART_WORDLENGTH_8B; + break; + case DATA_BITS_9: + uart->handle.Init.WordLength = UART_WORDLENGTH_9B; + break; + default: + uart->handle.Init.WordLength = UART_WORDLENGTH_8B; + break; + } + + switch (cfg->stop_bits) + { + case STOP_BITS_1: + uart->handle.Init.StopBits = UART_STOPBITS_1; + break; + case STOP_BITS_2: + uart->handle.Init.StopBits = UART_STOPBITS_2; + break; + default: + uart->handle.Init.StopBits = UART_STOPBITS_1; + break; + } + + switch (cfg->parity) + { + case PARITY_NONE: + uart->handle.Init.Parity = UART_PARITY_NONE; + break; + case PARITY_ODD: + uart->handle.Init.Parity = UART_PARITY_ODD; + break; + case PARITY_EVEN: + uart->handle.Init.Parity = UART_PARITY_EVEN; + break; + default: + uart->handle.Init.Parity = UART_PARITY_NONE; + break; + } + +#ifdef RT_SERIAL_USING_DMA + uart->dma_rx.remaining_cnt = serial->config.rx_bufsz; +#endif + + if (HAL_UART_Init(&uart->handle) != HAL_OK) + { + return -RT_ERROR; + } + + return RT_EOK; +} + +static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *arg) +{ + struct stm32_uart *uart; + + rt_ubase_t ctrl_arg = (rt_ubase_t)arg; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + if(ctrl_arg & (RT_DEVICE_FLAG_RX_BLOCKING | RT_DEVICE_FLAG_RX_NON_BLOCKING)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_RX) + ctrl_arg = RT_DEVICE_FLAG_DMA_RX; + else + ctrl_arg = RT_DEVICE_FLAG_INT_RX; + } + else if(ctrl_arg & (RT_DEVICE_FLAG_TX_BLOCKING | RT_DEVICE_FLAG_TX_NON_BLOCKING)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + ctrl_arg = RT_DEVICE_FLAG_DMA_TX; + else + ctrl_arg = RT_DEVICE_FLAG_INT_TX; + } + + switch (cmd) + { + /* disable interrupt */ + case RT_DEVICE_CTRL_CLR_INT: + + NVIC_DisableIRQ(uart->config->irq_type); + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TXE); +#ifdef RT_SERIAL_USING_DMA + else if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) + { + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE); + + HAL_NVIC_DisableIRQ(uart->config->dma_rx->dma_irq); + if (HAL_DMA_Abort(&(uart->dma_rx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + + if (HAL_DMA_DeInit(&(uart->dma_rx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + } + else if(ctrl_arg == RT_DEVICE_FLAG_DMA_TX) + { + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TC); + + HAL_NVIC_DisableIRQ(uart->config->dma_tx->dma_irq); + if (HAL_DMA_DeInit(&(uart->dma_tx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + } +#endif + break; + + case RT_DEVICE_CTRL_SET_INT: + + HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0); + HAL_NVIC_EnableIRQ(uart->config->irq_type); + + if (ctrl_arg == RT_DEVICE_FLAG_INT_RX) + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_RXNE); + else if (ctrl_arg == RT_DEVICE_FLAG_INT_TX) + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_TXE); + break; + + case RT_DEVICE_CTRL_CONFIG: + if (ctrl_arg & (RT_DEVICE_FLAG_DMA_RX | RT_DEVICE_FLAG_DMA_TX)) + { + +#ifdef RT_SERIAL_USING_DMA + stm32_dma_config(serial, ctrl_arg); +#endif + } + else + stm32_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)ctrl_arg); + break; + + case RT_DEVICE_CHECK_OPTMODE: + { + if (ctrl_arg & RT_DEVICE_FLAG_DMA_TX) + return RT_SERIAL_TX_BLOCKING_NO_BUFFER; + else + return RT_SERIAL_TX_BLOCKING_BUFFER; + } + case RT_DEVICE_CTRL_CLOSE: + if (HAL_UART_DeInit(&(uart->handle)) != HAL_OK ) + { + RT_ASSERT(0) + } + break; + + } + return RT_EOK; +} + +static int stm32_putc(struct rt_serial_device *serial, char c) +{ + struct stm32_uart *uart; + RT_ASSERT(serial != RT_NULL); + + uart = rt_container_of(serial, struct stm32_uart, serial); + while (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) == RESET); + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); + UART_SET_TDR(&uart->handle, c); + + return 1; +} + +static int stm32_getc(struct rt_serial_device *serial) +{ + int ch; + struct stm32_uart *uart; + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + ch = -1; + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) + ch = UART_GET_RDR(&uart->handle); + return ch; +} + +static rt_size_t stm32_transmit(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag) +{ + struct stm32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + { + HAL_UART_Transmit_DMA(&uart->handle, buf, size); + return size; + } + + stm32_control(serial, RT_DEVICE_CTRL_SET_INT, (void *)tx_flag); + + return size; +} + +#ifdef RT_SERIAL_USING_DMA +static void dma_recv_isr(struct rt_serial_device *serial, rt_uint8_t isr_flag) +{ + struct stm32_uart *uart; + rt_base_t level; + rt_uint16_t recv_len = 0; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + struct rt_serial_rx_fifo *rx_fifo; + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + level = rt_hw_interrupt_disable(); + rt_uint16_t index = __HAL_DMA_GET_COUNTER(&(uart->dma_rx.handle)); + switch (isr_flag) + { + + case UART_RX_DMA_IT_TC_FLAG: + if(index >= uart->dma_rx.remaining_cnt) + recv_len = serial->config.rx_bufsz + uart->dma_rx.remaining_cnt - index; + break; + + case UART_RX_DMA_IT_HT_FLAG: + case UART_RX_DMA_IT_IDLE_FLAG: + if(index < uart->dma_rx.remaining_cnt) + recv_len = uart->dma_rx.remaining_cnt - index; + break; + + default: + break; + } + + uart->dma_rx.remaining_cnt = index; + rt_serial_update_write_index(&(rx_fifo->rb), recv_len); + rt_hw_interrupt_enable(level); + +} +#endif /* RT_SERIAL_USING_DMA */ + + +/** + * Uart common interrupt process. This need add to uart ISR. + * + * @param serial serial device + */ +static void uart_isr(struct rt_serial_device *serial) +{ + struct stm32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + /* If the Read data register is not empty and the RXNE interrupt is enabled (RDR) */ + if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_RXNE) != RESET)) + { + 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), UART_GET_RDR(&uart->handle)); + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + } + /* If the Transmit data register is empty and the TXE interrupt enable is enabled (TDR)*/ + else if ((__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TXE) != RESET) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_TXE)) != RESET) + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + rt_uint8_t put_char = 0; + if (rt_ringbuffer_getchar(&(tx_fifo->rb), &put_char)) + { + UART_SET_TDR(&uart->handle, put_char); + } + else + { + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TXE); + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_TC); + } + } + else if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_TC) != RESET)) + { + if (uart->uart_dma_flag & RT_DEVICE_FLAG_DMA_TX) + { + /* The HAL_UART_TxCpltCallback will be triggered */ + HAL_UART_IRQHandler(&(uart->handle)); + } + else + { + /* Transmission complete interrupt disable ( CR1 Register) */ + __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_TC); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DONE); + } + /* Clear Transmission complete interrupt flag ( ISR Register ) */ + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); + } + +#ifdef RT_SERIAL_USING_DMA + else if ((uart->uart_dma_flag) && (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_IDLE) != RESET) + && (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_IDLE) != RESET)) + { + dma_recv_isr(serial, UART_RX_DMA_IT_IDLE_FLAG); + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND); + __HAL_UART_CLEAR_IDLEFLAG(&uart->handle); + } +#endif + else + { + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_ORE) != RESET) + { + __HAL_UART_CLEAR_OREFLAG(&uart->handle); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_NE) != RESET) + { + __HAL_UART_CLEAR_NEFLAG(&uart->handle); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_FE) != RESET) + { + __HAL_UART_CLEAR_FEFLAG(&uart->handle); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_PE) != RESET) + { + __HAL_UART_CLEAR_PEFLAG(&uart->handle); + } +#if !defined(SOC_SERIES_STM32L4) && !defined(SOC_SERIES_STM32WL) && !defined(SOC_SERIES_STM32F7) && !defined(SOC_SERIES_STM32F0) \ + && !defined(SOC_SERIES_STM32L0) && !defined(SOC_SERIES_STM32G0) && !defined(SOC_SERIES_STM32H7) \ + && !defined(SOC_SERIES_STM32G4) && !defined(SOC_SERIES_STM32MP1) && !defined(SOC_SERIES_STM32WB) + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_LBD) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_LBD); + } +#endif + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_CTS) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_CTS); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TXE) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TXE); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); + } + if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_RXNE) != RESET) + { + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_RXNE); + } + } +} + +#if defined(BSP_USING_UART1) +void USART1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART1_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_RX_USING_DMA) +void UART1_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART1_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_TX_USING_DMA) +void UART1_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART1_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART1_TX_USING_DMA) */ +#endif /* BSP_USING_UART1 */ + +#if defined(BSP_USING_UART2) +void USART2_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART2_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_RX_USING_DMA) +void UART2_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART2_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_TX_USING_DMA) +void UART2_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART2_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART2_TX_USING_DMA) */ +#endif /* BSP_USING_UART2 */ + +#if defined(BSP_USING_UART3) +void USART3_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART3_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART3_RX_USING_DMA) +void UART3_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART3_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_RX) && defined(BSP_UART3_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART3_TX_USING_DMA) +void UART3_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART3_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_TX) && defined(BSP_UART3_TX_USING_DMA) */ +#endif /* BSP_USING_UART3*/ + +#if defined(BSP_USING_UART4) +void UART4_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART4_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART4_RX_USING_DMA) +void UART4_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART4_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_RX) && defined(BSP_UART4_RX_USING_DMA) */ + +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART4_TX_USING_DMA) +void UART4_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART4_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(BSP_UART_USING_DMA_TX) && defined(BSP_UART4_TX_USING_DMA) */ +#endif /* BSP_USING_UART4*/ + +#if defined(BSP_USING_UART5) +void UART5_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART5_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_RX_USING_DMA) +void UART5_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART5_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_TX_USING_DMA) +void UART5_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART5_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART5_TX_USING_DMA) */ +#endif /* BSP_USING_UART5*/ + +#if defined(BSP_USING_UART6) +void USART6_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART6_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_RX_USING_DMA) +void UART6_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART6_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_TX_USING_DMA) +void UART6_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART6_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART6_TX_USING_DMA) */ +#endif /* BSP_USING_UART6*/ + +#if defined(BSP_USING_UART7) +void UART7_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART7_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_RX_USING_DMA) +void UART7_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART7_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_TX_USING_DMA) +void UART7_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART7_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART7_TX_USING_DMA) */ +#endif /* BSP_USING_UART7*/ + +#if defined(BSP_USING_UART8) +void UART8_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[UART8_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_RX_USING_DMA) +void UART8_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART8_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_RX_USING_DMA) */ +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_TX_USING_DMA) +void UART8_DMA_TX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[UART8_INDEX].dma_tx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_UART8_TX_USING_DMA) */ +#endif /* BSP_USING_UART8*/ + +#if defined(BSP_USING_LPUART1) +void LPUART1_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + uart_isr(&(uart_obj[LPUART1_INDEX].serial)); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#if defined(RT_SERIAL_USING_DMA) && defined(BSP_LPUART1_RX_USING_DMA) +void LPUART1_DMA_RX_IRQHandler(void) +{ + /* enter interrupt */ + rt_interrupt_enter(); + + HAL_DMA_IRQHandler(&uart_obj[LPUART1_INDEX].dma_rx.handle); + + /* leave interrupt */ + rt_interrupt_leave(); +} +#endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_LPUART1_RX_USING_DMA) */ +#endif /* BSP_USING_LPUART1*/ +static void stm32_uart_get_config(void) +{ + struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; +#ifdef BSP_USING_UART1 + uart_obj[UART1_INDEX].serial.config = config; + uart_obj[UART1_INDEX].uart_dma_flag = 0; + + uart_obj[UART1_INDEX].serial.config.rx_bufsz = BSP_UART1_RX_BUFSIZE; + uart_obj[UART1_INDEX].serial.config.tx_bufsz = BSP_UART1_TX_BUFSIZE; + +#ifdef BSP_UART1_RX_USING_DMA + uart_obj[UART1_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart1_dma_rx = UART1_DMA_RX_CONFIG; + uart_config[UART1_INDEX].dma_rx = &uart1_dma_rx; +#endif + +#ifdef BSP_UART1_TX_USING_DMA + uart_obj[UART1_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart1_dma_tx = UART1_DMA_TX_CONFIG; + uart_config[UART1_INDEX].dma_tx = &uart1_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART2 + uart_obj[UART2_INDEX].serial.config = config; + uart_obj[UART2_INDEX].uart_dma_flag = 0; + + uart_obj[UART2_INDEX].serial.config.rx_bufsz = BSP_UART2_RX_BUFSIZE; + uart_obj[UART2_INDEX].serial.config.tx_bufsz = BSP_UART2_TX_BUFSIZE; + +#ifdef BSP_UART2_RX_USING_DMA + uart_obj[UART2_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart2_dma_rx = UART2_DMA_RX_CONFIG; + uart_config[UART2_INDEX].dma_rx = &uart2_dma_rx; +#endif + +#ifdef BSP_UART2_TX_USING_DMA + uart_obj[UART2_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart2_dma_tx = UART2_DMA_TX_CONFIG; + uart_config[UART2_INDEX].dma_tx = &uart2_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART3 + uart_obj[UART3_INDEX].serial.config = config; + uart_obj[UART3_INDEX].uart_dma_flag = 0; + + uart_obj[UART3_INDEX].serial.config.rx_bufsz = BSP_UART3_RX_BUFSIZE; + uart_obj[UART3_INDEX].serial.config.tx_bufsz = BSP_UART3_TX_BUFSIZE; + +#ifdef BSP_UART3_RX_USING_DMA + uart_obj[UART3_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart3_dma_rx = UART3_DMA_RX_CONFIG; + uart_config[UART3_INDEX].dma_rx = &uart3_dma_rx; +#endif + +#ifdef BSP_UART3_TX_USING_DMA + uart_obj[UART3_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart3_dma_tx = UART3_DMA_TX_CONFIG; + uart_config[UART3_INDEX].dma_tx = &uart3_dma_tx; +#endif +#endif + +#ifdef BSP_USING_UART4 + uart_obj[UART4_INDEX].serial.config = config; + uart_obj[UART4_INDEX].uart_dma_flag = 0; + + uart_obj[UART4_INDEX].serial.config.rx_bufsz = BSP_UART4_RX_BUFSIZE; + uart_obj[UART4_INDEX].serial.config.tx_bufsz = BSP_UART4_TX_BUFSIZE; + +#ifdef BSP_UART4_RX_USING_DMA + uart_obj[UART4_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX; + static struct dma_config uart4_dma_rx = UART4_DMA_RX_CONFIG; + uart_config[UART4_INDEX].dma_rx = &uart4_dma_rx; +#endif + +#ifdef BSP_UART4_TX_USING_DMA + uart_obj[UART4_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX; + static struct dma_config uart4_dma_tx = UART4_DMA_TX_CONFIG; + uart_config[UART4_INDEX].dma_tx = &uart4_dma_tx; +#endif +#endif +} + +#ifdef RT_SERIAL_USING_DMA +static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag) +{ + struct rt_serial_rx_fifo *rx_fifo; + DMA_HandleTypeDef *DMA_Handle; + struct dma_config *dma_config; + struct stm32_uart *uart; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + DMA_Handle = &uart->dma_rx.handle; + dma_config = uart->config->dma_rx; + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + DMA_Handle = &uart->dma_tx.handle; + dma_config = uart->config->dma_tx; + } + LOG_D("%s dma config start", uart->config->name); + + { + rt_uint32_t tmpreg = 0x00U; +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32G0) \ + || defined(SOC_SERIES_STM32L0) + /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ + SET_BIT(RCC->AHBENR, dma_config->dma_rcc); + tmpreg = READ_BIT(RCC->AHBENR, dma_config->dma_rcc); +#elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) \ + || defined(SOC_SERIES_STM32G4)|| defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32WB) + /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ + SET_BIT(RCC->AHB1ENR, dma_config->dma_rcc); + tmpreg = READ_BIT(RCC->AHB1ENR, dma_config->dma_rcc); +#elif defined(SOC_SERIES_STM32MP1) + /* enable DMA clock && Delay after an RCC peripheral clock enabling*/ + SET_BIT(RCC->MP_AHB2ENSETR, dma_config->dma_rcc); + tmpreg = READ_BIT(RCC->MP_AHB2ENSETR, dma_config->dma_rcc); +#endif + +#if defined(DMAMUX1) && (defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32WB)) + /* enable DMAMUX clock for L4+ and G4 */ + __HAL_RCC_DMAMUX1_CLK_ENABLE(); +#elif defined(SOC_SERIES_STM32MP1) + __HAL_RCC_DMAMUX_CLK_ENABLE(); +#endif + + UNUSED(tmpreg); /* To avoid compiler warnings */ + } + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + __HAL_LINKDMA(&(uart->handle), hdmarx, uart->dma_rx.handle); + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + __HAL_LINKDMA(&(uart->handle), hdmatx, uart->dma_tx.handle); + } + +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32L0) + DMA_Handle->Instance = dma_config->Instance; +#elif defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) + DMA_Handle->Instance = dma_config->Instance; + DMA_Handle->Init.Channel = dma_config->channel; +#elif defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32WL) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32WB)\ + || defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32MP1) + DMA_Handle->Instance = dma_config->Instance; + DMA_Handle->Init.Request = dma_config->request; +#endif + DMA_Handle->Init.PeriphInc = DMA_PINC_DISABLE; + DMA_Handle->Init.MemInc = DMA_MINC_ENABLE; + DMA_Handle->Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; + DMA_Handle->Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; + + if (RT_DEVICE_FLAG_DMA_RX == flag) + { + DMA_Handle->Init.Direction = DMA_PERIPH_TO_MEMORY; + DMA_Handle->Init.Mode = DMA_CIRCULAR; + } + else if (RT_DEVICE_FLAG_DMA_TX == flag) + { + DMA_Handle->Init.Direction = DMA_MEMORY_TO_PERIPH; + DMA_Handle->Init.Mode = DMA_NORMAL; + } + + DMA_Handle->Init.Priority = DMA_PRIORITY_MEDIUM; +#if defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32H7) || defined(SOC_SERIES_STM32MP1) + DMA_Handle->Init.FIFOMode = DMA_FIFOMODE_DISABLE; +#endif + if (HAL_DMA_DeInit(DMA_Handle) != HAL_OK) + { + RT_ASSERT(0); + } + + if (HAL_DMA_Init(DMA_Handle) != HAL_OK) + { + RT_ASSERT(0); + } + + /* enable interrupt */ + if (flag == RT_DEVICE_FLAG_DMA_RX) + { + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + /* Start DMA transfer */ + if (HAL_UART_Receive_DMA(&(uart->handle), rx_fifo->buffer, serial->config.rx_bufsz) != HAL_OK) + { + /* Transfer error in reception process */ + RT_ASSERT(0); + } + CLEAR_BIT(uart->handle.Instance->CR3, USART_CR3_EIE); + __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_IDLE); + } + + /* DMA irq should set in DMA TX mode, or HAL_UART_TxCpltCallback function will not be called */ + HAL_NVIC_SetPriority(dma_config->dma_irq, 0, 0); + HAL_NVIC_EnableIRQ(dma_config->dma_irq); + + HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0); + HAL_NVIC_EnableIRQ(uart->config->irq_type); + + LOG_D("%s dma %s instance: %x", uart->config->name, flag == RT_DEVICE_FLAG_DMA_RX ? "RX" : "TX", DMA_Handle->Instance); + LOG_D("%s dma config done", uart->config->name); +} + +/** + * @brief UART error callbacks + * @param huart: UART handle + * @note This example shows a simple way to report transfer error, and you can + * add your own implementation. + * @retval None + */ +void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + RT_ASSERT(huart != NULL); + struct stm32_uart *uart = (struct stm32_uart *)huart; + LOG_D("%s: %s %d\n", __FUNCTION__, uart->config->name, huart->ErrorCode); + UNUSED(uart); +} + +/** + * @brief Rx Transfer completed callback + * @param huart: UART handle + * @note This example shows a simple way to report end of DMA Rx transfer, and + * you can add your own implementation. + * @retval None + */ +void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) +{ + struct stm32_uart *uart; + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + + dma_recv_isr(&uart->serial, UART_RX_DMA_IT_TC_FLAG); + rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE); +} + +/** + * @brief Rx Half transfer completed callback + * @param huart: UART handle + * @note This example shows a simple way to report end of DMA Rx Half transfer, + * and you can add your own implementation. + * @retval None + */ +void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) +{ + struct stm32_uart *uart; + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + + dma_recv_isr(&uart->serial, UART_RX_DMA_IT_HT_FLAG); + rt_hw_serial_isr(&uart->serial, RT_SERIAL_EVENT_RX_DMADONE); +} + +/** + * @brief HAL_UART_TxCpltCallback + * @param huart: UART handle + * @note This callback can be called by two functions, first in UART_EndTransmit_IT when + * UART Tx complete and second in UART_DMATransmitCplt function in DMA Circular mode. + * @retval None + */ +void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +{ + struct stm32_uart *uart; + struct rt_serial_device *serial; + rt_size_t trans_total_index; + rt_base_t level; + + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + serial = &uart->serial; + RT_ASSERT(serial != RT_NULL); + + level = rt_hw_interrupt_disable(); + trans_total_index = __HAL_DMA_GET_COUNTER(&(uart->dma_tx.handle)); + rt_hw_interrupt_enable(level); + + if (trans_total_index) return; + + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); + +} +#endif /* RT_SERIAL_USING_DMA */ + +static const struct rt_uart_ops stm32_uart_ops = +{ + .configure = stm32_configure, + .control = stm32_control, + .putc = stm32_putc, + .getc = stm32_getc, + .transmit = stm32_transmit +}; + +int rt_hw_usart_init(void) +{ + rt_err_t result = 0; + rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct stm32_uart); + + stm32_uart_get_config(); + for (int i = 0; i < obj_num; i++) + { + /* init UART object */ + uart_obj[i].config = &uart_config[i]; + uart_obj[i].serial.ops = &stm32_uart_ops; + /* register UART device */ + result = rt_hw_serial_register(&uart_obj[i].serial, + uart_obj[i].config->name, + RT_DEVICE_FLAG_RDWR, + NULL); + RT_ASSERT(result == RT_EOK); + } + + return result; +} + +#endif /* RT_USING_SERIAL_V2 */ diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h new file mode 100644 index 0000000000000000000000000000000000000000..3350b9086418512bfdad8b9731e8793744889df7 --- /dev/null +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart_v2.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#ifndef __DRV_USART_V2_H__ +#define __DRV_USART_V2_H__ + +#include +#include +#include +#include +#include +#include + +int rt_hw_usart_init(void); + +#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \ + || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \ + || defined(SOC_SERIES_STM32G4) +#define UART_SET_TDR(__HANDLE__, __DATA__) ((__HANDLE__)->Instance->TDR = (__DATA__)) +#define UART_GET_RDR(__HANDLE__) ((__HANDLE__)->Instance->RDR & 0xFF) + +#else +#define UART_SET_TDR(__HANDLE__, __DATA__) ((__HANDLE__)->Instance->DR = (__DATA__)) +#define UART_GET_RDR(__HANDLE__) (return (__HANDLE__)->Instance->DR & 0xFF)) +#endif + + +#if defined(SOC_SERIES_STM32F1) || defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F2) \ + || defined(SOC_SERIES_STM32F4) || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) \ + || defined(SOC_SERIES_STM32G4) || defined(SOC_SERIES_STM32WB) +#define UART_INSTANCE_CLEAR_FUNCTION __HAL_UART_CLEAR_FLAG +#elif defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) || defined(SOC_SERIES_STM32H7) \ + || defined(SOC_SERIES_STM32MP1) +#define UART_INSTANCE_CLEAR_FUNCTION __HAL_UART_CLEAR_IT +#endif + +#define UART_RX_DMA_IT_IDLE_FLAG 0x00 +#define UART_RX_DMA_IT_HT_FLAG 0x01 +#define UART_RX_DMA_IT_TC_FLAG 0x02 + + +/* stm32 config class */ +struct stm32_uart_config +{ + const char *name; + USART_TypeDef *Instance; + IRQn_Type irq_type; + +#ifdef RT_SERIAL_USING_DMA + struct dma_config *dma_rx; + struct dma_config *dma_tx; +#endif +}; + +/* stm32 uart dirver class */ +struct stm32_uart +{ + UART_HandleTypeDef handle; + struct stm32_uart_config *config; + +#ifdef RT_SERIAL_USING_DMA + struct + { + DMA_HandleTypeDef handle; + rt_size_t remaining_cnt; + } dma_rx; + struct + { + DMA_HandleTypeDef handle; + } dma_tx; +#endif + rt_uint16_t uart_dma_flag; + struct rt_serial_device serial; +}; + +#endif /* __DRV_USART_H__ */ diff --git a/bsp/stm32/stm32l475-atk-pandora/.config b/bsp/stm32/stm32l475-atk-pandora/.config index 18377e1e4e4477e9363ea65c5eabec5368760f0c..365e154c1788fe2be83798452c0a88811c626a97 100644 --- a/bsp/stm32/stm32l475-atk-pandora/.config +++ b/bsp/stm32/stm32l475-atk-pandora/.config @@ -21,6 +21,12 @@ CONFIG_RT_USING_IDLE_HOOK=y CONFIG_RT_IDLE_HOOK_LIST_SIZE=4 CONFIG_IDLE_THREAD_STACK_SIZE=256 # CONFIG_RT_USING_TIMER_SOFT is not set + +# +# kservice optimization +# +# CONFIG_RT_KSERVICE_USING_STDLIB is not set +# CONFIG_RT_KSERVICE_USING_TINY_SIZE is not set CONFIG_RT_DEBUG=y CONFIG_RT_DEBUG_COLOR=y # CONFIG_RT_DEBUG_INIT_CONFIG is not set @@ -52,6 +58,7 @@ CONFIG_RT_USING_MEMPOOL=y # CONFIG_RT_USING_NOHEAP is not set CONFIG_RT_USING_SMALL_MEM=y # CONFIG_RT_USING_SLAB is not set +# CONFIG_RT_USING_USERHEAP is not set # CONFIG_RT_USING_MEMTRACE is not set CONFIG_RT_USING_HEAP=y @@ -64,7 +71,7 @@ CONFIG_RT_USING_DEVICE=y CONFIG_RT_USING_CONSOLE=y CONFIG_RT_CONSOLEBUF_SIZE=256 CONFIG_RT_CONSOLE_DEVICE_NAME="uart1" -CONFIG_RT_VER_NUM=0x40002 +CONFIG_RT_VER_NUM=0x40004 CONFIG_ARCH_ARM=y CONFIG_RT_USING_CPU_FFS=y CONFIG_ARCH_ARM_CORTEX_M=y @@ -115,14 +122,17 @@ CONFIG_RT_USING_DEVICE_IPC=y CONFIG_RT_PIPE_BUFSZ=512 # CONFIG_RT_USING_SYSTEM_WORKQUEUE is not set CONFIG_RT_USING_SERIAL=y +# CONFIG_RT_USING_SERIAL_V1 is not set +CONFIG_RT_USING_SERIAL_V2=y CONFIG_RT_SERIAL_USING_DMA=y -CONFIG_RT_SERIAL_RB_BUFSZ=64 # CONFIG_RT_USING_CAN is not set # CONFIG_RT_USING_HWTIMER is not set # CONFIG_RT_USING_CPUTIME is not set # CONFIG_RT_USING_I2C is not set +# CONFIG_RT_USING_PHY is not set CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_ADC is not set +# CONFIG_RT_USING_DAC is not set # CONFIG_RT_USING_PWM is not set # CONFIG_RT_USING_MTD_NOR is not set # CONFIG_RT_USING_MTD_NAND is not set @@ -135,7 +145,7 @@ CONFIG_RT_USING_PIN=y # CONFIG_RT_USING_SENSOR is not set # CONFIG_RT_USING_TOUCH is not set # CONFIG_RT_USING_HWCRYPTO is not set -# CONFIG_RT_USING_ENCODER is not set +# CONFIG_RT_USING_PULSE_ENCODER is not set # CONFIG_RT_USING_INPUT_CAPTURE is not set # CONFIG_RT_USING_WIFI is not set @@ -150,7 +160,7 @@ CONFIG_RT_USING_PIN=y # # CONFIG_RT_USING_LIBC is not set # CONFIG_RT_USING_PTHREADS is not set -CONFIG_RT_LIBC_USING_TIME=y +# CONFIG_RT_LIBC_USING_TIME is not set # # Network @@ -187,8 +197,28 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_RT_USING_RYM is not set # CONFIG_RT_USING_ULOG is not set # CONFIG_RT_USING_UTEST is not set +CONFIG_RT_USING_RT_LINK=y +CONFIG_RT_LINK_USING_SF_CRC=y +# CONFIG_RT_LINK_USING_HW_CRC is not set + +# +# rt-link hardware device configuration +# +CONFIG_RT_LINK_HW_DEVICE_NAME="uart2" +CONFIG_RT_LINK_USING_UART=y + +# +# rt link debug option +# +# CONFIG_USING_RT_LINK_DEBUG is not set +# CONFIG_USING_RT_LINK_HW_DEBUG is not set # CONFIG_RT_USING_LWP is not set +# +# RT-Thread Utestcases +# +# CONFIG_RT_USING_UTESTCASES is not set + # # RT-Thread online packages # @@ -196,10 +226,15 @@ CONFIG_RT_LIBC_USING_TIME=y # # IoT - internet of things # +# CONFIG_PKG_USING_LORAWAN_DRIVER is not set # CONFIG_PKG_USING_PAHOMQTT is not set +# CONFIG_PKG_USING_UMQTT is not set # CONFIG_PKG_USING_WEBCLIENT is not set # CONFIG_PKG_USING_WEBNET is not set # CONFIG_PKG_USING_MONGOOSE is not set +# CONFIG_PKG_USING_MYMQTT is not set +# CONFIG_PKG_USING_KAWAII_MQTT is not set +# CONFIG_PKG_USING_BC28_MQTT is not set # CONFIG_PKG_USING_WEBTERMINAL is not set # CONFIG_PKG_USING_CJSON is not set # CONFIG_PKG_USING_JSMN is not set @@ -226,6 +261,8 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_COAP is not set # CONFIG_PKG_USING_NOPOLL is not set # CONFIG_PKG_USING_NETUTILS is not set +# CONFIG_PKG_USING_CMUX is not set +# CONFIG_PKG_USING_PPP_DEVICE is not set # CONFIG_PKG_USING_AT_DEVICE is not set # CONFIG_PKG_USING_ATSRV_SOCKET is not set # CONFIG_PKG_USING_WIZNET is not set @@ -237,7 +274,10 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_GAGENT_CLOUD is not set # CONFIG_PKG_USING_ALI_IOTKIT is not set # CONFIG_PKG_USING_AZURE is not set -# CONFIG_PKG_USING_TENCENT_IOTHUB is not set +# CONFIG_PKG_USING_TENCENT_IOT_EXPLORER is not set +# CONFIG_PKG_USING_JIOT-C-SDK is not set +# CONFIG_PKG_USING_UCLOUD_IOT_SDK is not set +# CONFIG_PKG_USING_JOYLINK is not set # CONFIG_PKG_USING_NIMBLE is not set # CONFIG_PKG_USING_OTA_DOWNLOADER is not set # CONFIG_PKG_USING_IPMSG is not set @@ -246,8 +286,23 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_LIBRWS is not set # CONFIG_PKG_USING_TCPSERVER is not set # CONFIG_PKG_USING_PROTOBUF_C is not set -# CONFIG_PKG_USING_ONNX_PARSER is not set -# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_DLT645 is not set +# CONFIG_PKG_USING_QXWZ is not set +# CONFIG_PKG_USING_SMTP_CLIENT is not set +# CONFIG_PKG_USING_ABUP_FOTA is not set +# CONFIG_PKG_USING_LIBCURL2RTT is not set +# CONFIG_PKG_USING_CAPNP is not set +# CONFIG_PKG_USING_RT_CJSON_TOOLS is not set +# CONFIG_PKG_USING_AGILE_TELNET is not set +# CONFIG_PKG_USING_NMEALIB is not set +# CONFIG_PKG_USING_AGILE_JSMN is not set +# CONFIG_PKG_USING_PDULIB is not set +# CONFIG_PKG_USING_BTSTACK is not set +# CONFIG_PKG_USING_LORAWAN_ED_STACK is not set +# CONFIG_PKG_USING_WAYZ_IOTKIT is not set +# CONFIG_PKG_USING_MAVLINK is not set +# CONFIG_PKG_USING_RAPIDJSON is not set +# CONFIG_PKG_USING_BSAL is not set # # security packages @@ -255,6 +310,8 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_MBEDTLS is not set # CONFIG_PKG_USING_libsodium is not set # CONFIG_PKG_USING_TINYCRYPT is not set +# CONFIG_PKG_USING_TFM is not set +# CONFIG_PKG_USING_YD_CRYPTO is not set # # language packages @@ -270,6 +327,10 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_MUPDF is not set # CONFIG_PKG_USING_STEMWIN is not set # CONFIG_PKG_USING_WAVPLAYER is not set +# CONFIG_PKG_USING_TJPGD is not set +# CONFIG_PKG_USING_HELIX is not set +# CONFIG_PKG_USING_AZUREGUIX is not set +# CONFIG_PKG_USING_TOUCHGFX2RTT is not set # # tools packages @@ -281,7 +342,31 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_RDB is not set # CONFIG_PKG_USING_QRCODE is not set # CONFIG_PKG_USING_ULOG_EASYFLASH is not set +# CONFIG_PKG_USING_ULOG_FILE is not set +# CONFIG_PKG_USING_LOGMGR is not set # CONFIG_PKG_USING_ADBD is not set +# CONFIG_PKG_USING_COREMARK is not set +# CONFIG_PKG_USING_DHRYSTONE is not set +# CONFIG_PKG_USING_MEMORYPERF is not set +# CONFIG_PKG_USING_NR_MICRO_SHELL is not set +# CONFIG_PKG_USING_CHINESE_FONT_LIBRARY is not set +# CONFIG_PKG_USING_LUNAR_CALENDAR is not set +# CONFIG_PKG_USING_BS8116A is not set +# CONFIG_PKG_USING_GPS_RMC is not set +# CONFIG_PKG_USING_URLENCODE is not set +# CONFIG_PKG_USING_UMCN is not set +# CONFIG_PKG_USING_LWRB2RTT is not set +# CONFIG_PKG_USING_CPU_USAGE is not set +# CONFIG_PKG_USING_GBK2UTF8 is not set +# CONFIG_PKG_USING_VCONSOLE is not set +# CONFIG_PKG_USING_KDB is not set +# CONFIG_PKG_USING_WAMR is not set +# CONFIG_PKG_USING_MICRO_XRCE_DDS_CLIENT is not set +# CONFIG_PKG_USING_LWLOG is not set +# CONFIG_PKG_USING_ANV_TRACE is not set +# CONFIG_PKG_USING_ANV_MEMLEAK is not set +# CONFIG_PKG_USING_ANV_TESTSUIT is not set +# CONFIG_PKG_USING_ANV_BENCH is not set # # system packages @@ -293,14 +378,43 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_LWEXT4 is not set # CONFIG_PKG_USING_PARTITION is not set # CONFIG_PKG_USING_FAL is not set +# CONFIG_PKG_USING_FLASHDB is not set # CONFIG_PKG_USING_SQLITE is not set # CONFIG_PKG_USING_RTI is not set # CONFIG_PKG_USING_LITTLEVGL2RTT is not set # CONFIG_PKG_USING_CMSIS is not set # CONFIG_PKG_USING_DFS_YAFFS is not set # CONFIG_PKG_USING_LITTLEFS is not set +# CONFIG_PKG_USING_DFS_JFFS2 is not set +# CONFIG_PKG_USING_DFS_UFFS is not set # CONFIG_PKG_USING_THREAD_POOL is not set # CONFIG_PKG_USING_ROBOTS is not set +# CONFIG_PKG_USING_EV is not set +# CONFIG_PKG_USING_SYSWATCH is not set +# CONFIG_PKG_USING_SYS_LOAD_MONITOR is not set +# CONFIG_PKG_USING_PLCCORE is not set +# CONFIG_PKG_USING_RAMDISK is not set +# CONFIG_PKG_USING_MININI is not set +# CONFIG_PKG_USING_QBOOT is not set + +# +# Micrium: Micrium software products porting for RT-Thread +# +# CONFIG_PKG_USING_UCOSIII_WRAPPER is not set +# CONFIG_PKG_USING_UCOSII_WRAPPER is not set +# CONFIG_PKG_USING_UC_CRC is not set +# CONFIG_PKG_USING_UC_CLK is not set +# CONFIG_PKG_USING_UC_COMMON is not set +# CONFIG_PKG_USING_UC_MODBUS is not set +# CONFIG_PKG_USING_PPOOL is not set +# CONFIG_PKG_USING_OPENAMP is not set +# CONFIG_PKG_USING_RT_KPRINTF_THREADSAFE is not set +# CONFIG_PKG_USING_RT_MEMCPY_CM is not set +# CONFIG_PKG_USING_QFPLIB_M0_FULL is not set +# CONFIG_PKG_USING_QFPLIB_M0_TINY is not set +# CONFIG_PKG_USING_QFPLIB_M3 is not set +# CONFIG_PKG_USING_LPM is not set +# CONFIG_PKG_USING_TLSF is not set # # peripheral libraries and drivers @@ -308,6 +422,8 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_SENSORS_DRIVERS is not set # CONFIG_PKG_USING_REALTEK_AMEBA is not set # CONFIG_PKG_USING_SHT2X is not set +# CONFIG_PKG_USING_SHT3X is not set +# CONFIG_PKG_USING_AS7341 is not set # CONFIG_PKG_USING_STM32_SDIO is not set # CONFIG_PKG_USING_ICM20608 is not set # CONFIG_PKG_USING_U8G2 is not set @@ -316,10 +432,16 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_SX12XX is not set # CONFIG_PKG_USING_SIGNAL_LED is not set # CONFIG_PKG_USING_LEDBLINK is not set +# CONFIG_PKG_USING_LITTLED is not set +# CONFIG_PKG_USING_LKDGUI is not set +# CONFIG_PKG_USING_NRF5X_SDK is not set +# CONFIG_PKG_USING_NRFX is not set # CONFIG_PKG_USING_WM_LIBRARIES is not set # CONFIG_PKG_USING_KENDRYTE_SDK is not set # CONFIG_PKG_USING_INFRARED is not set # CONFIG_PKG_USING_ROSSERIAL is not set +# CONFIG_PKG_USING_AGILE_BUTTON is not set +# CONFIG_PKG_USING_AGILE_LED is not set # CONFIG_PKG_USING_AT24CXX is not set # CONFIG_PKG_USING_MOTIONDRIVER2RTT is not set # CONFIG_PKG_USING_AD7746 is not set @@ -327,7 +449,47 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_I2C_TOOLS is not set # CONFIG_PKG_USING_NRF24L01 is not set # CONFIG_PKG_USING_TOUCH_DRIVERS is not set -# CONFIG_PKG_USING_LCD_DRIVERS is not set +# CONFIG_PKG_USING_MAX17048 is not set +# CONFIG_PKG_USING_RPLIDAR is not set +# CONFIG_PKG_USING_AS608 is not set +# CONFIG_PKG_USING_RC522 is not set +# CONFIG_PKG_USING_WS2812B is not set +# CONFIG_PKG_USING_EMBARC_BSP is not set +# CONFIG_PKG_USING_EXTERN_RTC_DRIVERS is not set +# CONFIG_PKG_USING_MULTI_RTIMER is not set +# CONFIG_PKG_USING_MAX7219 is not set +# CONFIG_PKG_USING_BEEP is not set +# CONFIG_PKG_USING_EASYBLINK is not set +# CONFIG_PKG_USING_PMS_SERIES is not set +# CONFIG_PKG_USING_CAN_YMODEM is not set +# CONFIG_PKG_USING_LORA_RADIO_DRIVER is not set +# CONFIG_PKG_USING_QLED is not set +# CONFIG_PKG_USING_PAJ7620 is not set +# CONFIG_PKG_USING_AGILE_CONSOLE is not set +# CONFIG_PKG_USING_LD3320 is not set +# CONFIG_PKG_USING_WK2124 is not set +# CONFIG_PKG_USING_LY68L6400 is not set +# CONFIG_PKG_USING_DM9051 is not set +# CONFIG_PKG_USING_SSD1306 is not set +# CONFIG_PKG_USING_QKEY is not set +# CONFIG_PKG_USING_RS485 is not set +# CONFIG_PKG_USING_NES is not set +# CONFIG_PKG_USING_VIRTUAL_SENSOR is not set +# CONFIG_PKG_USING_VDEVICE is not set +# CONFIG_PKG_USING_SGM706 is not set +# CONFIG_PKG_USING_RDA58XX is not set + +# +# AI packages +# +# CONFIG_PKG_USING_LIBANN is not set +# CONFIG_PKG_USING_NNOM is not set +# CONFIG_PKG_USING_ONNX_BACKEND is not set +# CONFIG_PKG_USING_ONNX_PARSER is not set +# CONFIG_PKG_USING_TENSORFLOWLITEMICRO is not set +# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_ULAPACK is not set +# CONFIG_PKG_USING_QUEST is not set # # miscellaneous packages @@ -337,6 +499,7 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_FASTLZ is not set # CONFIG_PKG_USING_MINILZO is not set # CONFIG_PKG_USING_QUICKLZ is not set +# CONFIG_PKG_USING_LZMA is not set # CONFIG_PKG_USING_MULTIBUTTON is not set # CONFIG_PKG_USING_FLEXIBLE_BUTTON is not set # CONFIG_PKG_USING_CANFESTIVAL is not set @@ -345,6 +508,8 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_TINYFRAME is not set # CONFIG_PKG_USING_KENDRYTE_DEMO is not set # CONFIG_PKG_USING_DIGITALCTRL is not set +# CONFIG_PKG_USING_UPACKER is not set +# CONFIG_PKG_USING_UPARAM is not set # # samples: kernel and components samples @@ -355,9 +520,69 @@ CONFIG_RT_LIBC_USING_TIME=y # CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set # CONFIG_PKG_USING_HELLO is not set # CONFIG_PKG_USING_VI is not set -# CONFIG_PKG_USING_NNOM is not set -# CONFIG_PKG_USING_LIBANN is not set -# CONFIG_PKG_USING_ELAPACK is not set +# CONFIG_PKG_USING_KI is not set +# CONFIG_PKG_USING_ARMv7M_DWT is not set +# CONFIG_PKG_USING_VT100 is not set +# CONFIG_PKG_USING_UKAL is not set +# CONFIG_PKG_USING_CRCLIB is not set + +# +# games: games run on RT-Thread console +# +# CONFIG_PKG_USING_THREES is not set +# CONFIG_PKG_USING_2048 is not set +# CONFIG_PKG_USING_SNAKE is not set +# CONFIG_PKG_USING_TETRIS is not set +# CONFIG_PKG_USING_LWGPS is not set +# CONFIG_PKG_USING_STATE_MACHINE is not set +# CONFIG_PKG_USING_MCURSES is not set +# CONFIG_PKG_USING_COWSAY is not set + +# +# Privated Packages of RealThread +# +# CONFIG_PKG_USING_CODEC is not set +# CONFIG_PKG_USING_PLAYER is not set +# CONFIG_PKG_USING_MPLAYER is not set +# CONFIG_PKG_USING_PERSIMMON_SRC is not set +# CONFIG_PKG_USING_JS_PERSIMMON is not set +# CONFIG_PKG_USING_JERRYSCRIPT_WIN32 is not set + +# +# Network Utilities +# +# CONFIG_PKG_USING_WICED is not set +# CONFIG_PKG_USING_CLOUDSDK is not set +# CONFIG_PKG_USING_POWER_MANAGER is not set +# CONFIG_PKG_USING_RT_OTA is not set +# CONFIG_PKG_USING_RTINSIGHT is not set +# CONFIG_PKG_USING_SMARTCONFIG is not set +# CONFIG_PKG_USING_RTX is not set +# CONFIG_RT_USING_TESTCASE is not set +# CONFIG_PKG_USING_NGHTTP2 is not set +# CONFIG_PKG_USING_AVS is not set +# CONFIG_PKG_USING_ALI_LINKKIT is not set +# CONFIG_PKG_USING_STS is not set +# CONFIG_PKG_USING_DLMS is not set +# CONFIG_PKG_USING_AUDIO_FRAMEWORK is not set +# CONFIG_PKG_USING_ZBAR is not set +# CONFIG_PKG_USING_MCF is not set +# CONFIG_PKG_USING_URPC is not set +# CONFIG_PKG_USING_DCM is not set +# CONFIG_PKG_USING_EMQ is not set +# CONFIG_PKG_USING_CFGM is not set +# CONFIG_PKG_USING_RT_CMSIS_DAP is not set +# CONFIG_PKG_USING_SMODULE is not set +# CONFIG_PKG_USING_SNFD is not set +# CONFIG_PKG_USING_UDBD is not set +# CONFIG_PKG_USING_BENCHMARK is not set +# CONFIG_PKG_USING_UBJSON is not set +# CONFIG_PKG_USING_DATATYPE is not set +# CONFIG_PKG_USING_FASTFS is not set +# CONFIG_PKG_USING_RIL is not set +# CONFIG_PKG_USING_WATCH_DCM_SVC is not set +# CONFIG_PKG_USING_GUI_TEST is not set +# CONFIG_PKG_USING_PMEM is not set CONFIG_SOC_FAMILY_STM32=y CONFIG_SOC_SERIES_STM32L4=y @@ -370,12 +595,15 @@ CONFIG_SOC_STM32L475VE=y # Onboard Peripheral Drivers # CONFIG_BSP_USING_STLINK_TO_USART=y +# CONFIG_BSP_USING_KEY is not set # CONFIG_BSP_USING_QSPI_FLASH is not set # CONFIG_BSP_USING_SPI_LCD is not set # CONFIG_BSP_USING_SDCARD is not set # CONFIG_BSP_USING_ICM20608 is not set # CONFIG_BSP_USING_AHT10 is not set # CONFIG_BSP_USING_AUDIO is not set +# CONFIG_BSP_USING_USB_AUDIO is not set +# CONFIG_BSP_USING_WIFI is not set # # On-chip Peripheral Drivers @@ -384,7 +612,14 @@ CONFIG_BSP_USING_GPIO=y CONFIG_BSP_USING_UART=y CONFIG_BSP_USING_UART1=y # CONFIG_BSP_UART1_RX_USING_DMA is not set -# CONFIG_BSP_USING_UART2 is not set +# CONFIG_BSP_UART1_TX_USING_DMA is not set +CONFIG_BSP_UART1_RX_BUFSIZE=256 +CONFIG_BSP_UART1_TX_BUFSIZE=0 +CONFIG_BSP_USING_UART2=y +CONFIG_BSP_UART2_RX_USING_DMA=y +CONFIG_BSP_UART2_TX_USING_DMA=y +CONFIG_BSP_UART2_RX_BUFSIZE=256 +CONFIG_BSP_UART2_TX_BUFSIZE=256 # CONFIG_BSP_USING_ON_CHIP_FLASH is not set # CONFIG_BSP_USING_SPI is not set # CONFIG_BSP_USING_QSPI is not set @@ -393,9 +628,11 @@ CONFIG_BSP_USING_UART1=y # CONFIG_BSP_USING_TIM is not set # CONFIG_BSP_USING_PWM is not set # CONFIG_BSP_USING_ADC is not set +# CONFIG_BSP_USING_DAC is not set # CONFIG_BSP_USING_ONCHIP_RTC is not set # CONFIG_BSP_USING_WDT is not set -# CONFIG_BSP_USING_USBD_FS is not set +# CONFIG_BSP_USING_USBD is not set +# CONFIG_BSP_USING_STM32_SDIO is not set # CONFIG_BSP_USING_CRC is not set # CONFIG_BSP_USING_RNG is not set # CONFIG_BSP_USING_UDID is not set diff --git a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig index bc71249fa00de6768e01da1a7c403955982aef88..e8a071364733828abc612564d76b43a010ebeed0 100644 --- a/bsp/stm32/stm32l475-atk-pandora/board/Kconfig +++ b/bsp/stm32/stm32l475-atk-pandora/board/Kconfig @@ -152,23 +152,59 @@ menu "On-chip Peripheral Drivers" default y select RT_USING_SERIAL if BSP_USING_UART - config BSP_USING_UART1 - bool "Enable UART1" + menuconfig BSP_USING_UART1 + bool "Enable UART1 (Debugger)" default y + if BSP_USING_UART1 + config BSP_UART1_RX_USING_DMA + bool "Enable UART1 RX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + + config BSP_UART1_TX_USING_DMA + bool "Enable UART1 TX DMA" + depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA + default n + + config BSP_UART1_RX_BUFSIZE + int "Set UART1 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART1_TX_BUFSIZE + int "Set UART1 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 0 + endif - config BSP_UART1_RX_USING_DMA - bool "Enable UART1 RX DMA" - depends on BSP_USING_UART1 && RT_SERIAL_USING_DMA - default n - - config BSP_USING_UART2 + menuconfig BSP_USING_UART2 bool "Enable UART2" default n - - config BSP_UART2_RX_USING_DMA - bool "Enable UART2 RX DMA" - depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA - default n + if BSP_USING_UART2 + config BSP_UART2_RX_USING_DMA + bool "Enable UART2 RX DMA" + depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA + default n + + config BSP_UART2_TX_USING_DMA + bool "Enable UART2 TX DMA" + depends on BSP_USING_UART2 && RT_SERIAL_USING_DMA + default n + + config BSP_UART2_RX_BUFSIZE + int "Set UART2 RX buffer size" + range 64 65535 + depends on RT_USING_SERIAL_V2 + default 256 + + config BSP_UART2_TX_BUFSIZE + int "Set UART2 TX buffer size" + range 0 65535 + depends on RT_USING_SERIAL_V2 + default 256 + endif endif config BSP_USING_ON_CHIP_FLASH diff --git a/bsp/stm32/stm32l475-atk-pandora/rtconfig.h b/bsp/stm32/stm32l475-atk-pandora/rtconfig.h index e18e51ae82d3dbe0fcb368ca9c9b2e3b101d3852..178f69b3eca7246fd1c93bff833abb45efdb2f49 100644 --- a/bsp/stm32/stm32l475-atk-pandora/rtconfig.h +++ b/bsp/stm32/stm32l475-atk-pandora/rtconfig.h @@ -16,6 +16,9 @@ #define RT_USING_IDLE_HOOK #define RT_IDLE_HOOK_LIST_SIZE 4 #define IDLE_THREAD_STACK_SIZE 256 + +/* kservice optimization */ + #define RT_DEBUG #define RT_DEBUG_COLOR @@ -39,7 +42,7 @@ #define RT_USING_CONSOLE #define RT_CONSOLEBUF_SIZE 256 #define RT_CONSOLE_DEVICE_NAME "uart1" -#define RT_VER_NUM 0x40002 +#define RT_VER_NUM 0x40004 #define ARCH_ARM #define RT_USING_CPU_FFS #define ARCH_ARM_CORTEX_M @@ -79,8 +82,8 @@ #define RT_USING_DEVICE_IPC #define RT_PIPE_BUFSZ 512 #define RT_USING_SERIAL +#define RT_USING_SERIAL_V2 #define RT_SERIAL_USING_DMA -#define RT_SERIAL_RB_BUFSZ 64 #define RT_USING_PIN /* Using USB */ @@ -88,7 +91,6 @@ /* POSIX layer and C standard library */ -#define RT_LIBC_USING_TIME /* Network */ @@ -109,6 +111,19 @@ /* Utilities */ +#define RT_USING_RT_LINK +#define RT_LINK_USING_SF_CRC + +/* rt-link hardware device configuration */ + +#define RT_LINK_HW_DEVICE_NAME "uart2" +#define RT_LINK_USING_UART + +/* rt link debug option */ + + +/* RT-Thread Utestcases */ + /* RT-Thread online packages */ @@ -141,14 +156,29 @@ /* system packages */ +/* Micrium: Micrium software products porting for RT-Thread */ + + /* peripheral libraries and drivers */ +/* AI packages */ + + /* miscellaneous packages */ /* samples: kernel and components samples */ + +/* games: games run on RT-Thread console */ + + +/* Privated Packages of RealThread */ + + +/* Network Utilities */ + #define SOC_FAMILY_STM32 #define SOC_SERIES_STM32L4 @@ -165,6 +195,13 @@ #define BSP_USING_GPIO #define BSP_USING_UART #define BSP_USING_UART1 +#define BSP_UART1_RX_BUFSIZE 256 +#define BSP_UART1_TX_BUFSIZE 0 +#define BSP_USING_UART2 +#define BSP_UART2_RX_USING_DMA +#define BSP_UART2_TX_USING_DMA +#define BSP_UART2_RX_BUFSIZE 256 +#define BSP_UART2_TX_BUFSIZE 256 /* Board extended module Drivers */ diff --git a/components/drivers/Kconfig b/components/drivers/Kconfig index c7fec6cba92d0693fa871e9b399a0bce212bf919..d3fd14b52dde801a99264bb0e04ba32d34e03131 100755 --- a/components/drivers/Kconfig +++ b/components/drivers/Kconfig @@ -24,22 +24,30 @@ if RT_USING_DEVICE_IPC endif endif -config RT_USING_SERIAL - bool "Using serial device drivers" +menuconfig RT_USING_SERIAL + bool "USING Serial device drivers" select RT_USING_DEVICE_IPC select RT_USING_DEVICE default y -if RT_USING_SERIAL - config RT_SERIAL_USING_DMA - bool "Enable serial DMA mode" - default y - - config RT_SERIAL_RB_BUFSZ - int "Set RX buffer size" - default 64 + if RT_USING_SERIAL + choice + prompt "Choice Serial version" + default RT_USING_SERIAL_V1 + config RT_USING_SERIAL_V1 + bool "RT_USING_SERIAL_V1" + config RT_USING_SERIAL_V2 + bool "RT_USING_SERIAL_V2" + endchoice + config RT_SERIAL_USING_DMA + bool "Enable serial DMA mode" + default y -endif + config RT_SERIAL_RB_BUFSZ + int "Set RX buffer size" + depends on !RT_USING_SERIAL_V2 + default 64 + endif config RT_USING_CAN bool "Using CAN device drivers" diff --git a/components/drivers/include/drivers/serial_v2.h b/components/drivers/include/drivers/serial_v2.h new file mode 100644 index 0000000000000000000000000000000000000000..18187bc0f55998fb6afe915b6e155e06b6e53f2d --- /dev/null +++ b/components/drivers/include/drivers/serial_v2.h @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#ifndef __SERIAL_V2_H__ +#define __SERIAL_V2_H__ + +#include + +#define BAUD_RATE_2400 2400 +#define BAUD_RATE_4800 4800 +#define BAUD_RATE_9600 9600 +#define BAUD_RATE_19200 19200 +#define BAUD_RATE_38400 38400 +#define BAUD_RATE_57600 57600 +#define BAUD_RATE_115200 115200 +#define BAUD_RATE_230400 230400 +#define BAUD_RATE_460800 460800 +#define BAUD_RATE_921600 921600 +#define BAUD_RATE_2000000 2000000 +#define BAUD_RATE_3000000 3000000 + +#define DATA_BITS_5 5 +#define DATA_BITS_6 6 +#define DATA_BITS_7 7 +#define DATA_BITS_8 8 +#define DATA_BITS_9 9 + +#define STOP_BITS_1 0 +#define STOP_BITS_2 1 +#define STOP_BITS_3 2 +#define STOP_BITS_4 3 + +#ifdef _WIN32 +#include +#else +#define PARITY_NONE 0 +#define PARITY_ODD 1 +#define PARITY_EVEN 2 +#endif + +#define BIT_ORDER_LSB 0 +#define BIT_ORDER_MSB 1 + +#define NRZ_NORMAL 0 /* Non Return to Zero : normal mode */ +#define NRZ_INVERTED 1 /* Non Return to Zero : inverted mode */ + +#define RT_DEVICE_FLAG_RX_BLOCKING 0x1000 +#define RT_DEVICE_FLAG_RX_NON_BLOCKING 0x2000 + +#define RT_DEVICE_FLAG_TX_BLOCKING 0x4000 +#define RT_DEVICE_FLAG_TX_NON_BLOCKING 0x8000 + +#define RT_SERIAL_RX_BLOCKING RT_DEVICE_FLAG_RX_BLOCKING +#define RT_SERIAL_RX_NON_BLOCKING RT_DEVICE_FLAG_RX_NON_BLOCKING +#define RT_SERIAL_TX_BLOCKING RT_DEVICE_FLAG_TX_BLOCKING +#define RT_SERIAL_TX_NON_BLOCKING RT_DEVICE_FLAG_TX_NON_BLOCKING + +#define RT_DEVICE_CHECK_OPTMODE 0x20 + +#define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */ +#define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */ +#define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */ +#define RT_SERIAL_EVENT_TX_DMADONE 0x04 /* Tx DMA transfer done */ +#define RT_SERIAL_EVENT_RX_TIMEOUT 0x05 /* Rx timeout */ + +#define RT_SERIAL_ERR_OVERRUN 0x01 +#define RT_SERIAL_ERR_FRAMING 0x02 +#define RT_SERIAL_ERR_PARITY 0x03 + +#define RT_SERIAL_TX_DATAQUEUE_SIZE 2048 +#define RT_SERIAL_TX_DATAQUEUE_LWM 30 + +#define RT_SERIAL_RX_MINBUFSZ 64 +#define RT_SERIAL_TX_MINBUFSZ 64 + +#define RT_SERIAL_TX_BLOCKING_BUFFER 1 +#define RT_SERIAL_TX_BLOCKING_NO_BUFFER 0 + +/* Default config for serial_configure structure */ +#define RT_SERIAL_CONFIG_DEFAULT \ +{ \ + BAUD_RATE_115200, /* 115200 bits/s */ \ + DATA_BITS_8, /* 8 databits */ \ + STOP_BITS_1, /* 1 stopbit */ \ + PARITY_NONE, /* No parity */ \ + BIT_ORDER_LSB, /* LSB first sent */ \ + NRZ_NORMAL, /* Normal mode */ \ + RT_SERIAL_RX_MINBUFSZ, /* rxBuf size */ \ + RT_SERIAL_TX_MINBUFSZ, /* txBuf size */ \ + 0 \ +} + +struct serial_configure +{ + rt_uint32_t baud_rate; + + rt_uint32_t data_bits :4; + rt_uint32_t stop_bits :2; + rt_uint32_t parity :2; + rt_uint32_t bit_order :1; + rt_uint32_t invert :1; + rt_uint32_t rx_bufsz :16; + rt_uint32_t tx_bufsz :16; + rt_uint32_t reserved :6; +}; + +/* + * Serial FIFO mode + */ +struct rt_serial_rx_fifo +{ + struct rt_ringbuffer rb; + + rt_uint16_t rx_index; + + struct rt_completion rx_cpt; + + rt_uint16_t rx_cpt_index; + + /* software fifo */ + rt_uint8_t buffer[]; +}; + +struct rt_serial_tx_fifo +{ + struct rt_ringbuffer rb; + + rt_size_t put_size; + + rt_bool_t activated; + + struct rt_completion tx_cpt; + + /* software fifo */ + rt_uint8_t buffer[]; +}; + +struct rt_serial_device +{ + struct rt_device parent; + + const struct rt_uart_ops *ops; + struct serial_configure config; + + void *serial_rx; + void *serial_tx; +}; + +/** + * uart operators + */ +struct rt_uart_ops +{ + rt_err_t (*configure)(struct rt_serial_device *serial, + struct serial_configure *cfg); + + rt_err_t (*control)(struct rt_serial_device *serial, + int cmd, + void *arg); + + int (*putc)(struct rt_serial_device *serial, char c); + int (*getc)(struct rt_serial_device *serial); + + rt_size_t (*transmit)(struct rt_serial_device *serial, + rt_uint8_t *buf, + rt_size_t size, + rt_uint32_t tx_flag); +}; + +rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, + rt_uint8_t **ptr); + +rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, + rt_uint16_t read_index); + +rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, + rt_uint16_t write_index); + +void rt_hw_serial_isr(struct rt_serial_device *serial, int event); + +rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, + const char *name, + rt_uint32_t flag, + void *data); + +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index fbd3c9e7b20f004d1d10524cfcd08be0916e7c79..07a2be361e8a4985d0ce1d0c3b054d2a4a9b8a13 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -57,7 +57,11 @@ extern "C" { #endif /* RT_USING_USB_HOST */ #ifdef RT_USING_SERIAL +#ifdef RT_USING_SERIAL_V2 +#include "drivers/serial_v2.h" +#else #include "drivers/serial.h" +#endif #endif /* RT_USING_SERIAL */ #ifdef RT_USING_I2C diff --git a/components/drivers/serial/SConscript b/components/drivers/serial/SConscript index a6eb1159190efeb5f3724ef0dcf39a7bdd1bd304..f3f69991f522381d72025bb5f217056ca88de452 100644 --- a/components/drivers/serial/SConscript +++ b/components/drivers/serial/SConscript @@ -1,8 +1,13 @@ from building import * -cwd = GetCurrentDir() -src = Glob('*.c') +cwd = GetCurrentDir() CPPPATH = [cwd + '/../include'] -group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) +if GetDepend(['RT_USING_SERIAL']): + if GetDepend(['RT_USING_SERIAL_V2']): + src = Glob('serial_v2.c') + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL_V2'], CPPPATH = CPPPATH) + else: + src = Glob('serial.c') + group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SERIAL'], CPPPATH = CPPPATH) Return('group') diff --git a/components/drivers/serial/serial_v2.c b/components/drivers/serial/serial_v2.c new file mode 100644 index 0000000000000000000000000000000000000000..f41cdcd8f96170a550ea8c54bc67944a72215124 --- /dev/null +++ b/components/drivers/serial/serial_v2.c @@ -0,0 +1,1171 @@ +/* + * Copyright (c) 2006-2018, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2021-06-01 KyleChan first version + */ + +#include +#include +#include + +#define DBG_TAG "UART" +#define DBG_LVL DBG_INFO +#include + +#ifdef RT_USING_POSIX +#include +#include + +#ifdef getc +#undef getc +#endif + +#ifdef putc +#undef putc +#endif + +static rt_err_t serial_fops_rx_ind(rt_device_t dev, rt_size_t size) +{ + rt_wqueue_wakeup(&(dev->wait_queue), (void*)POLLIN); + + return RT_EOK; +} + +/* fops for serial */ +static int serial_fops_open(struct dfs_fd *fd) +{ + rt_err_t ret = 0; + rt_uint16_t flags = 0; + rt_device_t device; + + device = (rt_device_t)fd->data; + RT_ASSERT(device != RT_NULL); + + switch (fd->flags & O_ACCMODE) + { + case O_RDONLY: + LOG_D("fops open: O_RDONLY!"); + flags = RT_DEVICE_FLAG_RDONLY; + break; + case O_WRONLY: + LOG_D("fops open: O_WRONLY!"); + flags = RT_DEVICE_FLAG_WRONLY; + break; + case O_RDWR: + LOG_D("fops open: O_RDWR!"); + flags = RT_DEVICE_FLAG_RDWR; + break; + default: + LOG_E("fops open: unknown mode - %d!", fd->flags & O_ACCMODE); + break; + } + + if ((fd->flags & O_ACCMODE) != O_WRONLY) + rt_device_set_rx_indicate(device, serial_fops_rx_ind); + ret = rt_device_open(device, flags); + if (ret == RT_EOK) return 0; + + return ret; +} + +static int serial_fops_close(struct dfs_fd *fd) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + + rt_device_set_rx_indicate(device, RT_NULL); + rt_device_close(device); + + return 0; +} + +static int serial_fops_ioctl(struct dfs_fd *fd, int cmd, void *args) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + switch (cmd) + { + case FIONREAD: + break; + case FIONWRITE: + break; + } + + return rt_device_control(device, cmd, args); +} + +static int serial_fops_read(struct dfs_fd *fd, void *buf, size_t count) +{ + int size = 0; + rt_device_t device; + + device = (rt_device_t)fd->data; + + do + { + size = rt_device_read(device, -1, buf, count); + if (size <= 0) + { + if (fd->flags & O_NONBLOCK) + { + size = -EAGAIN; + break; + } + + rt_wqueue_wait(&(device->wait_queue), 0, RT_WAITING_FOREVER); + } + }while (size <= 0); + + return size; +} + +static int serial_fops_write(struct dfs_fd *fd, const void *buf, size_t count) +{ + rt_device_t device; + + device = (rt_device_t)fd->data; + return rt_device_write(device, -1, buf, count); +} + +static int serial_fops_poll(struct dfs_fd *fd, struct rt_pollreq *req) +{ + int mask = 0; + int flags = 0; + rt_device_t device; + struct rt_serial_device *serial; + + device = (rt_device_t)fd->data; + RT_ASSERT(device != RT_NULL); + + serial = (struct rt_serial_device *)device; + + /* only support POLLIN */ + flags = fd->flags & O_ACCMODE; + if (flags == O_RDONLY || flags == O_RDWR) + { + rt_base_t level; + struct rt_serial_rx_fifo* rx_fifo; + + rt_poll_add(&(device->wait_queue), req); + + rx_fifo = (struct rt_serial_rx_fifo*) serial->serial_rx; + + level = rt_hw_interrupt_disable(); + + if (rt_ringbuffer_data_len(&rx_fifo->rb)) + mask |= POLLIN; + rt_hw_interrupt_enable(level); + } + // mask|=POLLOUT; + return mask; +} + +const static struct dfs_file_ops _serial_fops = +{ + serial_fops_open, + serial_fops_close, + serial_fops_ioctl, + serial_fops_read, + serial_fops_write, + RT_NULL, /* flush */ + RT_NULL, /* lseek */ + RT_NULL, /* getdents */ + serial_fops_poll, +}; +#endif + +rt_size_t rt_serial_get_linear_buffer(struct rt_ringbuffer *rb, + rt_uint8_t **ptr) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + *ptr = RT_NULL; + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + *ptr = &rb->buffer_ptr[rb->read_index]; + + if(rb->buffer_size - rb->read_index > size) + { + return size; + } + + return rb->buffer_size - rb->read_index; +} + +rt_size_t rt_serial_update_read_index(struct rt_ringbuffer *rb, + rt_uint16_t read_index) +{ + rt_size_t size; + + RT_ASSERT(rb != RT_NULL); + + /* whether has enough data */ + size = rt_ringbuffer_data_len(rb); + + /* no data */ + if (size == 0) + return 0; + + /* less data */ + if(size < read_index) + read_index = size; + + if(rb->buffer_size - rb->read_index > read_index) + { + rb->read_index += read_index; + return read_index; + } + + read_index = rb->buffer_size - rb->read_index; + + /* we are going into the other side of the mirror */ + rb->read_mirror = ~rb->read_mirror; + rb->read_index = 0; + + return read_index; +} + +rt_size_t rt_serial_update_write_index(struct rt_ringbuffer *rb, + rt_uint16_t write_index) +{ + rt_uint16_t size; + RT_ASSERT(rb != RT_NULL); + + /* whether has enough space */ + size = rt_ringbuffer_space_len(rb); + + /* no space */ + if (size == 0) + return 0; + + /* drop some data */ + if (size < write_index) + write_index = size; + + if (rb->buffer_size - rb->write_index > write_index) + { + /* this should not cause overflow because there is enough space for + * length of data in current mirror */ + rb->write_index += write_index; + return write_index; + } + + /* we are going into the other side of the mirror */ + rb->write_mirror = ~rb->write_mirror; + rb->write_index = write_index - (rb->buffer_size - rb->write_index); + + return write_index; +} + + +/** + * @brief Serial polling receive data routine, This function will receive data + * in a continuous loop by one by one byte. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Receive data buffer. + * @param size Receive data buffer length. + * @return Return the final length of data received. + */ +rt_size_t _serial_poll_rx(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + rt_size_t getc_size; + int getc_element; /* Gets one byte of data received */ + rt_uint8_t *getc_buffer; /* Pointer to the receive data buffer */ + + RT_ASSERT(dev != RT_NULL); + + serial = (struct rt_serial_device *)dev; + RT_ASSERT(serial != RT_NULL); + getc_buffer = (rt_uint8_t *)buffer; + getc_size = size; + + while(size) + { + getc_element = serial->ops->getc(serial); + if (getc_element == -1) break; + + *getc_buffer = getc_element; + + ++ getc_buffer; + -- size; + + if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) + { + /* If open_flag satisfies RT_DEVICE_FLAG_STREAM + * and the received character is '\n', exit the loop directly */ + if (getc_element == '\n') break; + } + } + + return getc_size - size; +} + +/** + * @brief Serial polling transmit data routines, This function will transmit + * data in a continuous loop by one by one byte. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data received. + */ +rt_size_t _serial_poll_tx(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + rt_size_t putc_size; + rt_uint8_t *putc_buffer; /* Pointer to the transmit data buffer */ + RT_ASSERT(dev != RT_NULL); + + serial = (struct rt_serial_device *)dev; + RT_ASSERT(serial != RT_NULL); + + putc_buffer = (rt_uint8_t *)buffer; + putc_size = size; + + while (size) + { + if (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM) + { + /* If open_flag satisfies RT_DEVICE_FLAG_STREAM and the received character is '\n', + * inserts '\r' character before '\n' character for the effect of carriage return newline */ + if (*putc_buffer == '\n') + serial->ops->putc(serial, '\r'); + } + serial->ops->putc(serial, *putc_buffer); + + ++ putc_buffer; + -- size; + } + + return putc_size - size; +} + +/** + * @brief Serial receive data routines, This function will receive + * data by using fifo + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Receive data buffer. + * @param size Receive data buffer length. + * @return Return the final length of data received. + */ +static rt_size_t _serial_fifo_rx(struct rt_device *dev, + rt_off_t pos, + void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo; + rt_base_t level; + rt_size_t recv_len; /* The length of data from the ringbuffer */ + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + + rx_fifo = (struct rt_serial_rx_fifo *) serial->serial_rx; + + if (dev->open_flag & RT_SERIAL_RX_BLOCKING) + { + if (size > serial->config.rx_bufsz) + { + LOG_W("(%s) serial device received data:[%d] larger than " + "rx_bufsz:[%d], please increase the BSP_UARTx_RX_BUFSIZE option", + dev->parent.name, size, serial->config.rx_bufsz); + + return 0; + } + /* Get the length of the data from the ringbuffer */ + recv_len = rt_ringbuffer_data_len(&(rx_fifo->rb)); + + if (recv_len < size) + { + /* When recv_len is less than size, rx_cpt_index is updated to the size + * and rt_current_thread is suspend until rx_cpt_index is equal to 0 */ + rx_fifo->rx_cpt_index = size; + rt_completion_wait(&(rx_fifo->rx_cpt), RT_WAITING_FOREVER); + } + } + + /* This part of the code is open_flag as RT_SERIAL_RX_NON_BLOCKING */ + + level = rt_hw_interrupt_disable(); + /* When open_flag is RT_SERIAL_RX_NON_BLOCKING, + * the data is retrieved directly from the ringbuffer and returned */ + recv_len = rt_ringbuffer_get(&(rx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + return recv_len; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using blocking_nbuf. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_blocking_nbuf(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + /* When serial transmit in tx_blocking mode, + * if the activated mode is RT_TRUE, it will return directly */ + if (tx_fifo->activated == RT_TRUE) return 0; + + tx_fifo->activated = RT_TRUE; + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + (rt_uint8_t *)buffer, + size, + RT_SERIAL_TX_BLOCKING); + /* Waiting for the transmission to complete */ + rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER); + + return size; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using blocking_buf. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_blocking_buf(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + /* When serial transmit in tx_blocking mode, + * if the activated mode is RT_TRUE, it will return directly */ + if (tx_fifo->activated == RT_TRUE) return 0; + + tx_fifo->activated = RT_TRUE; + rt_size_t length = size; + rt_size_t offset = 0; + + while (size) + { + /* Copy one piece of data into the ringbuffer at a time + * until the length of the data is equal to size */ + tx_fifo->put_size = rt_ringbuffer_put(&(tx_fifo->rb), + (rt_uint8_t *)buffer + offset, + size); + + offset += tx_fifo->put_size; + size -= tx_fifo->put_size; + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + (rt_uint8_t *)buffer + offset, + tx_fifo->put_size, + RT_SERIAL_TX_BLOCKING); + /* Waiting for the transmission to complete */ + rt_completion_wait(&(tx_fifo->tx_cpt), RT_WAITING_FOREVER); + } + + return length; +} + +/** + * @brief Serial transmit data routines, This function will transmit + * data by using nonblocking. + * @param dev The pointer of device driver structure + * @param pos Empty parameter. + * @param buffer Transmit data buffer. + * @param size Transmit data buffer length. + * @return Return the final length of data transmit. + */ +static rt_size_t _serial_fifo_tx_nonblocking(struct rt_device *dev, + rt_off_t pos, + const void *buffer, + rt_size_t size) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + rt_base_t level; + rt_size_t length; + + RT_ASSERT(dev != RT_NULL); + if (size == 0) return 0; + + serial = (struct rt_serial_device *)dev; + RT_ASSERT((serial != RT_NULL) && (buffer != RT_NULL)); + tx_fifo = (struct rt_serial_tx_fifo *) serial->serial_tx; + + level = rt_hw_interrupt_disable(); + + if (tx_fifo->activated == RT_FALSE) + { + /* When serial transmit in tx_non_blocking mode, if the activated mode is RT_FALSE, + * start copying data into the ringbuffer */ + tx_fifo->activated = RT_TRUE; + /* Copying data into the ringbuffer */ + length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + rt_uint8_t *put_ptr = RT_NULL; + /* Get the linear length buffer from rinbuffer */ + tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr); + /* Call the transmit interface for transmission */ + serial->ops->transmit(serial, + put_ptr, + tx_fifo->put_size, + RT_SERIAL_TX_NON_BLOCKING); + /* In tx_nonblocking mode, there is no need to call rt_completion_wait() APIs to wait + * for the rt_current_thread to resume */ + return length; + } + + /* If the activated mode is RT_FALSE, it means that serial device is transmitting, + * where only the data in the ringbuffer and there is no need to call the transmit() API. + * Note that this part of the code requires disable interrupts + * to prevent multi thread reentrant */ + + /* Copying data into the ringbuffer */ + length = rt_ringbuffer_put(&(tx_fifo->rb), buffer, size); + + rt_hw_interrupt_enable(level); + + return length; +} + + +/** + * @brief Enable serial transmit mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_tx_enable(struct rt_device *dev, + rt_uint16_t tx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + if (serial->config.tx_bufsz == 0) + { + /* Cannot use RT_SERIAL_TX_NON_BLOCKING when tx_bufsz is 0 */ + if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) + { + LOG_E("(%s) serial device with misconfigure: tx_bufsz = 0", + dev->parent.name); + return -RT_EINVAL; + } + + dev->write = _serial_poll_tx; + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + return RT_EOK; + } + /* Limits the minimum value of tx_bufsz */ + if (serial->config.tx_bufsz < RT_SERIAL_TX_MINBUFSZ) + serial->config.tx_bufsz = RT_SERIAL_TX_MINBUFSZ; + + if (tx_oflag == RT_SERIAL_TX_BLOCKING) + { + /* When using RT_SERIAL_TX_BLOCKING, it is necessary to determine + * whether serial device needs to use buffer */ + rt_err_t optmode; /* The operating mode used by serial device */ + /* Call the Control() API to get the operating mode */ + optmode = serial->ops->control(serial, + RT_DEVICE_CHECK_OPTMODE, + (void *)RT_DEVICE_FLAG_TX_BLOCKING); + if (optmode == RT_SERIAL_TX_BLOCKING_BUFFER) + { + /* If use RT_SERIAL_TX_BLOCKING_BUFFER, the ringbuffer is initialized */ + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); + RT_ASSERT(tx_fifo != RT_NULL); + + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, + serial->config.tx_bufsz); + serial->serial_tx = tx_fifo; + dev->write = _serial_fifo_tx_blocking_buf; + } + else + { + /* If not use RT_SERIAL_TX_BLOCKING_BUFFER, + * the control() API is called to configure the serial device */ + tx_fifo = (struct rt_serial_tx_fifo*) rt_malloc + (sizeof(struct rt_serial_tx_fifo)); + RT_ASSERT(tx_fifo != RT_NULL); + + serial->serial_tx = tx_fifo; + dev->write = _serial_fifo_tx_blocking_nbuf; + /* Call the control() API to configure the serial device by RT_SERIAL_TX_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *)RT_SERIAL_TX_BLOCKING); + } + + tx_fifo->activated = RT_FALSE; + tx_fifo->put_size = 0; + rt_completion_init(&(tx_fifo->tx_cpt)); + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + + return RT_EOK; + } + /* When using RT_SERIAL_TX_NON_BLOCKING, ringbuffer needs to be initialized, + * and initialize the tx_fifo->activated value is RT_FALSE. + */ + tx_fifo = (struct rt_serial_tx_fifo *) rt_malloc + (sizeof(struct rt_serial_tx_fifo) + serial->config.tx_bufsz); + RT_ASSERT(tx_fifo != RT_NULL); + + tx_fifo->activated = RT_FALSE; + tx_fifo->put_size = 0; + rt_ringbuffer_init(&(tx_fifo->rb), + tx_fifo->buffer, + serial->config.tx_bufsz); + serial->serial_tx = tx_fifo; + + dev->write = _serial_fifo_tx_nonblocking; + dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_TX_NON_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *)RT_SERIAL_TX_NON_BLOCKING); + + return RT_EOK; +} + + +/** + * @brief Enable serial receive mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_rx_enable(struct rt_device *dev, + rt_uint16_t rx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo = RT_NULL; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + if (serial->config.rx_bufsz == 0) + { + /* Cannot use RT_SERIAL_RX_NON_BLOCKING when rx_bufsz is 0 */ + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + LOG_E("(%s) serial device with misconfigure: rx_bufsz = 0", + dev->parent.name); + return -RT_EINVAL; + } + + dev->read = _serial_poll_rx; + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + return RT_EOK; + } + /* Limits the minimum value of rx_bufsz */ + if (serial->config.rx_bufsz < RT_SERIAL_RX_MINBUFSZ) + serial->config.rx_bufsz = RT_SERIAL_RX_MINBUFSZ; + + rx_fifo = (struct rt_serial_rx_fifo *) rt_malloc + (sizeof(struct rt_serial_rx_fifo) + serial->config.rx_bufsz); + + RT_ASSERT(rx_fifo != RT_NULL); + rt_ringbuffer_init(&(rx_fifo->rb), rx_fifo->buffer, serial->config.rx_bufsz); + + rx_fifo->rx_index = serial->config.rx_bufsz; + serial->serial_rx = rx_fifo; + dev->read = _serial_fifo_rx; + + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_RX_NON_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *) RT_SERIAL_RX_NON_BLOCKING); + + return RT_EOK; + } + /* When using RT_SERIAL_RX_BLOCKING, rt_completion_init() and rx_cpt_index are initialized */ + rx_fifo->rx_cpt_index = 0; + rt_completion_init(&(rx_fifo->rx_cpt)); + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + /* Call the control() API to configure the serial device by RT_SERIAL_RX_BLOCKING*/ + serial->ops->control(serial, + RT_DEVICE_CTRL_CONFIG, + (void *) RT_SERIAL_RX_BLOCKING); + + return RT_EOK; +} + +/** + * @brief Disable serial receive mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_rx_disable(struct rt_device *dev, + rt_uint16_t rx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_rx_fifo *rx_fifo; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + dev->read = RT_NULL; + if (serial->serial_rx == RT_NULL) return RT_EOK; + + do + { + if (rx_oflag == RT_SERIAL_RX_NON_BLOCKING) + { + dev->open_flag &= ~ RT_SERIAL_RX_NON_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_RX_NON_BLOCKING); + break; + } + + dev->open_flag &= ~ RT_SERIAL_RX_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_RX_BLOCKING); + } while (0); + + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + rt_free(rx_fifo); + serial->serial_rx = RT_NULL; + + return RT_EOK; +} + +/** + * @brief Disable serial tranmit mode. + * @param dev The pointer of device driver structure + * @param rx_oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_tx_disable(struct rt_device *dev, + rt_uint16_t tx_oflag) +{ + struct rt_serial_device *serial; + struct rt_serial_tx_fifo *tx_fifo; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + dev->write = RT_NULL; + if (serial->serial_tx == RT_NULL) return RT_EOK; + + do + { + if (tx_oflag == RT_SERIAL_TX_NON_BLOCKING) + { + dev->open_flag &= ~ RT_SERIAL_TX_NON_BLOCKING; + + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_TX_NON_BLOCKING); + break; + } + + dev->open_flag &= ~ RT_SERIAL_TX_BLOCKING; + serial->ops->control(serial, + RT_DEVICE_CTRL_CLR_INT, + (void *)RT_SERIAL_TX_BLOCKING); + } while (0); + + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + rt_free(tx_fifo); + serial->serial_tx = RT_NULL; + + return RT_EOK; +} + +/** + * @brief Initialize the serial device. + * @param dev The pointer of device driver structure + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_init(struct rt_device *dev) +{ + rt_err_t result = RT_EOK; + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* initialize rx/tx */ + serial->serial_rx = RT_NULL; + serial->serial_tx = RT_NULL; + + /* apply configuration */ + if (serial->ops->configure) + result = serial->ops->configure(serial, &serial->config); + + return result; +} + +/** + * @brief Open the serial device. + * @param dev The pointer of device driver structure + * @param oflag The flag of that the serial port opens. + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + LOG_D("open serial device: 0x%08x with open flag: 0x%04x", + dev, oflag); + + /* By default, the receive mode of a serial devide is RT_SERIAL_RX_NON_BLOCKING */ + if ((oflag & RT_SERIAL_RX_BLOCKING) == RT_SERIAL_RX_BLOCKING) + dev->open_flag |= RT_SERIAL_RX_BLOCKING; + else + dev->open_flag |= RT_SERIAL_RX_NON_BLOCKING; + + /* By default, the transmit mode of a serial devide is RT_SERIAL_TX_BLOCKING */ + if ((oflag & RT_SERIAL_TX_NON_BLOCKING) == RT_SERIAL_TX_NON_BLOCKING) + dev->open_flag |= RT_SERIAL_TX_NON_BLOCKING; + else + dev->open_flag |= RT_SERIAL_TX_BLOCKING; + + /* set steam flag */ + if ((oflag & RT_DEVICE_FLAG_STREAM) || + (dev->open_flag & RT_DEVICE_FLAG_STREAM)) + dev->open_flag |= RT_DEVICE_FLAG_STREAM; + + /* initialize the Rx structure according to open flag */ + if (serial->serial_rx == RT_NULL) + rt_serial_rx_enable(dev, dev->open_flag & + (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); + + /* initialize the Tx structure according to open flag */ + if (serial->serial_tx == RT_NULL) + rt_serial_tx_enable(dev, dev->open_flag & + (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + + return RT_EOK; +} + + +/** + * @brief Close the serial device. + * @param dev The pointer of device driver structure + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_close(struct rt_device *dev) +{ + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + /* this device has more reference count */ + if (dev->ref_count > 1) return -RT_ERROR; + /* Disable serial receive mode. */ + rt_serial_rx_disable(dev, dev->open_flag & + (RT_SERIAL_RX_BLOCKING | RT_SERIAL_RX_NON_BLOCKING)); + /* Disable serial tranmit mode. */ + rt_serial_tx_disable(dev, dev->open_flag & + (RT_SERIAL_TX_BLOCKING | RT_SERIAL_TX_NON_BLOCKING)); + + /* Call the control() API to close the serial device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); + dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; + + return RT_EOK; +} + +/** + * @brief Control the serial device. + * @param dev The pointer of device driver structure + * @param cmd The command value that controls the serial device + * @param args The parameter value that controls the serial device + * @return Return the status of the operation. + */ +static rt_err_t rt_serial_control(struct rt_device *dev, + int cmd, + void *args) +{ + rt_err_t ret = RT_EOK; + struct rt_serial_device *serial; + + RT_ASSERT(dev != RT_NULL); + serial = (struct rt_serial_device *)dev; + + switch (cmd) + { + case RT_DEVICE_CTRL_SUSPEND: + /* suspend device */ + dev->flag |= RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_RESUME: + /* resume device */ + dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED; + break; + + case RT_DEVICE_CTRL_CONFIG: + if (args != RT_NULL) + { + struct serial_configure *pconfig = (struct serial_configure *) args; + if (serial->parent.ref_count) + { + /*can not change buffer size*/ + return -RT_EBUSY; + } + /* set serial configure */ + serial->config = *pconfig; + serial->ops->configure(serial, + (struct serial_configure *) args); + } + + break; + + default : + /* control device */ + ret = serial->ops->control(serial, cmd, args); + break; + } + + return ret; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops serial_ops = +{ + rt_serial_init, + rt_serial_open, + rt_serial_close, + rt_serial_read, + rt_serial_write, + rt_serial_control +}; +#endif + +/** + * @brief Register the serial device. + * @param serial RT-thread serial device. + * @param name The device driver's name + * @param flag The capabilities flag of device. + * @param data The device driver's data. + * @return Return the status of the operation. + */ +rt_err_t rt_hw_serial_register(struct rt_serial_device *serial, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_err_t ret; + struct rt_device *device; + RT_ASSERT(serial != RT_NULL); + + device = &(serial->parent); + + device->type = RT_Device_Class_Char; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &serial_ops; +#else + device->init = rt_serial_init; + device->open = rt_serial_open; + device->close = rt_serial_close; + device->read = RT_NULL; + device->write = RT_NULL; + device->control = rt_serial_control; +#endif + device->user_data = data; + + /* register a character device */ + ret = rt_device_register(device, name, flag); + +#if defined(RT_USING_POSIX) + /* set fops */ + device->fops = &_serial_fops; +#endif + return ret; +} + +/** + * @brief ISR for serial interrupt + * @param serial RT-thread serial device. + * @param event ISR event type. + */ +void rt_hw_serial_isr(struct rt_serial_device *serial, int event) +{ + RT_ASSERT(serial != RT_NULL); + + switch (event & 0xff) + { + /* Interrupt receive event */ + case RT_SERIAL_EVENT_RX_IND: + case RT_SERIAL_EVENT_RX_DMADONE: + { + struct rt_serial_rx_fifo *rx_fifo; + rt_size_t rx_length = 0; + rx_fifo = (struct rt_serial_rx_fifo *)serial->serial_rx; + RT_ASSERT(rx_fifo != RT_NULL); + + /* Get the length of the data from the ringbuffer */ + rx_length = rt_ringbuffer_data_len(&rx_fifo->rb); + + if (rx_length == 0) break; + + if (serial->parent.open_flag & RT_SERIAL_RX_BLOCKING) + { + if (rx_fifo->rx_cpt_index && rx_length >= rx_fifo->rx_cpt_index ) + { + rx_fifo->rx_cpt_index = 0; + rt_completion_done(&(rx_fifo->rx_cpt)); + } + } + /* Trigger the receiving completion callback */ + if (serial->parent.rx_indicate != RT_NULL) + serial->parent.rx_indicate(&(serial->parent), rx_length); + break; + } + + /* Interrupt transmit event */ + case RT_SERIAL_EVENT_TX_DONE: + { + struct rt_serial_tx_fifo *tx_fifo; + rt_size_t tx_length = 0; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + /* Get the length of the data from the ringbuffer */ + tx_length = rt_ringbuffer_data_len(&tx_fifo->rb); + /* If there is no data in tx_ringbuffer, + * then the transmit completion callback is triggered*/ + if (tx_length == 0) + { + tx_fifo->activated = RT_FALSE; + /* Trigger the transmit completion callback */ + if (serial->parent.tx_complete != RT_NULL) + serial->parent.tx_complete(&serial->parent, RT_NULL); + + if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) + rt_completion_done(&(tx_fifo->tx_cpt)); + + break; + } + + /* Call the transmit interface for transmission again */ + /* Note that in interrupt mode, tx_fifo->buffer and tx_length + * are inactive parameters */ + serial->ops->transmit(serial, + tx_fifo->buffer, + tx_length, + serial->parent.open_flag & ( \ + RT_SERIAL_TX_BLOCKING | \ + RT_SERIAL_TX_NON_BLOCKING)); + break; + } + + case RT_SERIAL_EVENT_TX_DMADONE: + { + struct rt_serial_tx_fifo *tx_fifo; + tx_fifo = (struct rt_serial_tx_fifo *)serial->serial_tx; + RT_ASSERT(tx_fifo != RT_NULL); + + tx_fifo->activated = RT_FALSE; + + /* Trigger the transmit completion callback */ + if (serial->parent.tx_complete != RT_NULL) + serial->parent.tx_complete(&serial->parent, RT_NULL); + + if (serial->parent.open_flag & RT_SERIAL_TX_BLOCKING) + { + rt_completion_done(&(tx_fifo->tx_cpt)); + break; + } + + rt_serial_update_read_index(&tx_fifo->rb, tx_fifo->put_size); + /* Get the length of the data from the ringbuffer. + * If there is some data in tx_ringbuffer, + * then call the transmit interface for transmission again */ + if (rt_ringbuffer_data_len(&tx_fifo->rb)) + { + tx_fifo->activated = RT_TRUE; + + rt_uint8_t *put_ptr = RT_NULL; + /* Get the linear length buffer from rinbuffer */ + tx_fifo->put_size = rt_serial_get_linear_buffer(&(tx_fifo->rb), &put_ptr); + /* Call the transmit interface for transmission again */ + serial->ops->transmit(serial, + put_ptr, + tx_fifo->put_size, + RT_SERIAL_TX_NON_BLOCKING); + } + + break; + } + + default: + break; + } +}