历史上的今天

今天是:2024年08月26日(星期一)

正在发生

2019年08月26日 | 【STM32H7教程】第24章 STM32H7的Cache解读(非常重要)

发布者:科技驿站 来源: eefocus关键字:STM32H7  Cache解读 手机看文章 扫描二维码
随时随地手机看文章

24.1 初学者重要提示


学习本章节前,务必保证已经学习了第23章的MPU知识。


本章是半年的实践经验总结,非常具有参考价值,而且是入门STM32H7的必学章节。


Cache的熟练运用需要不断的经验积累。对于初学者来说,可能无法一下子理解所有知识点,但是一定要的花时间多读几遍,随着后面章节的不断运用,认识会不断的深入。


24.2 引出问题


当前芯片厂商出的M7内核芯片基本都做了一级Cache支持,Cache又分数据缓存D-Cache和指令缓冲I-Cache,STM32H7的数据缓存和指令缓存大小都是16KB。对于指令缓冲,用户不用管,这里主要说的是数据缓存D-Cache。以STM32H7为例,主频是400MHz,除了TCM和Cache以400MHz工作,其它AXI SRAM,SRAM1,SRAM2等都是以200MHz工作。数据缓存D-Cache就是解决CPU加速访问SRAM。


如果每次CPU要读写SRAM区的数据,都能够在Cache里面进行,自然是最好的,实现了200MHz到400MHz的飞跃,实际是做不到的,因为数据Cache只有16KB大小,总有用完的时候。


对于使能了Cache的SRAM区,要分读写两种情况考虑。


读操作:

如果CPU要读取的SRAM区数据在Cache中已经加载好,这就叫读命中(Cache hit),如果Cache里面没有怎么办,这就是所谓的读Cache Miss。


写操作:

如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域(专业词汇叫Cache Line,以32字节为单位),这就叫写命中(Cache hit),如果Cache里面没有开辟对应的区域怎么办,这就是所谓的写Cache Miss。


24.3 支持的Cache配置

(这个知识点在上一章节进行了详细说明,这里再简述下核心内容)


Cache的配置是通过MPU来设置的,通常只用到下几种方式。



其中的TEX是用来设置Cache策略的,C是Cache,B是缓冲用来配合Cache设置的,而S是共享,用来解决多总线或者多核访问时的同步问题。MPU配置的时候,最主要的也是配置这几个参数。


Cache支持的策略有如下四种:


有了这四种方式,就可以正式进入本章的主题,Cache的读写操作是如何工作的,下面分这四种情况做介绍。


24.4 四种Cache(MPU)配置的读写操作流程

24.4.1 配置Non-cacheable

这个最好理解,就是正常的读写操作,无Cache。


对应四种MPU配置如下:


  TEX = 000  C=0  B=0  S=忽略此位,强制为共享

  TEX = 000  C=0  B=1  S=忽略此位,强制为共享

  TEX = 001  C=0  B=0  S=0

  TEX = 001  C=0  B=0  S=1

24.4.2 配置Write through,read allocate,no write allocate

注意,M7内核只要开启了Cache,read allocate就是开启的。


  使能了此配置的SRAM缓冲区写操作

    如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,那么会同时写到Cache里面和SRAM里面;如果没有,就用到配置no write allocate了,意思就是CPU会直接往SRAM里面写数据,而不再需要在Cache里面开辟空间了。


    在写Cache命中的情况下,这个方式的优点是Cache和SRAM的数据同步更新了,没有多总线访问造成的数据一致性问题。缺点也明显,Cache在写操作上无法有效发挥性能。


  使能了此配置的SRAM缓冲区读操作

    如果CPU要读取的SRAM区数据在Cache中已经加载好,就可以直接从Cache里面读取。如果没有,就用到配置read allocate了,意思就是在Cache里面开辟区域,将SRAM区数据加载进来,后续的操作,CPU可以直接从Cache里面读取,从而时间加速。


    安全隐患,如果Cache命中的情况下,DMA写操作也更新了SRAM区的数据,CPU直接从Cache里面读取的数据就是错误的。


  对应的两种MPU配置如下:

TEX = 000 C=1 B=0  S=1


TEX = 000 C=1 B=0  S=0


24.4.3 配置Write back,read allocate,no write allocate

注意,M7内核只要开启了Cache,read allocate就是开启的。


  使能了此配置的SRAM缓冲区写操作

    如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,那么会写到Cache里面,而不会立即更新SRAM;如果没有,就用到配置no write allocate了,意思就是CPU会直接往SRAM里面写数据,而不再需要在Cache里面开辟空间了。


    安全隐患,如果Cache命中的情况下,此时仅Cache更新了,而SRAM没有更新,那么DMA直接从SRAM里面读出来的就是错误的。


  使能了此配置的SRAM缓冲区读操作

   如果CPU要读取的SRAM区数据在Cache中已经加载好,就可以直接从Cache里面读取。如果没有,就用到配置read allocate了,意思就是在Cache里面开辟区域,将SRAM区数据加载进来,后续的操作,CPU可以直接从Cache里面读取,从而时间加速。


    安全隐患,如果Cache命中的情况下,DMA写操作也更新了SRAM区的数据,CPU直接从Cache里面读取的数据就是错误的。


  对应两种MPU配置如下:

TEX = 000 C=1 B=1  S=1


TEX = 000 C=1 B=1  S=0


24.4.4 配置Write back,read allocate,write allocate

注意,M7内核只要开启了Cache,read allocate就是开启的。


  使能了此配置的SRAM缓冲区写操作

    如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,那么会写到Cache里面,而不会立即更新SRAM;如果没有,就用到配置write allocate了,意思就是CPU写到往SRAM里面的数据,会同步在Cache里面开辟一个空间将SRAM中写入的数据加载进来,如果此时立即读此SRAM区,那么就会有很大的速度优势。


    安全隐患,如果Cache命中的情况下,此时仅Cache更新了,而SRAM没有更新,那么DMA直接从SRAM里面读出来的就是错误的。


  使能了此配置的SRAM缓冲区读操作

    如果CPU要读取的SRAM区数据在Cache中已经加载好,就可以直接从Cache里面读取。如果没有,就用到配置read allocate了,意思就是在Cache里面开辟区域,将SRAM区数据加载进来,后续的操作,CPU可以直接从Cache里面读取,从而时间加速。


    安全隐患,如果Cache命中的情况下,DMA写操作也更新了SRAM区的数据,CPU直接从Cache里面读取的数据就是错误的。


    这个配置被誉为可以最大程度发挥Cache性能,不过具体应用仍需具体分析。


  对应两种MPU配置如下:

TEX = 001 C=1 B=1  S=1


TEX = 001 C=1 B=1  S=0


24.4.5 共享配置是个隐形的大坑

STM32H7编程手册对其的描述是多核共享。

而H7的应用笔记对齐的描述是开启共享基本等同于关闭Cache。

实际测试下面四种开Cache的情况,开关共享对缓冲区的大批量数据的读操作影响很大,基本差出两倍,而写操作基本没有影响,也许这就是所谓的多总线同步读造成的。另外共享开关仅对开启了Cache的情况下有影响,而对于关闭了Cache的情况是没有影响的,开不开没关系。


24.4.6 总结这几种方式的几个关键知识点

Cortex-M7内核的L1 Cache由多行内存区组成,每行有32字节,每行都配有一个地址标签。数据缓冲DCache是每4行为一组,称为4-way set associative。而指令缓冲区ICache是2行为一组,这样节省地址标签,不用每个行都标记一个地址。

对于读操作,只有在第1次访问指定地址时才会加载到Cache,而写操作的话,可以直接写到内存中(write-through模式)或者放到Cache里面,后面再写入(write-back模式)。

如果采用的是Write back,Cache line会被标为dirty,等到此行被evicted时,才会执行实际的写操作,将Cache Line里面的数据写入到相应的存储区。

Cache命中是访问的地址落在了给定的Cache Line里面,所以硬件需要做少量的地址比较工作,以检查此地址是否被缓存。如果命中了,将用于缓存读操作或者写操作。如果没有命中,则分配和标记新行,填充新的读写操作。如果所有行都分配完毕了,Cache控制器将支持eviction操作。根据Cache Line替换算法,一行将被清除Clean,无效化Invalid或者重新配置。数据缓存和指令缓存是采用的伪随机替换算法。

Cache支持的4种基本操作,使能,禁止,清空和无效化。Clean清空操作是将Cache Line中标记为dirty的数据写入到内存里面,而无效化Invalid是将Cache Line标记为无效,即删除操作。

24.5 面对繁冗复杂的Cache配置,推荐方式和安全隐患解决办法

  推荐使用128KB的TCM作为主RAM区,其它的专门用于大缓冲和DMA操作等。

  Cache问题主要是CPU和DMA都操作这个缓冲区时容易出现,使用时要注意。

  Cache配置的选择,优先考虑的是WB,然后是WT和关闭Cache,其中WB和WT的使用中可以配合ARM提供的函数解决上面说到的隐患问题(见本章24.6小节)。但不是万能的,在不起作用的时候,直接暴力选择函数SCB_CleanInvlaidateDCache解决。关于这个问题,在分别配置以太网MAC的描述符缓冲区,发送缓冲区和接收缓冲区时尤其突出。

24.6 Cache的相关函数

CMSIS软件包的core_cm7.h文件为Cache的配置提供了11个函数:


  SCB_EnableICache

  SCB_DisableICache

  SCB_InvalidateICache

  SCB_EnableDCache

  SCB_DisableDCache

  SCB_InvalidateDCache

  SCB_CleanDCache

  SCB_CleanInvalidateDCache

  SCB_InvalidateDCache_by_Addr

  SCB_CleanDCache_by_Addr

  SCB_CleanInvalidateDCache_by_Addr

 

下面将这几个函数依次做个讲解。其中前三个函数是指令Cache,比较容易掌握。重点是后面几个数据Cache函数。由于函数SCB_CleanInvalidateDCache,SCB_CleanDCache和SCB_InvalidateDCache是对整个Cache的操作,所以比最后的三个函数SCB_InvalidateDCache_by_Addr,SCB_CleanDCache_by_Addr和SCB_CleanInvalidateDCache_by_Addr要耗时,当然,如果用户操作的存储器超过了数据Cache的大小,即16KB,那么就跟前三个函数没有区别了。


24.6.1 函数SCB_EnableICache

函数原型:


__STATIC_INLINE void SCB_EnableICache (void)

{

  #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

    __DSB();

    __ISB();

    SCB->ICIALLU = 0UL;                     /* invalidate I-Cache */

    __DSB();

    __ISB();

    SCB->CCR |=  (uint32_t)SCB_CCR_IC_Msk;  /* enable I-Cache */

    __DSB();

    __ISB();

  #endif

}

函数描述:


此函数用于使能指令Cache,系统上电后优先初始化即可。


注意事项:


  __STATIC_INLINE:

表示内联函数,这种类型函数的作用就是将函数直接嵌入到调用此函数的代码中,从而降低调用此函数所占用的时间。


  __DMB指令:

Data Memory Barrier(数据存储器隔离),DMB 指令保证所有在它前面的存储器访问操作都执行完毕后,才提交在它后面的存储器访问操作。


  __DSB指令:

Data Synchronization Barrier(数据同步隔离),比DMB严格,当所有在它前面的存储器访问操作都执行完毕后,才执行在它后面的指令。


  __ISB指令:

Instruction Synchronization Barrier(指令同步隔离),它会清洗流水线,以保证所有它前面的指令都执行完毕之后,才执行它后面的指令。


24.6.2 函数SCB_DisableICache

函数原型:


__STATIC_INLINE void SCB_DisableICache (void)

{

  #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

    __DSB();

    __ISB();

    SCB->CCR &= ~(uint32_t)SCB_CCR_IC_Msk;  /* disable I-Cache */

    SCB->ICIALLU = 0UL;                     /* invalidate I-Cache */

    __DSB();

    __ISB();

  #endif

}

函数描述:


此函数用于禁止指令Cache。


注意事项:


__STATIC_INLINE,__DMB,__DSB和__ISB的作用看本章24.6.1小节的说明。


24.6.3 函数SCB_InvalidateICache

函数原型:


__STATIC_INLINE void SCB_InvalidateICache (void)

{

  #if defined (__ICACHE_PRESENT) && (__ICACHE_PRESENT == 1U)

    __DSB();

    __ISB();

    SCB->ICIALLU = 0UL;

    __DSB();

    __ISB();

  #endif

}

函数描述:


此函数用于将指令Cache无效化,无效化的意思是将Cache Line标记为无效,等同于删除操作。这样Cache空间就都腾出来了,可以加载新的指令。


注意事项:


__STATIC_INLINE,__DMB,__DSB和__ISB的作用看本章24.6.1小节的说明。


24.6.4 函数SCB_EnableDCache

函数原型:


__STATIC_INLINE void SCB_EnableDCache (void)

{

  #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)

    uint32_t ccsidr;

    uint32_t sets;

    uint32_t ways;

 

    SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/  /* Level 1 data cache */

    __DSB();

 

    ccsidr = SCB->CCSIDR;

 

                                            /* invalidate D-Cache */

    sets = (uint32_t)(CCSIDR_SETS(ccsidr));

    do {

      ways = (uint32_t)(CCSIDR_WAYS(ccsidr));

      do {

        SCB->DCISW = (((sets << SCB_DCISW_SET_Pos) & SCB_DCISW_SET_Msk) |

                      ((ways << SCB_DCISW_WAY_Pos) & SCB_DCISW_WAY_Msk)  );

        #if defined ( __CC_ARM )

          __schedule_barrier();

        #endif

      } while (ways-- != 0U);

    } while(sets-- != 0U);

    __DSB();

 

    SCB->CCR |=  (uint32_t)SCB_CCR_DC_Msk;  /* enable D-Cache */

 

    __DSB();

    __ISB();

  #endif

}

函数描述:


此函数用于使能数据Cache,系统上电后优先初始化即可。


注意事项:


__STATIC_INLINE,__DMB,__DSB和__ISB的作用看本章24.6.1小节的说明。


24.6.5 函数SCB_DisableDCache

函数原型:


__STATIC_INLINE void SCB_DisableDCache (void)

{

  #if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)

    register uint32_t ccsidr;

    register uint32_t sets;

    register uint32_t ways;

 

    SCB->CSSELR = 0U; /*(0U << 1U) | 0U;*/  /* Level 1 data cache */

    __DSB();

 

    SCB->CCR &= ~(uint32_t)SCB_CCR_DC_Msk;  /* disable D-Cache */

    __DSB();

 

    ccsidr = SCB->CCSIDR;

 

                                            /* clean & invalidate D-Cache */

    sets = (uint32_t)(CCSIDR_SETS(ccsidr));

    do {

      ways = (uint32_t)(CCSIDR_WAYS(ccsidr));

      do {

        SCB->DCCISW = (((sets << SCB_DCCISW_SET_Pos) & SCB_DCCISW_SET_Msk) |

                       ((ways << SCB_DCCISW_WAY_Pos) & SCB_DCCISW_WAY_Msk)  );

        #if defined ( __CC_ARM )

          __schedule_barrier();

        #endif

      } while (ways-- != 0U);

    } while(sets-- != 0U);

 

    __DSB();

    __ISB();

  #endif

}

函数描述:


此函数用于禁止数据Cache。


注意事项:


__STATIC_INLINE,__DMB,__DSB和__ISB的作用看本章24.6.1小节的说明


24.6.6 函数SCB_InvalidateDCache

[1] [2]
关键字:STM32H7  Cache解读 引用地址:【STM32H7教程】第24章 STM32H7的Cache解读(非常重要)

上一篇:【STM32H7教程】第25章 STM32H7的TCM,SRAM等五块内存基础知识
下一篇:【STM32H7教程】第23章 STM32H7的MPU内存保护单元(重要)

推荐阅读

使用BRR和BSRR寄存器可以方便地快速地实现对端口某些特定位的操作,而不影响其它位的状态。比如希望快速地对GPIOE的位7进行翻转,则可以:GPIOE->BSRR = 0x80; // 置&#39;1&#39;GPIOE->BRR = 0x80; // 置&#39;0&#39;如果使用常规&#39;读-改-写&#39;的方法:GPIOE->ODR = GPIOE->ODR | 0x80; // 置&#39;1&#39;GPIOE->ODR = GPIOE->ODR & ...
Strategy Analytics消费者感官分析(CSA)团队通过研究两个最受欢迎的音乐流媒体服务Spotify和Pandora的消费者评分和评论发现,尽管总的来说消费者对Spotify比Pandora更满意,但就客户服务的提供来说,Spotify 的用户比Pandora的用户挫败感高出三倍。 报告的关键发现包括: 通过对美国超过2100条评论的分析发现,总体而言, 用户对Spotify的评分为4.07...
  针对工业4.0的工厂自动化系统通常主要包括三个层级的设备,用于驱动实时通信和控制:  1. 在现场层级,I/O模块、制动器和驱动器负责工厂内的物理运作;  2. 在控制层级,可编程逻辑控制器(PLC)或计算机数控(CNC)负责从现场级搜集信息并向现场发出指令;  3. 在操作员层级,人机界面(HMI)设备与操作员交互通信,同时...
在英特尔超级计算机交期延迟几个月后,美国能源部(DOE)旗下阿贡国家实验室(ANL)正在接近与英伟达和AMD达成供货协议。据路透社报道援引知情人士透露,英伟达和AMD将向ANL供应双方联合推出的超级计算机“北极星”(Polaris),但其不会取代英特尔供应的 “极光”(Aurora),后者于2019年推出时被认为有望成为美国速度最快的计算机,能够进行一百万亿次(exa...

史海拾趣

问答坊 | AI 解惑

(wince)长按屏幕,出现圆圈不完整

长按屏幕后出现圆圈,但是显示不完整,怎么修改代码                        case WM_LBUTTONDOWN:             &nb ...…

查看全部问答∨

ARM32位单片机 LM3S系列有没可以代替_nop_()的C51指令的指令?

    开发环境为IAR。     ARM32位单片机 LM3S系列没有_nop_()这条C51指令,我想问下可以用啥代替,精确延时一个机器周期。…

查看全部问答∨

51单片机实现PWM线性调频脉冲信号提问?

我用的是AT89C52 想做到0.5KHZ~20KHZ之间精确线性调频脉冲信号,怎么也实现不了,以下是代码,请教一下高手意见! /***************************************************************************** * 程序名称:        ...…

查看全部问答∨

国内白光发光二极管发光粉部分专利信息

replyreload += \',\' + 749676;Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答∨

详述LED行业七大常用测试方法

详述LED行业七大常用测试方法如下 1,高温高压及其冲击: 针对对象:(含 Driver的成品灯具) 参照标准:行业经验 测试方法: 1,将5款LED灯具放置在一个室温为60℃的房间; 2,通过调压器将LED灯具的输入电压调为最大额定输入电压的1.1倍; ...…

查看全部问答∨

请教急急:IAR.for.MSP430

请教:购买注册同样版本的IAR.for.MSP430编译工具,是EW430-KS-web-4212好(106M),还是EW430-EV-web-4212好(88M)。敬候您的指点!…

查看全部问答∨

DM6446开发攻略:UBL移植 (转帖)

    UBL的程序设计,相对UBOOT、KERNEL、ROOTFS、设备驱动、DSP开发来说,还是比较简单。我们先从DAVINCI的启动说起,了解UBL在DAVIN系统中的位置和作用。对于固件程序烧写在NAND FLASH 的Davinci dm644x嵌入式系统, 上电启动的过 ...…

查看全部问答∨

MT47H128M16HG 数据手册 谁有啊

MT47H128M16HG 的数据手册谁有啊 ,上传一个呗,急用…

查看全部问答∨

怎样生成bin文件

请问下我用IAR编译环境调试好的代码,怎样转成.bin文件?…

查看全部问答∨

TI网站上发现的hercules全部27个应用

Showing 27 of 27 results      TitleAbstractTypeSize (KB)DateViews Reduction of Power Consumption for RM48L950 (Rev. A) Read Abstract PDF15630 Oct 2012 371 Initialization of the TMS570LS043x, 570LS033x ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved