From e5c1183350966cd242093c626f2f2c3944122498 Mon Sep 17 00:00:00 2001 From: SummerGift Date: Mon, 23 Mar 2020 15:35:27 +0800 Subject: [PATCH] [optimize] stm32 uart driver --- bsp/stm32/libraries/HAL_Drivers/drv_usart.c | 476 +++++++++++--------- bsp/stm32/libraries/HAL_Drivers/drv_usart.h | 4 +- components/drivers/serial/serial.c | 14 +- include/rtdef.h | 1 + 4 files changed, 276 insertions(+), 219 deletions(-) diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart.c b/bsp/stm32/libraries/HAL_Drivers/drv_usart.c index 64ca8fe4b3..faf010c138 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart.c +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart.c @@ -6,6 +6,8 @@ * Change Logs: * Date Author Notes * 2018-10-30 SummerGift first version + * 2020-03-16 SummerGift add device close feature + * 2020-03-20 SummerGift fix bug caused by ORE */ #include "board.h" @@ -21,12 +23,12 @@ #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 */ +#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); +static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag); #endif enum @@ -100,12 +102,12 @@ static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_c 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; + switch (cfg->data_bits) { case DATA_BITS_8: @@ -118,6 +120,7 @@ static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_c uart->handle.Init.WordLength = UART_WORDLENGTH_8B; break; } + switch (cfg->stop_bits) { case STOP_BITS_1: @@ -130,6 +133,7 @@ static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_c uart->handle.Init.StopBits = UART_STOPBITS_1; break; } + switch (cfg->parity) { case PARITY_NONE: @@ -146,6 +150,10 @@ static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_c break; } +#ifdef RT_SERIAL_USING_DMA + uart->dma_rx.last_index = 0; +#endif + if (HAL_UART_Init(&uart->handle) != HAL_OK) { return -RT_ERROR; @@ -172,7 +180,33 @@ static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *ar NVIC_DisableIRQ(uart->config->irq_type); /* disable interrupt */ __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE); + +#ifdef RT_SERIAL_USING_DMA + /* disable DMA */ + if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX) + { + 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_NVIC_DisableIRQ(uart->config->dma_tx->dma_irq); + if (HAL_DMA_DeInit(&(uart->dma_tx.handle)) != HAL_OK) + { + RT_ASSERT(0); + } + } +#endif break; + /* enable interrupt */ case RT_DEVICE_CTRL_SET_INT: /* enable rx irq */ @@ -186,6 +220,14 @@ static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *ar stm32_dma_config(serial, ctrl_arg); break; #endif + + case RT_DEVICE_CTRL_CLOSE: + if (HAL_UART_DeInit(&(uart->handle)) != HAL_OK ) + { + RT_ASSERT(0) + } + break; + } return RT_EOK; } @@ -233,13 +275,14 @@ static rt_size_t stm32_dma_transmit(struct rt_serial_device *serial, rt_uint8_t { struct stm32_uart *uart; RT_ASSERT(serial != RT_NULL); + RT_ASSERT(buf != RT_NULL); uart = rt_container_of(serial, struct stm32_uart, serial); - + if (size == 0) { return 0; } - + if (RT_SERIAL_DMA_TX == direction) { if (HAL_UART_Transmit_DMA(&uart->handle, buf, size) == HAL_OK) @@ -254,15 +297,6 @@ static rt_size_t stm32_dma_transmit(struct rt_serial_device *serial, rt_uint8_t return 0; } -static const struct rt_uart_ops stm32_uart_ops = -{ - .configure = stm32_configure, - .control = stm32_control, - .putc = stm32_putc, - .getc = stm32_getc, - .dma_transmit = stm32_dma_transmit -}; - /** * Uart common interrupt process. This need add to uart ISR. * @@ -301,16 +335,14 @@ static void uart_isr(struct rt_serial_device *serial) } __HAL_UART_CLEAR_IDLEFLAG(&uart->handle); } - else if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) != RESET) + else if (__HAL_UART_GET_FLAG(&(uart->handle), UART_FLAG_TC) && + (__HAL_UART_GET_IT_SOURCE(&(uart->handle), UART_IT_TC) != RESET)) { if ((serial->parent.open_flag & RT_DEVICE_FLAG_DMA_TX) != 0) { HAL_UART_IRQHandler(&(uart->handle)); } - else - { - UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); - } + UART_INSTANCE_CLEAR_FUNCTION(&(uart->handle), UART_FLAG_TC); } #endif else @@ -714,201 +746,6 @@ void LPUART1_DMA_RX_IRQHandler(void) #endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_LPUART1_RX_USING_DMA) */ #endif /* BSP_USING_LPUART1*/ -#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_STM32G4) - /* 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); - -#if (defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G4)) && defined(DMAMUX1) - /* enable DMAMUX clock for L4+ and G4 */ - __HAL_RCC_DMAMUX1_CLK_ENABLE(); -#endif - -#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_STM32G0) || defined(SOC_SERIES_STM32G4) - 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) - 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; - /* Start DMA transfer */ - if (HAL_UART_Receive_DMA(&(uart->handle), rx_fifo->buffer, serial->config.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); - } - - /* enable irq */ - 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_isr(&uart->serial); -} - -/** - * @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_isr(&uart->serial); -} - -static void _dma_tx_complete(struct rt_serial_device *serial) -{ - struct stm32_uart *uart; - rt_size_t trans_total_index; - rt_base_t level; - - RT_ASSERT(serial != RT_NULL); - uart = rt_container_of(serial, struct stm32_uart, serial); - - if ((__HAL_DMA_GET_IT_SOURCE(&(uart->dma_tx.handle), DMA_IT_TC) != RESET) || - (__HAL_DMA_GET_IT_SOURCE(&(uart->dma_tx.handle), DMA_IT_HT) != RESET)) - { - 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 == 0) - { - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_DMADONE); - } - } -} - -void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) -{ - struct stm32_uart *uart; - RT_ASSERT(huart != NULL); - uart = (struct stm32_uart *)huart; - _dma_tx_complete(&uart->serial); -} -#endif /* RT_SERIAL_USING_DMA */ - static void stm32_uart_get_dma_config(void) { #ifdef BSP_USING_UART1 @@ -996,6 +833,213 @@ static void stm32_uart_get_dma_config(void) #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_STM32G4) + /* 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); + +#if (defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32G4)) && defined(DMAMUX1) + /* enable DMAMUX clock for L4+ and G4 */ + __HAL_RCC_DMAMUX1_CLK_ENABLE(); +#endif + +#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_STM32G0) || defined(SOC_SERIES_STM32G4) + 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) + 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; + /* Start DMA transfer */ + if (HAL_UART_Receive_DMA(&(uart->handle), rx_fifo->buffer, serial->config.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_isr(&uart->serial); +} + +/** + * @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_isr(&uart->serial); +} + +static void _dma_tx_complete(struct rt_serial_device *serial) +{ + struct stm32_uart *uart; + rt_size_t trans_total_index; + rt_base_t level; + + RT_ASSERT(serial != RT_NULL); + uart = rt_container_of(serial, struct stm32_uart, serial); + + 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 == 0) + { + rt_hw_serial_isr(serial, RT_SERIAL_EVENT_TX_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; + RT_ASSERT(huart != NULL); + uart = (struct stm32_uart *)huart; + _dma_tx_complete(&uart->serial); +} +#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, + .dma_transmit = stm32_dma_transmit +}; + int rt_hw_usart_init(void) { rt_size_t obj_num = sizeof(uart_obj) / sizeof(struct stm32_uart); @@ -1006,9 +1050,11 @@ int rt_hw_usart_init(void) 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; uart_obj[i].serial.config = config; + /* register UART device */ result = rt_hw_serial_register(&uart_obj[i].serial, uart_obj[i].config->name, RT_DEVICE_FLAG_RDWR diff --git a/bsp/stm32/libraries/HAL_Drivers/drv_usart.h b/bsp/stm32/libraries/HAL_Drivers/drv_usart.h index f8b0703a33..b6e4060288 100644 --- a/bsp/stm32/libraries/HAL_Drivers/drv_usart.h +++ b/bsp/stm32/libraries/HAL_Drivers/drv_usart.h @@ -6,7 +6,7 @@ * Change Logs: * Date Author Notes * 2018.10.30 SummerGift first version - * 2019.03.05 whj4674672 add stm32h7 + * 2019.03.05 whj4674672 add stm32h7 */ #ifndef __DRV_USART_H__ @@ -50,7 +50,7 @@ struct stm32_uart { UART_HandleTypeDef handle; struct stm32_uart_config *config; - + #ifdef RT_SERIAL_USING_DMA struct { diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index d1c04dec6f..7dd2918b9b 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -733,6 +733,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(rx_fifo); serial->serial_rx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_INT_RX; + /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_RX); } @@ -754,10 +755,11 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(rx_fifo); } - /* configure low level device */ - serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX); serial->serial_rx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_DMA_RX; + + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_RX); } #endif /* RT_SERIAL_USING_DMA */ @@ -771,6 +773,7 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(tx_fifo); serial->serial_tx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_INT_TX; + /* configure low level device */ serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void*)RT_DEVICE_FLAG_INT_TX); } @@ -785,7 +788,14 @@ static rt_err_t rt_serial_close(struct rt_device *dev) rt_free(tx_dma); serial->serial_tx = RT_NULL; dev->open_flag &= ~RT_DEVICE_FLAG_DMA_TX; + + /* configure low level device */ + serial->ops->control(serial, RT_DEVICE_CTRL_CLR_INT, (void *) RT_DEVICE_FLAG_DMA_TX); } + + serial->ops->control(serial, RT_DEVICE_CTRL_CLOSE, RT_NULL); + dev->flag &= ~RT_DEVICE_FLAG_ACTIVATED; + #endif /* RT_SERIAL_USING_DMA */ return RT_EOK; } diff --git a/include/rtdef.h b/include/rtdef.h index 8b86213082..f2b546f75e 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -898,6 +898,7 @@ enum rt_device_class_type #define RT_DEVICE_CTRL_RESUME 0x01 /**< resume device */ #define RT_DEVICE_CTRL_SUSPEND 0x02 /**< suspend device */ #define RT_DEVICE_CTRL_CONFIG 0x03 /**< configure device */ +#define RT_DEVICE_CTRL_CLOSE 0x04 /**< close device */ #define RT_DEVICE_CTRL_SET_INT 0x10 /**< set interrupt */ #define RT_DEVICE_CTRL_CLR_INT 0x11 /**< clear interrupt */