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

【经验分享】STM32F7 MPU Cache 浅析

[复制链接]
STMCU小助手 发布时间:2022-2-26 16:28
前言
* S( F( O! @% g本文会从结构,原理以及应用方面对 MPU 和 Cache 进行分析,主要目的是希望读者对 Cache 有基本的了解,在具体的实际应用中,使用带有一级 cache 的 MCU 时,避免常见的错误。- Q, D3 n  L) ^- e

/ H5 o" D$ k3 R6 OCache 介绍
- n0 @: W1 u4 g- vCache 及其原理
/ j7 e9 m1 `# t( c" ^
Cache,高速缓存,一般指的是 L1 cache,即和 Core 紧耦合的,从 STM32F7 系列开始,基于 ARM cortex-M7 内核,增加了对 L1 Cache 的支持。
" U4 V. c$ I6 D/ @- i- M8 w, L7 V; ?: A6 T/ r- L! L* }
1 w! s& T* c; Q0 @

  J/ X/ g! E/ n& E! R0 Y从这张图片可以看出来,无论是指令 Cache(I-cache)还是数据 Cache(D-cache),一旦使能之后,就分别与 Core 的 prefetch unit(I-cache)和 load-store unit(D-cache)相连,以 D-cache 为例,因为直接与 LSU 相连,访问速度会比直接访问 SRAM 或外部 RAM 快很多,只要保证 cache 有足够高的命中率(由 cache 策略保证),尽量少的 cache miss,读/写的速度会有比较大的提高。+ o+ `8 y, y0 K) [

, G. {4 @( ~1 l; ~1 X/ A  ^! ]
. T/ }5 k/ L+ q, A* L结构及策略7 b. Q; ?2 @: h6 o8 Y; q  m+ ]
同样这里以 D-cache 为例,看一下 D-cache 的构成:
/ c" F; `2 }, l9 c2 }- t6 s
4 e% E' J* w1 ]1 U/ F4 v) ] 0M0XX3FES7UPW2W34YG}SI7.png 0 x2 I+ p( r# u% J% r

; k1 |& R8 @% c包括 Address 和 cache-line,Address 表明其地址,对应一条包含 32bytes 的 cache-line:% x7 ~( l7 x: e+ P, x4 D* y
读数据时,当地址命中时即 cache-hit,便可以直接从 cache line 中取出相应的数据,反之,当遍历了address 都没有找到,就会产生 cache-miss,这时便会从实际的内存单元(如 SRAM)中取出相应的数据,并更新到某一条 cache-line 中并修改相应的 cache-line 信息;7 }+ h: r) v, A! R. G7 ^/ [
写数据时,就有点不同了,包括 write-through 策略和 write-back 策略,当使用 write-though 策略时,更新 cache-line 的同时,同样会更新其对应的实际物理地址的区域,当采用 write-back 策略时,更新cache-line 的同时,并不是马上去更新其对应的实际物理地址的内容,而是在其认为合适或者所有的cache-line 都 dirty 的时候才会去更新,当然,也可以通过软件让其强制更新,即 clean 的动作,这一块会在后面的 cache 一致性问题上也会有体现;
, g  ?+ E/ _+ P+ B4 V同样,对于为什么将 cache 拆分为 2-way 或是 4-way,这和 cache 自身的策略如查找算法等相关,由于本文侧重讨论 cache 的应用相关问题,所以关于 cache 本身的策略这里不再详述。: O4 u' H0 w$ T1 Q+ \) s" j

+ Y$ l, g' ?% }! C8 O5 WCache 及 MPU 属性
- u! |4 L6 ]: G# ]; C5 T* R
这里需要注意的是,cache 一般是配合 MPU(memory protection unit)一起使用的,首先需要通过 MPU配置相应 memory 的属性(normal, strongly-ordered, device, XN etc.),如下表所示:
8 L9 x0 _6 @5 l! \% q
: a- L+ S! H+ `) N, Y8 ?' K3 A Z[@$LNTW{4W{]~YJGQ(IK)W.png ' `/ k! `" O1 t' [) d$ S

) [! r+ f' S( U+ M7 Q) M选取几个有特点的作为示例:
- j6 n' E: h. m0~0x1FFF_FFFF: flash 空间,属性为 normal,cache 的属性为 Write-through,即更新 cache 的同时,将数据同时写入相应的物理地址空间! g9 p2 S# ?# g) n- R2 s
0x2000_0000~0x3FFF_FFFF: SRAM 空间,属性为 normal,cache 的属性为 write-back,即仅更新cache,在合适的时候(由 cache 策略决定或者软件强制更新)将数据更新到相应的SRAM 空间% W& l% Q; l1 z1 V+ [. {- n4 W
0x4000_0000~0x5FFFF_FFFF: 芯片内部的外设空间,属性为 device,这一版是外设寄存器所处的位置,对其读写的过程中不会经过 cache; O' d( p- ^; D% e1 g2 a7 k! W5 E
XN 的意思是 Execute-Never,其含义为如果相应的地址空间是 XN,是绝不允许执行代码的。& w5 u( z0 s1 T/ W
* b; B) V6 d+ ~4 Q
Cache 相关函数及作用
- D. s- s' ?7 I+ q# u
这里以 core_cm7.h 里对 cache 封装的函数为例7 ?4 o/ U" f8 v" l+ F6 t" C0 r% Q
(C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.2\arm\CMSIS\Include)0 o+ N2 h, F5 P$ u
SCB_EnableDCache4 X* x- b  x7 `$ U. l
## 使能 D-cache1 ~1 F/ j* q( T) P

! @. u: P2 k6 y9 I$ F- c. LSCB_DisableDCache* A. {+ v$ A# Y
## 禁用 D-cache  s! y4 a: Q6 n# {7 x
' b: D$ a! o4 ], i
SCB_EnableICache
) r6 @# J* w# j6 M! n## 使能 I-cache% d+ e+ x5 _3 K6 F" ]

& B/ p3 P# Y9 x) C* SSCB_DisableICache
/ D5 n  [% m/ \## 禁用 I-cache
! j! x' l$ G7 O! L& c" A: f# G
6 y" \1 _  b1 E' FSCB_CleanDCache1 M  C3 c  y* a2 X8 u7 B; E
## Clean 所有的 cache-line,即将 dirty 的 cache-line 全部写到 cache line 对应的真实的物理地址中所谓的 drity 属性,即写操作时,更新了相应的 cache-line,但是没有更新到真实的物理地址,而这个 clean 的动作,就是将 cache 中的内容更新到真实的物理地址中
8 ?' {9 X1 ?5 U+ K& D) l# F- j8 t; z; }- B& R3 m5 o( u2 D) h

1 p! x0 w7 |5 p9 }& m* A4 j! aSCB_CleanDCache_by_Addr' ?6 _; {1 _! x* v% e: e
## 根据地址信息 clean 其对应的 cache-line6 Y  I6 C6 V. s/ C1 P+ s

5 I' i, X/ A& D! B% rSCB_InvalidateDCache- c! C; O0 E5 {; P- s' m% o, n" V6 {
## 无效 D-cache,D-cache 被 invalidate 之后,当有 Host(如 core,DMA 等)读取数据时,会忽略相应的 cache-line 中的内容(因为被 validate 了),从真实的物理地址中去获取相应的数据: @6 q4 a: \+ B, i& T; ~

& n' u6 j$ F6 QSCB_InvalidateDCache_by_Addr
& t$ u4 s6 Y/ ^5 C! q; }/ |## 根据地址信息无效其对应的 cache-line
) h% M2 `- J, X9 Q  d6 X  L$ |5 T& J/ V7 I
Cache 一致性问题  P" b7 I- g# n7 p+ {
所谓的 Cache 一致性问题,主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的core,DMA 等)访问同一块内存时,由于数据会缓存在 D-cache 中而没有更新实际的物理内存。2 n* ], V- ^0 i& e1 L
第一种情况是当有写物理内存的指令时,core 会先去更新相应的 cache-line(Write-back 策略),在没有clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题!
, w0 C0 j  A. t1 Y7 _" n0 Q8 y: k, X+ L
第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line中的数据,而非被 DMA 更新过的实际物理内存的数据,下面这张图比较清晰的展示了上述两个过程:( a0 h) h: g+ O, @; O" j$ N

, R: V. W5 Y' v8 Q8 B第一种情况
7 u1 q. k* Z( I! k$ E5 m
" k" z7 ~5 G7 a: O3 T `%6SA{SE@WRL(F476[AQE[3.png $ F" `6 ~9 T* S$ @8 G) d! y

$ u; D9 W5 t# z, z% D# k# ^! i$ Q, d$ C
第二种情况( @( [5 n& c* C& ?9 n6 i

8 z# c" `& k9 D+ d _S~5$R)KX_)JPA_IVP@ZO.png
; l  d; N& {! p6 C( ^
6 v# D; Q! S4 X- R8 @下面以一个实例来分析 cache 一致性问题,展示的是上面的第一种情况,如下图所示:
+ K  i- Q9 H6 h2 c" k8 ~7 e9 ?
# F* Y% G: D' E1 x9 t 7(`{5{1__~FFQYT%()H32VF.png , C$ _' u0 }" x' O# R: d

1 H' E8 H' v. ~) n- r2 h! B先看一下这个例程数据的传输流程和路径:
. e9 Q& M" N1 m0 w" \2 j SRAM1_Buffer 先全部写入 0x55
: g% }: d( x% g0 o; `4 f* F6 ]& M Core 将 Flash 中的 Const_Buffer 写入 SRAM1_Buffer(这里会先经过 d-cache)2 ]4 f9 h; [0 t7 N! Q
 配置 DMA,将 SRAM1_Buffer 中的数据通过 DMA 写入另一段内存 DTCM_Buffer
& m2 K% C: F! ^+ ?( U, b' g, C 比较 DTCM_Buffer 中的数据和 Flash 中的 Const_Buffer 数据,看是否一致- k# N) f+ t: E4 d$ y
: F7 G8 m2 E" ^7 ]& r
# a: ?; _, i0 Y. d
代码示例如下:: _% L$ |, S6 m/ _8 C( |2 o
MPU 对 memory 的配置 - - - - step1$ h, |! `( s4 c
# v3 t3 \0 P8 H2 C9 p* P
6WK1[R2A[OD)ON@T3SOZ]3C.png , P. X; z  Y3 p0 Z

6 B3 k" b+ H2 `5 q* }重点介绍一下高亮部分的配置:, D. X# g" i7 ~# N+ W! i% C
 BaseAddress 为要配置的存储空间的起始地址;
. J8 ^" W" K% {7 S Size 为要配置的存储空间的大小& C+ z$ T/ a: v# I! l7 r
 IsCacheable 表明这段存储空间是否可以 cache& N" O/ v, @# R0 Q
 IsBufferable 表明使能 cache 之后,策略是 write-through 还是 write-back(bufferable)5 P" h" M& R1 r/ o. H! G; w
这里需要特别注意的 1 点:配置的 BaseAddress 需要被 Size 整除,以上述配置为例,即0x20010000 除以 256K 需要是整数!
5 V4 y' c$ L. \9 k8 j
3 u  v8 o; @$ C7 e5 N, X0 G" r# ?8 D, K1 {5 B6 |  @7 g/ ^
使能 Cache - - - - step2* |! s, c$ ^1 S7 `9 I+ E

3 X% q) v( D! T6 y( }; G* e6 Q
8 D/ j: [, d& B
~HQI5FQ%T77QGZHR_GUH.png
% t4 \  X( }9 f
/ ]3 e( ?# p. v8 P8 B4 Z: R4 u- B
初始化 SRAM1_Buffer 为 0x55 - - - - step3/ b; t+ N( O; ~1 K$ b6 y

& A) h2 b; F5 A$ ?7 t0 h Copy Flash 中的 Const_Buffer 到 SRAM1_Buffer - - - - step4
6 W, @( f: ^( G5 @
+ i1 _/ E6 v; [" [8 W1 n& G- m. ~ 配置 DMA,将 SRAM1_Buffer 写入 DTCM_Buffer - - - - step5" n6 I# F8 y1 e; ~" |  O/ s/ f

7 @* E; s* Z" P: m2 x9 ?) r 比较 DTCM_Buffer 和 Const_Buffer,看是否一致 - - - - step67 }: t* p: C2 c+ Z

  z  j) ?' B5 S% _" k从结果上看,最后一步比较的结果并不一致,原因比较简单,由于设定的 WB 策略,所以在step4 的时候,数据会暂存在 D-cache 当中,并没有更新到 SRAM1_Buffer,所以当SRAM1_Buffer 被 DMA 拷到 DTCM_Buffer 中的时候,有一部分可能还是初始值,导致最终4 e& r5 P8 o# \) g; N2 v
的比较不一样,而解决的方法有以下几个:
* ~  s' s+ F: |; Y( [7 J1. MPU 配置的代码,将属性改为 MPU_ACCESS_BUFFERABLE,即使用 write-though 策略
6 B: \# c9 l4 o0 Z2. 通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 write-though1 j+ |% T0 l' l6 C
1 B+ [3 K; `/ d4 N6 t: E% R3 `" o7 E
0KEO6(IB`X}UN@JCV@SE@SA.png
- I! g" r% S" R9 G4 s. t( q
8 }9 w8 E, f; g) Y 6O@]V~V_51C]`5Q3]BK}N5O.png   M2 s" M1 W. @+ u
& D: }0 a8 J: p: K1 ~+ v
3. 将 dirty cache-line 更新到真实的物理地址中
( x  }: Q7 G& }2 i8 s在 step5 操作之前,先调用 SCB_CleanDCache 或 SCB_CleanDCache_by_Addr 将相应 cache-line 中的数据写入 SRAM1_Buffer,就解决了这个问题!
8 F2 _$ C% q/ i5 ~5 D( Z3 b7 I/ B- w1 t6 s- _
这是最常用的方法,在实际的开发过程中,为了提高性能,一般都会使能 cache,同时将其配置为 WB策略,这就需要开发者在使用时特别小心!同样如之前的第二种情况,需要先调用SCB_InvalidateDCache 或 SCB_InvalidateDCache_by_Addr 去 Invalidate 相应的 cache-line,这样当core 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据!
3 D/ R6 c' [* k5 D! W& H8 n" C+ C4 h1 Q* m3 @* S7 P
收藏 评论0 发布时间:2022-2-26 16:28

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版