Skip to main content
This topic has been closed for replies.
Best answer by Piranha

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.

2 replies

Piranha
PiranhaBest answer
Principal III
April 2, 2021

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_it
fb_itAuthor
Associate III
April 2, 2021

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);

Piranha
Principal III
April 3, 2021

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