armcortex-mdmastm32h7

How to manage devices that cannot access d-cache in ARM


I'm using an SPI device with DMA enabled in an STM32H7 SoC. The DMA periph. cannot access d-cache, so in order to make it work I have disabled d-cache entirely (for more info. about this, see this explanation). However, I would like to avoid disabling d-cache globally for a problem that only affects to a small region of memory.

I have read this post about the meaning of clean and invalidate cache operations, in the ARM domain. My understanding is that, by cleaning a cache area, you force it to be written in the actual memory. On the other hand, by invalidating a cache area, you force the actual memory to be cached. Is this correct?

My intention with this is to follow these steps to transmit something over SPI (with DMA):

  1. Write the value you want on the buffer that DMA will read from.
  2. Clean d-cache for that area to force it to go to actual memory, so DMA can see it.
  3. Launch the operation: DMA will read the value from the area above and write it to the SPI's Tx buffer.
  4. SPI reads data at the same time it writes, so there will be data in the SPI's Rx buffer, which will be read by DMA and then it will write it to the recv. buffer provided by the user. It could happen that an observer of such buffer can indeed access d-cache. The latter could not be updated with the new value received by SPI yet, so invalidate the recv. buffer area to force d-cache to get updated.

Does the above make sense?

EDIT

Adding some more sources/examples of the problem I'm facing:

Example from the ST github: https://github.com/STMicroelectronics/STM32CubeH7/issues/153

Post in ST forums answring and explaining the d-cache problem: https://community.st.com/s/question/0D53W00000m2fjHSAQ/confused-about-dma-and-cache-on-stm32-h7-devices

Here the interconnection between memory and DMA: enter image description here As you can see, DMA1 can access sram1, 2 and 3. I'm using sram2.

Here the cache attributes of sram2:

enter image description here

As you can see, it is write back,write allocate, but not write through. I'm not familiar with these attributes, so I read the definition from here. However, that article seems to talk about the CPU physical cache (L1, L2 etc.) I'm not sure if ARM i-cache and d-cache refer to this physical cache. In any case, I'm assuming the definition for write through and the other terms are valid for d-cache as well.


Solution

  • I have investigated a bit more:

    With regards to clean and invalidate memory question, the answer is yes: clean will force cache to be written in memory and invalidate will force memory to be cached.

    With regards to the steps I proposed, again yes, it makes sense.

    Here is a sequence of 4 videos that explain this exact situation (DMA and memory coherency). As can be seen, the 'software' solution (doesn't involve MPU) proposed by the videos (and other resources provided above) is exactly the sequence of steps I posted.

    https://youtu.be/5xVKIGCPy2s

    https://youtu.be/2q8IvCxSjaY

    https://youtu.be/6IEtoG7m0jI

    https://youtu.be/0DhYTqPCRiA

    The other proposed solution is to configure the cortex-m7 MPU to change the attributes of a particular memory region to keep memory coherency.

    This all apart from the easiest solution which is to globally disable d-cache, although, naturally, this is not desirable.