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

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

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题
: W: d0 \, E1 n+ D+ q' c& z3.1 什么是 cache 一致性问题
4 ?  u% Q9 \, Z* E0 O5 F所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。9 u: x; q& x9 W/ J/ t% y& w" x
4 T# Z2 g) r6 U0 h, y% A/ J$ T$ |
在实际应用中,有以下两种情况:) ]) i* v! |0 C

; f# q( M! o1 ?0 m! k6 e第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。
4 ]0 G) g  Z8 U! Y9 ?/ P6 z' o8 S
516a4fcb212a09183f4c3f3efa77d170.png
1 A% G; \; Q7 t6 W. v

+ J5 }6 K- Z1 x$ F7 b/ `/ V5 g( e3 y; C
图3.1 Cache 一致性问题 第1种情况

/ f2 e( {  m) j  `2 m' p+ s$ O+ ^+ C+ |( Q" ~2 \4 U
第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。
5 o2 z0 e; e( F1 E1 k0 Q" w  ]* m% v0 Y! F
ba3341c9a0e0ddc198b5fe0466a465dc.png

$ Y! L# b) c" F
9 V% u$ A6 \0 k  I6 [; {3 z: o
图3.2 Cache 一致性问题 第2种情况

" o+ L$ w+ ~, o8 l% m4 ]/ V; }6 u7 z4 s! P# H
3.2 如何处理 cache 一致性问题

* _& x2 z1 t7 L/ x  m: w( @8 ~我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。
7 ^& K4 n# V" K2 v
1 P% X2 n1 r: ]9 U6 r因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。
- i: n' Y9 ]) d9 g7 @& ~% H: m2 f, }3 u+ t7 O+ i, B
好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:
1 T7 R- k4 B& M7 o( \7 x9 }! n" @* d1 n
所有的共享存储器都定义为共享属性
4 s9 ~; G& y8 t, l6 ^/ }. ?
4 i# P& I0 Q% U% Y这些区域将默认不被缓存到 D-Cache。* n; E! Q* J9 y( |/ [0 ^
所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。
# @+ ^: C, G" i8 f+ p' z因为缓存对这些区域是透明的,写软件更容易。
3 b( [$ E. L! X1 A; l5 y: T" Y) g+ b( H4 F. Q2 n; p; l
通过软件进行cache的维护/ R) f" k7 z! g- U# n3 j  o* z" A
(1)Cortex-M7 的写操作要是全局可见的
: r0 f/ C2 L5 P' K+ u
1 z/ K+ p4 r1 p& S使用透写属性(通过 MPU 设置)。' V" l8 C6 N3 @; \6 P
使用 SIWT@CACR(Shared = Write Through)。# N8 a9 R# s" h9 G$ V: w
通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。3 L/ g0 b+ N- X; ^7 X& n
(2)其他主设备的写操作要对 Cortex-M7 可见
1 w' ^* b7 z9 c" Y8 N' A9 u
$ \9 e+ j1 H, U) W% d比如作废 Cortex-M7 Dache 中数据。$ j. c% Q7 y: b7 S- T  q' f
3.3 示例/ M& K5 \" }# h8 I8 t/ \
3.3.1 程序描述; R3 \  p& O6 k2 V& z
(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。& \5 ^% H+ L. f: `2 |& ^5 |6 B6 P. A3 M
(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。
8 Z# x1 F: F/ U# G: }2 Q/ a(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。
. w9 c( G8 D& z: m9 y. w4 _: n(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。
& z7 C2 s2 z! m$ e
$ v, ]: d, Y; p2 {' m7 V显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。. j3 m7 a2 Q' k9 e' I8 }

. {4 i; }3 n( t3 P# \  V程数据的传输流程和路径如下图所示:
/ g9 m8 C/ g. ^# m- W6 y1 }7 N
0 `3 M3 Z; z4 z8 n% {6 N
d0db73574a58707717ae26695e9dc302.png
7 ?4 q9 W/ }# {" i# M, c0 M, U3 o

# k4 a% I, |2 O8 J" \7 p: \
图3.3 Cache 示例数据传输框图

$ n  S+ t9 Z' r; g) g. z  A/ O) z' R6 X1 u) E
3.3.2 复现 cache 一致性问题
: O% g/ H$ m5 b6 D; B& g. ?我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。
7 q& {0 k: i: D2 g8 L6 ~4 D5 Y0 X) q  J! j% D" k! f. v! m7 |& j
本文所使用的环境是 IAR,其链接文件 *.icf 如下:4 k: p; a9 S- x( Z
2 U% B: V: ^0 H: E4 A9 j4 V
5377967a69d8334b1bbd7b99f41c9e23.png
# j5 W/ E, e/ X3 b
8 N+ x7 N) A+ G( A
然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。. K9 G) z$ P" M1 |. o5 L# {
. ^" B; c+ l9 y9 P( f( b+ V6 i$ X" }
好了,代码主体部分如下:
( ]. W' L% O% J# x
" I! o8 M- Z1 Y; ^: ]8 \8 d
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)! l  E5 ^  H& D6 B( o( k1 ^

  2. 2 r. i0 m# F( q( e' V6 r, G: g# X
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
      g9 H' J/ \1 Z- [
  4. {
    1 y6 \' B5 e9 R" _4 I5 }1 W
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,0 L( V0 b, I* _) K$ T+ F
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
    5 I' n: i1 k5 A9 r/ A% W, q$ S  y
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,- R+ z6 u0 ~& L- y9 |
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,7 N0 i7 `" f6 m
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,8 |9 y$ S( ?+ ?2 U+ v
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
    5 A1 X! ^4 r' s
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,; r2 a" _  c: h
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
    % u  e. n! E' s0 s' @
  13. };# Q. S9 V0 B) a3 e2 o% k( ]' J- \

  14. ( T. a- y% [  ]. }5 Q& h
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];
    % m' W. [; J; G% M; n2 z& G- F

  16. 9 b' z# G, e; i! M4 X+ e, M
  17. int main(void); D( ~" t% {. _2 m* Y
  18. {
    " M% R+ ^( K. p0 _& r- z
  19.   uint32_t counter = 0;
    / S/ X% E7 A) K4 X9 }
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;
    * N( f% [7 F$ Y( s9 [1 V
  21. % l% N; l" ^6 f* ]4 y; z
  22.   if (HAL_Init() != HAL_OK)& I' e9 T& k! d0 u
  23.   {" r- E3 r- d) \+ H/ G# O3 F
  24.     Error_Handler();
    * I# R, x! y3 L
  25.   }$ B2 {. w! D% G3 ^# h1 \. @
  26. ' e6 L$ f2 y! d- x& B' C0 N, k; P4 {
  27.   /* Initialize LEDs */, m+ l: q5 K/ H& v
  28.   BSP_LED_Init(LED1);
    0 {  ]) `/ D' U# i' g- n
  29.   y% c. _3 f: I& h% F- V: }
  30.   /* Configure the system clock to 216 MHz */' e9 f- P$ W2 s- i! {) k. L9 R
  31.   SystemClock_Config();
    - r. T" L' i) o
  32.   BSP_LCD_Config();
    ) r1 v& L4 ?$ W( V, Z

  33.   E: _0 V7 d' o) z: z
  34.   /* Set to 1 if an transfer error is detected *// k& C& E% X- Q! _+ J+ b) J. c3 p
  35.   transferErrorDetected = 0;" Y# m! H6 w2 C! c, E& B  @+ v
  36.         : [( z/ Y( Z$ t, x, \/ d% `
  37.   /* Fill 128 bytes with 0x55 pattern */5 E- X2 W" r/ R  ~# m
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
    0 x( l/ f! I6 ^" B8 }
  39. ; |6 r; G) Z; w# Z. U3 X  t
  40.   /* TODO:Enable MPU and change SRAM region attribute 1 t* `5 h  a7 f; I1 n
  41.   * set write-back policy on SRAM */
    & I/ E0 b8 K4 Z3 L- P
  42.   MPU_Config();3 C# N5 i) Q. E) n
  43. , R- U' t# i/ P: j; Q4 q2 L% s9 U8 u
  44.   /* Enable Data cache */
    + g3 j  ^- [/ |
  45.   SCB_EnableDCache();; K+ }( q3 W2 b! F+ B( B- U

  46. 0 ?8 o' R. [" D2 w/ w- [& G7 z
  47.   /* Copy data from Flash to SRAM by CPU */% o* M* A5 U3 M* `
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++): D1 h. T9 `) c( t3 L
  49.   {
    / J( W3 X( I, W+ b; B2 E+ I5 C, Q9 U
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];6 t' |% i  S" k1 L. A2 |5 L% k
  51.   }
    $ v0 f$ `8 Z6 {* n3 C
  52.         
    ' {0 K% |( y& {) m1 [
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    ' |  ]* P8 P# [) J7 ?
  54.   DMA_Config();
    $ |! u( s; b( N3 M) I

  55. % M" b+ _, {' U4 O5 x; k+ m& [
  56.   /* Wait for DMA end-of-transfer */
    & M3 z) u# a! J8 V" @: v

  57. , W$ n3 P* m, ]6 s
  58.   while(TransferCompleteFlag == RESET)' {7 i7 o0 u  d1 l& `, J! K2 k2 x+ z2 G
  59.   {
    # F8 ~7 [* d; L; K* O
  60.   }
    " f8 @! L# c# L5 v. O- G9 C' D

  61. ' e, h# R" U/ f# U7 g5 [1 |
  62.   /* Check data integrity*/
    " F) Z/ }! q2 i/ s2 Y4 r  F& [+ ?2 ?% m* w
  63.   pBuffer = (uint32_t*)&aDST_Buffer;0 t# f- S1 o9 J
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)
    7 _  ^" r2 ~/ W% S' Z6 I
  65.   {
    3 h- z: G2 R3 c' R$ }! O8 k
  66.                 7 T! Q* B: {) E  A) @
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)1 {# x) Z' V0 o
  68.     {& \2 V2 a- V/ P# ]5 L5 v$ n, x
  69.         compareErrorDetected++;
    & p2 C" `, i& U! B) e
  70.     }
    ( L, F) n8 {7 F
  71.     pBuffer++;9 k+ ]" V) Z) q7 ~* I- p5 x  C% l; j) F& @
  72.   }% E+ j; q2 d0 Z, B- F# f- B  O
  73.         
    ) {$ F+ q) I# @/ ~, w
  74.   if (compareErrorDetected != 0)
    / ^0 R% T4 _4 t+ n  ]* x4 Z& n
  75.   {
    ' d% |2 T$ P1 X1 S8 ^* |/ s% L
  76.       /* Toggle LED1 */8 L( Y: |& a1 R! L  e
  77.       BSP_LED_Off(LED1);
    9 j) V+ y) a. `1 J
  78.       compareErrorDetected = 0;        
    . Y. D+ S1 E. @2 r( L# l( ^
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");) r0 f6 m, c* n9 d7 }, U3 T
  80.   }
    # A. T$ A1 J4 H2 u4 e/ r$ H8 H0 Z. Z! H
  81.   else
    8 o! o' }: a2 z  g) H5 {$ D
  82.   {% ^& v: i  }/ v& X' ^
  83.       /* Turn LED1 on */! b. D. N4 e% d( L' ^8 @. A
  84.       BSP_LED_On(LED1);
    ; ^4 d# B$ T6 f# q
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");" t& y' J, ^/ d; v
  86.   }( S& E' e) R1 _7 x; F- s
  87. 8 O. F6 r- a5 r0 Q1 b7 b& r& K8 J
  88.   while (1)
    " }' ^; g5 ?6 ^/ J- }. _2 v
  89.   {
    : l7 ]8 W9 M; S3 K  {: E
  90. $ {1 b' y6 G0 U; ]/ R# p$ b
  91.   }
    3 q# ~6 a4 m" [; A
  92. }
    6 b4 S  K. _" v+ J% {6 S
  93. ) E& I) k$ |7 W) R/ \
  94. static void MPU_Config(void)
    ! ]7 I' |8 `8 t) B2 `: l
  95. {& k4 Y# [7 c/ p( G+ T
  96.   /* Disable MPU */% v& C1 S% V1 q- y5 B' \9 f
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;, P/ v! m! |0 g
  98. 6 C3 r/ N; n3 F) c  X5 _
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    8 X1 L4 F$ W( H6 [5 n- f. {
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;" I9 Y/ O/ h0 P( O
  101.   MPU->RBAR = SRAM1_ADDRESS_START;
    # ^" t9 A. P0 Z7 B. Z
  102.          ( |, h* w, e1 [7 _, M, N$ t6 {* X
  103.    /* Write-Back policy */
    3 i/ D, h) `5 n$ u6 Q8 U5 U* X
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;$ P9 @" Z* C3 J( c0 f$ u
  105. 9 f+ ^/ b  H5 {9 d
  106.   /* Enable MPU */8 q! H  D3 X; q7 t5 ]! e: j* j: A
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    1 G  c: B9 l3 l# e1 B
  108. }
    7 A; D+ {; w3 F# U
复制代码

2 r: {1 [- r, c' c0 ]9 Y% g+ O! f为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:- H  ^! D2 v) a
/ g& E( g. r7 O9 z8 E! T8 o
d4c481b36d81bb11f17b07a56ac1f054.png

" A8 u4 d& \8 t" q
( @- S6 O( Z6 y0 A2 s
图3.4 检查常量和变量分配情况
( D3 ?5 f5 J2 @

. q3 s/ z  m) S; k下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:) P. I7 v: D, Q4 x
9 _$ o9 v4 F' T5 Y$ p0 S) R
bd661d50dcd8f45abeeabdd2ac3c0289.jpg
2 M: e* }; F8 ^1 y

, v% Q0 s3 z3 E# Y( _6 i
图3.5 Cache 数据不一致
! x$ x% X$ t' W* `& }- x5 o( h
9 O* r8 Q) {- O
3.3.3 解决方案- r1 I. b# N: `  W) E
(1)不启动 D-Cache' O: `% R9 g* K) A  V! v
' m/ a3 I. j' B  }
注释掉 SCB_EnableDCache();
6 R! p' @$ [3 R  k2 t1 W6 f+ x6 V6 Y
不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~$ Y4 }% `3 ~; [2 V) g" ]  N/ H. K+ }

- `9 K4 g1 j8 b% B: B  b(2)将 SRAM1 相应区域设置为 shareable
  g  o' i6 {2 J+ }( p6 u0 U
7 G8 ~; |6 U' M( ?1 _% Q通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:, e3 A: f, h8 r; n- b
  1. static void MPU_Config(void)
    1 M# x* e8 `- f  s6 H. m3 J
  2. {
    ) k+ y- F$ z. @# }( ~/ H5 C/ Z) T
  3.   /* Disable MPU *// a9 I) |: b- r8 d1 Q: i
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    ; l, S# c' D9 n  U
  5. 9 J% n% B  p- E; o0 C* z; W% l
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
      w( u% e- V( R3 g4 f& ?
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
      O- X. f# x& c+ U6 W" d
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    . J" k; z  ~% ]
  9. ! j8 E7 k1 i/ w; n1 U0 l
  10.   /* Shareable */
    ! x7 e/ ?. r& ]' D. D- y
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;( J5 @0 e( [( y- b/ Y) v$ N1 W

  12. & ]/ Q5 s. K  h7 V0 u0 ^2 [
  13.   /* Enable MPU */
    2 i: L" u* @" u. a! b: _$ C% ^
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
      Y9 B! y) U8 T, V
  15. }
复制代码
" ]3 [/ k" \  p% `
(3)DMA 访问 SRAM1 前先 Clean cache
4 I, r; f& _+ B8 g/ t3 X$ A& e" Y/ n' w; Y
在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。
5 S# a3 p5 g; o# d+ p
* I5 T) a& S  C8 r在本示例中,可以在 DMA_Config(); 前调用:  n* B% F. }6 W2 W$ k
  1. SCB_CleanDCache();
复制代码
或者6 W  I9 D) g- W) ^* t% \6 ?
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码
. Q/ V7 ~" s9 Q9 }
(4)将 SRAM1 相应区域设置为 Write-through 策略  j3 e! b, B3 |6 e  {" \# ^

7 C0 \* O8 r3 e+ M1 F通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:7 F( [7 I0 s1 Q  z$ P8 _0 X

0 x  g# q% X0 Y+ `  J7 p1 u
  1. static void MPU_Config(void)
    0 o- f1 i  {: X. {" F  P7 Q% ]
  2. {3 i- I6 O/ q7 {  I0 V; v; |
  3.   /* Disable MPU */
    1 X! C. s3 R5 ?" o* N
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;/ D1 d3 A" c& g9 ~) v) D
  5. ! J9 I  {$ |" n, s& N2 [% M) R
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */5 |8 v* [+ e7 b0 f; F& R
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    ; U% d3 G9 ?9 a% r$ [
  8.   MPU->RBAR = SRAM1_ADDRESS_START;! G) z0 @( I1 M# c/ N0 P& Y9 R

  9. 0 S' t: D4 T: G4 W+ z' T
  10.   /*Write Through policy*/# H9 _2 H5 g! W( V4 U
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;$ ^$ w. G! t9 E6 u! H

  12. 0 W$ x+ x. ~  d
  13.   /* Enable MPU */7 i0 W2 b/ }2 ^  O# H
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    4 q% `- F* D9 j  m; `! ^' P8 r! X
  15. }
复制代码

% r$ i4 q/ o/ b- R(5)将所有 cacheable 的空间全部强制 Write-though' V2 N! ]1 o: k! Q
' d- u+ s) c  J
通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。% ?: R- d( {( I5 i3 D

/ |6 @  G0 [" u/ Z
e131d05081f8e30ba2296e50f3e9f392.png

# z) f/ K/ r  `5 h* E# r$ n) G* h* J2 I" `
图3.6 CACR 寄存器(来自 PM0253)

5 l3 X1 @0 Q# h2 N+ Z/ o% X  Q. b& X1 t5 `. g0 w; y  s) h, K
在初始化的时候进行设置:
1 E% t* O; \* s" x9 g5 w5 f
  1. __FORCE_WRITE_THROUGH();
复制代码
# k6 B) N" S3 F7 }' e. j& A
宏定义为:* Y- W5 j; J9 G0 z! O" w+ H4 T& G
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码
) B% Z( U9 e/ k1 h
以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!4 V/ m5 L8 G4 H

. u7 U% V) G9 `# M. M值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。
" n" k7 m; T7 \$ P$ I. e  {  g" D' |9 F
9dffde7b310ed170c1b45f9dd7f75abe.jpg
9 A& _1 x* v- ]

4 \- x2 ~( H$ }& z0 ^
图3.7 Cache 数据一致

% i# ]9 \. v  F6 N" G# A8 s; X2 e7 v/ Q, F1 l
好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~
5 x% x, \! g* @" E$ S
. D5 _* e! P! P# L7 J8 h, f# W$ ~; E" w- U' L3 t" M
4 N$ s  B  S6 s& G+ O
收藏 评论0 发布时间:2021-12-13 23:02

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版