stm32f7:sdmmc defer invalidate until after DMA completion

The FAT was not coherent. Resulting in a write failed
   with errno:28 No space left on device.

   It is unclear how the memory is acesses prior to the DMA
   completion. But this restructuring ensures the data
   is coherent.

   This issue was not detected on the stm32h7
This commit is contained in:
David Sidrane 2021-11-19 14:21:22 -08:00 committed by Xiang Xiao
parent ac5a228d89
commit ad7e36d83f

View File

@ -412,6 +412,8 @@ struct stm32_dev_s
volatile uint8_t xfrflags; /* Used to synchronize SDMMC and DMA completion events */
bool dmamode; /* true: DMA mode transfer */
DMA_HANDLE dma; /* Handle for DMA channel */
uint8_t *rxbuffer; /* Address of read DMA operation for dcahe maintenance */
uint8_t *rxend; /* last byte of buffer for dcahe maintenance */
#endif
#ifdef HAVE_SDMMC_SDIO_MODE
@ -1565,6 +1567,15 @@ static void stm32_endtransfer(struct stm32_dev_s *priv,
*/
stm32_dmastop(priv->dma);
/* Force RAM re-read */
if (priv->rxbuffer)
{
up_invalidate_dcache((uintptr_t)priv->rxbuffer,
(uintptr_t)priv->rxend);
priv->rxbuffer = 0;
}
}
#endif
@ -1929,6 +1940,8 @@ static void stm32_reset(FAR struct sdio_dev_s *dev)
priv->widebus = false; /* Required for DMA support */
#ifdef CONFIG_STM32F7_SDMMC_DMA
priv->dmamode = false; /* true: DMA mode transfer */
priv->rxbuffer = 0;
priv->rxend = 0;
#endif
/* Configure the SDIO peripheral */
@ -2265,6 +2278,7 @@ static int stm32_recvsetup(FAR struct sdio_dev_s *dev, FAR uint8_t *buffer,
priv->remaining = nbytes;
#ifdef CONFIG_STM32F7_SDMMC_DMA
priv->dmamode = false;
priv->rxbuffer = 0;
#endif
/* Then set up the SDIO data path */
@ -2321,6 +2335,7 @@ static int stm32_sendsetup(FAR struct sdio_dev_s *dev, FAR const
priv->remaining = nbytes;
#ifdef CONFIG_STM32F7_SDMMC_DMA
priv->dmamode = false;
priv->rxbuffer = 0;
#endif
/* Then set up the SDIO data path */
@ -3074,6 +3089,7 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev,
priv->buffer = (uint32_t *)buffer;
priv->remaining = buflen;
priv->dmamode = true;
priv->rxbuffer = 0;
/* Then set up the SDIO data path */
@ -3092,12 +3108,13 @@ static int stm32_dmarecvsetup(FAR struct sdio_dev_s *dev,
(uint32_t)buffer, (buflen + 3) >> 2,
SDMMC_RXDMA32_CONFIG | priv->dmapri);
/* Force RAM reread */
/* Force deferred RAM reread */
if ((uintptr_t)buffer < DTCM_START ||
(uintptr_t)buffer + buflen > DTCM_END)
{
up_invalidate_dcache((uintptr_t)buffer, (uintptr_t)buffer + buflen);
priv->rxbuffer = buffer;
priv->rxend = buffer + buflen;
}
/* Start the DMA */
@ -3178,6 +3195,7 @@ static int stm32_dmasendsetup(FAR struct sdio_dev_s *dev,
priv->buffer = (uint32_t *)buffer;
priv->remaining = buflen;
priv->dmamode = true;
priv->rxbuffer = 0;
/* Then set up the SDIO data path */