different cache behavior between stm32H7 and stm32F7
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-05-21 1:16 PM
Hi,
I am facing a strange cache problem. I use the DCMI coupled to the DMA in order to acquire an image into the external SDRAM. As indicated in the application note AN4839, I proceed in this way.
- before to start the DMA transfer I clean the cache (cache_D_Clean();)
- At the end of the transfer (in the DMA interruption indicating the end), I invalidate the cache (cache_D_Invalidate();)
Everything work perfectly on the stm32H7.
On the stm32F7, as soon as the cache invalidation routine is called, the CPU generates a bus error.
On the stm32F7, in the DMA interruption indicating the end of the transfer, I replaced the cache invalidation (cache_D_Invalidate();) by the cache clean followed by the cache invalidation (cache_D_Clean(); cache_D_Invalidate();). Adding a clean (cache_D_Clean();) seems to avoid the bus error but I cannot understand why.
Why the behavior of the H7 and the F7 caches are different on the same code?
Thank you for your feedbacks.
Any idea why ?
Solved! Go to Solution.
- Labels:
-
DCMI
-
DMA
-
Flash
-
STM32F7 Series
-
STM32H7 Series
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-05-22 8:20 AM
The functions, which clean/invalidate the whole cache, normally should not be used at all and are almost useless. Typically I-cache can just be enabled and doesn't require any further management. For D-cache a proper management has to follow 3 basic rules:
- Make the address and size of all receive buffer instances aligned to __SCB_DCACHE_LINE_SIZE.
- Call SCB_InvalidateDCache_by_Addr() before passing the receive buffers to DMA.
- Call SCB_CleanDCache_by_Addr() before passing the transmit buffers to DMA.
Yes, even for receive part the invalidation must be done before passing buffers to DMA, because otherwise cache eviction can damage the receive buffers by writing back dirty lines during reception. A cite from AN4839:
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.
AN4838 is also closely related.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-05-21 1:36 PM
Use the By Address variant of Invalidate DCache, lest very bad things happen...
Why? Because it trashes data pending to the stack, among other things, and that's hard to unwind and will cause unpredictable behaviour.
https://www.keil.com/pack/doc/CMSIS/Core/html/group__Dcache__functions__m7.html
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-05-22 8:20 AM
The functions, which clean/invalidate the whole cache, normally should not be used at all and are almost useless. Typically I-cache can just be enabled and doesn't require any further management. For D-cache a proper management has to follow 3 basic rules:
- Make the address and size of all receive buffer instances aligned to __SCB_DCACHE_LINE_SIZE.
- Call SCB_InvalidateDCache_by_Addr() before passing the receive buffers to DMA.
- Call SCB_CleanDCache_by_Addr() before passing the transmit buffers to DMA.
Yes, even for receive part the invalidation must be done before passing buffers to DMA, because otherwise cache eviction can damage the receive buffers by writing back dirty lines during reception. A cite from AN4839:
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.
AN4838 is also closely related.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-05-22 1:38 PM
#ifndef __SCB_DCACHE_LINE_SIZE
#define __SCB_DCACHE_LINE_SIZE 32U
#endif
void flush_cache(bool is_TX, void *ptr, unsigned len)
{
if (!ptr || (len == 0))
__BKPT(0);
// ptr, len may be not cacheline aligned: see impl. of SCB_CleanDCache_by_Addr
// but we require alignment to be sure
if ( len & (__SCB_DCACHE_LINE_SIZE - 1))
__BKPT(0);
if ((uintptr_t)ptr & (__SCB_DCACHE_LINE_SIZE - 1))
__BKPT(0);
if (is_TX) {
SCB_CleanDCache_by_Addr(ptr, len);
} else {
SCB_InvalidateDCache_by_Addr(ptr, len);
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2021-05-23 5:44 AM
Hi All,
thank you for all your input.
I implemented the clean/invalidation by address and on all my hardware (M7 and H7) and things run well.
Great support, thank you.
Edo
