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

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

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题8 W" M3 L8 m: L
3.1 什么是 cache 一致性问题1 }8 ~4 R) p% I" G9 v/ d
所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。8 A7 z5 `1 J1 h
2 c# j1 @# q/ Q" I
在实际应用中,有以下两种情况:
8 z( i3 a" A' b4 O- J# @7 u3 k- T' G! M
3 N' ~& K0 G0 Q" F, u7 {) C第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。
1 b5 `  b, A" H- v' i8 }2 k6 I0 h3 q( `
516a4fcb212a09183f4c3f3efa77d170.png

) ~( H' k+ O7 o0 O% ?4 W
3 R, {0 c: U! u! I. A" T
图3.1 Cache 一致性问题 第1种情况

* B& _5 V7 W6 i( [5 P" n: }% A: l7 |: Z. }- L/ w
第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。
5 d) W4 ?; I! J) K% _6 O' B$ b9 x5 y8 V2 I0 ?" Z
ba3341c9a0e0ddc198b5fe0466a465dc.png
, _+ t5 h, R0 _

; M' M% q( r7 E  B: c/ P% S0 O# q0 V
图3.2 Cache 一致性问题 第2种情况
: E3 `$ G1 ?# e$ O' v

+ D( a3 ~- A) n, q3.2 如何处理 cache 一致性问题
! A/ v  x% `  h# d3 v
我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。$ D( p2 X% u5 O) L! B" T- c7 u: v

4 d% O( |' y4 e# f4 T4 F因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。, V' X3 a. K/ }& f1 ?& N1 a
6 b# F& {; J8 U& ]" o
好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:
1 W# H5 g. T- g7 T/ b% _0 f
9 `7 k6 b% S  k% g. [! Z6 U% I+ G所有的共享存储器都定义为共享属性3 m+ j) i' J( p2 ]/ g" X
' U# Z- D1 q7 Z! S3 L' `0 ~
这些区域将默认不被缓存到 D-Cache。& w% U: ]% p/ ]
所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。
% |% U8 x# ?" \) Q* u* L% D/ n因为缓存对这些区域是透明的,写软件更容易。
; g5 a& Y7 l5 J0 O8 l& Z( K% T& C
通过软件进行cache的维护
- N% O; O# A: C/ x(1)Cortex-M7 的写操作要是全局可见的( {7 [8 d; |0 O3 F; `/ j6 w) V

6 J4 n* ]' b" U1 R) D6 s使用透写属性(通过 MPU 设置)。
, x: n, p5 x  W9 ?; H使用 SIWT@CACR(Shared = Write Through)。2 b/ j6 |  f, o/ Y$ H1 J
通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。7 h. ^# P7 K2 o7 b! B$ y
(2)其他主设备的写操作要对 Cortex-M7 可见( X' o! Q! T! @/ T

( {+ c6 k" o2 {9 F比如作废 Cortex-M7 Dache 中数据。
3 N& g6 ^: ^0 n( q1 P) E3.3 示例. D3 i; P3 g' _' n) ~* z
3.3.1 程序描述
; K( y9 v5 M/ [; n& B, [" j  N' o; R(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。% ^& h% W9 u* p! `& \
(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。  L! D# q) a- u
(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。) ^% K% U4 \3 a2 J! j  J
(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。  K5 y( i# Q# G5 z9 K
* [. `, @+ @. I+ v; e$ I6 F
显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
, G8 E* a4 j: E& x1 H0 R6 v0 _  x$ ^) [' b* m
程数据的传输流程和路径如下图所示:+ ]8 u, n$ q! l1 ?1 B+ \) @
# w. m; F- J0 [) u6 H8 U8 s
d0db73574a58707717ae26695e9dc302.png
" Z8 G1 v0 l! g" q! D+ _" ~& q( {

$ Q$ A0 N# A+ b1 @" l
图3.3 Cache 示例数据传输框图

7 t8 F. l% E# k; S! V) i3 g* B; w! c  k& O9 I/ n
3.3.2 复现 cache 一致性问题2 Q# `& s6 x* @- l: B* D) O
我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。
7 T/ b, Q, n5 g7 T# |* G) _" `0 p0 s& G4 n( T1 [  ]4 ]
本文所使用的环境是 IAR,其链接文件 *.icf 如下:
  e; S% W; ~- U
# W! J4 b' }& N. O4 u7 F+ q3 g
5377967a69d8334b1bbd7b99f41c9e23.png
' @) O- ?0 w% n: n6 g
; r5 S) s& d  A% @) f  g, J
然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。& z2 ?, f+ X& s4 _2 Z

7 J8 z( C: K+ S4 _: U+ K好了,代码主体部分如下:4 p7 ^/ Y4 ?% B. e% X! W
: K. y; G2 ^9 q. g$ H4 `
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)
    8 o/ S& T" |6 Y; G

  2. / D/ I9 g3 {4 M
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
    3 {! q! B8 h7 V; a* A  b1 w4 D
  4. {  ?1 a2 I% \8 |+ K. U
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,) L7 Y2 S7 r2 I% \
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
    " W1 y  H0 r5 ]' ~
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
    * P, w9 ~4 h7 z
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
    * p; e7 o" u0 e( q1 O
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    4 ]: y& X# q1 w8 e' J) [
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
    9 C4 t8 C9 ^- o* {1 u4 D
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,; p" U5 Y' x1 A( c
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
    # A  Y* z; K$ ~' F, ?+ E/ R
  13. };
    + Z+ Z- I. k8 A0 R, U

  14. 0 J# l: h1 A& a& C7 \8 T
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];
    " p, V2 a3 f, G+ ?

  16. 0 W9 e- Y: e: {5 h
  17. int main(void)3 z  S7 w1 \/ m" Y! M
  18. {
    5 w* Q' v( L* F2 B, N1 O0 V( D5 M6 R
  19.   uint32_t counter = 0;
    * g  N% H. W% G: O6 Z0 N
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;% \9 u" O; l; Y, ?$ h  M1 e# b
  21. 7 z# \5 F& V7 {6 N4 E. r% o  `
  22.   if (HAL_Init() != HAL_OK)7 @2 B2 u' h" ~+ Y
  23.   {
    ( n% j/ x* D# G; J8 s& P
  24.     Error_Handler();
    ' E! B& @: |$ u) j+ M
  25.   }6 z8 U# v7 I9 f& R2 X0 v

  26. # c/ }9 [" y1 b% d% l, b! F
  27.   /* Initialize LEDs */+ O' \: b. k. W+ [- R0 u4 U6 h% m
  28.   BSP_LED_Init(LED1);6 E: u2 `6 M8 B6 V# r! t: l* H
  29. ) W- W. V/ f& F% T6 q+ `' j
  30.   /* Configure the system clock to 216 MHz */
    8 V8 R' B' q* w" Y  U0 c% v: d  @( V
  31.   SystemClock_Config();$ @" ]; H6 P( }! N  {1 t8 l$ i4 h4 U
  32.   BSP_LCD_Config();3 c" x0 i4 p5 |+ ?* P3 \

  33. 2 P- P* Y, s* e5 U
  34.   /* Set to 1 if an transfer error is detected */
      o  k! z# H4 {+ k. x$ D0 ^
  35.   transferErrorDetected = 0;
    2 }$ T" K% N% [6 w" f; Q( o
  36.         ( D: B" N0 w! y% A: ~
  37.   /* Fill 128 bytes with 0x55 pattern */
    & S, ~) C/ H3 a0 t$ E
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
      l# E' s/ m- c3 J
  39. 2 j2 _( u; ?& P, ~  a" n% j' ?
  40.   /* TODO:Enable MPU and change SRAM region attribute
    7 Z6 w  S! W$ q+ d; B
  41.   * set write-back policy on SRAM */
    9 O: k4 @: a3 G2 M3 s
  42.   MPU_Config();
      q9 t# u( _. @% Y+ }* |  o' O* _  G
  43. ( d9 Z9 W, K# h$ z2 |
  44.   /* Enable Data cache */9 B& T& Z6 X) y" _) e( R
  45.   SCB_EnableDCache();1 [2 w$ Y' L, L9 Y9 w

  46. 4 T4 o' p. A' c- ]- l2 t9 \+ h
  47.   /* Copy data from Flash to SRAM by CPU */
    5 o* n1 g5 L. j8 i; E! h
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)
    ' T- R/ q- X! K+ G. L
  49.   {
    # [" c1 Y2 H" P, ]( g0 u' V
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];
    5 P* j+ y2 j. o
  51.   }
    7 l! S) M7 P( f
  52.         
    ) \" o+ g% b! M
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    . D; |1 Z- F, Y& p/ a
  54.   DMA_Config();
    : T0 j  W' G2 H: j  _6 U

  55. ) `# W+ x6 y- \' }3 X# r
  56.   /* Wait for DMA end-of-transfer */
      x1 k8 ^5 w3 c% R5 d8 o
  57. 4 v" @7 T; e( ^: J+ `# ^( }" i
  58.   while(TransferCompleteFlag == RESET)
    . ?# ^3 D! @6 \+ z2 q( M
  59.   {
    + G5 @- [4 i3 ?8 o5 S9 H
  60.   }% I2 S" z! z  x$ y

  61.   D; |; ^' K2 @
  62.   /* Check data integrity*/
    + {2 G5 H' A7 R( h/ @/ x
  63.   pBuffer = (uint32_t*)&aDST_Buffer;2 V5 M5 ]1 H9 h+ P+ C1 x$ k% \0 F
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)
    * O4 F% b3 L) z% Q
  65.   {
    6 s9 E0 Z4 R. ~% H
  66.                
    : u0 Q& u* L5 [% `+ Y! Q5 D
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)
    $ [+ d5 A1 h2 |5 ]
  68.     {* G- ]6 M4 ^, g% }
  69.         compareErrorDetected++;
    ; v& j8 [: V0 e# v4 I! a
  70.     }
    % B5 M" o3 V: k  `
  71.     pBuffer++;1 _" r6 b6 |% f3 G
  72.   }
    ; {- L. W6 [; }+ r* s8 R
  73.         " ~- {$ d& B2 |; J
  74.   if (compareErrorDetected != 0)
    0 w# [/ k/ _( v: p( D5 K( Z
  75.   {. S. M9 X, v0 c$ O
  76.       /* Toggle LED1 */
    * L! |; K6 q9 j
  77.       BSP_LED_Off(LED1);
    / t  F+ q" o8 s' c) A
  78.       compareErrorDetected = 0;        
    3 Y3 J, J) r! B" |
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");
    0 `) M+ ~8 h& N" g
  80.   }" e: L+ [0 w$ k$ R5 _1 m: W2 t
  81.   else# Y; ?9 H6 f& I% i
  82.   {
    ; l5 C0 v0 s1 X* A
  83.       /* Turn LED1 on */
      t9 M6 T- O1 S) {
  84.       BSP_LED_On(LED1);
    0 Q( e: B6 W$ h
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");! Q8 }! E, g& K! o3 w7 X( U
  86.   }
    . \4 A7 P9 z9 E) g0 h2 H
  87.   Z& Z5 X$ E1 j# `$ t6 w$ [% A1 E
  88.   while (1)* g2 G" H  X2 f  C5 w+ B
  89.   {
    + s, X. w' U# a+ R& P; O0 F

  90. + U9 x! h" f. E; F3 F
  91.   }/ m# |$ {! H, Y1 `* U; y- B
  92. }- Y- d# x  {4 f# X; T
  93. * p0 U4 T3 g) K7 F* ?
  94. static void MPU_Config(void)8 o& u5 O0 R4 ^4 O' q
  95. {
    9 I; {9 j% k+ G' b3 ]
  96.   /* Disable MPU */+ p8 M! M& J* n
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    $ i. q1 O  U, f; d

  98. & A  ?" b7 b& z% e% x
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */. T4 s% |9 ]# Q
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;
    4 L* a; J6 E& f, ?+ A
  101.   MPU->RBAR = SRAM1_ADDRESS_START;
    2 d+ w% f# L+ @6 a
  102.          4 H7 O9 |4 w! w# |. f$ y* g
  103.    /* Write-Back policy */
    , S  \$ X# y8 w, H3 f8 N: [1 d/ q
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;  H* i5 a& j" ?" N4 {

  105. ( G9 @1 {) w. ?/ f
  106.   /* Enable MPU */9 A7 T# y' P( m4 Y7 {& G
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;1 H. f4 ^  U/ ]
  108. }! }; ^9 x5 [+ y4 p( ?
复制代码
2 g: p- J5 }- b, H* X$ q5 I$ S
为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:! ^" E0 O4 q( k9 q* j

( ^! f: ], L) _
d4c481b36d81bb11f17b07a56ac1f054.png
6 g/ k/ H0 j: O9 W, O2 h# O
8 q* S6 x; ?$ C0 D6 p) a2 b) K
图3.4 检查常量和变量分配情况

! w: g- ]  T0 v/ w4 m) l6 s1 {
% _4 b3 h; e5 E& w0 T3 q下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:# o: f3 @/ f& R8 \, O. q8 a

4 {- y7 h6 E" k1 a/ q0 g" E
bd661d50dcd8f45abeeabdd2ac3c0289.jpg

# g7 ]: p% o0 C7 v% l$ e* z. D7 `$ \# j/ S' e2 W( @
图3.5 Cache 数据不一致
1 K, ?- h% M6 ]. t- R; [9 l2 c
; D3 v) X6 }9 t  G- \4 p6 g
3.3.3 解决方案
; A2 Z2 W7 z9 K0 a(1)不启动 D-Cache
9 X( U$ x& {. S$ c3 l& O& ?/ a$ {
注释掉 SCB_EnableDCache();
9 ?6 B6 s5 H8 Z: m; h& C3 C2 D0 F3 P4 R# D+ x
不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~
0 q% `4 M, j0 T6 H& K2 S) K
6 |# X; w+ i8 g5 r+ u(2)将 SRAM1 相应区域设置为 shareable8 x8 u4 o) M: K. D6 ?/ V

& b) f3 V; T. i' y3 N9 L通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:% r% v4 V5 L/ l  ^( Z. V
  1. static void MPU_Config(void)
    ' U! b) H. p) F8 Y7 y6 }- |
  2. {- B& ?& t4 j* m5 x, p% `9 n4 N
  3.   /* Disable MPU */
    ; C% u: z3 Q" z6 d1 G+ L1 p# P! M
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;& ?3 i& v+ k6 p# {& i7 s/ f
  5. 5 i- _1 l9 X; r0 K9 {
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */4 Z: k$ h/ _* k: I3 M& R2 R! M
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    ( F" e4 f0 b" `% v3 W
  8.   MPU->RBAR = SRAM1_ADDRESS_START;  R1 {1 e2 E. M% g" Y- L; D
  9. ' S1 F" o4 C0 {* Z) u3 \% R4 A
  10.   /* Shareable */2 Z) s0 b  M; T5 G  E8 k
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;- W- }2 }+ @6 L% s

  12. * S+ M5 l# `6 B
  13.   /* Enable MPU */* C3 _& d9 s! e2 ]* G
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    + [# f  a5 q; z/ q
  15. }
复制代码

9 ?( S1 w( h9 h8 M9 K& b4 Z(3)DMA 访问 SRAM1 前先 Clean cache; y4 y% @% I: U/ `5 \$ P( e! J

5 n+ C6 p7 H( }2 S+ d在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。- B/ G. G: P$ u5 m0 ?
$ L  P. l3 a$ B" f; ~
在本示例中,可以在 DMA_Config(); 前调用:
) w4 u- b0 z! r7 n
  1. SCB_CleanDCache();
复制代码
或者
8 w* d! {$ }3 L0 U) p) E
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码
2 i7 B% e8 Z; m  A, f6 ~
(4)将 SRAM1 相应区域设置为 Write-through 策略  n  V; ~# }8 o' g
! V5 ?) t; n! n: ~
通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:
: L0 T% \" w! r: Q, U
: D9 K. J0 S5 c' \) _
  1. static void MPU_Config(void)
      Q" ?6 Q) H' S& q! E
  2. {% \# W, F* f& P) {! J( u" Z/ t
  3.   /* Disable MPU */7 Z& x1 o/ o+ F% P- K2 a
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;. F2 J0 k6 U( @( W

  5. 8 M5 C8 i* G* ]) l+ m7 Z8 S5 u, L
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    / a, n, v2 G+ k  U' t
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;; }3 `# L6 h# n+ q
  8.   MPU->RBAR = SRAM1_ADDRESS_START;1 Z- D6 G3 `0 h, H. c: K
  9. 8 z+ {4 H. g; ]" |+ c; E
  10.   /*Write Through policy*/
    ' s  e9 [7 U+ ~5 ~5 w
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;
    * a4 R& G0 D/ {' F  c$ r& {* X
  12. + O$ G0 n5 _  M& i3 [! b& O1 G
  13.   /* Enable MPU */
    - Y2 X4 P& d8 i( w) a
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    ! M; h& ~* u6 g/ Z: E
  15. }
复制代码
- v9 i1 X; ~8 s# y# x
(5)将所有 cacheable 的空间全部强制 Write-though
% I2 M, g! G- C" a8 X. N& X2 j; K2 y- ^
通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。
  C$ U0 t/ y4 W; E
" [6 k2 x) |5 D6 e+ R
e131d05081f8e30ba2296e50f3e9f392.png
; M, D; @& F4 L4 Q& T" l
  ^2 N4 g5 f' G; A0 V) s0 l( p- L
图3.6 CACR 寄存器(来自 PM0253)

) G7 V  T. u4 e, y
3 `+ b2 j) @+ w3 J! R在初始化的时候进行设置:  y5 _3 e4 g' W5 v2 l3 q
  1. __FORCE_WRITE_THROUGH();
复制代码

' i/ g7 Q; {4 w, C" p, t宏定义为:
- M4 r0 s! U' `7 j* j
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码
8 R+ L9 e0 C8 s, e
以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!9 F2 W0 j, |4 @* f
2 y3 f* w, Y2 |3 q+ }& o* A
值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。
4 J9 L$ ^7 U) p3 V. m$ _& m9 [* n3 g; G* K8 a! E8 o$ L
9dffde7b310ed170c1b45f9dd7f75abe.jpg
  K3 K; W( K4 y3 E# g6 N
  M! j2 Y/ h; t6 c5 l1 @7 O
图3.7 Cache 数据一致
% j  G7 x9 G7 G
4 K: Y9 f; e+ d9 Z, _( M& f) m
好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~
+ r% l3 T! u! U: v- \1 \. j* ^0 E
2 U3 \# I3 h. \0 f( m3 T
1 \6 Z5 j, j* D: V
6 [& N1 I$ a) o# ~, o2 @3 t' ?# q" C+ r
收藏 评论0 发布时间:2021-12-13 23:02

举报

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