首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >STM32H7的L1-缓存行为

STM32H7的L1-缓存行为
EN

Stack Overflow用户
提问于 2019-12-05 15:59:08
回答 1查看 3.2K关注 0票数 1

我在玩STM32H753的L1缓存。

我想要做的是激发-on的目的-缓存和内存之间的不一致性如下:

  • 将SRAM区域设置为可写缓存。
  • 启用数据缓存
  • 向内存中的变量写入某些内容,->数据将同时写入缓存和内存。
  • 禁用缓存而不使其失效
  • 向相同的变量->写入其他内容,只有内存将被修改,而不是缓存。
  • 再次启用缓存,而不使其无效
  • 读取内存->我希望读取的是旧值,而不是新值,因为此时缓存中应该有命中,因为缓存行应该仍然有效,并且应该仍然包含旧值?

以下是代码:

代码语言:javascript
复制
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区域内)。

算法和/或代码中有什么问题吗?

编辑:修复MPU配置

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-22 10:09:45

您正在尝试启用/禁用DTCMRAM的缓存,该缓存从地址0x200000000开始。然而,DTCMRAM是紧密耦合的内存。它直接连接到Cortex-M7内核,是,而不是缓存后面的。您可以在(参考手册)的图1 (系统架构)中看到这一点。因此,缓存操作对此内存没有影响。

如果要进行此测试,则必须使用另一个内存区域,例如AXI SRAM (从地址0x24000000开始)。这可以通过修改链接器脚本(可能是启动代码),或者通过使用指针变量直接写入固定内存地址来实现。

请注意,在不禁用缓存的情况下,在RAM和缓存之间创建不匹配的另一种可能性是使用DMA控制器访问与MCU相同的内存。DMA控制器不使用缓存,因此如果DMA控制器写入缓存中的内存,应用程序将读取旧的缓存版本,而不是新写入的数据。然后,您的测试将是这样的:

  • 软件将一个值写入AXI SRAM。它现在在缓存中。
  • DMA操作将数据写入相同的地址。这不是“看”的核心。
  • 通常,在读取数据之前,必须执行缓存无效操作。为了你的测试你不会这么做的。
  • 现在从AXI SRAM读取变量。如果启用了缓存,您可能会得到旧值(由软件编写的值,而不是DMA编写的值)。
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59198934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档