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

【实战经验】STM32F7 MPU Cache浅析  

[复制链接]
zero99 发布时间:2017-3-3 14:54
前言' T7 J( X2 L) z9 \
本文会从结构,原理以及应用方面对MPU和Cache进行分析,主要目的是希望读者对Cache有基本的了解,在具体的实际应用中,使用带有一级cache的MCU时,避免常见的错误。2 ^5 G, L$ h% ]9 w: w0 x* V
5 e) g# \; j8 M8 L  ~6 y; m
Cache介绍6 O! Y* G2 M- Y7 t& }1 X* Y
. b: \/ ?, H- Q
Cache及其原理
& Z' w6 Q) o1 G& NCache,高速缓存,一般指的是L1 cache,即和Core紧耦合的,从STM32F7系列开始,/ [5 m3 _  Z& S8 a; k# u0 W
基于ARM cortex-M7内核,增加了对L1 Cache的支持。* ~0 L, m- @% r& _- w) a4 T
21.jpg
- {3 V6 s) z% K, S0 H% B从这张图片可以看出来,无论是指令Cache(I-cache)还是数据Cache(D-cache),一旦使能之后,就分别与Core的prefetch unit(I-cache)和load-store unit(D-cache)相连,以D-cache为例,因为
& N7 b( k. }) L. k3 S直接与LSU相连,访问速度会比直接访问SRAM或外部RAM快很多,只要保证cache有足够高的命中率(由cache策略保证),尽量少的cache miss,读/写的速度会有比较大的提高。
) u$ }7 y/ ~" o7 P& R. O& P! a/ H) b5 v0 |; k5 I! g
结构及策略9 t7 f3 Z3 X3 T
同样这里以D-cache为例,看一下D-cache的构成:7 V" y3 e% |: S3 C$ Z+ }6 V
22.jpg
( t# A2 U4 D1 R6 S! q1 [包括Address和cache-line,Address表明其地址,对应一条包含32bytes的cache-line:. H% t: I7 |- K6 x
读数据时,当地址命中时即cache-hit,便可以直接从cache line中取出相应的数据,反之,当遍历了address都没有找到,就会产生cache-miss,这时便会从实际的内存单元(如SRAM)中取出相应的数据,并更新到某一条cache-line中并修改相应的cache-line信息;
0 F1 _1 J! p  U/ a: G8 I写数据时,就有点不同了,包括write-through策略和write-back策略,当使用write-though策略时,更新cache-line的同时,同样会更新其对应的实际物理地址的区域,当采用write-back策略时,更cache-line的同时,并不是马上去更新其对应的实际物理地址的内容,而是在其认为合适或者所有的cache-line都dirty的时候才会去更新,当然,也可以通过软件让其强制更新,即clean的动作,这一块会在后面的cache一致性问题上也会有体现;4 r$ ~  o0 b( |
同样,对于为什么将cache拆分为2-way或是4-way,这和cache自身的策略如查找算法等相关,由于本文侧重讨论cache的应用相关问题,所以关于cache本身的策略这里不再详述。3 {; j6 G0 A0 w8 d: n' K0 J  o

, ^; B  Y3 A+ U2 qCache及MPU属性. d6 W) O- n- i) ]
这里需要注意的是,cache一般是配合MPU(memory protection unit)一起使用的,首先需要通过MPU配置相应memory的属性(normal, strongly-ordered, device, XN etc.),如下表所示:/ a' x+ W8 Z5 ^$ n" A' h+ v$ f7 i% [
23.jpg
0 K9 K+ v9 |% N+ ?4 A+ a0 e/ U选取几个有特点的作为示例:
" c8 f- Y* @& J9 j$ k, q0~0x1FFF_FFFF: flash空间,属性为normal,cache的属性为Write-through,即更新cache的同时,将数据同时写入相应的物理地址空间. P" G& q5 Y$ `' T' Z3 `
0x2000_0000~0x3FFF_FFFF: SRAM空间,属性为normal,cache的属性为write-back,即仅更新cache,在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间; J6 g3 Y; w4 y' K+ z3 _- a3 h
0x4000_0000~0x5FFFF_FFFF: 芯片内部的外设空间,属性为device,这一版是外设寄存器所处的位置,对其读写的过程中不会经过cache
, {4 f3 e& y. c, V' [* O! r( M
1 N0 a4 l# d, A& Q% Z  ]XN的意思是Execute-Never,其含义为如果相应的地址空间是XN,是绝不允许执行代码的。" Z7 D6 F% u7 B2 Q1 W: M9 h  _

. v/ Z! E0 A, v7 ^Cache相关函数及作用
+ n( ^5 F% y+ w# `这里以core_cm7.h里对cache封装的函数为例  S" |4 j! I; N; g! D
(C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\arm\CMSIS\Include)
) p2 M/ f( L- J* m# c  [6 jSCB_EnableDCache1 E  O$ k" L: T, r4 W, t2 r6 `
## 使能D-cache
- h4 j  a9 ^3 a# ]
8 k* s& K0 n; |; j. uSCB_DisableDCache   F) s, e( Y- \& L5 ^
## 禁用D-cache

5 D4 }% P/ A6 Q; Z2 U! z! v  {+ `4 c1 D0 W& R- ?0 ?4 g
SCB_EnableICache4 G/ D3 P: P" P
## 使能I-cache- v2 }& Z- D9 b6 H+ [

1 h% o9 m/ V% P3 }# @SCB_DisableICache
. s2 @( e1 v# e7 z  N& i## 禁用I-cache
# A$ f2 X7 H8 `+ K6 y$ G2 n5 {1 a6 k; ^
SCB_CleanDCache
% o1 G' K0 y: E8 A/ z3 n5 Z## Clean所有的cache-line,即将dirty的cache-line全部写到cache line对应的真实的物理地址中 所谓的drity属性,即写操作时,更新了相应的cache-line,但是没有更新到真实的物理地址, 而这个clean的动作,就是将cache中的内容更新到真实的物理地址中* w" n" e$ f1 i2 u$ N# s+ \
9 {4 _% X) O" H! o, i) V4 y( k! x* {
SCB_CleanDCache_by_Addr 4 }  l3 l! ]1 Y, I* ?" Z6 D
## 根据地址信息clean其对应的cache-line

" \  y% `4 y$ E, j
: H2 p5 e: F0 j2 I0 t# l3 MSCB_InvalidateDCache
, {# o; e; |2 u; n. n0 I, e## 无效D-cache,D-cache被invalidate之后,当有Host(如core,DMA等)读取数据时,会忽略相应的cache-line中的内容(因为被validate了),从真实的物理地址中去获取相应的数据% ^, c( w1 U/ b) E7 {# N6 n% X0 [

& M2 n1 S( P9 \0 T  t$ e3 r& qSCB_InvalidateDCache_by_Addr
" }- J# k+ h1 X0 A## 根据地址信息无效其对应的cache-line
- A! u- R! g, N$ a4 N$ w: r' A- K

& K; z+ n, d5 \; q6 YCache一致性问题
" F2 i$ V* E0 ?+ j, J# B" X所谓的Cache一致性问题,主要指的是由于D-cache存在时,表现在有多个Host(典型的如MCU的core,DMA等)访问同一块内存时,由于数据会缓存在D-cache中而没有更新实际的物理内存。5 J/ m$ T, f( z1 u2 n4 O4 ?
第一种情况是当有写物理内存的指令时,core会先去更新相应的cache-line(Write-back策略),在没有clean的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的Host(如DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和D-cache中的不一致),这就是所谓的cache一致性的问题!
1 F) E2 Q7 g! E6 q6 K! W* h5 v' m7 t$ Q- u
第二种情况是DMA更新了某段物理内存(DMA和cache直接没有直接通道),而这个时候Core再读取这段内存的时候,由于相对应地址的cache-line没有被invalidate,导致Core读到的是cache-line中的数据,而非被DMA更新过的实际物理内存的数据,下面这张图比较清晰的展示了上述两个过程:
) P# [  u; R: G4 V: c/ o ●第一种情况
4 w5 N. c/ O; r6 q( j! b
24.jpg
, d& ~6 |1 ]! I5 ]3 G3 e, f" h! e( i7 E( n# |  Q% r- M
 ●第二种情况1 c, m* B9 G3 w/ j" F
25.jpg + Q4 y) {2 A4 E2 P) X: a
下面以一个实例来分析cache一致性问题,展示的是上面的第一种情况,如下图所示:
, A2 s8 f5 K5 D9 O0 Z4 I/ z/ M* W& V
26.jpg
: I5 W5 P# \3 Z  \1 c! x先看一下这个例程数据的传输流程和路径:
& O% K; L  D: p& F( y; g● SRAM1_Buffer先全部写入0x55: w4 t$ E: j2 r  {  @* Z$ U
●Core将Flash中的Const_Buffer写入SRAM1_Buffer(这里会先经过d-cache)
0 j- W. g, S- n● 配置DMA,将SRAM1_Buffer中的数据通过DMA写入另一段内存DTCM_Buffer8 W" T# Y7 o7 m% X* n
● 比较DTCM_Buffer中的数据和Flash中的Const_Buffer数据,看是否一致) f9 s  a1 O! T5 u* I5 k

3 N+ a: x7 F- m" ?  t- ?; W代码示例如下: 
& M  k! B$ ^! V0 i# \) U●MPU对memory的配置 - - - - step1& z+ c9 N( x$ @3 M" {
27.jpg
' l) q8 [4 ]9 I9 ]2 ^, E1 ~重点介绍一下高亮部分的配置:. Q: J* T$ P( E1 u
● BaseAddress为要配置的存储空间的起始地址;% C* E4 I) X* `) p" t$ F0 L+ Y* H% K  k( p
● Size为要配置的存储空间的大小
3 g( u& m2 N+ j& d) q9 q) t3 j● IsCacheable表明这段存储空间是否可以cache
6 l7 m6 R. W4 b  Q, b( V1 q$ x● IsBufferable表明使能cache之后,策略是write-through还是write-back(bufferable)
7 J6 Y' H/ T) Y' g这里需要特别注意的1点:配置的BaseAddress需要被Size整除,以上述配置为例,即0x20010000除以256K需要是整数!9 B" {; C& Z2 p. b% Z, L: F! M
8 W* @1 y: K+ b
● 使能Cache - - - - step2
# K! P  h/ W! Q$ C7 t+ T
28.png
( X; j1 u) i4 a" ^- H- J* v; W3 C9 c4 E" m
●  初始化SRAM1_Buffer为0x55 - - - - step3
- D1 `+ P/ W3 O# h6 \5 Q   ● Copy Flash中的Const_Buffer到SRAM1_Buffer - - - - step4
0 V& D: Z1 H8 c" ~+ w0 M  `% V   ● 配置DMA,将SRAM1_Buffer写入DTCM_Buffer - - - - step5
; H4 K$ D- D7 Y9 k9 I   ● 比较DTCM_Buffer和Const_Buffer,看是否一致 - - - - step6
( z: D  j6 ~1 @; b% E从结果上看,最后一步比较的结果并不一致,原因比较简单,由于设定的WB策略,所以在step4的时候,数据会暂存在D-cache当中,并没有更新到SRAM1_Buffer,所以当SRAM1_Buffer被DMA拷到DTCM_Buffer中的时候,有一部分可能还是初始值,导致最终的比较不一样,而解决的方法有以下几个:
  M  s& C9 P% `1. MPU配置的代码,将属性改为MPU_ACCESS_BUFFERABLE,即使用write-though策略
0 |+ D* o4 B4 [5 F+ z6 w" l- i- m2. 通过cache控制寄存器,将所有cacheable的空间全部强制write-though# Z7 Z' m. E7 z& p/ X
29.jpg
+ x) f2 v" \& `7 J% V! j
001.png . `  z6 c( X* n( W

' y. c% m. U, J5 I" A# y6 L7 `3. 将dirty cache-line更新到真实的物理地址中8 ^  M% A4 k  b5 w
step5操作之前,先调用SCB_CleanDCacheSCB_CleanDCache_by_Addr将相应cache-line中的数据写入SRAM1_Buffer,就解决了这个问题!
2 p2 Q5 ?' s2 u' ?7 X" k# c- g
. y- G# G8 z, ~# E这是最常用的方法,在实际的开发过程中,为了提高性能,一般都会使能cache,同时将其配置为WB策略,这就需要开发者在使用时特别小心!同样如之前的第二种情况,需要先调用SCB_InvalidateDCacheSCB_InvalidateDCache_by_Addr去Invalidate相应的cache-line,这样当core在读取时,会忽略D-cache中的内容,去真实的物理地址读取对应的数据!

7 z* Z% [3 G& o
7 D3 I8 P* j6 }( X( h9 a! ^

/ C# R& m- [- T" e  B% o  \- h' T2 c- [# ^
文档下载, _$ {) Y& G$ m( [) a

) f- R) S$ j, {& _& S9 v& B7 O更多实战经验
  `- d  ~- Q! d" n9 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。& x. W4 z" D% a  q/ f  k  O
( t5 h6 s  E' r; _7 n9 `
另外,执行 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:41
+ _) Q& I+ k8 T6 n% e6 ~$ E) G学习了,支持小破!

! G" V8 |+ u! ?# O: }# y- O/ |
野火_firege 回答时间:2017-3-3 14:59:01
学习了
zero99 回答时间:2017-3-3 15:05:23
野火_firege 发表于 2017-3-3 14:59) G* t' j; U* v1 _3 q8 C. J
学习了
8 r8 z$ }/ p) Q8 O! _/ o, o
火哥好
野火_firege 回答时间:2017-3-3 15:53:36
zero99 发表于 2017-3-3 15:05
* m2 t8 ]8 q' M4 N% F; e2 [! T火哥好
0 c; u+ n7 [: g) G9 b
管理员好
Paderboy 回答时间:2017-3-3 16:07:57
学习来了。。。
Stm32McuLover 回答时间:2017-3-3 17:52:19

1 _/ u0 Q# V( d. i学习了
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
学习学习,感恩无私的分享与奉献 6 H! k2 p7 s' [
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 手机版