Browse Source

[optimize] stm32 uart driver

SummerGift 5 years ago
parent
commit
e5c1183350

+ 167 - 121
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,6 +746,93 @@ void LPUART1_DMA_RX_IRQHandler(void)
 #endif /* defined(RT_SERIAL_USING_DMA) && defined(BSP_LPUART1_RX_USING_DMA) */
 #endif /* BSP_USING_LPUART1*/
 
+static void stm32_uart_get_dma_config(void)
+{
+#ifdef BSP_USING_UART1
+    uart_obj[UART1_INDEX].uart_dma_flag = 0;
+#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].uart_dma_flag = 0;
+#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].uart_dma_flag = 0;
+#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].uart_dma_flag = 0;
+#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 BSP_USING_UART5
+    uart_obj[UART5_INDEX].uart_dma_flag = 0;
+#ifdef BSP_UART5_RX_USING_DMA
+    uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
+    static struct dma_config uart5_dma_rx = UART5_DMA_RX_CONFIG;
+    uart_config[UART5_INDEX].dma_rx = &uart5_dma_rx;
+#endif
+#ifdef BSP_UART5_TX_USING_DMA
+    uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
+    static struct dma_config uart5_dma_tx = UART5_DMA_TX_CONFIG;
+    uart_config[UART5_INDEX].dma_tx = &uart5_dma_tx;
+#endif
+#endif
+
+#ifdef BSP_USING_UART6
+    uart_obj[UART6_INDEX].uart_dma_flag = 0;
+#ifdef BSP_UART6_RX_USING_DMA
+    uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
+    static struct dma_config uart6_dma_rx = UART6_DMA_RX_CONFIG;
+    uart_config[UART6_INDEX].dma_rx = &uart6_dma_rx;
+#endif
+#ifdef BSP_UART6_TX_USING_DMA
+    uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
+    static struct dma_config uart6_dma_tx = UART6_DMA_TX_CONFIG;
+    uart_config[UART6_INDEX].dma_tx = &uart6_dma_tx;
+#endif
+#endif
+}
+
 #ifdef RT_SERIAL_USING_DMA
 static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag)
 {
@@ -721,7 +840,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag)
     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);
 
@@ -781,7 +900,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag)
     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;
@@ -792,7 +911,7 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t 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;
@@ -820,8 +939,8 @@ static void stm32_dma_config(struct rt_serial_device *serial, rt_ubase_t flag)
         CLEAR_BIT(uart->handle.Instance->CR3, USART_CR3_EIE);
         __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_IDLE);
     }
- 
-    /* enable irq */
+
+    /* 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);
 
@@ -865,7 +984,7 @@ void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
 /**
   * @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, 
+  * @note   This example shows a simple way to report end of DMA Rx Half transfer,
   *         and you can add your own implementation.
   * @retval None
   */
@@ -886,20 +1005,23 @@ static void _dma_tx_complete(struct rt_serial_device *serial)
     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);
+    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);
-        }
+    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;
@@ -909,92 +1031,14 @@ void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
 }
 #endif  /* RT_SERIAL_USING_DMA */
 
-static void stm32_uart_get_dma_config(void)
+static const struct rt_uart_ops stm32_uart_ops =
 {
-#ifdef BSP_USING_UART1
-    uart_obj[UART1_INDEX].uart_dma_flag = 0;
-#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].uart_dma_flag = 0;
-#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].uart_dma_flag = 0;
-#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].uart_dma_flag = 0;
-#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 BSP_USING_UART5
-    uart_obj[UART5_INDEX].uart_dma_flag = 0;
-#ifdef BSP_UART5_RX_USING_DMA
-    uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
-    static struct dma_config uart5_dma_rx = UART5_DMA_RX_CONFIG;
-    uart_config[UART5_INDEX].dma_rx = &uart5_dma_rx;
-#endif
-#ifdef BSP_UART5_TX_USING_DMA
-    uart_obj[UART5_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
-    static struct dma_config uart5_dma_tx = UART5_DMA_TX_CONFIG;
-    uart_config[UART5_INDEX].dma_tx = &uart5_dma_tx;
-#endif
-#endif
-
-#ifdef BSP_USING_UART6
-    uart_obj[UART6_INDEX].uart_dma_flag = 0;
-#ifdef BSP_UART6_RX_USING_DMA
-    uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_RX;
-    static struct dma_config uart6_dma_rx = UART6_DMA_RX_CONFIG;
-    uart_config[UART6_INDEX].dma_rx = &uart6_dma_rx;
-#endif
-#ifdef BSP_UART6_TX_USING_DMA
-    uart_obj[UART6_INDEX].uart_dma_flag |= RT_DEVICE_FLAG_DMA_TX;
-    static struct dma_config uart6_dma_tx = UART6_DMA_TX_CONFIG;
-    uart_config[UART6_INDEX].dma_tx = &uart6_dma_tx;
-#endif
-#endif
-}
+    .configure = stm32_configure,
+    .control = stm32_control,
+    .putc = stm32_putc,
+    .getc = stm32_getc,
+    .dma_transmit = stm32_dma_transmit
+};
 
 int rt_hw_usart_init(void)
 {
@@ -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

+ 2 - 2
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
     {

+ 12 - 2
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;
 }

+ 1 - 0
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 */