STMCU小助手
发布时间:2021-12-18 17:42
|
一、Cache! a/ E2 Q- B: I: g0 t9 y- y ) `5 e5 }1 t; Y0 ^& v 1、介绍8 T* E- J# j$ _( D# w1 Y6 \ Cache又分数据缓存D-Cache和指令缓冲I-Cache,STM32H7的数据缓存和指令缓存大小都是16KB。STM32H7主频是400MHz,除了TCM和Cache以400MHz工作,其它AXI SRAM,SRAM1,SRAM2等都是以200MHz工作。数据缓存D-Cache就是解决CPU加速访问SRAM。 如果每次CPU要读写SRAM区的数据,都能够在Cache里面进行,自然是最好的,实现了200MHz到400MHz的飞跃,实际是做不到的,因为数据Cache只有16KB大小,总有用完的时候。 - N, ]) { w3 ]" ?& h' m' Q6 c 2、操作,分为读操作和写操作 读操作: 如果CPU要读取的SRAM区数据在Cache中已经加载好,这就叫读命中(Cache hit),如果Cache里面没有怎么办,这就是所谓的读Cache Miss。 写操作: 如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域(专业词汇叫Cache Line,以32字节为单位),这就叫写命中(Cache hit),如果Cache里面没有开辟对应的区域怎么办,这就是所谓的写Cache Miss。 3、H7支持的Cache策略,共4种! @9 \7 a! Q/ ?0 m4 l2 Q- W# g4 v! _0 v 8 g& B1 y( n5 Q) q; Q1 X, C
3 Q7 t2 p' [$ N7 Z7 @8 v <回写:如果Cache中有,写数据只写到Cache,不写到RAM。>' s4 ?( H- ~/ V7 g <透写:如果Cache中有,写数据也要同时写到Cache和RAM。>- k0 f& `9 R* c, z. e* ^6 l 6 a% k/ a* l( O* N8 x& F <write allocate:写数据时,如果Cache中没有,那么就要在Cache中开辟一个空间,把数据写入Cache,同时把RAM中的相邻数据加载进来填充Cache。>& X1 |( d. X3 C/ _# { <no write allocate:写数据时,如果Cache中没有,那么把数据直接写入RAM。> <read allocate:读数据时,如果Cache中没有,那么就要在Cache中开辟一个空间,把数据从RAM中加载进来,后续的读操作,就可以直接从Cache中读取了。> <no read allocate:读数据时,如果Cache中没有,那么直接从RAM中读。>" W2 H) _+ ?2 q6 B8 R0 k 4、风险4 @% G a$ N" l# q- {* o " @! E& P1 s: g6 k4 K8 @- t. ^
" H1 h0 R: N5 b" h 从上面的图就看出来使用Cache的风险,因为DMA是直接与SRAM交换数据的,而CPU与SRAM之间隔了一个Cache,如果DMA更新了某个数据到SRAM,CPU要去访问,而恰好Cache中有,那么CPU就不会去SRAM中拿,就会拿到Cache中已经过时的数据。因此使用了DMA的内存区要配置为无Cache或者拿数据前清一次Cache。 5、相关函数 SCB_EnableICache(void) :用于使能指令Cache,系统上电后优先初始化即可。2 h% D% ~4 d$ ?# a$ d8 ~ SCB_DisableICache(void) :用于禁止指令Cache。 SCB_InvalidateICache(void) :用于将指令Cache无效化,无效化的意思是将Cache Line标记为无效,等同于删除操作。这样Cache空间就都腾出来了,可以加载新的指令。 - V" n7 r; \* e7 I SCB_EnableDCache(void) :用于使能数据Cache,系统上电后优先初始化即可。1 o4 L% g" I' `2 \% J* z6 T2 ~ SCB_DisableDCache(void) :用于禁止数据Cache。' D8 k/ @& ?4 v7 U& j3 A ( J4 S, N& c/ L4 J# V- @& ]4 X! G F SCB_InvalidateDCache(void) :用于将数据Cache无效化,无效化的意思是将Cache Line标记为无效,等同于删除操作。这样Cache空间就都腾出来了,可以加载新的数据。 SCB_CleanDCache(void):用于将数据Cache清除,清除的意思是将Cache Line中标记为dirty的数据写入到相应的存储区。, Z1 |0 O# ]* t6 ]# R SCB_CleanInvalidateDCache(void) :此函数是前面两个函数SCB_InvalidateDCache和SCB_CleanDCache的二合一。将Cache Line中标记为dirty的数据写入到相应的存储区后,再将Cache Line标记为无效,表示删除。这样Cache空间就都腾出来了,可以加载新的数据。 SCB_InvalidateDCache_by_Addr(uint32_t *addr,int32_t dsize):可以指定地址和存储区大小,地址要32字节对齐,大小要是32字节的整数倍。用于将数据Cache无效化,无效化的意思是将Cache Line标记为无效,等同于删除操作。这样Cache空间就都腾出来了,可以加载新的数据。$ I! v/ o: Y; a. r& p# G: F3 a 4 X1 K( Z. d7 n) w$ L SCB_CleanDCache_by_Addr(uint32_t *addr,int32_t dsize):可以指定地址和存储区大小,地址要32字节对齐,大小要是32字节的整数倍。用于将数据Cache清除,清除的意思是将Cache Line中标记为dirty的数据写入到相应的存储区。1 U- p* U1 N7 Y6 G ' N( p( o9 G$ n0 m; ]9 g SCB_CleanInvalidateDCache_by_Addr(uint32_t *addr,int32_t dsize):可以指定地址和存储区大小,地址要32字节对齐,大小要是32字节的整数倍。将Cache Line中标记为dirty的数据写入到相应的存储区后,再将Cache Line标记为无效,表示删除。这样Cache空间就都腾出来了,可以加载新的数据。 + d: |* o( B" r* ~. F" h 5 X% c/ u& b6 t% C- c* p7 B 二、MPU 1、作用 防止不受信任的应用程序访问受保护的内存区域; 防止用户应用程序破坏操作系统使用的数据;通过阻止任务访问其它任务的数据区;允许将内存区域定义为只读,以便保护重要数据;检测意外的内存访问。 简单的说就是内存保护、外设保护和代码访问保护。 2、MPU可以配置的三种内存类型5 {. P; F- F5 o- T% X h - |5 Q. A' t& l 1)、Normal memory9 b; ~9 r, Y2 X CPU以最高效的方式加载和存储字节、半字和字,对于这种内存区,CPU的加载或存储不一定要按照程序列出的顺序执行。 0 j) ^+ E; B6 s 2)、Device memory ! Y# {: e* e1 P( V( }2 e 对于这种类型的内存区,加载和存储要严格按照次序进行,这样是为了确保寄存器按照正确顺序设置。 3)、Strongly ordered memory, n) b+ }+ Q# A 程序完全按照代码顺序执行,CPU需要等待当前的加载/存储指令执行完毕后才执行下一条指令。这样会导致性能下降。 3、MPU的使用 4 P [6 U8 [( `3 q# J MPU可以配置保护16个内存区域(这16个内存域是独立配置的),每个区域最小要求256字节,每个区域还可以配置为8个子区域。由于子区域一般都相同大小,这样每个子区域的大小就是32字节,正好跟Cache的Cache Line大小一样。 ! A$ f; x$ Y1 }3 K" n 使用时把一段连续的内存区配置为一个MPU保护区域,然后再配置这个MPU保护区域的特性。比如128KB的DTCM、64KB的SRAM4、32MB的SDRAM。MPU保护区域的特性使用MPU_RASR寄存器来配置,描述如下:5 P k6 s' v" k u5 T
1)、XN:用于控制这个MPU保护区域能否执行程序代码。9 V% O, S' X# Z: w, ^% P3 ? G; _1 c! ~ O 2)、AP:用于控制这个MPU保护区域的特权级和非特权级的读写访问权限。
0 ^' t/ c f2 M 3)、TEX、C、B、S:H7支持4种Cache策略,这几位就是用来控制这个MPU保护区域使用哪一种。 2 y) _) c& G7 O
S位用于解决多总线或者多核访问的共享问题,一般不要开启。 4)、SRD:这个位用于控制内存区的子区域 ,使用的是bit[15:8],共计8个bit,一个bit控制一个子区域, 0表示使能此子区域, 1表示禁止。一般情况下,取值0x00,表示8个子区域都使能。 5)、SIZE:配置这个MPU保护区域的大小。% r) L0 x. `! U/ \$ I4 _9 Z% G) ` 三、HAL配置例程
四、其他; s1 ]3 W! e9 E1 T 值得一提的是,LTDC也是直接从RAM拿数据的,如果你使用了GUI(比如EMWIN),你的显示数据可能会暂存在Cache,而LTDC直接从RAM拿数据,就可能造成画面撕裂、重影、斑点之类的问题。解决方法是,把显存设置成透写。 从下面的图可以看到,Cache是在M7那个框里面的。而框外面的外设都可以直接与RAM交换数据,因此使用外设操作数据时都要考虑一下Cache的影响,不然异常可能难以预料。1 F3 U: W3 i9 l6 h- M9 x0 A1 b
- V: n' U! @1 r0 p) h P/ k0 I! q& s# y6 e |
【 逢7发帖赢大礼】1、利用CubeMX生成正点原子H7R7开发板的STM32CubeIDE工程
【STM32H735G-DK测评】ADC3+TIMER1+DMA 采样模拟信号
【STM32H735DK测评】Ethernet+lwip DHCP获取IP地址
STM32H743基于CubeMx5.0配置手册
【STM32H735G-DK测评】lvgl移植
【STM32H735G-DK 测评】STM32H735G-DK External Loder 编译和测试
【福利三:逢7发帖赢大礼】使用MPU6050模块、img_dsc、img_btn机制实现一些简单有趣的动画效果
【福利三:逢7发帖赢大礼】使用arc弧形拉条控件控制PWM舵机及使用SPI3接口操作NRF24L01模块进行无线通信
【福利三:逢7发帖赢大礼】调试nucleo-WBA65RI工程测试样板的一些心得
【福利三:逢7发帖赢大礼】lv_timer和BME680实现温度、湿度、气压数据读取
微信公众号
手机版