From ad7e36d83f564b8d1948678c967a28dbaeb3d7d4 Mon Sep 17 00:00:00 2001 From: David Sidrane Date: Fri, 19 Nov 2021 14:21:22 -0800 Subject: [PATCH] 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 --- arch/arm/src/stm32f7/stm32_sdmmc.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/arch/arm/src/stm32f7/stm32_sdmmc.c b/arch/arm/src/stm32f7/stm32_sdmmc.c index 0126f871b0..0d7968cc40 100644 --- a/arch/arm/src/stm32f7/stm32_sdmmc.c +++ b/arch/arm/src/stm32f7/stm32_sdmmc.c @@ -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 */