你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【实战经验】STM32F7 MPU Cache浅析  

[复制链接]
zero99 发布时间:2017-3-3 14:54
前言2 b5 c$ s- Q3 B( l7 j4 Q
本文会从结构,原理以及应用方面对MPU和Cache进行分析,主要目的是希望读者对Cache有基本的了解,在具体的实际应用中,使用带有一级cache的MCU时,避免常见的错误。
0 B" |, O8 v3 p+ P
( Y& D( Q2 s$ |. S: _Cache介绍
5 z1 l$ `' B2 G5 k6 X5 u, ?; n5 x, O: }. m* V
Cache及其原理
' j) o0 Z, ^( |" @& nCache,高速缓存,一般指的是L1 cache,即和Core紧耦合的,从STM32F7系列开始,
  C+ `2 Q  z! n4 E3 z# z基于ARM cortex-M7内核,增加了对L1 Cache的支持。8 N3 ~0 f, c2 G, H/ U- q5 y( V
21.jpg & ~5 r" T, k( K4 p4 P* w
从这张图片可以看出来,无论是指令Cache(I-cache)还是数据Cache(D-cache),一旦使能之后,就分别与Core的prefetch unit(I-cache)和load-store unit(D-cache)相连,以D-cache为例,因为
8 {! D$ l* o: d* \直接与LSU相连,访问速度会比直接访问SRAM或外部RAM快很多,只要保证cache有足够高的命中率(由cache策略保证),尽量少的cache miss,读/写的速度会有比较大的提高。/ |. C: x" H/ t: V. ]

  \+ o' z9 e" |( G# Z, r结构及策略
2 u- b; S  @! M+ e+ h同样这里以D-cache为例,看一下D-cache的构成:$ _6 W0 N9 R# ?5 O; |- |
22.jpg & N. \+ I4 v$ _2 \4 k$ n
包括Address和cache-line,Address表明其地址,对应一条包含32bytes的cache-line:2 h2 \! X- u6 ?: n- C
读数据时,当地址命中时即cache-hit,便可以直接从cache line中取出相应的数据,反之,当遍历了address都没有找到,就会产生cache-miss,这时便会从实际的内存单元(如SRAM)中取出相应的数据,并更新到某一条cache-line中并修改相应的cache-line信息;* f2 V0 W5 b& J7 r" P' U+ O) o* Z
写数据时,就有点不同了,包括write-through策略和write-back策略,当使用write-though策略时,更新cache-line的同时,同样会更新其对应的实际物理地址的区域,当采用write-back策略时,更cache-line的同时,并不是马上去更新其对应的实际物理地址的内容,而是在其认为合适或者所有的cache-line都dirty的时候才会去更新,当然,也可以通过软件让其强制更新,即clean的动作,这一块会在后面的cache一致性问题上也会有体现;" ]3 L7 H$ i1 ?
同样,对于为什么将cache拆分为2-way或是4-way,这和cache自身的策略如查找算法等相关,由于本文侧重讨论cache的应用相关问题,所以关于cache本身的策略这里不再详述。/ D) f  h( v2 k! v( `/ y
7 X) o1 `5 G, E* Z
Cache及MPU属性
) J6 X* d1 D( N# b4 Z8 u这里需要注意的是,cache一般是配合MPU(memory protection unit)一起使用的,首先需要通过MPU配置相应memory的属性(normal, strongly-ordered, device, XN etc.),如下表所示:' y9 c4 t! x. D9 ^8 T+ R
23.jpg ( ?, D" N" q, {; C$ k! L" k% `3 X
选取几个有特点的作为示例:
( o; s- [6 U+ U; p( V0~0x1FFF_FFFF: flash空间,属性为normal,cache的属性为Write-through,即更新cache的同时,将数据同时写入相应的物理地址空间
. ?. g9 n8 G, v! P0x2000_0000~0x3FFF_FFFF: SRAM空间,属性为normal,cache的属性为write-back,即仅更新cache,在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间
% r: h. d( M! w1 q, O0 n0x4000_0000~0x5FFFF_FFFF: 芯片内部的外设空间,属性为device,这一版是外设寄存器所处的位置,对其读写的过程中不会经过cache
! ^9 t- I6 \- o: j) l
; i5 W. J6 }3 n3 \$ ?XN的意思是Execute-Never,其含义为如果相应的地址空间是XN,是绝不允许执行代码的。6 m- I! S0 C; i8 O! {
2 l% A- m. s- @$ a# X6 ^
Cache相关函数及作用
( W- ~9 @2 j9 w5 @这里以core_cm7.h里对cache封装的函数为例
  b) n' @0 x7 [(C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\arm\CMSIS\Include)
! O' q+ c- \1 F2 f' q" |4 i, M$ zSCB_EnableDCache1 W& `4 [- u& {" f$ H
## 使能D-cache" S' ?* G, r" S3 v* L

: X) K2 P8 w9 {SCB_DisableDCache
# |: w- j9 e( t6 a$ \  U  i## 禁用D-cache

# ?+ F- F0 |5 _/ Y8 g/ G& ^& c! |' e7 h* ^
SCB_EnableICache
( [( Q3 d" m7 \% F$ E## 使能I-cache
' H' W. e0 n+ c
% R8 ~+ W, J& USCB_DisableICache
& }! B  _( l) g% Y. }5 n6 l: M## 禁用I-cache
9 V. Z/ X9 N) s0 [% K! J) v  i; v  J$ _$ x9 i
SCB_CleanDCache ' u6 T/ B$ T8 }
## Clean所有的cache-line,即将dirty的cache-line全部写到cache line对应的真实的物理地址中 所谓的drity属性,即写操作时,更新了相应的cache-line,但是没有更新到真实的物理地址, 而这个clean的动作,就是将cache中的内容更新到真实的物理地址中, i7 l" c# p/ g. ?# x
9 V8 q; G0 E  c+ e: J' }; W5 s
SCB_CleanDCache_by_Addr
: ^9 m  O3 Y9 O% ^! R0 H## 根据地址信息clean其对应的cache-line
+ x# Q, a, E, l6 O6 `+ B% {0 P: P( [
$ v: s7 K8 ~( e! k4 [+ E& r
SCB_InvalidateDCache $ i* t' B& ?: c% k' L4 P' a
## 无效D-cache,D-cache被invalidate之后,当有Host(如core,DMA等)读取数据时,会忽略相应的cache-line中的内容(因为被validate了),从真实的物理地址中去获取相应的数据
; M; u$ }9 F1 O) T; a+ n$ _2 w" v" N! ?+ q; n( P! S
SCB_InvalidateDCache_by_Addr
4 b5 L4 O2 s5 X- [## 根据地址信息无效其对应的cache-line

- X. t5 x6 m: T
  E& u7 Y7 ?0 g/ ^$ t, l3 TCache一致性问题6 H  j% C# u* G; c3 Q
所谓的Cache一致性问题,主要指的是由于D-cache存在时,表现在有多个Host(典型的如MCU的core,DMA等)访问同一块内存时,由于数据会缓存在D-cache中而没有更新实际的物理内存。' R4 ~  u0 L3 z" p7 r& b6 \# I0 S
第一种情况是当有写物理内存的指令时,core会先去更新相应的cache-line(Write-back策略),在没有clean的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的Host(如DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和D-cache中的不一致),这就是所谓的cache一致性的问题!
+ [, b0 W, x$ |# N8 {% g: Z
$ a9 Z" J  C% a* p: L0 ?第二种情况是DMA更新了某段物理内存(DMA和cache直接没有直接通道),而这个时候Core再读取这段内存的时候,由于相对应地址的cache-line没有被invalidate,导致Core读到的是cache-line中的数据,而非被DMA更新过的实际物理内存的数据,下面这张图比较清晰的展示了上述两个过程:/ N. a. {6 O: M0 B4 d
 ●第一种情况
6 z) J6 t2 K  k; E
24.jpg * [* ^+ I4 ~( Y% w1 ~' I6 a
( ^- F# G, F4 h: Q7 x$ C
 ●第二种情况
, l4 U9 i$ @3 N- l$ n; t
25.jpg $ t$ E6 |6 K) z, W
下面以一个实例来分析cache一致性问题,展示的是上面的第一种情况,如下图所示:5 X% [$ K& z& Z" e
26.jpg
4 Q" H: j% d* L; ]1 M' ^" d* @先看一下这个例程数据的传输流程和路径:
9 B$ a1 G2 ?- Z& N3 F# Z7 ^● SRAM1_Buffer先全部写入0x55/ M6 H! H7 u: h+ b4 B
●Core将Flash中的Const_Buffer写入SRAM1_Buffer(这里会先经过d-cache)
7 l3 P' P& ^: Y8 F( |8 @● 配置DMA,将SRAM1_Buffer中的数据通过DMA写入另一段内存DTCM_Buffer
/ \) p: ?* A1 t3 {● 比较DTCM_Buffer中的数据和Flash中的Const_Buffer数据,看是否一致. v% }$ @  }4 {+ J3 Q( O' L

+ v8 k1 F, [0 w! p7 r; P! ^代码示例如下: 
; l! Q0 ~7 S( d5 D●MPU对memory的配置 - - - - step1$ H! `2 u' Z0 ]) Z( W
27.jpg
# k* E4 e! t* s, O6 c重点介绍一下高亮部分的配置:
( v/ X  ]2 t0 ?( Z( r● BaseAddress为要配置的存储空间的起始地址;
5 q7 E# ~: F9 `) R; d$ Y● Size为要配置的存储空间的大小
# n7 F& Y  Q* l- {● IsCacheable表明这段存储空间是否可以cache7 n% y% f: U2 c, S1 c
● IsBufferable表明使能cache之后,策略是write-through还是write-back(bufferable)
) p3 X  r. Z; x4 G这里需要特别注意的1点:配置的BaseAddress需要被Size整除,以上述配置为例,即0x20010000除以256K需要是整数!
0 f" V. Y! r7 N+ ~' F: Q& k6 ~0 g
: o3 P! M2 A$ ?: c$ d' H) P( H0 b● 使能Cache - - - - step2
( ]+ Q2 \2 w9 w/ V% Q4 [! ]" a
28.png
$ D' x- W, _0 {* n8 V8 o4 X& @/ f% T& t: L% m  B
●  初始化SRAM1_Buffer为0x55 - - - - step3
+ |! ^- {+ i! e3 E; m7 l   ● Copy Flash中的Const_Buffer到SRAM1_Buffer - - - - step4
/ @* L6 [, b8 {! P2 L& R   ● 配置DMA,将SRAM1_Buffer写入DTCM_Buffer - - - - step5 ; C# f0 j7 H1 }" A
   ● 比较DTCM_Buffer和Const_Buffer,看是否一致 - - - - step6
& e! V3 O# X8 d0 b) {  U从结果上看,最后一步比较的结果并不一致,原因比较简单,由于设定的WB策略,所以在step4的时候,数据会暂存在D-cache当中,并没有更新到SRAM1_Buffer,所以当SRAM1_Buffer被DMA拷到DTCM_Buffer中的时候,有一部分可能还是初始值,导致最终的比较不一样,而解决的方法有以下几个:
; I7 I$ u. V% L# r9 |1. MPU配置的代码,将属性改为MPU_ACCESS_BUFFERABLE,即使用write-though策略
9 T& Z7 S. I/ y2 {" i2 ^2. 通过cache控制寄存器,将所有cacheable的空间全部强制write-though
9 X4 ^8 B4 S" M5 D& ?5 \& B* e
29.jpg
" H7 d$ q  K1 ]7 r1 _
001.png ' g/ R2 \) @) i, |) Q

" f% v1 P  W& E. X3. 将dirty cache-line更新到真实的物理地址中
8 p( [% d7 K6 B* n7 a6 c/ kstep5操作之前,先调用SCB_CleanDCacheSCB_CleanDCache_by_Addr将相应cache-line中的数据写入SRAM1_Buffer,就解决了这个问题!* L3 `- T5 W- Q: [  j$ e+ F; N) f

( J* n9 ]6 h7 |4 Z0 w1 r3 c这是最常用的方法,在实际的开发过程中,为了提高性能,一般都会使能cache,同时将其配置为WB策略,这就需要开发者在使用时特别小心!同样如之前的第二种情况,需要先调用SCB_InvalidateDCacheSCB_InvalidateDCache_by_Addr去Invalidate相应的cache-line,这样当core在读取时,会忽略D-cache中的内容,去真实的物理地址读取对应的数据!

* a0 F0 R$ @) J
2 W8 ~; G3 z" ]9 b9 ]- r
, n  A/ }( i* F7 n2 ]( Q

0 t$ F; H: h  e: [6 @文档下载; [. z3 B  H* C. t$ ?7 v2 b& U
- x4 y7 L( a$ o9 C# q; l
更多实战经验
  i2 ~8 S$ I' U% @$ s; N

评分

参与人数 1 ST金币 +10 收起 理由
MrJiu + 10 支持原理讲解!!!!

查看全部评分

1 收藏 11 评论19 发布时间:2017-3-3 14:54

举报

19个回答
xzrsh 回答时间:2019-8-16 12:23:32
这个是有问题的。 Cacheable = 1 且 Bufferable = 1 是 WBWA。6 c$ a$ y; I  q* a7 W3 x
- @+ P7 H, P: O" E" a6 X
另外,执行 SCB_InvalidateDCache或SCB_InvalidateDCache_by_Addr 的时候会调用“__DSB();   __ISB();”这两个操作,即等待当前数据cache操作由指令完成,彻底打断了当前CPU的执行节奏(清空指令cache)。假如当前DMA从外设读取了10字节数据到SRAM中,在DMA中断里更新接收计数器为10(这个计数器操作是CPU完成的,将写入到cache中),如果中断后调用了InvalidateDCache,会导致计数器的写操作无效,因为写cache操作已经完成了,其策略是WB,它写入的是Cache,并没有写入到物理存储器中。当下次CPU要读取这个计数器值时,仍从Cache中读取,发现这个地址已经被Invalidate了,那么要从SRAM中读,结果是0。
Dandjinh 回答时间:2017-3-13 10:21:50
1. MPU配置的代码,将属性改为MPU_ACCESS_BUFFERABLE,即使用write-though策略
这里确定是BUFFERABLE是write-through?我怎么觉得是write-back呢?
zero99 回答时间:2017-3-7 15:40:18
donatello1996 发表于 2017-3-4 11:414 z2 x" [- G; h: r& Z! ]6 d
学习了,支持小破!
/ q' z8 x3 Y9 C: L# x' ?
野火_firege 回答时间:2017-3-3 14:59:01
学习了
zero99 回答时间:2017-3-3 15:05:23
野火_firege 发表于 2017-3-3 14:59
0 z/ k6 L' Y2 v  ?+ z9 q- v7 Y学习了

9 w) O' {6 C. i+ o9 d* ~- I火哥好
野火_firege 回答时间:2017-3-3 15:53:36
zero99 发表于 2017-3-3 15:057 y2 l$ D1 c( r7 U. N! V
火哥好

+ Q7 ?4 A* D; j* z9 V. F  L/ }管理员好
Paderboy 回答时间:2017-3-3 16:07:57
学习来了。。。
Stm32McuLover 回答时间:2017-3-3 17:52:19

3 N' v1 O" c1 N! S5 |& C学习了
zoomdy 回答时间:2017-3-3 21:12:49
收藏,学习再学习
斜阳 回答时间:2017-3-4 08:48:55
学习学习
epochal 回答时间:2017-3-4 09:24:23
学学!
五哥1 回答时间:2017-3-4 09:38:17
这让人想起inter芯片的发展历程
donatello1996 回答时间:2017-3-4 11:41:28
学习了,支持小破!
zbber 回答时间:2017-3-4 22:04:28
学习学习,感恩无私的分享与奉献 ; b: s  v2 L  a1 C
jcx0324 回答时间:2017-3-6 08:59:13
好文章,学习了
ddllxxrr 回答时间:2017-3-6 09:15:29
写地不错,学习了
lorosir 回答时间:2017-3-6 09:56:34
收藏起来,将来用
12下一页
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版