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

例说STM32F7高速缓存——Cache一致性问题(三)

[复制链接]
aimejia 发布时间:2018-5-30 14:40
本帖最后由 aimejia 于 2018-5-30 14:48 编辑
/ x/ U1 B- C) u: G% s3 T7 b1 c+ b( w) q0 O7 J  [
例说STM32F7高速缓存——Cache一致性问题(一): \5 ^4 q3 ~. E5 I
例说STM32F7高速缓存——Cache一致性问题(二)4 v+ v; Q+ n* K& h6 U( C
例说STM32F7 高速缓存——Cache一致性问题(三)7 \* H) A# x5 N, ?  H" P" E% Y

# W6 y1 T' i0 y/ C# a' E# z0 N3. Cache 一致性问题. C8 G; E9 C- O7 J+ E4 a+ Z

, L! F: @4 }. `/ m7 `3.1 什么是 cache 一致性问题
+ U' ]; w/ {8 i5 N1 B
  B' f* H/ _5 F7 N) A( p7 X* @所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。 ' M+ p, u: p" G& [; F3 ]/ u3 [9 S
: Q- S% _6 T6 j
在实际应用中,有以下两种情况:
7 ~, H- `# g- l9 g# q! b1 H, ^& }; g! X- Y- _+ [
第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。
5 |5 Z- X# k9 ]" g% E
" i2 }* M0 M( P" r: T" m
1.png

. d1 [- n0 W, o/ b" q
图3.1 Cache 一致性问题 第1种情况

+ ?; V% {/ D1 O) r  q* F$ l第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。
* r9 O/ f5 d; I  E$ |+ a! N1 m) N/ o+ V' W5 h6 u
2.png
图3.2 Cache 一致性问题 第2种情况
% M# F4 t5 D6 j! z/ ]' p! m
3.2 如何处理 cache 一致性问题) X, G$ b, f0 g) _* T

# ]2 O/ `: {: o" K我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。
+ s4 b) H- e# n* x# u& [/ g8 ]9 O8 c  u
因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。 % k) m! h) w  x" I9 J/ ]5 C

2 N1 M; a) {2 r* K2 O4 ]5 u4 q/ |好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:
( G3 M  ?, \' B- M" F
9 g8 K( J! w: ~- v所有的共享存储器都定义为共享属性 / d) ?+ `8 F4 r1 j
  • 这些区域将默认不被缓存到 D-Cache。
8 W! @, U. e- ]& {! ~  • 所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。
% L! t% C+ k  D$ [$ _5 g+ q0 q  • 因为缓存对这些区域是透明的,写软件更容易。
1 b1 J- X. H" X( H
: U4 u2 ^6 ^1 {& P通过软件进行cache的维护
5 D9 r' `: ]+ u0 J# Z( ^1 O   (1)Cortex-M7 的写操作要是全局可见的 . `3 q* i, b* b$ {* F) g* Q
   • 使用透写属性(通过 MPU 设置)。 : T4 L( P  b1 k& P- J. V3 Y
   • 使用 SIWT@CACR(Shared = Write Through)。 , \. O' b: D( ^6 d; A+ R
   • 通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。 # m% R5 f( ]+ {& D
 (2)其他主设备的写操作要对 Cortex-M7 可见
# _1 d6 s0 N4 W, c0 _$ z! \   • 比如作废 Cortex-M7 Dache 中数据。
* _- O! f& B0 i3 s7 `2 O, P: j4 x/ v7 i& o' s2 J9 c% b! V0 r5 N
3.3 示例  E2 J' O$ l) F" K3 e8 w9 Q

& ]4 Q" _& m& K5 A; N3.3.1 程序描述9 x( F/ E+ @- b% g5 n
  (1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。
1 O$ X+ y0 R5 L. L" U. e(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。 , x2 [; x$ @8 x6 T2 s
(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。
+ A* F8 ?0 H2 o; L1 U1 B( k(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。  h" x- X5 C+ ]( _2 s2 I( ~, J
+ Y! m- Q0 c$ v: }/ X
显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
" c6 E6 s" Q* D
$ d; Z$ H* \& Y8 K& X/ R程数据的传输流程和路径如下图所示:8 _9 {! W+ i5 M, q

* O7 M5 M5 W, I6 C2 y) J1 A( W
3.png
5 [* S0 a: n5 P6 O
图3.3 Cache 示例数据传输框图

, J! a7 _5 p, z& Y. B3.3.2 复现 cache 一致性问题. ]; Q" G! C: Z9 d

# ]- l; \3 R; I: E6 V& b- ]我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。 # ?0 ~5 w- K+ J" ^4 R2 w2 C
# M: `2 @; c) H6 L: P6 ]5 f; J
本文所使用的环境是 IAR,其链接文件 *.icf 如下:2 z) J. a- w3 b. O+ Y* k2 A
( ~- D; }& f5 T2 T5 F. n) @/ u
4.png

+ Q! K  H7 l- C' L9 t, S( h# m. \然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。
1 w# N; N, U8 Z6 a9 b6 h5 g7 @( y" L
好了,代码主体部分如下:
, N0 k/ G$ A& X% y6 n+ g
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)+ ^9 u0 ]& T: B
  2. 3 G, ?( ^4 m6 l1 g; n$ k* `
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =/ `$ y$ y! ^4 m" `9 Z3 U9 b
  4. {0 i0 i0 u9 I! @; f0 F
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,
    8 {3 b* O% x) _; D/ ^) ^
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,: n( }% X5 E' Q. ~
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,/ g( ]  ]6 n$ D. X  M
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
    4 a) Y! v( L: E  B+ R4 t+ {6 j
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    . g: j, L# C, i) G
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,& b- V+ E0 P1 V& f+ w8 ?. V9 a
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,/ ~6 K+ Q- T: ^
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80: P: y5 D. O' ?/ ~8 P- n
  13. };
    0 F( L- N0 c" T2 x

  14. 2 ?3 V# T$ R" C1 s5 ]% ]
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];
    ' [5 ]7 H- f/ v) M: U3 Q

  16. ) r! d  \! V# k
  17. int main(void)+ w) {0 N# X- H& _% O
  18. {
    / @& j6 \( T1 }" p
  19.   uint32_t counter = 0;  u6 w$ U" N7 l  Y  j  S
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;
    ' j6 q- a; T) H1 g; W* R

  21. 5 E$ ?1 ?+ R6 a- b" R
  22.   if (HAL_Init() != HAL_OK)
    2 H6 d4 v, e/ E, D0 V0 W8 d+ ~
  23.   {
    " O' Z3 Z5 G1 Y! M: l, d2 W
  24.     Error_Handler();
    ( {- Y) I" x8 S% ~5 n1 ]
  25.   }* K. }8 V2 h. z1 u9 q

  26. - ~8 H- P. w  f
  27.   /* Initialize LEDs */
    4 K3 I1 U! d/ z( B
  28.   BSP_LED_Init(LED1);
    . X  O9 z6 n8 Q, q/ x3 G7 W0 e

  29. ) i% `! N8 y7 U. V8 b  e8 n
  30.   /* Configure the system clock to 216 MHz */
    6 j, w5 }. [8 C: L. l& t3 F
  31.   SystemClock_Config();
    % b# A& g) z& V/ W
  32.   BSP_LCD_Config();
    . c( |: [( f' W( e  ]) O

  33. 0 Z* C5 X9 O) i* ^& i: M
  34.   /* Set to 1 if an transfer error is detected */
    1 s4 ?) U$ r4 }% C: g5 E! u: m
  35.   transferErrorDetected = 0;4 `0 h# ~- |7 k: i9 e; D% V/ y5 Z( p

  36. ; h; v+ h$ H* K) u" f$ `
  37.   /* Fill 128 bytes with 0x55 pattern */
    4 o$ t7 S  {8 c; U2 r9 c6 s
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
    4 _( i, f  w) u; L  ^' M
  39.   c& W! q1 r$ w7 l1 ^# V& E
  40.   /* TODO:Enable MPU and change SRAM region attribute 7 X* ^+ [9 `  ^( W' @) e
  41.   * set write-back policy on SRAM */
    / N, o! X7 d' C9 e2 T8 q$ a
  42.   MPU_Config();  N1 h9 ]# G5 I+ h7 ?. }
  43. # ^7 v' E# P/ q
  44.   /* Enable Data cache */
    . |& J$ ^8 \; |, a. @4 b# d
  45.   SCB_EnableDCache();
    # ?" ]) |0 w4 k$ o( ^

  46. 1 @2 u; k" z% @) W# q; ~* h% r
  47.   /* Copy data from Flash to SRAM by CPU */8 ]* X( d' b0 U6 R( D* k( ?  S
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)
    $ Y+ x# L& J4 @4 W
  49.   {
    & M6 d" i0 @, p3 w, L. I6 P: h
  50.     *pBuffer++ = aSRC_Const_Buffer[counter];
    2 \  _3 B6 \9 s' c: U
  51.   }: e+ t. f( Z* [

  52. ! z) u( E% a% Q1 k
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */- t' _- v: Y* v, z3 M8 i0 ~
  54.   DMA_Config();8 t3 `9 j7 A# |! M
  55. 8 p+ _, w4 @& u& p
  56.   /* Wait for DMA end-of-transfer */
    9 S; y* S8 R* \: V% F6 \. d

  57. & _0 F# G# h$ e% ?1 Z8 L1 o0 h
  58.   while(TransferCompleteFlag == RESET)
    - W# ^+ \7 e: O! j0 ~
  59.   {. v  Y5 s" y  ^  q6 Y0 v
  60.   }0 V% y3 I( h& i# o
  61. $ I0 r) i$ j" I: p" R* _$ r3 |
  62.   /* Check data integrity*/$ J1 W8 W" c2 Q/ E
  63.   pBuffer = (uint32_t*)&aDST_Buffer;
    % ~7 H( }  r- t
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)
      i% E( E* Z! ?) J0 q3 s
  65.   {
    5 M% f  a$ K: t; I+ g/ V
  66. 5 l4 \6 O1 X+ z3 |. X5 h( N
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)! S7 F, O- P! X% b4 e
  68.     {2 t, }$ [) b6 r' V
  69.     compareErrorDetected++;
    / v* H; n0 S! y" {
  70.     }
    ' x8 R, L0 G$ P* R: m9 Y' B" Q  Z
  71.     pBuffer++;8 J4 a7 C2 m$ @; U7 N! [. c8 W
  72.   }* Z8 F) ^, g# e+ u* b
  73. ( k  b) j. z5 _6 t: l4 b6 ^) L
  74.   if (compareErrorDetected != 0); B5 y* }, N( D" L: l* k! y  [
  75.   {
    : U. L& K  w- m" j& ?9 h2 P, J
  76.       /* Toggle LED1 */
    0 w; d# l3 e4 M* j( }
  77.       BSP_LED_Off(LED1);" s/ N; c( Z! h% i
  78.       compareErrorDetected = 0;
    % W( |. f# r& p9 c. O; C
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");9 S3 N# J" I5 y1 H
  80.   }
    ' I# [! R4 j; I* }
  81.   else7 P, ]" Q1 A6 l4 u
  82.   {% h) P9 o% n' T9 |1 I2 }1 S7 q5 P$ b
  83.       /* Turn LED1 on */
    3 V1 P7 {4 H# P5 [: T) U
  84.       BSP_LED_On(LED1);4 u$ I0 b! T" S, Q  G% ?
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");; ~2 d/ v: ]3 q. P. o( L
  86.   }
    . ]% N, t4 p7 a! g" R8 ~

  87. * ?& _0 i# u$ P& n/ L
  88.   while (1); k0 e0 c+ {2 K6 v& [0 c
  89.   {
    + [7 X% f; Y) q2 Y6 X& ^" _
  90. / A5 _7 G0 G8 x) h7 v2 `7 ?
  91.   }/ `% l4 N9 r1 q
  92. }
    . ?9 k3 X- x6 H) S( G! I) Y
  93. 7 F2 p/ f" H3 l* }. y
  94. static void MPU_Config(void)
    1 R  ^4 Q$ B$ z3 R9 k
  95. {. O/ [% K% e3 P
  96.   /* Disable MPU */. U+ f, M; E9 g2 L% A
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    8 l( N5 L3 s1 h! x* }

  98.   G: `2 m1 n* C5 S. m5 @
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    ) l5 D! e8 n. }( O- i, Z
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;5 E, U! k; v' S4 M/ O
  101.   MPU->RBAR = SRAM1_ADDRESS_START;1 S. ~, Y% Q; t: L7 L* q# g7 N) |, u3 x

  102. 4 Y; o$ B- d" g7 s$ \
  103.    /* Write-Back policy */
    . L5 V- F1 b! U4 d9 U. F$ Q. B
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;
    - i# H& W7 p0 u  o5 ]; T; P

  105. ! K5 u/ ?' E- x' b" ?7 Y: e2 N. i
  106.   /* Enable MPU */
    ' s# \, t; U! Y9 T- a
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    8 d' p* o. ]5 ~# K' M: s
  108. }
    / T2 f$ P$ X# @) L% y' U9 z8 B. }! I
复制代码
为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:' X) K; }' a2 n* F  P$ N

* v6 ~9 A8 W, z8 C
5.png

7 P. y( ], Q5 z
图3.4 检查常量和变量分配情况
6 }0 l5 t' S" ?5 j8 Z6 b+ R$ n" j
下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:
, z; o: {6 s$ N1 |( v/ u/ V1 M* g
6.jpg
, t7 d- D. b/ P- W0 f
图3.5 Cache 数据不一致
) ?* r7 R& P) V# |. r0 [+ r4 f
3.3.3 解决方案

" F# h& q& g7 s5 A( Y8 X(1)不启动 D-Cache
4 u4 w6 F) h. r  _7 `  注释掉 SCB_EnableDCache(); 2 j. G" i4 u4 b2 I6 P2 |1 q; f6 G
  不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~
8 E+ N+ R% O5 I# y2 \. D' T7 v, U% K' M/ y2 z
(2)将 SRAM1 相应区域设置为 shareable# e9 P7 t" m4 \* G0 p
  通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:
- J7 W1 O$ m% F9 Y3 b5 W" E9 @( r
  1. static void MPU_Config(void)7 J4 c) v: G3 q. |" ^! y( E9 E
  2. {5 @/ {+ }+ O; W1 C: O9 B: {9 k
  3.   /* Disable MPU */
    & S* W2 C6 V: }+ K
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;# P" {: n& G, F
  5. 1 e3 j% c7 G3 s* g! F- n
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */9 W4 j: m5 T, v, m$ H$ J
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;. d: A. b. L. k2 s* m5 @3 U
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    9 j7 s. b' `2 u! U
  9. - L9 _5 i" k- S9 M
  10.   /* Shareable */
    5 C  V6 G) `2 M% k
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;3 j8 c5 _/ U9 z7 @3 M

  12. . T. F& l; F& ]+ t6 O8 R1 o# n
  13.   /* Enable MPU */
    # T" i6 F0 W# v
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;2 \. I' T& K/ \  o3 ~
  15. }
复制代码
(3)DMA 访问 SRAM1 前先 Clean cache
" D& I* v# D- n; g+ Q. C4 X, N  在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。 7 o5 Z7 H; F9 X
  在本示例中,可以在 DMA_Config(); 前调用:
$ v# M" f) A" l7 C: P) L
  1. SCB_CleanDCache();
复制代码
或者
# K$ ?* }+ h: v' Q1 S  N
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码
(4)将 SRAM1 相应区域设置为 Write-through 策略( `# L; o6 J4 c% i3 F/ }5 R
  通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:
0 t4 v8 j5 l0 J
  1. static void MPU_Config(void)
    ; R% E9 ]3 v( f: x% v7 d
  2. {
    . p8 J6 p& ~8 _/ A- K
  3.   /* Disable MPU */, d( }8 G3 j9 P  v6 k3 f1 h
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    ( K) Q* m! R  C2 d/ H; t* b
  5. . u# n# d# Z6 _& `/ w
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    , z4 O; g  |7 s6 ]5 f8 k9 Q& l, w0 q
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;' U$ v( n& k2 g! `5 r
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    ( n& y! g* k: N8 h9 X+ g' k! P5 k9 u, ~

  9. 9 a9 y- z. F& g
  10.   /*Write Through policy*/
    + g3 X! O7 f5 x( C
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;  ]( U+ ?1 v/ `- Y0 t: R* \

  12. ! A4 b& I; x8 ]8 y- ^1 R, x
  13.   /* Enable MPU */
    $ Q2 C' P& W4 U4 w
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;0 y7 e  B  x+ ?/ _/ b
  15. }
    + L8 r# w' x: Z3 E, Y/ a/ o
复制代码
(5)将所有 cacheable 的空间全部强制 Write-though" v3 N2 x9 A6 B7 c! b% z
  通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。
  g, }8 w' e7 g
* W& Q; H$ A. N
7.png
) \* X# s7 e: F/ e
. H% g4 m5 l& @8 E4 R4 E
图3.6 CACR 寄存器(来自 PM0253)
9 i& M8 F5 P# L. E" Z5 V
在初始化的时候进行设置:
! Q1 ]# Z3 m% b# n1 n
  1. __FORCE_WRITE_THROUGH();
复制代码
宏定义为:' ^5 A3 Q8 K# _0 G" @! \% D
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码
以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!
& {' x$ }0 ^# o/ `: y6 m; n" O* j% ~' F0 A: L7 S
值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。
1 ?3 B1 S  X! E' r, R/ R4 B4 \/ C6 T2 D9 v/ w5 [) b
8.jpg

# f4 G; j9 g  F. e0 {1 k2 \2 p; K! q5 x/ e: W( @' H
图3.7 Cache 数据一致

. l$ Z9 [- B9 F1 H' Y
1 \5 t( f- _( d) u4 t好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦.
! G" E6 l+ ^% m3 a5 z8 I
3 Z$ z3 m! S# L
: S6 Q0 R) R  v3 }& b- t  K4 k7 h6 f3 x5 p" y$ {- `

4 O' D: ?$ }  b. W/ m2 J9 Z! k' h# p
- n+ {2 z9 Q5 s2 b2 O; |6 l转载自阿基米东1 P8 M" P6 t, L+ A5 _/ V8 i
5 K/ G- Q8 e: }& j

- Y, l  [  k* a) P2 p

评分

参与人数 1 ST金币 +6 收起 理由
MrJiu + 6 很给力!

查看全部评分

赞 收藏 1 评论0 发布时间:2018-5-30 14:40

举报

0个回答

所属标签

相似技术帖

官网相关资源

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