This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 611309b956 imxrt:serial Ensure the cache is updated if the DMA has 
updated again
611309b956 is described below

commit 611309b95690b6a5a5017e3bef9b517e44ace44c
Author: David Sidrane <[email protected]>
AuthorDate: Tue Oct 24 08:45:51 2023 -0700

    imxrt:serial Ensure the cache is updated if the DMA has updated again
    
       The DMA can bring in more rx data, than the number of
       DMA completions call backs. The call back happen on
       idle, 1/2 and full events. But in between these events
       the DMA can write more data to the buffers memory that
       need to be brought in to the cache. (invalidate)
    
       We do the invalidate on the reads from the fifo memory
       if the the DMA as commited since the last read.
---
 arch/arm/src/imxrt/imxrt_serial.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/arch/arm/src/imxrt/imxrt_serial.c 
b/arch/arm/src/imxrt/imxrt_serial.c
index 6a2faf50fc..30a487b553 100644
--- a/arch/arm/src/imxrt/imxrt_serial.c
+++ b/arch/arm/src/imxrt/imxrt_serial.c
@@ -1373,6 +1373,7 @@ static inline void imxrt_serialout(struct imxrt_uart_s 
*priv,
 static int imxrt_dma_nextrx(struct imxrt_uart_s *priv)
 {
   int dmaresidual = imxrt_dmach_getcount(priv->rxdma);
+  DEBUGASSERT(dmaresidual <= RXDMA_BUFFER_SIZE);
 
   return RXDMA_BUFFER_SIZE - dmaresidual;
 }
@@ -2345,14 +2346,26 @@ static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
 #ifdef SERIAL_HAVE_RXDMA
 static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status)
 {
-  struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
-  uint32_t nextrx = imxrt_dma_nextrx(priv);
-  int c = 0;
+  struct imxrt_uart_s *priv   = (struct imxrt_uart_s *)dev;
+  static uint32_t last_nextrx = -1;
+  uint32_t nextrx             = imxrt_dma_nextrx(priv);
+  int c                       = 0;
 
   /* Check if more data is available */
 
   if (nextrx != priv->rxdmanext)
     {
+      /* Now we must ensure the cache is updated if the DMA has
+       * updated again.
+       */
+
+      if (last_nextrx != nextrx)
+        {
+          up_invalidate_dcache((uintptr_t)priv->rxfifo,
+                               (uintptr_t)priv->rxfifo + RXDMA_BUFFER_SIZE);
+          last_nextrx = nextrx;
+        }
+
       /* Now read from the DMA buffer */
 
       c = priv->rxfifo[priv->rxdmanext];
@@ -2721,9 +2734,6 @@ static void imxrt_dma_rxcallback(DMACH_HANDLE handle, 
void *arg, bool done,
   struct imxrt_uart_s *priv = (struct imxrt_uart_s *)arg;
   uint32_t sr;
 
-  up_invalidate_dcache((uintptr_t)priv->rxfifo,
-                       (uintptr_t)priv->rxfifo + RXDMA_BUFFER_SIZE);
-
   if (priv->rxenable && imxrt_dma_rxavailable(&priv->dev))
     {
       uart_recvchars(&priv->dev);

Reply via email to