C STM32H7的一级缓存行为
我在玩STM32H753的一级缓存 我试图做的是故意挑起缓存和RAM之间的不一致,如下所示:C STM32H7的一级缓存行为,c,caching,stm32,C,Caching,Stm32,我在玩STM32H753的一级缓存 我试图做的是故意挑起缓存和RAM之间的不一致,如下所示: 将SRAM区域设置为可直写缓存 启用数据缓存 向RAM中的变量写入内容->数据将同时写入缓存和RAM 禁用缓存而不使其无效 将其他内容写入同一变量->只修改RAM,而不修改缓存 再次启用缓存,但不使其无效 读取RAM->我希望读取旧值而不是新值,因为此时缓存中应该有命中,因为缓存线应该仍然有效,并且应该仍然包含旧值 代码如下: volatile uint32_t someDummyVariable
- 将SRAM区域设置为可直写缓存
- 启用数据缓存
- 向RAM中的变量写入内容->数据将同时写入缓存和RAM
- 禁用缓存而不使其无效
- 将其他内容写入同一变量->只修改RAM,而不修改缓存
- 再次启用缓存,但不使其无效
- 读取RAM->我希望读取旧值而不是新值,因为此时缓存中应该有命中,因为缓存线应该仍然有效,并且应该仍然包含旧值
volatile uint32_t someDummyVariable ;
int main(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;
HAL_Init();
/* Configure the MPU attributes as Write-through for SRAM */
HAL_MPU_Disable();
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x20000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_32MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE; // -> means write through ?
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Configure the MPU attributes as WT for the Flash */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x08000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
HAL_MPU_Enable(MPU_HARDFAULT_NMI);
SCB_EnableDCache();
// write something in a variable in RAM -> thanks to write-through attribute
// it will be copied to real RAM, not only to the cache
someDummyVariable = 0x12345678;
// disable cache without invalidating it
SCB->CSSELR = 0U; /* select Level 1 data cache */
__DSB();
SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk; /* disable D-Cache */
__DSB();
__ISB();
// write something else to RAM -> will NOT be written to cache
someDummyVariable = 0xAAAAAAAA;
// enable cache again (without invalidating or cleaning it)
__DSB();
SCB->CCR |= (uint32_t)SCB_CCR_DC_Msk; /* enable D-Cache */
__DSB();
__ISB();
// now we should read the old value that is still in the cache
if ( someDummyVariable != 0x12345678 )
{
__NOP();
}
用keil5,-O0编译。变量写入是通过STR完成的(我的意思是:据我所知,没有奇怪的CPU优化)
我检查了MPU寄存器的值,RAM变量的地址(实际上在MPU区域内)
算法和/或代码中是否有错误
编辑:修复了试图启用/禁用DTCMRAM缓存的MPU配置,该缓存从地址0x200000000开始。然而,DTCMRAM是紧密耦合的存储器。它直接连接到Cortex-M7内核,并且不在缓存后面。 您可以在图1中看到这一点。(系统架构)的。 因此,缓存操作不会对该内存产生影响 如果要执行此测试,必须使用另一个内存区域,例如AXI SRAM(从地址0x24000000开始)。这可以通过修改链接器脚本(可能还有启动代码)或使用指针变量直接写入固定内存地址来实现 请注意,在不禁用缓存的情况下,在RAM和缓存之间创建不匹配的另一种可能性是使用DMA控制器访问与MCU相同的内存。DMA控制器不使用缓存,因此如果DMA控制器写入已在缓存中的内存,则应用程序将读取旧的缓存版本,而不是新写入的数据。您的测试将是这样的:
- 软件将值写入AXI SRAM。它现在在缓存中
- DMA操作将数据写入同一地址。核心没有“看到”这一点
- 通常,您必须在现在读取数据之前执行缓存失效操作。对于你的测试,你不会这样做
- 现在从AXI SRAM读取变量。如果启用缓存,您可能会获得旧值(由软件写入的值,而不是由DMA写入的值)