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

言简意赅介绍M7内核Cache工作流程, 摸爬滚打半年的经验总结

[复制链接]
baiyongbin2009 发布时间:2018-11-6 01:01
本帖最后由 baiyongbin2009 于 2018-11-6 01:01 编辑
) [) g$ D5 g* j, v* F6 d3 `5 k$ w" O9 j+ I/ x3 O  Z( X! u5 ~( k
说明:- [" M2 u/ q' Z% ~# B
    初学M7的Cache时,经常是ARM的手册和ST的手册看了一遍又一遍,虽然每次看,每次都有收获,但是一直无法形成系统的认识,说到某一个知识点也明白,但是具体到读写操作的时候是怎么个流程,就懵逼了,也是心里烦躁,最近脑子开窍了些,特此分享下经验。$ [( }: }, F5 v& N  k
' O9 D- B7 t5 k* z% D
当前的认识能力有限,有不对的地方,欢迎批评指正。7 \5 C: t6 t# T0 v/ `

, x0 X# k$ @) W* G3 y0 v一、引出问题:. U1 s* x% f! q) q( }
    当前芯片厂商出的M7内核芯片基本都做了一级Cache支持,Cache又分数据缓存D-Cache和指令缓冲I-Cache,对于指令缓冲,用户不用管,这里主要说的是数据缓存D-Cache。以STM32H7为例,主频是400MHz,除了TCM和Cache以400MHz工作,其它AXI SRAM,SRAM1,SRAM2等都是以200MHz工作。数据缓存D-Cache就是解决CPU加速访问SRAM。
1 O2 P" R3 F$ ]+ S" T& N
' w6 }  j+ r* [/ R! F) P5 g    如果每次CPU要读写SRAM区的数据,都能够在Cache里面进行,自然是最好的,实现了200MHz到400MHz的飞跃,实际是做不到的,因为数据Cache只有16KB大小,总有用完的时候。
! \4 i9 @1 P9 G4 z5 C4 I. T  L- w
& m& p" d! \! o& o对于使能了Cache的SRAM区,要分读写两种情况考虑。9 ]5 L4 S% d# c4 P( D
读操作:8 D: _" [( |1 p# \6 H. `9 P
如果CPU要读取的SRAM区数据在Cache中已经加载好,这就叫读命中(Cache hit),如果Cache里面没有怎么办,这就是所谓的读Cache Miss。
$ L0 a. {5 S% q5 G7 h
3 N9 W- I9 I/ y写操作:
  t% Y% ?7 i- Y$ n1 p0 `9 V) \如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域(专业词汇叫Cache Line,以32字节为单位),这就叫写命中(Cache hit),如果Cache里面没有开辟对应的区域怎么办,这就是所谓的写Cache Miss。
5 ^( o8 y7 z3 ^. g& z' v6 T- b" t: ^5 z( [9 C
: h, K1 B  X) S5 `7 ~% n$ b: ^

1 k: t6 K1 n8 R# h: l0 L( i: M- @3 Q' T
二、支持的Cache配置:
. @4 z; O( s' XCache的配置是通过MPU来设置的,通常只用到下几种方式。& i# l6 I7 A0 ?7 W* M, ~3 o
8 j/ F9 c; W2 h. z
8 k, p& f4 Z; T4 o* X, M  [/ d) ~1 R
其中的TEX是用来设置Cache策略的,C是Cache,B是缓冲用来配合Cache设置的,而S是共享,用来解决多总线或者多核访问时的同步问题。MPU配置的时候,最主要的也是配置这几个参数。
, ^3 E. D2 |/ {3 ?5 W
* ?! ^; g- K. ], {- CCache支持的策略有如下四种:
9 X7 m6 S5 N6 f$ M
0 Z3 c( h! F' b0 z  \: X, [5 x, C& A7 v( b- j2 F7 q
有了这四种方式,就可以在正式进入本帖的主题,Cache的读写操作是如何工作的,下面分这四种情况做一 一介绍。
( F$ ~, U2 e2 j( B  Y* f" i3 I* b" `8 K" z3 Z4 b, e" O5 n
三、四种Cache(MPU)配置的读写操作流程说明
3 X/ a' m! p4 f7 e1 ~6 Q1、 Non-cacheable  j5 m, J" t9 J" y  Y
这个最好理解,就是正常的读写操作,无Cache。0 R) u& R6 B+ {& D3 l
/ H& P6 H: C. b; D) R) k" |
(1)对应四种MPU配置如下:* o6 i% g9 j9 I  A3 q9 ~
TEX = 000 C=0 B=0  S=忽略此位,强制为共享
. \# j5 Q/ m9 ?) ITEX = 000 C=0 B=1  S=忽略此位,强制为共享
7 \: z, k0 e" W- L. t; rTEX = 001 C=0 B=0  S=0- N+ n0 M! n1 f- `! A
TEX = 001 C=0 B=0  S=1- [* {$ ?& a1 C
/ q7 {) ^4 j) X8 {" \  t: o  H
2、Write through, read allocate,no write allocate+ }0 H) ]9 {5 y1 r# T' f7 y; u( {
注意,M7内核只要开启了Cache,read allocate就是开启的。
) i9 ]% r9 l* _1 Z
5 k$ P$ y) B" s* o6 j; b" ^(1)使能了此配置的SRAM缓冲区写操作6 Q' e* A! @4 ]# W1 V; o  t
    如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,那么会同时写到Cache里面和SRAM里面;如果没有,就用到配置no write allocate了,意思就是CPU会直接往SRAM里面写数据,而不再需要在Cache里面开辟空间了。  C" `9 {! {+ q; O

3 z! c8 u! h. Y  R* V% N& D    在写Cache命中的情况下,这个方式的优点是Cache和SRAM的数据同步更新了,没有多总线访问造成的数据一致性问题。缺点也明显,Cache在写操作上无法有效发挥性能。7 I  u. u+ [, \& ~; Q, q

. ^: ^' g% \- L9 G% y  W. R) }(2)使能了此配置的SRAM缓冲区读操作/ F6 V' _8 M3 n) N4 [
    如果CPU要读取的SRAM区数据在Cache中已经加载好,就可以直接从Cache里面读取。如果没有,就用到配置read allocate了,意思就是在Cache里面开辟区域,将SRAM区数据加载进来,后续的操作,CPU可以直接从Cache里面读取,从而时间加速。( Y" H) g5 V" N/ p) Q
4 d$ L# V4 g! g2 Z5 F4 o
    安全隐患,如果Cache命中的情况下,DMA写操作也更新了SRAM区的数据,CPU直接从Cache里面读取的数据就是错误的。( c' P# C3 z" I# i' ?# s$ z( c
5 g4 w- B! G; ~6 E* C
(3)对应两种MPU配置如下:
5 v1 o; t! i* R; [TEX = 000 C=1 B=0  S=1
" ?9 p: t! D$ J+ BTEX = 000 C=1 B=0  S=07 R4 |* N! Y# m
4 z6 n4 H1 _. f# _6 W$ v! O- \2 e
3、Write back, read allocate,no write allocate$ h) x, r' s& y: p
注意,M7内核只要开启了Cache,read allocate就是开启的。7 @3 W, m( X1 a' X& [9 R% T* F0 Q
# m. S2 e! h3 R! ~  V9 I0 }
(1)使能了此配置的SRAM缓冲区写操作5 M  w; Z+ A5 R! ~0 A! r
    如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,那么会写到Cache里面,而不会立即更新SRAM;如果没有,就用到配置no write allocate了,意思就是CPU会直接往SRAM里面写数据,而不再需要在Cache里面开辟空间了。
+ I0 D0 W' [: d/ A1 N: J! {' D1 w9 M( l( r4 @: F
    安全隐患,如果Cache命中的情况下,此时仅Cache更新了,而SRAM没有更新,那么DMA直接从SRAM里面读出来的就是错误的。- ^6 _( Z- X9 Y5 t
7 u  f& F' P# I1 ~
(2)使能了此配置的SRAM缓冲区读操作
/ W5 `; P6 G# G9 W   如果CPU要读取的SRAM区数据在Cache中已经加载好,就可以直接从Cache里面读取。如果没有,就用到配置read allocate了,意思就是在Cache里面开辟区域,将SRAM区数据加载进来,后续的操作,CPU可以直接从Cache里面读取,从而时间加速。
  H# P, g1 M3 T" u- z3 Q- p. U  P4 g: ?; M% y
    安全隐患,如果Cache命中的情况下,DMA写操作也更新了SRAM区的数据,CPU直接从Cache里面读取的数据就是错误的。" Z2 D  a' h1 b5 ]) H( K5 Q6 S
5 R) d! `, ^: T8 j, g' O
(3)对应两种MPU配置如下:
; P+ b! I. X3 ~. o. X2 OTEX = 000 C=1 B=1  S=1/ d/ ^2 E8 h5 T  w# f0 w. v- I% A
TEX = 000 C=1 B=1  S=0
# i7 J- l4 u' V4 B. x  c5 v( K0 d) g6 j
4、Write back, read allocate,write allocate
9 L" y& n5 M4 ]# k9 B! r注意,M7内核只要开启了Cache,read allocate就是开启的。8 `0 a6 ?; c7 e* s4 m# w: F
( \4 z0 }$ x8 a! Z4 o, ^# x# e
(1)使能了此配置的SRAM缓冲区写操作8 R2 \; ]; e9 p5 \: G) A/ j
    如果CPU要写的SRAM区数据在Cache中已经开辟了对应的区域,那么会写到Cache里面,而不会立即更新SRAM;如果没有,就用到配置write allocate了,意思就是CPU写到往SRAM里面的数据,会同步在Cache里面开辟一个空间将SRAM中写入的数据加载进来,如果此时立即读此SRAM区,那么就会有很大的速度优势。: H$ j3 W$ A+ \9 e

* c: M( ^# U( g& a    安全隐患,如果Cache命中的情况下,此时仅Cache更新了,而SRAM没有更新,那么DMA直接从SRAM里面读出来的就是错误的。) q# e2 n$ Y. n) t" z
0 e+ A& {) T/ e1 M+ X
(2)使能了此配置的SRAM缓冲区读操作- x. q) |0 d5 y, [% }& V  j6 `& \% y
    如果CPU要读取的SRAM区数据在Cache中已经加载好,就可以直接从Cache里面读取。如果没有,就用到配置read allocate了,意思就是在Cache里面开辟区域,将SRAM区数据加载进来,后续的操作,CPU可以直接从Cache里面读取,从而时间加速。
! R+ S) `2 e, n7 E8 T" ?" I6 ~- A! N8 H5 c% B
    安全隐患,如果Cache命中的情况下,DMA写操作也更新了SRAM区的数据,CPU直接从Cache里面读取的数据就是错误的。1 T7 S9 l, _9 y0 t5 e  R! J4 m

4 B2 v1 Q' [) ^    这个配置被誉可以最大程度发挥Cache性能,不过具体应用仍需具体分析。6 f- [1 j- x% D0 F# @& u. U

: Q4 d8 e4 d$ ^( K* s( R(3)对应两种MPU配置如下:% @6 e! b3 g' }6 _% W2 y
TEX = 001 C=1 B=1  S=1
  u9 Y* X  o4 n8 g" q" eTEX = 001 C=1 B=1  S=07 U  f# A; D" X  x

! x) h; K: x! B  J5、共享配置是个隐形的大坑. }5 ]4 m! {' T- d% b9 ~
这里以STM32H7为例进行说明,STM32H7编程手册对其的描述是多核共享。/ b: q. ^; Z7 o  u# h- T7 t6 V
: m$ x6 J& |- V. n% P
: f. P  u" t6 Q2 q! C
而H7的应用笔记对齐的描述是开启共享基本等同于关闭Cache。0 v. C& C& a7 J, O; m

/ }! Y" ^% `. G4 T$ F+ t- l5 ~/ |9 a% d+ K& w
实际测试下面四种开Cache的情况,开关共享对缓冲区的大批量数据的读操作影响很大,基本差出两倍,而写操作基本没有影响,也许这就是所谓的多总线同步读造成的。
& ?$ k2 o5 P( U8 D9 I/ J$ _另外共享开关仅对开启了Cache的情况下有影响,而对于关闭了Cache的情况是没有影响的,开不开没关系。" ^6 h9 {/ }/ C5 u9 v5 e- j
: l7 A+ ]7 D+ S# N& z
6、总结这几种方式的几个关键知识点
; h4 W) G* T8 Z% b8 w+ ]0 ^(1)Cortex-M7内核的L1 Cache由多行内存区组成,每行有32字节,每行都配有一个地址标签。数据缓冲DCache是每4行为一组,称为4-way set associative。而指令缓冲区ICache是2行为一组,这样节省地址标签,不用每个行都标记一个地址。
' D* Y5 |$ i: D4 q
$ o, p2 i% q) y(2)对于读操作,只有在第1次访问指定地址时才会加载到Cache,而写操作的话,可以直接写到内存中(write-through模式)或者放到Cache里面,后面再写入(write-back模式)。
3 R0 w! ]! q* g" D" k6 x8 W# W
4 R& y# s" y- b! u" C(3)如果采用的是Write back,Cache line会被标为dirty,等到此行被evicted时,才会执行实际的写操作,将Cache Line里面的数据写入到相应的存储区。5 V7 h3 [" i2 `" B  a
& r9 |2 o- G! C/ I
(4)Cache命中是访问的地址落在了给定的Cache Line里面,所以硬件需要做少量的地址比较工作,以检查此地址是否被缓存。如果命中了,将用于缓存读操作或者写操作。如果没有命中,则分配和标记新行,填充新的读写操作。如果所有行都分配完毕了,Cache控制器将支持eviction操作。根据Cache Line替换算法,一行将被清除Clean,无效化Invalid或者重新配置。数据缓存和指令缓存是采用的伪随机替换算法。
" d- |' C# v0 J4 C+ y' N2 G$ H# `1 A4 q0 P
(5)Cache支持的4种基本操作,使能,禁止,清空和无效化。Clean清空操作是将Cache Line中标记为dirty的数据写入到内存里面,而无效化Invalid是将Cache Line标记为无效,即删除操作。: L8 P9 n0 b! X5 n" p
" s. ?' Q& J1 c' k7 w) a2 R

- H* [) J( |/ |$ s# o四、面对这种繁冗复杂的Cache配置,推荐方式和安全隐患解决如下(以H7为例):3 n5 e$ T0 n# z: E
(1)推荐使用128KB的TCM作为主RAM区,其它的专门用于大缓冲和DMA操作等。
4 f4 w% E$ ], S+ S; l  q. g(2)Cache问题主要是CPU和DMA都操作这个缓冲区时容易出现,使用时要注意。
  V8 {( F3 |, H0 f; w(3)Cache配置的选择,优先考虑的是WB,然后是WT和关闭Cache,其中WB和WT的使用中可以配合ARM提供的如下几个函数解决上面说到的隐患问题。但不是万能的,在不起作用的时候,直接暴力选择函数SCB_CleanInvlaidateDCache解决。关于这个问题,在分别配置以太网MAC的描述符缓冲区,发送缓冲区和接收缓冲区时尤其突出。4 b4 ^: B; y) D* |# R! K
4 h. o, l1 H2 x) g5 X9 Y, y. C

; }9 D% t% }' a: _; r( M" p
赞 收藏 6 评论8 发布时间:2018-11-6 01:01

举报

8个回答
myccl 回答时间:2018-11-6 08:55:28
总结的很好,通俗易懂,但是中间有一段重复了
西点钟灵毓秀 回答时间:2018-11-6 09:03:16
非常不错,好好学习
baobo 回答时间:2018-11-6 09:52:25
好资料,学习了,谢谢。
baiyongbin2009 回答时间:2018-11-6 11:48:51
myccl 发表于 2018-11-6 08:55. H( K- h& K8 j6 b7 j! |& E- [4 n& X
总结的很好,通俗易懂,但是中间有一段重复了
2 W* u& W$ e1 V: G+ w5 B# Q
2,3,4的读是一样的
baiyongbin2009 回答时间:2018-11-7 11:25:04
zts329547875 发表于 2018-11-6 09:03
7 C' ?; M# s) i; V: B1 B非常不错,好好学习
$ @8 @- }3 s9 B; }
3111272 回答时间:2019-3-5 17:08:39
学习了
lwg8458 回答时间:2019-3-6 09:39:06
学习
jinling 回答时间:2022-12-15 11:05:07
您好,看不到图片,有点不好理解。能重新上传下图片吗。9 n3 B* b  R2 I0 G. n* x/ M
  J, J. ^  \$ [, \

所属标签

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版