From 82a4d42b0e10771775bb72de203200b1dda3d0eb Mon Sep 17 00:00:00 2001 From: jflyper Date: Sat, 20 Oct 2018 21:31:49 +0900 Subject: [PATCH] Reinstate UART TX DMA for F7 (HAL driver) --- src/main/drivers/serial_uart_hal.c | 52 +++++++++++++++--------- src/main/drivers/serial_uart_impl.h | 4 -- src/main/drivers/serial_uart_stm32f7xx.c | 7 +--- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/main/drivers/serial_uart_hal.c b/src/main/drivers/serial_uart_hal.c index 1488495211..668c696a9c 100644 --- a/src/main/drivers/serial_uart_hal.c +++ b/src/main/drivers/serial_uart_hal.c @@ -33,6 +33,7 @@ #ifdef USE_UART #include "build/build_config.h" +#include "build/atomic.h" #include "common/utils.h" #include "drivers/io.h" @@ -232,26 +233,40 @@ void uartSetMode(serialPort_t *instance, portMode_e mode) uartReconfigure(uartPort); } -void uartStartTxDMA(uartPort_t *s) +void uartTryStartTxDMA(uartPort_t *s) { - uint16_t size = 0; - uint32_t fromwhere=0; - HAL_UART_StateTypeDef state = HAL_UART_GetState(&s->Handle); - if ((state & HAL_UART_STATE_BUSY_TX) == HAL_UART_STATE_BUSY_TX) - return; + ATOMIC_BLOCK(NVIC_PRIO_SERIALUART_TXDMA) { + if (s->txDMAStream->CR & DMA_SxCR_EN) { + // DMA is already in progress + return; + } - if (s->port.txBufferHead > s->port.txBufferTail) { - size = s->port.txBufferHead - s->port.txBufferTail; - fromwhere = s->port.txBufferTail; - s->port.txBufferTail = s->port.txBufferHead; - } else { - size = s->port.txBufferSize - s->port.txBufferTail; - fromwhere = s->port.txBufferTail; - s->port.txBufferTail = 0; + HAL_UART_StateTypeDef state = HAL_UART_GetState(&s->Handle); + if ((state & HAL_UART_STATE_BUSY_TX) == HAL_UART_STATE_BUSY_TX) { + return; + } + + if (s->port.txBufferHead == s->port.txBufferTail) { + // No more data to transmit + s->txDMAEmpty = true; + return; + } + + uint16_t size; + uint32_t fromWhere = s->port.txBufferTail; + + if (s->port.txBufferHead > s->port.txBufferTail) { + size = s->port.txBufferHead - s->port.txBufferTail; + s->port.txBufferTail = s->port.txBufferHead; + } else { + size = s->port.txBufferSize - s->port.txBufferTail; + s->port.txBufferTail = 0; + } + + s->txDMAEmpty = false; + + HAL_UART_Transmit_DMA(&s->Handle, (uint8_t *)&s->port.txBuffer[fromWhere], size); } - s->txDMAEmpty = false; - //HAL_CLEANCACHE((uint8_t *)&s->port.txBuffer[fromwhere],size); - HAL_UART_Transmit_DMA(&s->Handle, (uint8_t *)&s->port.txBuffer[fromwhere], size); } uint32_t uartTotalRxBytesWaiting(const serialPort_t *instance) @@ -351,8 +366,7 @@ void uartWrite(serialPort_t *instance, uint8_t ch) } if (s->txDMAStream) { - if (!(s->txDMAStream->CR & 1)) - uartStartTxDMA(s); + uartTryStartTxDMA(s); } else { __HAL_UART_ENABLE_IT(&s->Handle, UART_IT_TXE); } diff --git a/src/main/drivers/serial_uart_impl.h b/src/main/drivers/serial_uart_impl.h index 3c76ef758b..b549ecf6ac 100644 --- a/src/main/drivers/serial_uart_impl.h +++ b/src/main/drivers/serial_uart_impl.h @@ -171,11 +171,7 @@ extern uartDevice_t *uartDevmap[]; extern const struct serialPortVTable uartVTable[]; -#ifdef USE_HAL_DRIVER -void uartStartTxDMA(uartPort_t *s); -#else void uartTryStartTxDMA(uartPort_t *s); -#endif uartPort_t *serialUART(UARTDevice_e device, uint32_t baudRate, portMode_e mode, portOptions_e options); diff --git a/src/main/drivers/serial_uart_stm32f7xx.c b/src/main/drivers/serial_uart_stm32f7xx.c index 67350bad09..0154d255be 100644 --- a/src/main/drivers/serial_uart_stm32f7xx.c +++ b/src/main/drivers/serial_uart_stm32f7xx.c @@ -376,12 +376,7 @@ void uartIrqHandler(uartPort_t *s) static void handleUsartTxDma(uartPort_t *s) { - if (s->port.txBufferHead != s->port.txBufferTail) - uartStartTxDMA(s); - else - { - s->txDMAEmpty = true; - } + uartTryStartTxDMA(s); } void dmaIRQHandler(dmaChannelDescriptor_t* descriptor)