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

【经验分享】例说STM32F7高速缓存——Cache一致性问题(三)

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题
) N2 P2 J/ ~8 _7 ?3.1 什么是 cache 一致性问题# m7 t9 n4 ~1 K7 J* b1 m
所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。" c% c! G) r+ {" W9 X# v6 l# B
) W; Q3 }% ?$ e7 ^* R7 p
在实际应用中,有以下两种情况:
' y* x/ N5 X% u  R0 x# H$ |
; ~; [- p9 d( t* Y' c第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。# [; K; U% @: Q% I; e4 _; m

9 W+ r, l- r# k1 d  K/ [7 v
516a4fcb212a09183f4c3f3efa77d170.png

8 ^# o- z( o, S5 \/ @0 p' }3 b" g' _
图3.1 Cache 一致性问题 第1种情况

" ?3 R# h, h4 f" O# _
6 ~* z& e* N4 z5 b, H第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。& Y$ _$ A. i. X# ?6 `

1 j; C4 e2 D' w% N
ba3341c9a0e0ddc198b5fe0466a465dc.png

' G/ `( r+ n* |* y$ a8 y+ N, q2 x+ B. f( S' }% b) F  L) Z
图3.2 Cache 一致性问题 第2种情况
+ w' F) v" _; j/ `) v
7 x0 ?+ ^+ P- m  c
3.2 如何处理 cache 一致性问题
* z5 U" c  J2 i/ l: i
我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。# Y( Y9 B3 r: c* h6 \
3 s: ~% O: }) ?7 A
因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。. i5 W3 A) Q' p0 }) X
" @1 T2 L( `4 L9 k
好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:+ |* C: X0 R; j' n& K% y
! u$ L! f% z! }
所有的共享存储器都定义为共享属性( r; a9 V: f, K/ ~/ Y! q9 Y' d0 Z
$ {: e* o8 C3 Z. l1 A8 h# g
这些区域将默认不被缓存到 D-Cache。
2 Y. `% B( N' X2 p, j: A3 F, t. J* K所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。( c4 ]6 w3 Q$ S$ a/ @2 O  [
因为缓存对这些区域是透明的,写软件更容易。  t+ T9 r; A, U3 Q& a7 G6 D
; V+ J4 N1 v# S" d6 q" l
通过软件进行cache的维护( j: u  x$ z7 k, G* E
(1)Cortex-M7 的写操作要是全局可见的& R. L2 _1 r$ e9 t1 O. F# |, D1 U8 _

3 L% @2 }( i0 y' t" f  {使用透写属性(通过 MPU 设置)。
3 R2 T; S; {% `' _4 ^5 H' o' |使用 SIWT@CACR(Shared = Write Through)。1 ]) W1 c& h7 e$ I
通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。$ H6 d) w$ P5 q) V9 C
(2)其他主设备的写操作要对 Cortex-M7 可见' n3 e$ u4 o8 w; _

+ Q" Z* Y% S2 b1 ?$ o比如作废 Cortex-M7 Dache 中数据。" O; }. p* k) u! N2 M, S
3.3 示例) x$ r3 S. y% h4 k
3.3.1 程序描述0 n( n3 D2 J  N+ }0 a8 I; {
(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。
' w* g- d8 V5 N* g  R% A, U(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。
8 s- ^+ Z* `# d! [3 f(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。
( Q- f6 S4 I/ a+ g(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。
5 ]* d/ f2 Y+ S) `0 Z, A
" e5 s. L2 ~6 F( ~9 O' h! v显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
# t& M$ a% K! j. }! B
  b2 {7 e# P! _3 |. `- F6 h程数据的传输流程和路径如下图所示:
8 e$ B- S& F( E# S4 a9 H& G. S. ]$ |, X- |4 L! Q) A
d0db73574a58707717ae26695e9dc302.png
$ X# U+ r& r) t

1 q" z( Y# ?/ {) e) Z. F3 d. K
图3.3 Cache 示例数据传输框图

2 D* n7 v9 u# o+ y. f& o$ ]4 w: Q/ @, V
3.3.2 复现 cache 一致性问题
. L4 e* d7 l) F+ |我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。. o$ e4 W! D+ w6 n% R2 t" W
  @8 v# k# P3 R# v/ R
本文所使用的环境是 IAR,其链接文件 *.icf 如下:* e9 n% `+ J5 E2 E' k
9 N% v/ r0 b8 }& x
5377967a69d8334b1bbd7b99f41c9e23.png
4 h( w3 e# D: r* {+ q

  k' J5 c8 F5 Q) r! E  v然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。4 K% P# ~# ~. d, e

# S& e6 U6 `9 k: |2 R1 @好了,代码主体部分如下:  e7 r. J. g4 J9 k6 h0 \# q& N

) M& |7 b. D+ l. n6 V* R
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)5 N- [8 W4 C9 W

  2. : h7 t; I' ~- K1 \9 U3 O
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =: B$ ?( y1 e! z( V+ A+ D. y$ p
  4. {7 C1 P- R8 M! \: k& O& b( l8 i* ]& H
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,; v' }' e& J& G' I+ U' a
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,6 k( y( [; `/ [7 O5 F
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,3 N" n: ?9 {+ j; x( q# m7 V0 t# ~
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,- b3 c# I- j$ w$ q5 [
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    0 v9 n3 [3 Z- Z) R
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,& L  d& ?$ m* q1 q5 {
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,! z  I* ~% F# _. \2 ~6 e7 w
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
    ( ~* l- k% Q8 N* D/ w$ U
  13. };! U/ m& E' u7 p9 L: R

  14. - N1 p5 k- w2 h6 T  B: r$ G
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];
    0 k' C; }+ S1 f: G

  16. : x1 b  D! [' H$ L# t  p& s5 L! o8 d
  17. int main(void)
    $ _3 r. l6 V4 \. }
  18. {) c9 L* c/ k0 S  t0 J+ \4 I  ]
  19.   uint32_t counter = 0;9 n2 N  T1 m9 ~6 _# [% A
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;" l" \1 T& R5 ]0 V3 k( R
  21. % W" f6 x9 S. e) R
  22.   if (HAL_Init() != HAL_OK)) j, K! |7 C6 i7 W
  23.   {/ m" A/ i# {/ a) Y- c* v
  24.     Error_Handler();' L2 S( i( `  Z7 R+ Z, [2 R
  25.   }
    $ \2 C- W: c4 Z
  26. ) R# B8 }# z# O
  27.   /* Initialize LEDs */
    2 i7 `+ W  P  W7 n$ |) w4 s
  28.   BSP_LED_Init(LED1);6 y% u. J0 w8 n+ @2 V

  29. " a0 v9 C/ H, C6 B/ j8 J
  30.   /* Configure the system clock to 216 MHz */
    0 G( F6 G! A% ]+ G5 m7 L; N9 d
  31.   SystemClock_Config();4 K/ _" V! {: r5 v: T) X
  32.   BSP_LCD_Config();
    6 n% d2 `) E/ m8 L8 I" a6 v
  33. ' f# m5 X; F" ^) Z
  34.   /* Set to 1 if an transfer error is detected */
    ( l. o2 ^9 R0 g& n4 R
  35.   transferErrorDetected = 0;) U) {' ^7 A( _' E
  36.         
    1 A; A# e2 S0 ^6 Z7 {
  37.   /* Fill 128 bytes with 0x55 pattern */
    8 N& k5 q* `, F
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
    2 i2 }2 u. v4 ?' K

  39. 1 W9 k, ^- W+ r+ n, [
  40.   /* TODO:Enable MPU and change SRAM region attribute ; U  q5 T. }# }' _9 ~6 w
  41.   * set write-back policy on SRAM */! O: g. n# p7 `5 s% w
  42.   MPU_Config();* v: n( T9 f2 ~) ?. c; T" }0 c1 Y5 n

  43. 5 i5 f. U! j) T8 m1 S3 w) M3 h, ~# E
  44.   /* Enable Data cache */  H8 J6 I% J$ i2 R
  45.   SCB_EnableDCache();5 j( V5 n2 B' P' G3 g! P
  46. ) L8 `& j# s8 E: q' R
  47.   /* Copy data from Flash to SRAM by CPU */& H6 _& z. g+ K
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)
    1 Z0 P& ~. k8 A- M$ I9 q
  49.   {
    - T; q  m& V. ]9 H* Z0 e
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];3 y% D! {0 I4 @4 P
  51.   }8 A# E' h9 V8 i
  52.         
    $ K0 L$ G$ J+ M8 b2 X
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    9 E- P7 K7 C/ e3 T
  54.   DMA_Config();0 S9 e' ^' o$ w% E
  55. - h3 v9 ~6 z  Y6 S' ^( M6 s/ h
  56.   /* Wait for DMA end-of-transfer */0 q( a! ]( c" H; O' W9 N

  57. ' o! J3 p7 N7 G: A( z) f
  58.   while(TransferCompleteFlag == RESET)! v! p+ ]# g/ Z
  59.   {: a; X+ g; F( ]' P* }0 _* r4 [
  60.   }' B' t3 o; D2 r2 m

  61. ' T: a7 G1 I0 ?! C( ^
  62.   /* Check data integrity*/$ U5 l9 V( e; Y! `( t1 V
  63.   pBuffer = (uint32_t*)&aDST_Buffer;
    - ?. E0 y9 z  d& v
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)( X5 Z1 Y8 J: c% }: [
  65.   {
    9 _9 O# d6 w& f4 ?( U( G
  66.                 + B3 L: h# B0 r1 I
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer); T3 e2 k1 \- x' L' q6 i. _
  68.     {1 i9 p6 C) C' P1 Y+ T
  69.         compareErrorDetected++;
    4 X* I; W5 t9 s% m# T  E
  70.     }4 ^) N3 d' m; B) Y
  71.     pBuffer++;) d" |! H% w& U3 a
  72.   }5 n+ s  P0 m2 J% R  |& k
  73.         / \/ L9 }5 ?& F
  74.   if (compareErrorDetected != 0)
    , Y3 p! ?( ^% G$ g. o
  75.   {
    & O/ z/ }! N! F5 b( T4 l6 p) n. O
  76.       /* Toggle LED1 */
    8 q5 a0 S& b7 ?" k+ W8 w  v* J( a
  77.       BSP_LED_Off(LED1);% p) ]# g: _) G5 {7 b7 w& }
  78.       compareErrorDetected = 0;        , F2 }7 p1 l, o1 V: \7 t) u
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");
    . M9 R8 k3 ?' B  Z1 D- I
  80.   }
    + P) p: Z' N7 V
  81.   else
    " d; q. V3 Q9 Y( s& ^8 {7 o: ]7 Q7 R
  82.   {, }& \3 f* i) b! e( e* R+ ?  T
  83.       /* Turn LED1 on *// ^! e8 c, s: r$ c( Q5 M! k+ z
  84.       BSP_LED_On(LED1);2 |9 Z4 L1 J  P+ [* O- ?5 \& b6 r
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");( O0 E2 \6 i0 P: Z0 z: F8 r
  86.   }
      {5 O% d6 o0 H8 q5 f+ {
  87. " l4 h9 r- e5 W  e, c( `: x- G/ P9 ~
  88.   while (1)
    ! f6 {4 b) l! y. K; J3 X: o  B
  89.   {+ z  S$ p4 H5 x/ ^! t/ b% v

  90. 3 F' d# j3 ]! ~1 m& r
  91.   }  r2 H2 \2 k  v. y% L
  92. }, u9 P1 G7 @  e* d1 o
  93. . \" b- J' `3 Z8 {% z: i" r: v, H
  94. static void MPU_Config(void)2 `; ?2 S$ h  j. @3 G7 d
  95. {( Y, y  u; Z( w5 h
  96.   /* Disable MPU */
    ; h# P1 P( e, [" Y. p& |7 c
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;) z# P/ i2 o0 S, v1 M; x0 ~8 d

  98. . d  `  O# Y4 [' d( k; Z
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */2 m6 m- X" i- `; r. X, x8 p, W7 x. C* E
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;1 F; `; P# j$ w
  101.   MPU->RBAR = SRAM1_ADDRESS_START;
    - P3 f' T7 d  @3 L1 k  r
  102.          " Q8 w: E9 }$ @  n- E9 b9 V' @
  103.    /* Write-Back policy */
    ! e& Q2 n! X8 T2 A; b+ K# }6 ~* X
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;
    , w& Y* W- C$ I$ ~& L2 e
  105. ' L8 t6 |$ W# F8 j
  106.   /* Enable MPU */3 H+ D# ]! J6 f4 |  C2 m
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    ; T5 y: E1 U7 I* D
  108. }
    3 N' g0 O6 k* O
复制代码

% t8 A: E( i& R为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:$ S4 z" }5 z! G9 U: ]  r1 ~. d

4 {4 y6 S/ d7 G
d4c481b36d81bb11f17b07a56ac1f054.png
3 _9 h1 K0 K* [- O+ H& V: D

8 ~$ O+ _# y  Z) W% ?, v5 X
图3.4 检查常量和变量分配情况
" n9 u2 a* Q" `/ o5 V( s" Z

5 J! l( u& r5 @6 x5 b; A, `! a$ y( d下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:8 {  t7 j+ u& m) V# o2 x4 m2 ^* H

6 r$ Z; N2 W' l/ L1 \3 I
bd661d50dcd8f45abeeabdd2ac3c0289.jpg
7 ]+ x& s$ g' v- ~* c" ~
' C+ u  X! k- b+ j( x! f6 |
图3.5 Cache 数据不一致
* G  ^* l; b: @4 u5 u- Y; y: j
" G( o/ f+ {. y1 K5 V0 @2 }# D
3.3.3 解决方案$ e. o. o7 U7 N% R# g8 c
(1)不启动 D-Cache
4 T+ i% G& k6 ]2 ^' m# u* O  N
7 g- P) ^" ]7 @% z! N注释掉 SCB_EnableDCache();
3 J* x% L9 {4 M+ ]! M9 U
, N! p  x# }" `6 c4 Z- J" n不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~
+ n2 L- G9 ]9 m, A0 @
' a5 f8 `) P9 t# l2 [: p(2)将 SRAM1 相应区域设置为 shareable3 {/ f* s' ^3 i+ x* y, k

9 P. G) i$ I# V4 @1 i4 v9 `0 I/ ~! E, q通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:
# h# z$ q" X# a7 C
  1. static void MPU_Config(void)' A! E/ g$ K% K% H+ |! ]3 I
  2. {; u. j' k, x1 w1 g5 |  n
  3.   /* Disable MPU */: Y1 Z5 I. P3 t) S1 C! Q) G" t
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;. R2 @. v8 P# H( I/ F
  5. . ^' W% F. Z, E5 b. J0 i0 D
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    ! a0 q6 y  z9 @& p% J: ~. U3 N
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    , K/ _# Q0 Q- j( u; p
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    3 b5 W- q  m2 ^+ W) _4 B
  9. 5 G3 D" e' n, R6 d
  10.   /* Shareable */
    0 T$ {$ J" J& K4 _  y
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;0 K& g- S' E3 S2 [
  12. 5 V: g- ~8 Z& g- ?: D2 v' A# f
  13.   /* Enable MPU *// l( j8 ~, G5 l# j  Z2 t
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
      \' t8 Q# Z$ s) ~, m  C3 c2 P4 }
  15. }
复制代码

* V! O# m+ D! d& V; _) r(3)DMA 访问 SRAM1 前先 Clean cache
- [4 u4 i$ A4 P6 b! C, @  E+ P; n% G' b2 d: Z' ]; N+ |( M
在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。
9 _) }% K9 `8 e
: S) N$ R% q) Z2 z9 z* g( |: A) n在本示例中,可以在 DMA_Config(); 前调用:8 N( l* x! {  h  D
  1. SCB_CleanDCache();
复制代码
或者
4 q8 M) s6 J" ~9 s" n2 `
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码

7 K3 H' K6 N% E  L' b5 B9 a2 s; D(4)将 SRAM1 相应区域设置为 Write-through 策略7 O3 T$ q' ]* O* N8 A% c, \

- T: \% \/ N3 F  v8 }8 V9 s6 ?通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:' T3 D% U7 o; z- J' w& e- i
6 A0 P6 [7 s. a7 }
  1. static void MPU_Config(void)! q& m5 _7 Y, w
  2. {( c" d/ B  _7 z$ a7 t6 C! c- O6 D: j" ]
  3.   /* Disable MPU */
    5 l  H9 f6 l! ]# w/ y3 }. d4 Q
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;; T0 G; o3 B$ @' c
  5. , q# z  ?  Q3 K" Z5 d) E1 ]
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    . x7 K! ?/ H, @, `5 ~; R
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    , G, X) S% I3 x4 E
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    : E; y! {& t# d  |2 F& _- W

  9. ! `* P- T- q. L
  10.   /*Write Through policy*/
    ( U2 O/ l2 I% W
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;) }/ H( I7 M) S

  12. - {3 D" b; m% h. X" [
  13.   /* Enable MPU */
    * K' D8 ~4 J1 N0 d( d+ K9 ]
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    % a3 N" E. k, C6 w7 a; G  g
  15. }
复制代码

, K7 A( C# l$ c2 m* R  P(5)将所有 cacheable 的空间全部强制 Write-though7 @* M" W& |- X0 y2 g
( J: R4 d) W& e0 o
通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。2 l1 F8 s) V$ T# ]. K/ u

# `& _  @- X; R/ j2 j3 d. {4 g
e131d05081f8e30ba2296e50f3e9f392.png

2 u& M* J" y2 [- o  U
- a4 ^4 ^% I% r% L4 M
图3.6 CACR 寄存器(来自 PM0253)

7 S9 l; r' N8 i' s/ d" m7 ^
' |' t1 b% X. Z5 ^在初始化的时候进行设置:
* O! ]/ v: q! Z! s+ |* P
  1. __FORCE_WRITE_THROUGH();
复制代码

# ]% I" H0 n: v宏定义为:" _1 W2 |% H  V/ o! P/ ?& a
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码
( g5 h* T! w3 ~0 j- ^
以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!8 x& A! S( v+ C7 b6 c" M, }5 l

" X/ I# S. H2 W2 V4 x6 i) \9 a# x值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。/ g, }/ f, N! F: Z$ \! l. c+ x
+ ^& ~5 o  f$ }5 O; w5 H& K7 [
9dffde7b310ed170c1b45f9dd7f75abe.jpg
7 ?: i/ r  R) F$ e7 t" v
4 ^5 m5 A  K  i5 ?
图3.7 Cache 数据一致
# J# }) Z, _! b$ u, |
7 \( [% W! K5 Q6 m! x4 d8 E; u
好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~
3 x! B: Z" |& u8 h/ u( G/ w7 p3 W4 E1 Z; i

  W6 m( V0 W  @( t6 I  ~& ^1 |$ P4 p9 k7 D
收藏 评论0 发布时间:2021-12-13 23:02

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版