cancel
Showing results for 
Search instead for 
Did you mean: 

Cache coherency issues when reading DMA buffer from ADC

Floki.1
Associate II

Hello,

I face serveral data coherency issues on my dma buffer which is used to place the values of serveral ADC channels into it. This is executed on M7 context

Just as a reference, I have a dummy project without any MPU configuration and data cache is globally disabled. I start the DMA sampling via Software (On-Shot-Mode) several times. When I set different voltage levels on different ADC channels, I see the expected values inside the DMA buffer.

When I enable the data cache, then my buffer keeps freezing. I don't see any updates inside the dma buffer. I was following the example code form ST as well as the link "https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices"

According to this page, I created a seperate memory region for the DMA. The dma buffer is 32 byte aligned and placed into the SRAM3 region via linker attributes

ALIGN_32BYTES (__attribute__ ((section (".dma"))) static uint16_t Buff[I5]) = {0U};

.dma is a section of SRAM3 (0x38000000).

Starting address of the buffer is 0x38000000 as well.

After the complete initialization stuff on the M7, I call HAL_ADC_Start_DMA() to start the ADC sampling of all 5 channels in the background.

After that, I call SCB_InvalidateDCache_by_Addr(). This function seems to work only once because I see that the buffer changed to its expected values correctly. When I call HAL_ADC_Stop_DMA and call HAL_ADC_Start_DMA() again due to One-Shot mode procedure follewed by SCB_InvalidateDCache_by_Addr(), the values are not updated anymore. The previous value from the first SCB_InvalidateDCache_by_Addr() are still reflected in the dma buffer although I put a different set of voltages on a different channel. I can evaluate the ADC DR register with its latest value from the last channel (depending on rank config), I see that this value didn't make it into the dma buffer

I also tried to use SCB_InvalidateDCache() which is stucked in an endless loop till I manually leave the loop via ajump instruction with the debugger

I also tried SCB_CleanDCache_by_Addr() afterwards but it doesn't seem to work at all

What part I am missing here?

Whats a littble bit confusin is that the ST example use the SCB_InvalidateDCache_by_Addr after the data is available (actually inside the DMA complete interrupt) while the page mentioned above tells you to use it even before reading data from the DMA buffer.

Do I need adapt the MPU as well for SRAM3 region ? Any assistance?

The same project without Cache and MPU on M7 is running without any issue, but the loss of d-cache is not a option for me due to performance loss on other interfaces (FMC, etc.)

Why is it working ony once ?

2 REPLIES 2
TDK
Guru

Would be nice to see some code. Probably a bug in what you're doing somewhere. How are verifying that "data doesn't change"?

> I also tried to use SCB_InvalidateDCache() which is stucked in an endless loop

Invalidating all memory is not a wise idea as this discards modified memory which hasn't yet been written.

> Whats a littble bit confusin is that the ST example use the SCB_InvalidateDCache_by_Addr after the data is available (actually inside the DMA complete interrupt) while the page mentioned above tells you to use it even before reading data from the DMA buffer.

Isn't that basically the same advice? You need to invalidate it after the data arrives and before you read it. This doesn't mean twice, this means a single point in time which satisfies both of those conditions.

If you feel a post has answered your question, please click "Accept as Solution".
Floki.1
Associate II

Hello TDK,

1)for the SCB_InvalidateDCache(). it caused once a Hardfault issue. on my sinde and it keeps stucking.

Verfifying is done like this: Attach a voltage level e.g. 2.5V on ADC channel 1. When starting the sample procedure, I see that the raw data value got updated in the buffer with index 0. Then apply the test voltage from ADC channel 1 to 2. I would expect here in the next sample period to see the buffer updated on index 1 position, while the raw value from the previous channel (index=0) is approx 0 + some noise.

2)Yes , you are right

PS: Anyhow, it seems that the issue is fixed now via explicit settings in the MPU region. I assume that text on ST page should emphasze more on the MPU confiugration for cache coherency as you don't see a real example on this page to configure the MPU with its attributes once. At least from my side, I have the impression that the importance of the MPU apart from the figures is not really taken into account as most of the developpers read and go directly the "code snippets", in this casen the linker script and cache maintenance functions.