diff --git a/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c index 44324fc7e..b346dba82 100644 --- a/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv1/uart_lld.c @@ -291,12 +291,6 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { dmaStreamDisable(uartp->dmatx); - /* Only enable TC interrupt if there's a callback attached to it. - We have to do it here, rather than earlier, because TC flag is set - until transmission starts.*/ - if (uartp->config->txend2_cb != NULL) - uartp->usart->CR1 |= USART_CR1_TCIE; - /* A callback is generated, if enabled, after a completed transfer.*/ uartp->txstate = UART_TX_COMPLETE; if (uartp->config->txend1_cb != NULL) @@ -749,11 +743,20 @@ void uart_lld_stop(UARTDriver *uartp) { */ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { - /* TX DMA channel preparation and start.*/ + /* TX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmatx, txbuf); dmaStreamSetTransactionSize(uartp->dmatx, n); dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Only enable TC interrupt if there's a callback attached to it. + Also we need to clear TC flag which could be set before. */ + if (uartp->config->txend2_cb != NULL) { + uartp->usart->SR = ~USART_SR_TC; + uartp->usart->CR1 |= USART_CR1_TCIE; + } + + /* Starting transfer.*/ dmaStreamEnable(uartp->dmatx); } @@ -771,6 +774,7 @@ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { size_t uart_lld_stop_send(UARTDriver *uartp) { dmaStreamDisable(uartp->dmatx); + return dmaStreamGetTransactionSize(uartp->dmatx); } @@ -790,11 +794,13 @@ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { /* Stopping previous activity (idle state).*/ dmaStreamDisable(uartp->dmarx); - /* RX DMA channel preparation and start.*/ + /* RX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmarx, rxbuf); dmaStreamSetTransactionSize(uartp->dmarx, n); dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Starting transfer.*/ dmaStreamEnable(uartp->dmarx); } @@ -815,6 +821,7 @@ size_t uart_lld_stop_receive(UARTDriver *uartp) { dmaStreamDisable(uartp->dmarx); n = dmaStreamGetTransactionSize(uartp->dmarx); set_rx_idle_loop(uartp); + return n; } diff --git a/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c b/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c index 1cce68503..95e80594d 100644 --- a/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c +++ b/os/hal/ports/STM32/LLD/USARTv2/uart_lld.c @@ -245,12 +245,6 @@ static void uart_lld_serve_tx_end_irq(UARTDriver *uartp, uint32_t flags) { dmaStreamDisable(uartp->dmatx); - /* Only enable TC interrupt if there's a callback attached to it. - We have to do it here, rather than earlier, because TC flag is set - until transmission starts.*/ - if (uartp->config->txend2_cb != NULL) - uartp->usart->CR1 |= USART_CR1_TCIE; - /* A callback is generated, if enabled, after a completed transfer.*/ uartp->txstate = UART_TX_COMPLETE; if (uartp->config->txend1_cb != NULL) @@ -526,11 +520,20 @@ void uart_lld_stop(UARTDriver *uartp) { */ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { - /* TX DMA channel preparation and start.*/ + /* TX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmatx, txbuf); dmaStreamSetTransactionSize(uartp->dmatx, n); dmaStreamSetMode(uartp->dmatx, uartp->dmamode | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Only enable TC interrupt if there's a callback attached to it. + Also we need to clear TC flag which could be set before. */ + if (uartp->config->txend2_cb != NULL) { + uartp->usart->ICR = USART_ICR_TCCF; + uartp->usart->CR1 |= USART_CR1_TCIE; + } + + /* Starting transfer.*/ dmaStreamEnable(uartp->dmatx); } @@ -548,6 +551,7 @@ void uart_lld_start_send(UARTDriver *uartp, size_t n, const void *txbuf) { size_t uart_lld_stop_send(UARTDriver *uartp) { dmaStreamDisable(uartp->dmatx); + return dmaStreamGetTransactionSize(uartp->dmatx); } @@ -567,11 +571,13 @@ void uart_lld_start_receive(UARTDriver *uartp, size_t n, void *rxbuf) { /* Stopping previous activity (idle state).*/ dmaStreamDisable(uartp->dmarx); - /* RX DMA channel preparation and start.*/ + /* RX DMA channel preparation.*/ dmaStreamSetMemory0(uartp->dmarx, rxbuf); dmaStreamSetTransactionSize(uartp->dmarx, n); dmaStreamSetMode(uartp->dmarx, uartp->dmamode | STM32_DMA_CR_DIR_P2M | STM32_DMA_CR_MINC | STM32_DMA_CR_TCIE); + + /* Starting transfer.*/ dmaStreamEnable(uartp->dmarx); } @@ -592,6 +598,7 @@ size_t uart_lld_stop_receive(UARTDriver *uartp) { dmaStreamDisable(uartp->dmarx); n = dmaStreamGetTransactionSize(uartp->dmarx); set_rx_idle_loop(uartp); + return n; } diff --git a/readme.txt b/readme.txt index b056ff4f3..55e5d2eff 100644 --- a/readme.txt +++ b/readme.txt @@ -76,6 +76,7 @@ *** 3.0.0p5 *** - HAL: Added DAC support to all STM32 sub-platforms, added another demo for the STM32F3xx. +- HAL: Fixed STM32 USARTv1: incorrect txend2_cb callback behavior (bug #596). - DEM: Fixed wrong comment in ARMCM4-STM32F401RE-NUCLEO demo (bug #595). - HAL: Fixed STM32 SDC LLD driver initialization with Asserts disabled (bug #594).