From cebbee7908053618c5a4d03b3169b4d5765bce84 Mon Sep 17 00:00:00 2001 From: armink Date: Fri, 17 Mar 2017 13:31:47 +0800 Subject: [PATCH] [BSP] Enhanced stm32f40x serial DMA rx driver reliability. --- bsp/stm32f40x/drivers/usart.c | 50 ++++++++++++++++++++++++----------- 1 file changed, 35 insertions(+), 15 deletions(-) diff --git a/bsp/stm32f40x/drivers/usart.c b/bsp/stm32f40x/drivers/usart.c index 539ea5fafc..d9d0f74c6c 100644 --- a/bsp/stm32f40x/drivers/usart.c +++ b/bsp/stm32f40x/drivers/usart.c @@ -70,7 +70,8 @@ struct stm32_uart { USART_TypeDef *uart_device; IRQn_Type irq; - struct stm32_uart_dma { + struct stm32_uart_dma + { /* dma stream */ DMA_Stream_TypeDef *rx_stream; /* dma channel */ @@ -200,7 +201,8 @@ static int stm32_getc(struct rt_serial_device *serial) * @param mem_base_addr memory 0 base address for DMA stream */ static void dma_uart_config(struct rt_serial_device *serial, uint32_t setting_recv_len, - void *mem_base_addr) { + void *mem_base_addr) +{ struct stm32_uart *uart = (struct stm32_uart *) serial->parent.user_data; DMA_InitTypeDef DMA_InitStructure; @@ -234,16 +236,26 @@ static void dma_uart_config(struct rt_serial_device *serial, uint32_t setting_re static void dma_uart_rx_idle_isr(struct rt_serial_device *serial) { struct stm32_uart *uart = (struct stm32_uart *) serial->parent.user_data; rt_size_t recv_total_index, recv_len; + rt_base_t level; + + /* disable interrupt */ + level = rt_hw_interrupt_disable(); recv_total_index = uart->dma.setting_recv_len - DMA_GetCurrDataCounter(uart->dma.rx_stream); - if (recv_total_index >= uart->dma.last_recv_index) { + if (recv_total_index >= uart->dma.last_recv_index) + { recv_len = recv_total_index - uart->dma.last_recv_index; - } else { + } + else + { recv_len = uart->dma.setting_recv_len - uart->dma.last_recv_index + recv_total_index; } + uart->dma.last_recv_index = recv_total_index; + /* enable interrupt */ + rt_hw_interrupt_enable(level); - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); + if (recv_len) rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); /* read a data for clear receive idle interrupt flag */ USART_ReceiveData(uart->uart_device); @@ -254,28 +266,35 @@ static void dma_uart_rx_idle_isr(struct rt_serial_device *serial) { * * @param serial serial device */ -static void dma_rx_done_isr(struct rt_serial_device *serial) { +static void dma_rx_done_isr(struct rt_serial_device *serial) +{ struct stm32_uart *uart = (struct stm32_uart *) serial->parent.user_data; rt_size_t recv_total_index, recv_len; + rt_base_t level; - if (DMA_GetFlagStatus(uart->dma.rx_stream, uart->dma.rx_flag) != RESET) { - /* disable dma, stop receive data */ - DMA_Cmd(uart->dma.rx_stream, DISABLE); + if (DMA_GetFlagStatus(uart->dma.rx_stream, uart->dma.rx_flag) != RESET) + { + /* disable interrupt */ + level = rt_hw_interrupt_disable(); recv_total_index = uart->dma.setting_recv_len - DMA_GetCurrDataCounter(uart->dma.rx_stream); - if (recv_total_index >= uart->dma.last_recv_index) { + if (recv_total_index >= uart->dma.last_recv_index) + { recv_len = recv_total_index - uart->dma.last_recv_index; - } else { + } + else + { recv_len = uart->dma.setting_recv_len - uart->dma.last_recv_index + recv_total_index; - uart->dma.last_recv_index = recv_total_index; } + uart->dma.last_recv_index = recv_total_index; + /* enable interrupt */ + rt_hw_interrupt_enable(level); - rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); + if (recv_len) rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_DMADONE | (recv_len << 8)); /* start receive data */ DMA_ClearFlag(uart->dma.rx_stream, uart->dma.rx_flag); - DMA_Cmd(uart->dma.rx_stream, ENABLE); } } @@ -284,7 +303,8 @@ static void dma_rx_done_isr(struct rt_serial_device *serial) { * * @param serial serial device */ -static void uart_isr(struct rt_serial_device *serial) { +static void uart_isr(struct rt_serial_device *serial) +{ struct stm32_uart *uart = (struct stm32_uart *) serial->parent.user_data; RT_ASSERT(uart != RT_NULL); -- GitLab