AnsweredAssumed Answered

SD card memory corruption due to overly aggressive cache maintenance

Question asked by Rick Sladkey on Mar 8, 2018
Latest reply on Mar 30, 2018 by gonzalez.laurent

I just spent two harrowing days debugging random memory corruption in my application and the problem turned out to be overly aggressive cache invalidation.

 

In sd_diskio.c this section of code (STM32Cube_FW_F7_V1.9.0):

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
            /*
               the SCB_InvalidateDCache_by_Addr() requires a 32-Byte aligned address,
               adjust the address and the D-Cache size to invalidate accordingly.
             */

            alignedAddr = (uint32_t)buff & ~0x1F;
            SCB_InvalidateDCache_by_Addr((uint32_t*)alignedAddr, count*BLOCKSIZE + ((uint32_t)buff - alignedAddr));
#endif

 

This invalidates more memory than the actual size of the buffer by up to 31 bytes in each direction. In particular, if the cache is dirty in the memory surrounding the buffer, and the cache is invalidated, then valid memory contents will be discarded. The symptom of this occurring is that memory surrounding the SD card read buffer may suddenly appear to revert to the contents it had earlier in the execution of the program.

 

There are several ways to fix this problem, but one is to clean the cache surrounding the read buffer before the DMA operation is performed:

 

#if (ENABLE_SD_DMA_CACHE_MAINTENANCE == 1)
  uint32_t alignedAddr;
#if 1
  // Clean cache surrounding buffer so we don't accidentally invalidate valid cached memory.
  alignedAddr = (uint32_t)buff &  ~0x1F;
  SCB_CleanDCache_by_Addr((uint32_t*)alignedAddr, 32);
  SCB_CleanDCache_by_Addr((uint32_t*)(alignedAddr + count*BLOCKSIZE), 32);
#endif
#endif

 

I hope this is useful to others experiencing the same problem or to users trying to understand the subtleties of the interaction between the use of DMA and presence of a data cache.

Outcomes