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

【实战经验】STM32F7 MPU Cache浅析  

[复制链接]
zero99 发布时间:2017-3-3 14:54
前言7 ~1 Z! Z$ Q  K  V
本文会从结构,原理以及应用方面对MPU和Cache进行分析,主要目的是希望读者对Cache有基本的了解,在具体的实际应用中,使用带有一级cache的MCU时,避免常见的错误。  V& Q. u% F( A/ H
9 |) S4 R$ B: k. v. q
Cache介绍
5 N; u% g$ d. w* Z) H" ~7 u$ ^0 g  }. `: S- h( H( g
Cache及其原理
) h$ i) O9 L, f3 b2 q% \4 uCache,高速缓存,一般指的是L1 cache,即和Core紧耦合的,从STM32F7系列开始,
* ^/ k7 k9 i# \% B6 Z8 K5 }基于ARM cortex-M7内核,增加了对L1 Cache的支持。
. U& V0 W. d' I) r8 P# h9 C
21.jpg
1 H' u3 @5 b# P' X4 l% K从这张图片可以看出来,无论是指令Cache(I-cache)还是数据Cache(D-cache),一旦使能之后,就分别与Core的prefetch unit(I-cache)和load-store unit(D-cache)相连,以D-cache为例,因为; B1 n# i+ p' r! L( |) F
直接与LSU相连,访问速度会比直接访问SRAM或外部RAM快很多,只要保证cache有足够高的命中率(由cache策略保证),尽量少的cache miss,读/写的速度会有比较大的提高。5 p0 h0 a) Z4 f
$ i) @2 I9 v' o2 Y3 [$ G
结构及策略
9 \9 s2 ]9 I% ?! |- X6 }' O同样这里以D-cache为例,看一下D-cache的构成:
  D6 f- C1 V& n0 m2 B9 c
22.jpg
4 I+ O1 N0 w; H  d* y" i包括Address和cache-line,Address表明其地址,对应一条包含32bytes的cache-line:% g% B1 z7 Z+ k1 K5 m+ ~' s% G% D
读数据时,当地址命中时即cache-hit,便可以直接从cache line中取出相应的数据,反之,当遍历了address都没有找到,就会产生cache-miss,这时便会从实际的内存单元(如SRAM)中取出相应的数据,并更新到某一条cache-line中并修改相应的cache-line信息;. `7 e1 u6 [: r3 ?4 @7 Q4 ?% e
写数据时,就有点不同了,包括write-through策略和write-back策略,当使用write-though策略时,更新cache-line的同时,同样会更新其对应的实际物理地址的区域,当采用write-back策略时,更cache-line的同时,并不是马上去更新其对应的实际物理地址的内容,而是在其认为合适或者所有的cache-line都dirty的时候才会去更新,当然,也可以通过软件让其强制更新,即clean的动作,这一块会在后面的cache一致性问题上也会有体现;5 W3 m7 B+ S  O8 N) S: Q
同样,对于为什么将cache拆分为2-way或是4-way,这和cache自身的策略如查找算法等相关,由于本文侧重讨论cache的应用相关问题,所以关于cache本身的策略这里不再详述。
& e+ E1 |* m# c# N$ ~( E8 T+ `- [' }, V  e: g$ _" G9 E5 U+ Q4 ^
Cache及MPU属性
& k- E5 J' v+ L这里需要注意的是,cache一般是配合MPU(memory protection unit)一起使用的,首先需要通过MPU配置相应memory的属性(normal, strongly-ordered, device, XN etc.),如下表所示:
6 l6 w( U. i8 X2 R% v1 Q' s
23.jpg
$ r! c: r1 o1 B" H4 F7 J选取几个有特点的作为示例:$ c8 G: h! @8 q& h, ?/ p7 y
0~0x1FFF_FFFF: flash空间,属性为normal,cache的属性为Write-through,即更新cache的同时,将数据同时写入相应的物理地址空间
" V; h+ c: @) y; \) j0x2000_0000~0x3FFF_FFFF: SRAM空间,属性为normal,cache的属性为write-back,即仅更新cache,在合适的时候(由cache策略决定或者软件强制更新)将数据更新到相应的SRAM空间  w( m# z+ ?; E8 Z2 k
0x4000_0000~0x5FFFF_FFFF: 芯片内部的外设空间,属性为device,这一版是外设寄存器所处的位置,对其读写的过程中不会经过cache
  h! _- y: i6 z' B" A; n& z- _8 ^8 F5 E+ e: z
XN的意思是Execute-Never,其含义为如果相应的地址空间是XN,是绝不允许执行代码的。
4 y+ r8 F( Z0 z
7 `! O7 u4 F8 Z! V2 W3 I* o. NCache相关函数及作用9 t4 B# C' R# N+ X
这里以core_cm7.h里对cache封装的函数为例
6 h0 n) R: {0 n; t% K6 N( T(C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\arm\CMSIS\Include) : e4 C2 ]% {7 L. V' ]4 ~/ B
SCB_EnableDCache
7 p4 |! _4 Z, T# \4 s## 使能D-cache# j. n8 J! i, `& ^8 a
8 k5 }- X( N6 R4 y: x
SCB_DisableDCache 6 ?3 w, G) ^, J9 S6 j
## 禁用D-cache

$ F$ k6 q( C9 Z8 |$ S, ~! h/ N
- T- K+ R1 Z$ s2 ~* pSCB_EnableICache
0 _9 i  r- h# T8 z' m## 使能I-cache- [: {0 K4 F# T& |* k% p

! |- X& ]( k4 _( wSCB_DisableICache' X4 |; w( \- t4 }8 C( Q
## 禁用I-cache
% \4 ?- C& T% l+ ]2 ^1 ^& P; m
/ x4 F" k% l5 ]  I6 W  e. kSCB_CleanDCache % o( z+ e' d  U; C
## Clean所有的cache-line,即将dirty的cache-line全部写到cache line对应的真实的物理地址中 所谓的drity属性,即写操作时,更新了相应的cache-line,但是没有更新到真实的物理地址, 而这个clean的动作,就是将cache中的内容更新到真实的物理地址中
; j( S5 p% x9 X7 M/ P' L
+ A# b& k, u9 ^9 z$ J( R, XSCB_CleanDCache_by_Addr ( G7 m2 p7 Z! O, t. e* t  x( t. G
## 根据地址信息clean其对应的cache-line
$ X  E5 g2 T( D# n
5 c; u9 w% d( A; Q0 c
SCB_InvalidateDCache
* Q+ x) g) i& y& N3 n## 无效D-cache,D-cache被invalidate之后,当有Host(如core,DMA等)读取数据时,会忽略相应的cache-line中的内容(因为被validate了),从真实的物理地址中去获取相应的数据
1 t" v( o; b3 R0 n* v0 }
, `/ {- E! x' dSCB_InvalidateDCache_by_Addr / @7 c  ~4 l: M  t1 P, I8 G2 R7 X
## 根据地址信息无效其对应的cache-line
+ b) T% e& x" P$ G* Q# w, ?" v+ G& e
# S2 F( U* x, m, f8 O
Cache一致性问题
7 L; r# h: d; C所谓的Cache一致性问题,主要指的是由于D-cache存在时,表现在有多个Host(典型的如MCU的core,DMA等)访问同一块内存时,由于数据会缓存在D-cache中而没有更新实际的物理内存。
# c' F+ H8 L* u4 F' \第一种情况是当有写物理内存的指令时,core会先去更新相应的cache-line(Write-back策略),在没有clean的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的Host(如DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和D-cache中的不一致),这就是所谓的cache一致性的问题!
. i/ k2 I/ T3 [' W& k; d& J* u
* {* t+ Z+ P& ~' Q第二种情况是DMA更新了某段物理内存(DMA和cache直接没有直接通道),而这个时候Core再读取这段内存的时候,由于相对应地址的cache-line没有被invalidate,导致Core读到的是cache-line中的数据,而非被DMA更新过的实际物理内存的数据,下面这张图比较清晰的展示了上述两个过程:& B. \' Z: G: {
 ●第一种情况$ q4 t$ f0 H. [
24.jpg & s3 [  W: V2 B  M4 D) c
5 v* d. i6 S# a2 r8 `/ _& ?
 ●第二种情况
; f  @! h4 S) E+ U+ d* y" b* u
25.jpg 7 B6 X5 c5 q  i9 B
下面以一个实例来分析cache一致性问题,展示的是上面的第一种情况,如下图所示:
; ~2 {% C' y6 m, w" [7 _
26.jpg " w; g2 s+ I* T& {
先看一下这个例程数据的传输流程和路径:8 c( G5 @* `0 y3 C% i+ r
● SRAM1_Buffer先全部写入0x552 R0 P! z) v$ A8 q! B3 B
●Core将Flash中的Const_Buffer写入SRAM1_Buffer(这里会先经过d-cache)8 X" s+ V, R8 l7 W/ K! |
● 配置DMA,将SRAM1_Buffer中的数据通过DMA写入另一段内存DTCM_Buffer8 i7 M1 ~& k/ o* Z) n' }; A7 F. Q
● 比较DTCM_Buffer中的数据和Flash中的Const_Buffer数据,看是否一致
/ m% H) D% P8 f4 b% P
! e8 h9 D: I& {- q代码示例如下: 
6 z+ W- n: o8 Z7 k8 \" B# L●MPU对memory的配置 - - - - step11 \) ^4 j$ D: B: Q  K/ E
27.jpg
% F' B7 J& j, e; v! n重点介绍一下高亮部分的配置:
1 ]2 b. Q. O# G' o9 K● BaseAddress为要配置的存储空间的起始地址;& n5 b$ X0 g3 _" K1 Q6 w
● Size为要配置的存储空间的大小9 u: m2 G" Q; _8 D/ g/ H8 \0 |5 L9 Y: i
● IsCacheable表明这段存储空间是否可以cache
/ ^/ F8 g& B- q% Y7 a, T● IsBufferable表明使能cache之后,策略是write-through还是write-back(bufferable)$ i# V3 N' ^/ x( h. d
这里需要特别注意的1点:配置的BaseAddress需要被Size整除,以上述配置为例,即0x20010000除以256K需要是整数!
; n& [$ J- v2 ?8 G# X4 `# k
+ `7 m  B3 C1 C) B* k: O; Z1 u● 使能Cache - - - - step2# T: p1 H+ \5 l. P) r  p8 N
28.png 2 V0 M8 h" k% F: |) h# `
1 A& I% T+ s) J( P
●  初始化SRAM1_Buffer为0x55 - - - - step3 4 O/ U) J6 O6 h7 X! |
   ● Copy Flash中的Const_Buffer到SRAM1_Buffer - - - - step4
$ z/ L& u8 g! l: I3 d3 z   ● 配置DMA,将SRAM1_Buffer写入DTCM_Buffer - - - - step5 % V9 {3 n! C9 n
   ● 比较DTCM_Buffer和Const_Buffer,看是否一致 - - - - step6 # v. U! {+ v4 G( n# i+ K" B0 T9 x
从结果上看,最后一步比较的结果并不一致,原因比较简单,由于设定的WB策略,所以在step4的时候,数据会暂存在D-cache当中,并没有更新到SRAM1_Buffer,所以当SRAM1_Buffer被DMA拷到DTCM_Buffer中的时候,有一部分可能还是初始值,导致最终的比较不一样,而解决的方法有以下几个:
" F6 s* y1 m+ }( [, \' S: M1. MPU配置的代码,将属性改为MPU_ACCESS_BUFFERABLE,即使用write-though策略
. q8 N* u  q6 m8 s' |5 Z! O8 e2. 通过cache控制寄存器,将所有cacheable的空间全部强制write-though
/ q3 j" e/ A/ L" |: H
29.jpg 7 n4 L# v# B1 h5 M
001.png 3 ^& `: I: Q% M& A

+ S, r" Z' v3 M; N3. 将dirty cache-line更新到真实的物理地址中
9 @6 Y9 P1 i+ {' E* @step5操作之前,先调用SCB_CleanDCacheSCB_CleanDCache_by_Addr将相应cache-line中的数据写入SRAM1_Buffer,就解决了这个问题!
+ L/ Z- k1 e! l6 A7 e' E% i. q. z; l) E3 E( g! ]6 ]% K3 [
这是最常用的方法,在实际的开发过程中,为了提高性能,一般都会使能cache,同时将其配置为WB策略,这就需要开发者在使用时特别小心!同样如之前的第二种情况,需要先调用SCB_InvalidateDCacheSCB_InvalidateDCache_by_Addr去Invalidate相应的cache-line,这样当core在读取时,会忽略D-cache中的内容,去真实的物理地址读取对应的数据!

' e" m4 j: U. t( S, X5 Y$ i
0 `) @2 a+ U% Q4 o: c  M9 ~
  z3 ?) G$ c& _

" P) F$ l' p; I: r文档下载
: P/ h+ x' V! F! ~
9 i# d4 {& O" M  `" J: ?0 d更多实战经验
& b- y# N* @  S7 |% J2 h5 v# `

评分

参与人数 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。
' j) \& }, {# R: _
8 ~& ?. T. D* S" ~$ r另外,执行 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& s. A, N" l6 Q! P0 \
学习了,支持小破!

# C, w; _5 L" \
野火_firege 回答时间:2017-3-3 14:59:01
学习了
zero99 回答时间:2017-3-3 15:05:23
野火_firege 发表于 2017-3-3 14:594 s" g- Q) m: `. p, Z2 |! `1 ~
学习了
( ^6 u; Y+ M* N$ i( `/ d% ^
火哥好
野火_firege 回答时间:2017-3-3 15:53:36
zero99 发表于 2017-3-3 15:05, |9 n2 y1 Y* @: T5 o: N
火哥好

( Z9 k. G" K8 `) O管理员好
Paderboy 回答时间:2017-3-3 16:07:57
学习来了。。。
Stm32McuLover 回答时间:2017-3-3 17:52:19
3 Y6 D$ G1 h1 a( p: G  e
学习了
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
学习学习,感恩无私的分享与奉献 2 V4 u% H: |5 e
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 手机版