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.
This commit is contained in:
David Sidrane 2023-10-24 08:45:51 -07:00 committed by Petro Karashchenko
parent 87d6084f31
commit 611309b956

View File

@ -1373,6 +1373,7 @@ static inline void imxrt_serialout(struct imxrt_uart_s *priv,
static int imxrt_dma_nextrx(struct imxrt_uart_s *priv) static int imxrt_dma_nextrx(struct imxrt_uart_s *priv)
{ {
int dmaresidual = imxrt_dmach_getcount(priv->rxdma); int dmaresidual = imxrt_dmach_getcount(priv->rxdma);
DEBUGASSERT(dmaresidual <= RXDMA_BUFFER_SIZE);
return RXDMA_BUFFER_SIZE - dmaresidual; return RXDMA_BUFFER_SIZE - dmaresidual;
} }
@ -2345,14 +2346,26 @@ static bool imxrt_rxflowcontrol(struct uart_dev_s *dev,
#ifdef SERIAL_HAVE_RXDMA #ifdef SERIAL_HAVE_RXDMA
static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status) static int imxrt_dma_receive(struct uart_dev_s *dev, unsigned int *status)
{ {
struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev; struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev;
uint32_t nextrx = imxrt_dma_nextrx(priv); static uint32_t last_nextrx = -1;
int c = 0; uint32_t nextrx = imxrt_dma_nextrx(priv);
int c = 0;
/* Check if more data is available */ /* Check if more data is available */
if (nextrx != priv->rxdmanext) 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 */ /* Now read from the DMA buffer */
c = priv->rxfifo[priv->rxdmanext]; 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; struct imxrt_uart_s *priv = (struct imxrt_uart_s *)arg;
uint32_t sr; 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)) if (priv->rxenable && imxrt_dma_rxavailable(&priv->dev))
{ {
uart_recvchars(&priv->dev); uart_recvchars(&priv->dev);