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

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

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题( D  j) t3 a8 `! w/ i' |1 v& L1 ~
3.1 什么是 cache 一致性问题
4 C& V, |1 c4 Z% J所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。6 R; o, z: q) E4 F8 {% F, `

$ `3 k6 g+ K2 s0 J在实际应用中,有以下两种情况:# Z4 a1 ~- O$ S. _% k% r
6 Y0 g8 o! k" u. ^
第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。8 a" l* g/ H4 v# g
% _4 E4 `5 y7 c; [
516a4fcb212a09183f4c3f3efa77d170.png

5 c9 E$ u  {: ?; R2 i, T$ m
( p8 @/ \" H" f1 K1 q1 ?& w
图3.1 Cache 一致性问题 第1种情况
8 \0 J: L) [) e' Y9 g' z# k- t
8 |9 x6 `" ~" g! p& N+ v* P3 K$ b8 @
第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。
4 \* Q1 }6 a1 ~3 o* L, m0 W& [, N$ \4 }' ^/ m  p. K
ba3341c9a0e0ddc198b5fe0466a465dc.png

0 r4 U, n0 R4 w8 Y! V
7 F$ Y0 q2 Z- n
图3.2 Cache 一致性问题 第2种情况

( W& G$ y4 N' b$ S, D. Y
* \" [5 j7 G- I$ a3.2 如何处理 cache 一致性问题
9 j. g4 s# b3 R: A8 ]
我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。
& I6 ~- a" V* t% x# @3 q3 N0 J; c4 P- z: ?  z' y& h, E5 d& z
因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。
+ |+ {5 J: i" C, q; W  ~
6 s4 ]$ ^) l" L# X( N好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:7 V, u. Y0 R5 i: B- n( S+ ~$ u: W

/ O1 J2 R8 f* c2 a+ r$ L所有的共享存储器都定义为共享属性8 ?6 Q' W0 r( V4 g% a9 F$ f

$ g* M! h/ o. u( I这些区域将默认不被缓存到 D-Cache。
& K5 Q: w/ {! [6 {所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。2 S" c$ p, B. P3 I' q
因为缓存对这些区域是透明的,写软件更容易。
- a+ Y( [$ [0 L9 R$ g& \4 ]( H2 p1 ]' H$ c; a: v. G' E7 ^
通过软件进行cache的维护9 `# K* a0 @7 p. {/ {
(1)Cortex-M7 的写操作要是全局可见的# S% K5 q% u* F% m, t+ t
& t& u' M  _' |1 Y
使用透写属性(通过 MPU 设置)。# X2 `3 |2 [+ q5 h+ Z% R
使用 SIWT@CACR(Shared = Write Through)。
- j. P. y8 T: Y. F4 O通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。* x( x7 R0 n" d" z: _" @
(2)其他主设备的写操作要对 Cortex-M7 可见( Z+ u5 P5 e6 E4 K! p5 ?9 N& ^) V3 t

+ O! d# ]/ ^" A2 c. G7 k- g比如作废 Cortex-M7 Dache 中数据。% I2 }; k+ r( }+ k, V7 V8 V& F
3.3 示例9 D( V# U$ }8 f% D% J4 p
3.3.1 程序描述* t% [9 ~5 X' N$ U8 |
(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。
% F# I4 y  G. K1 z(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。5 G/ p( I2 ^( H) O- g! `. ~7 l
(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。5 h' ~* g9 h% j0 s( e) K: X- J
(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。
: r, Q$ E( _9 @- H4 j& M% ~" H; M" f' P8 O4 ]
显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。0 U; u/ p/ |* g4 d1 |% I

( B3 _: C9 a* d% ~程数据的传输流程和路径如下图所示:: R1 s* m& q/ r- {9 H3 d
0 S! B+ r" |* B
d0db73574a58707717ae26695e9dc302.png
$ r% p" y) w6 b  Z
" v& c. E5 s5 Q7 c
图3.3 Cache 示例数据传输框图
1 ~! K* G6 p* _  q" B
; m* S' H$ \. ]+ W5 s% d7 Q
3.3.2 复现 cache 一致性问题
2 H/ l3 o) P$ w: o我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。; C1 ]+ C! R& L: }7 z4 [
) W6 j3 a5 q% O2 N, ~
本文所使用的环境是 IAR,其链接文件 *.icf 如下:
( u- E6 \' u* l7 U
! U! N% K" g& w# V# z0 H' o& }( r
5377967a69d8334b1bbd7b99f41c9e23.png

$ L$ A* R& b& F' l: _6 C+ Q' _3 F* g& |
然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。
- c2 K4 h8 m' c$ @3 W) P, v1 c. Z) Z. D# d) Y3 V0 a+ ]% \7 o0 ~2 I
好了,代码主体部分如下:
4 ~" x# ]+ `( ?8 `  v4 P
' }5 t; W& g  `0 `; h' ^& Q( i
  1. #define SRAM1_ADDRESS_START   (0x20020000UL): P( k: b; K+ T/ |

  2. 3 {( Z# K& l! T4 Z, c; [
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =2 l* w; E' g: f& m+ ?
  4. {
    ! y! }. P7 a: u' |
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
    7 m. Q, H2 j5 Y$ ]8 L% f
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,. m2 ?# o3 E8 w3 C0 H( S  K  z* ^
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30," u. g4 L; e% b* ]* F
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,: k( J% e2 N& A& ~( f0 ~3 [
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    1 V. `7 s0 z8 T: H, |6 t) i  ?
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,/ I/ G) ^/ m4 J3 ^
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
      I0 b& v/ n. O( P9 j. N( j
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
    5 q2 p7 _; t9 b; v
  13. };
    4 w$ y& m! p0 j" W5 G3 {  _

  14. ; t. ~4 o( Q8 t: x5 O; j
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];2 f5 ~6 t3 Z1 U3 D0 h; d; c) L
  16. ' q5 ^6 e/ w" i. i% J  k& l& e
  17. int main(void)+ C! p, L2 `( \  O# M7 v5 ~
  18. {
    7 Z, G. E! b" @8 K' Y1 @0 g7 T. a6 _5 @
  19.   uint32_t counter = 0;
    + ~2 J& B& S5 K! \/ `2 H3 V
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;
    ( Y& }6 [$ I: }0 F+ ?& t
  21. / v+ @. Y% J% S# ~7 Y
  22.   if (HAL_Init() != HAL_OK)
    0 r$ {7 u* |6 T2 S
  23.   {1 L* H4 _( w, t0 [3 P5 _+ @
  24.     Error_Handler();
    * b  N2 w- b" W5 q
  25.   }+ v+ H1 m  g2 S+ b% m
  26. ; M1 J1 b5 d% _- ~2 b: ]
  27.   /* Initialize LEDs */
    ; D# z0 x( y3 P; }+ r/ Q5 N- u
  28.   BSP_LED_Init(LED1);( T/ P5 `1 {; S% c9 S

  29. 4 p) g! @% A3 k1 r( w$ I5 O: _
  30.   /* Configure the system clock to 216 MHz */# }8 s9 g- \2 n, l
  31.   SystemClock_Config();3 F1 f+ v3 p! G; b0 W4 b2 l! d
  32.   BSP_LCD_Config();
    $ F- C0 O- i. d+ Q7 C9 P
  33. ' D: _9 v9 x* s) k. \: J
  34.   /* Set to 1 if an transfer error is detected */* V! W5 p$ O( R0 Z
  35.   transferErrorDetected = 0;
    , M' u2 y" B, u
  36.         
    ' h1 Y- i8 r; ~; [" X* a$ U
  37.   /* Fill 128 bytes with 0x55 pattern */
      ]% W0 a9 l7 @+ G# C
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
    1 M8 B( y4 b% e0 Z6 H1 }3 `

  39. 2 k5 \  C0 a7 w5 C! k
  40.   /* TODO:Enable MPU and change SRAM region attribute
    * ?: |$ n- |) X
  41.   * set write-back policy on SRAM */
    . f) ~( L2 O5 t9 D8 J: v
  42.   MPU_Config();
    8 a1 h6 v( x; t' F* a: n& m
  43. * z/ C5 e( Z# W
  44.   /* Enable Data cache */
    9 |! E4 t, u  \- v: s9 G
  45.   SCB_EnableDCache();
    5 `7 H, T% V5 J! }) V

  46. , C3 @4 i! H; _5 Y2 E7 q1 V; r
  47.   /* Copy data from Flash to SRAM by CPU */
    * B! C' u$ |! t1 s
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)& R5 ?4 M: S; z) O, H9 E
  49.   {
    $ t  q. ?5 |3 b( O. C8 E% ~/ q
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];7 d! @& ]' q+ X% U% h. \. V
  51.   }" ~. ~6 |- y5 K/ \% W9 y* ^
  52.         ' |0 W% L8 m4 @7 I  @/ E' L% D0 V
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    * A! ^+ d( b3 [. F
  54.   DMA_Config();
    0 @# b1 ?9 }/ r
  55. : [' M. b3 J( X: I4 m
  56.   /* Wait for DMA end-of-transfer */
    0 ^+ X* V0 _+ |1 {8 {

  57. 3 f( s6 ]  P' a: V, K( D. |  ?5 c
  58.   while(TransferCompleteFlag == RESET)
    3 t  T3 S* [. L& k
  59.   {
    7 f# O4 l* x' ~1 T1 F* I
  60.   }3 v6 P9 K4 T& \6 S2 {5 c

  61. $ U0 _) e' p0 S- J
  62.   /* Check data integrity*/! e$ c) Q4 W; I: j; S8 L
  63.   pBuffer = (uint32_t*)&aDST_Buffer;
    0 y+ x1 M2 [0 P
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)
    # `6 M% T; O0 l/ d
  65.   {
    + z9 `( U, |* }+ O
  66.                
    , E( ~% M6 o; @3 c  U
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)) T9 b3 \7 I: b! L
  68.     {& L2 \5 @6 Y" |" D. J. E) H
  69.         compareErrorDetected++;
    3 S$ m0 K9 O9 H2 w( \  K. ^
  70.     }
    1 {# m$ W" H& i0 \# x( @
  71.     pBuffer++;
    , i' o. t8 Z. n
  72.   }) @% x6 \# y) Q0 h3 b8 J4 z5 ?
  73.         
    6 H& s( O1 M& H( C9 C
  74.   if (compareErrorDetected != 0)2 b& d+ C) n" s* c2 f
  75.   {& Y; Z) N  Z1 c  t- o1 H
  76.       /* Toggle LED1 */
    2 h  ~' ]6 i5 Q0 W/ i) s
  77.       BSP_LED_Off(LED1);) I: x- n9 |8 t' c4 A& R, G
  78.       compareErrorDetected = 0;        ; x8 h, j, Q* N; h8 g
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");5 Z  _1 W% K7 Z3 t
  80.   }
    & |& w# |) z2 U% h" R: q( M, _
  81.   else5 h' I. u5 ]8 I# W/ j; X5 O! L
  82.   {4 R7 l8 F: [; W6 {% ?  Y
  83.       /* Turn LED1 on */: c2 y5 d& u6 Z' N6 q) @
  84.       BSP_LED_On(LED1);, l. U& o  H  w5 f
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");# i, D  C% `7 \1 y6 ?
  86.   }" f: }: v, x3 p! n

  87. % R+ G8 N: L% n2 a" N
  88.   while (1)
      H' b! c! ^6 D) i
  89.   {
    % n5 A, ^5 a6 d: Y

  90. ( m& |5 M0 F6 i
  91.   }& u  R9 j1 I' h1 s" ?) c
  92. }: j2 X) _0 l3 B
  93. 6 R' G5 ~1 q5 F# K6 ?8 @
  94. static void MPU_Config(void)$ o# |3 t& o& l3 ~0 Y1 G8 p; `0 p, \9 Q
  95. {& n9 S, K% k3 G* t' Y) K6 Q/ X
  96.   /* Disable MPU */
    - {8 |/ b0 n% j0 s2 u$ w/ A8 D7 V
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;; c  l; {6 A: U0 R& H% E, W8 O
  98. 4 s- P% ]8 h0 v
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    & r" ?+ E" U% f& M/ I
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;( n& y$ [* }7 \* T! e' d! n- L0 w
  101.   MPU->RBAR = SRAM1_ADDRESS_START;( c+ H2 g8 S# _5 D- N
  102.          
    # X  ]. }2 _! ~1 X
  103.    /* Write-Back policy */- ~) A- n+ \* D) }( b/ T
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;
    - ]3 T3 e5 l1 L9 r

  105. ; }: g$ g# P8 H& {3 `: K
  106.   /* Enable MPU */) i# T0 c; E: n) J% I
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;9 e9 E# \3 m/ L8 b' ]
  108. }) G* C) z* L3 q
复制代码

, u' F# y, o$ g! M7 `0 m+ {  X为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:
/ _4 S( i  S8 y0 {# l6 E
& p0 n/ Q3 u! q# T
d4c481b36d81bb11f17b07a56ac1f054.png

/ d8 r7 I- O3 m
: x0 X/ p. j: B) x0 m( Y
图3.4 检查常量和变量分配情况
+ r- E& w" R# d' d! x. l
! @+ X1 U8 d3 u5 w; y- S
下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:$ d- O3 O3 E8 y& S8 ]" \
- G2 }. J8 f6 P. C" v5 x
bd661d50dcd8f45abeeabdd2ac3c0289.jpg

3 P: q' z) F% g) E
1 F% g0 }" q6 q, k
图3.5 Cache 数据不一致
% K. F, t  Z) `
8 d& S. V/ q9 Y, ?' y1 c/ i+ ~
3.3.3 解决方案1 q! |1 R" {, k. G4 b9 G$ h
(1)不启动 D-Cache+ @* [! ]3 C$ w3 g4 P: f
: M# ]! k% r9 k) K+ n! S) s+ y+ E" a
注释掉 SCB_EnableDCache();
: S( ]( n# ]  \$ Q+ G1 _% _
7 t) r1 S/ i' ?5 e& f不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~5 \: c9 U9 ]) N/ {$ H# K
) \( U1 ?; T0 M" U
(2)将 SRAM1 相应区域设置为 shareable- e; ?4 @( n0 \+ d  a( H* |, K
% `3 ]5 r# W- m. V9 y
通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:
( ?) S* T. z. ~( `) P7 Z
  1. static void MPU_Config(void)& l" o4 h2 R( [1 N% U+ O& A
  2. {
    0 m6 x9 }+ n* t8 e  G, ?
  3.   /* Disable MPU */9 S  B$ N, ?: Y; ^  k
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    ( Z7 H" S& C4 B1 s

  5. . @" R! E6 A/ f2 Q- a6 L3 `, n" s
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    % f% \: e! g! w* F- x
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    # u- l+ @" v: ^" O% d& P& Z6 V
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    % |4 @0 Z4 n9 v1 V" k
  9. # ]  d. N6 ^/ Y  C4 |+ |
  10.   /* Shareable */
    . R4 j9 P8 {" Q
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;
    & a$ _0 N6 m, H: v6 U2 K  a

  12. , q4 @/ P1 m8 T3 U
  13.   /* Enable MPU */
    - X' E8 }2 o' t1 U
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    9 b: o) D$ k. g: {% n" c
  15. }
复制代码

" g2 J1 ^8 P, M* n( {/ |$ |# D(3)DMA 访问 SRAM1 前先 Clean cache
9 R+ D/ \+ y' y+ f+ |& c/ j" i. f8 B
在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。+ k! f. d8 X) H0 A2 O+ s
: E9 \8 X6 f" a: G( _
在本示例中,可以在 DMA_Config(); 前调用:
* _& X& V. s. [- M5 K+ u; q
  1. SCB_CleanDCache();
复制代码
或者
1 B6 Z$ {$ p+ x4 o( N3 M& j* n
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码
: s/ L6 P% l( d7 S) q
(4)将 SRAM1 相应区域设置为 Write-through 策略
! [; ~, X0 I( q) Y+ t3 ^+ F8 q$ B: a- [2 [( Y  `
通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:# u, `; y8 E' E9 Z$ _' Y+ C

: ?4 [0 b; k) M5 M
  1. static void MPU_Config(void)
      s$ J+ y: B# ^5 f! E
  2. {
    / c' g7 ~8 f; {1 l% f
  3.   /* Disable MPU */
      I' e" M% e5 j; ^, \
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;3 A  I0 r) Y" ~( A! t. b+ I, J: G
  5. . d3 N6 `9 o. Z) D# K5 E1 ~
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */# G; J1 g% p  Q7 p
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    " u- B, T+ V, w' J
  8.   MPU->RBAR = SRAM1_ADDRESS_START;/ C& }: ]7 A' s' c& B! c0 H

  9. + K8 P4 H* C7 P2 t
  10.   /*Write Through policy*/6 w2 r2 K) e4 W, w3 n7 P
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;! t$ w, N& e, s2 J- n$ O, D
  12. ) Q: c* a. u; q9 G
  13.   /* Enable MPU */: i# j( m' C; t. T
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;3 e; C) @) c( W! k  }' E
  15. }
复制代码
( i2 n( k" g; O' v
(5)将所有 cacheable 的空间全部强制 Write-though, ?2 C! A1 Q1 f9 l$ u+ q2 Q: w; b
6 V3 p7 R: ^$ @, L
通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。
; w2 {6 {1 J) W7 ]8 o$ _9 F6 g
: q9 x& x: ~; Y
e131d05081f8e30ba2296e50f3e9f392.png

! k! G) _' j& X% Z
7 K0 r( @3 A- {. ]- n+ e5 P) E
图3.6 CACR 寄存器(来自 PM0253)
1 i# }' D. |, O( X6 [/ c$ _% o

: L: A' i  `' u6 J在初始化的时候进行设置:
/ _. g1 c# {5 B' P
  1. __FORCE_WRITE_THROUGH();
复制代码
$ K( T" t7 P" I! |" ]" D
宏定义为:
  {7 ?  B9 r1 S: U+ e! A
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码

+ R- C/ ^- G1 }: s, D+ ^( X以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!
( ]" I' {- Z6 R' Z2 W# [# x  G
% a4 Q2 G# A+ }% l3 i7 x! R值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。
* V8 q' y9 \% G1 G& ?+ u
  V7 q9 ~( l6 a: i" E5 g! e; K
9dffde7b310ed170c1b45f9dd7f75abe.jpg
. b% E) S8 {. T) G& [% D% f
0 }# }2 n% N. u' V' C! y& Q, ~
图3.7 Cache 数据一致

6 S3 ], b+ L1 q5 `7 F+ M& Z$ ?. h. B4 `
好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~
; i: S$ `/ a+ d
3 U# z! |/ c4 q* r
) G# h  ]0 ]7 G2 U4 l, i: M2 t! G3 [  h
赞 收藏 评论0 发布时间:2021-12-13 23:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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