Hi community The STM32H7 serial driver TX DMA logic is no longer working properly.
The issues started with commit 660ac63b. Subsequent attempts (f92a9068, 6c186b60) have failed to get it working again. I think the original idea of 660ac63b is right, it just failed to restart TX DMA upon TX DMA completion (if needed). I would suggest reverting the following commits: 6c186b60 58f2a7b1 69a8b5b5. Then add the following patch as an amendment: diff --git a/arch/arm/src/stm32h7/stm32_serial.c b/arch/arm/src/stm32h7/stm32_serial.c index 120ea0f3b5..fc90c5d521 100644 --- a/arch/arm/src/stm32h7/stm32_serial.c +++ b/arch/arm/src/stm32h7/stm32_serial.c @@ -3780,11 +3780,20 @@ static void up_dma_txcallback(DMA_HANDLE handle, uint8_t status, void *arg) } } - nxsem_post(&priv->txdmasem); - /* Adjust the pointers */ uart_xmitchars_done(&priv->dev); + + /* Initiate another transmit if data is ready */ + + if (priv->dev.xmit.tail != priv->dev.xmit.head) + { + uart_xmitchars_dma(&priv->dev); + } + else + { + nxsem_post(&priv->txdmasem); + } } #endif @@ -3806,6 +3815,14 @@ static void up_dma_txavailable(struct uart_dev_s *dev) int rv = nxsem_trywait(&priv->txdmasem); if (rv == OK) { + if (dev->xmit.head == dev->xmit.tail) + { + /* No data to transfer. Release semaphore. */ + + nxsem_post(&priv->txdmasem); + return; + } + uart_xmitchars_dma(dev); } } However, uart_xmitchars_dma() is currently not safe to call from an interrupt service routine, so the following patch would also be required: diff --git a/drivers/serial/serial_dma.c b/drivers/serial/serial_dma.c index aa99e801ff..b2603953ad 100644 --- a/drivers/serial/serial_dma.c +++ b/drivers/serial/serial_dma.c @@ -97,26 +97,29 @@ void uart_xmitchars_dma(FAR uart_dev_t *dev) { FAR struct uart_dmaxfer_s *xfer = &dev->dmatx; - if (dev->xmit.head == dev->xmit.tail) + size_t head = dev->xmit.head; + size_t tail = dev->xmit.tail; + + if (head == tail) { /* No data to transfer. */ return; } - if (dev->xmit.tail < dev->xmit.head) + if (tail < head) { - xfer->buffer = &dev->xmit.buffer[dev->xmit.tail]; - xfer->length = dev->xmit.head - dev->xmit.tail; + xfer->buffer = &dev->xmit.buffer[tail]; + xfer->length = head - tail; xfer->nbuffer = NULL; xfer->nlength = 0; } else { - xfer->buffer = &dev->xmit.buffer[dev->xmit.tail]; - xfer->length = dev->xmit.size - dev->xmit.tail; + xfer->buffer = &dev->xmit.buffer[tail]; + xfer->length = dev->xmit.size - tail; xfer->nbuffer = dev->xmit.buffer; - xfer->nlength = dev->xmit.head; + xfer->nlength = head; } dev->tx_count += xfer->length + xfer->nlength; Any thoughts? Regards Kian