cancel
Showing results for 
Search instead for 
Did you mean: 

"DMA is not working on STM32H7 devices" article is wrong

fb
Associate III

I think the article here:

https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices

is wrong. In solution 3 it invalidate D-cache before reception. This doesn't make sense, it has to invalidate the D-cache after reception.

1 ACCEPTED SOLUTION

Accepted Solutions
Piranha
Chief II

Regarding the before/after, the article is right - invalidation must be done before starting the reception. Read my post in this topic:

https://community.st.com/s/question/0D53W000009j3IKSAY/stm32h7-sai-dma-cache-enabled-nothing-works-as-before

AN4839 page 4:

  • If all the lines are allocated, the cache controller runs the line eviction process, where a line is selected (depending on replacement algorithm) cleaned/invalidated, and reallocated. The data cache and Instruction cache implement a pseudo-random replacement algorithm.

Detailed discussion:

https://community.st.com/s/question/0D50X0000C9hGoz/weird-cache-writeback-behavior-for-stm32f7508

But the article is wrong on other issues:

#define RX_LENGTH  (16)
uint8_t rx_buffer[RX_LENGTH];
 
/* Make sure the address is 32-byte aligned and add 32-bytes to length, in case it overlaps cacheline */
SCB_InvalidateDCache_by_Addr((uint32_t*)(((uint32_t)rx_buffer) & ~(uint32_t)0x1F), RX_LENGTH+32);
  1. The math of the size (second) parameter is completely wrong. It doesn't do even what was intended and damages data.
  2. The intended "expand to the nearest cache line boundaries" logic is already done internally in SCB_*() functions and those manual calculations are useless.
  3. The address and size expansion logic doesn't cancel the requirement of a buffer address and size to be aligned to cache line size. Not doing that still damages other variables placed before and after that buffer.
  4. The points 1 and 2 are true also for a transmission part of the example.

View solution in original post

3 REPLIES 3
Piranha
Chief II

Regarding the before/after, the article is right - invalidation must be done before starting the reception. Read my post in this topic:

https://community.st.com/s/question/0D53W000009j3IKSAY/stm32h7-sai-dma-cache-enabled-nothing-works-as-before

AN4839 page 4:

  • If all the lines are allocated, the cache controller runs the line eviction process, where a line is selected (depending on replacement algorithm) cleaned/invalidated, and reallocated. The data cache and Instruction cache implement a pseudo-random replacement algorithm.

Detailed discussion:

https://community.st.com/s/question/0D50X0000C9hGoz/weird-cache-writeback-behavior-for-stm32f7508

But the article is wrong on other issues:

#define RX_LENGTH  (16)
uint8_t rx_buffer[RX_LENGTH];
 
/* Make sure the address is 32-byte aligned and add 32-bytes to length, in case it overlaps cacheline */
SCB_InvalidateDCache_by_Addr((uint32_t*)(((uint32_t)rx_buffer) & ~(uint32_t)0x1F), RX_LENGTH+32);
  1. The math of the size (second) parameter is completely wrong. It doesn't do even what was intended and damages data.
  2. The intended "expand to the nearest cache line boundaries" logic is already done internally in SCB_*() functions and those manual calculations are useless.
  3. The address and size expansion logic doesn't cancel the requirement of a buffer address and size to be aligned to cache line size. Not doing that still damages other variables placed before and after that buffer.
  4. The points 1 and 2 are true also for a transmission part of the example.
fb
Associate III

Thanks, that's tricky. And bugs actually happened when I tested it with an external flash, every few MB there were a few bytes wrong. Invalidating it before works now:

	SCB_InvalidateDCache_by_Addr((uint32_t*)ramDestination, FLASH_PAGE_SIZE);
	HAL_OSPI_Receive_DMA(&hospi1, ramDestination);

I added more details and a link to another detailed discussion to the initial post. Could be interesting read... 🙂