Description:
When building in debug mode (-Og), the function SCB_DisableDCache in CMSIS/Core/Include/m-profile/armv7m_cachel1.h may cause data inconsistency or endless loops. This is because local variables (such as locals) are likely stored on the stack, and after disabling the D-Cache, their cache lines may not be flushed, leading to stale values being read from RAM. The current implementation addresses this only for non-optimized builds by cleaning and invalidating the cache line containing locals:
#if !defined(__OPTIMIZE__)
/*
* For the endless loop issue with no optimization builds.
* More details, see https://github.com/ARM-software/CMSIS_5/issues/620
*
* The issue only happens when local variables are in stack. If
* local variables are saved in general purpose register, then the function
* is OK.
*
* When local variables are in stack, after disabling the cache, flush the
* local variables cache line for data consistency.
*/
/* Clean and invalidate the local variable cache. */
#if defined(__ICCARM__)
/* As we can't align the stack to the cache line size, invalidate each of the variables */
SCB->DCCIMVAC = (uint32_t)&locals.sets;
SCB->DCCIMVAC = (uint32_t)&locals.ways;
SCB->DCCIMVAC = (uint32_t)&locals.ccsidr;
#else
SCB->DCCIMVAC = (uint32_t)&locals;
#endif
__DSB();
__ISB();
#endif
see lines 198-221 in armv7m_cachel1.h:
|
#if !defined(__OPTIMIZE__) |
However, there is no strict guarantee that, with optimization enabled, all local variables will always be kept in registers. The compiler may still spill variables to the stack depending on register pressure and function complexity. Thus, the bug can potentially occur in optimized builds as well, even if it is less likely.
Steps to Reproduce:
This issue is difficult to reproduce reliably, as it depends on code size and compiler decisions (e.g., under debug optimization). In our builds, it occurs with the optimization level -Og.
Expected Behavior:
Local variables should always be consistent after disabling D-Cache, regardless of optimization level or build type.
Actual Behavior:
With D-Cache disabled and local variables on the stack, their values may be stale, causing incorrect behavior or infinite loops. The current workaround only applies to non-optimized builds.
Suggested Fix:
Always perform the cache clean/invalidate operation for the local variables, regardless of the optimization level or build type. This ensures robust and portable code, preventing subtle data inconsistency bugs.
Environment:
CMSIS version: 6.1.0
Compiler: arm-zephyr-eabi-g++ v12.2.0
Linker: arm-zephyr-eabi-ld v2.38
Build system: CMake 4.2.0
Target: STM32H743ZI
Build optimization: -Og
References:
ARM-software/CMSIS_5#620
Description:
When building in debug mode (-Og), the function SCB_DisableDCache in CMSIS/Core/Include/m-profile/armv7m_cachel1.h may cause data inconsistency or endless loops. This is because local variables (such as locals) are likely stored on the stack, and after disabling the D-Cache, their cache lines may not be flushed, leading to stale values being read from RAM. The current implementation addresses this only for non-optimized builds by cleaning and invalidating the cache line containing locals:
see lines 198-221 in armv7m_cachel1.h:
CMSIS_6/CMSIS/Core/Include/m-profile/armv7m_cachel1.h
Line 198 in fdbbc52
However, there is no strict guarantee that, with optimization enabled, all local variables will always be kept in registers. The compiler may still spill variables to the stack depending on register pressure and function complexity. Thus, the bug can potentially occur in optimized builds as well, even if it is less likely.
Steps to Reproduce:
This issue is difficult to reproduce reliably, as it depends on code size and compiler decisions (e.g., under debug optimization). In our builds, it occurs with the optimization level -Og.
Expected Behavior:
Local variables should always be consistent after disabling D-Cache, regardless of optimization level or build type.
Actual Behavior:
With D-Cache disabled and local variables on the stack, their values may be stale, causing incorrect behavior or infinite loops. The current workaround only applies to non-optimized builds.
Suggested Fix:
Always perform the cache clean/invalidate operation for the local variables, regardless of the optimization level or build type. This ensures robust and portable code, preventing subtle data inconsistency bugs.
Environment:
CMSIS version: 6.1.0
Compiler: arm-zephyr-eabi-g++ v12.2.0
Linker: arm-zephyr-eabi-ld v2.38
Build system: CMake 4.2.0
Target: STM32H743ZI
Build optimization: -Og
References:
ARM-software/CMSIS_5#620