我正在玩STM32H753的L1缓存。
我想做的是故意引起缓存和 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();
}
用Keil 5编译,
-O0
。变量写入是通过 STR
指令完成的(我的意思是:据我所知,没有奇怪的 CPU 优化)。
我检查了 MPU 寄存器值、RAM 变量的地址(确实在 MPU 区域内)。
算法和/或代码有问题吗?
您正在尝试启用/禁用 DTCMRAM 的缓存,该缓存从地址 0x200000000 开始。然而,DTCMRAM 是紧耦合存储器。它直接连接到 Cortex-M7 内核,并且“不”位于缓存后面。 您可以在(参考手册)的图 1.(系统架构)中看到这一点。 因此,缓存操作不会影响该内存。 如果您想进行此测试,则必须使用另一个内存区域,例如 AXI SRAM(从地址 0x24000000 开始)。这可以通过修改链接器脚本(可能还包括启动代码)或使用指针变量直接写入固定内存地址来完成。
请注意,在不禁用高速缓存的情况下造成 RAM 和高速缓存之间不匹配的另一种可能性是使用 DMA 控制器访问与 MCU 相同的内存。 DMA 控制器不使用缓存,因此如果 DMA 控制器写入已在缓存中的内存,您的应用程序将读取旧的缓存版本而不是新写入的数据。你的测试将是这样的:
软件将值写入 AXI SRAM。它现在在缓存中。