Hi,

here is the pull request:
https://github.com/apache/nuttx/pull/11871

My initial comments (and "fix") for uart_xmitchars_dma() are no longer 
relevant. Hence, those changes are no longer included.

Regards
Kian
________________________________
From: Sebastien Lorquet <sebast...@lorquet.fr>
Sent: 08 March 2024 11:13
To: dev@nuttx.apache.org <dev@nuttx.apache.org>
Subject: Re: STM32H7 serial TX DMA issues

Hello,

Yes, stm32h7 uart transmission has issues. You can easily test this in
nsh with just an echo command and a very long string, eg > 64 ascii
chars. At first I believed it was buffering problems.

This caused me some headaches 1.5 years ago, but the DMA serial driver
is too complex for me to debug. I have disabled CONFIG_UARTn_TXDMA on
relevant uarts of my board.

Please give the link to your PR when it's ready so I can follow this
closely.

Thank you,

Sebastien


Le 08/03/2024 à 10:29, David Sidrane a écrit :
>         Hi Kian,
>
>         The Problem with the semaphore is it cause blocking when the port
> is opened non blocking.
>
>         Please do PR so we can review it.
>
> David
>
>
> -----Original Message-----
> From: Kian Karas (KK) <k...@thrane.eu>
> Sent: Friday, March 8, 2024 4:18 AM
> To: dev@nuttx.apache.org
> Subject: STM32H7 serial TX DMA issues
>
> 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

Reply via email to