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

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

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题
, n) i2 U# F) i/ B3.1 什么是 cache 一致性问题$ z4 E2 \0 c' G
所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。% b% r( x# {7 v! V/ b7 X

! r, Z+ h( b; M  f, Z: k在实际应用中,有以下两种情况:# t! g9 {, }" X, e$ l

4 r' p# }3 x( J# s8 _- v* i第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。% H* D7 {' l. i: d9 F- h
- \+ U; X/ o6 h2 Z* \- n  t( \
516a4fcb212a09183f4c3f3efa77d170.png

& v1 T# Q& B# j  z+ @  I
# U/ K( M, N7 G2 M* g0 S$ W% g4 S
图3.1 Cache 一致性问题 第1种情况

2 J+ q4 r& q5 R8 B$ j* m2 r9 F! O# @; K- E! ~8 b: j
第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。4 A4 S, T) m; ^2 C- k

' `3 V! }- e; Y
ba3341c9a0e0ddc198b5fe0466a465dc.png

* u/ |4 p7 F  l' s) _/ l3 I8 U7 Y6 d
图3.2 Cache 一致性问题 第2种情况
* w' ?6 V5 P/ N5 q
; m) U5 K; z7 y1 p2 f2 U$ I+ _
3.2 如何处理 cache 一致性问题

$ A  l; E9 g4 P5 M" ^/ `0 [我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。
. ^0 F4 y6 M$ ~7 X2 z$ Z$ h% F7 V" M) \  ]$ O
因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。2 `) w" S! s  c! [$ }4 o

" c% X! T1 e- f: l5 s好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:2 n( J& t  i$ [1 @* Q* l

7 ^# d/ D& Y- ^* t! J所有的共享存储器都定义为共享属性- V3 w4 l- `4 }' _0 h6 ?$ T% ]
+ H) G/ _& m5 V, w( z( `
这些区域将默认不被缓存到 D-Cache。/ \9 C- Q8 Z# H8 m$ E
所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。, U: e8 G7 S$ F% s, u9 E
因为缓存对这些区域是透明的,写软件更容易。
: `1 i+ r: r' v& ~
1 }5 Z3 N2 N; J通过软件进行cache的维护
, I( p" |6 M7 ?2 H$ y: E(1)Cortex-M7 的写操作要是全局可见的- W, D5 b2 v$ T2 r2 C1 B6 @2 w
. H; V. @& T# T5 u
使用透写属性(通过 MPU 设置)。9 G: J/ [5 g- Z) A$ [* ]
使用 SIWT@CACR(Shared = Write Through)。$ ?2 m) V* U! s, `2 ~6 Z
通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。# @+ m% v2 ^, N7 b6 x+ {) |
(2)其他主设备的写操作要对 Cortex-M7 可见
/ }/ t6 b- A3 q3 U( Q" P' k# N
+ N4 X- R4 l* U: I5 w) q7 g比如作废 Cortex-M7 Dache 中数据。
* G  S1 g* Q4 g) t$ V1 V# Z$ d3.3 示例0 j4 `9 L* Q( s& s
3.3.1 程序描述
- f  c% D* I% a(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。; h, p9 w% O7 {. F
(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。
" x2 H# Z7 K1 b6 R9 T2 J(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。
+ Q7 m% u6 U8 J% V( G+ s(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。
2 v, \, f/ h$ t+ _
1 Z& F, Z& a8 B( O* E显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
$ j  {- |* U, `+ e, L; l$ x
5 K3 {& X. l3 F2 t程数据的传输流程和路径如下图所示:# \0 K0 l- q0 {- N6 E5 }- L

( E, F3 g( X2 C7 k& ?: \! Z- z
d0db73574a58707717ae26695e9dc302.png

4 b- H; m4 o7 D. p, A
8 g  v+ X% y) |( `7 B
图3.3 Cache 示例数据传输框图

% a! m4 U1 a: A$ `5 ?* x8 T4 d/ A$ u: }# p
3.3.2 复现 cache 一致性问题- \$ y0 X6 d% B' C" [
我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。( N8 [- g# }- j6 T$ c
" K, @$ b' i3 b+ P6 d
本文所使用的环境是 IAR,其链接文件 *.icf 如下:
. J8 P! }9 m0 T$ F8 b$ z. D: h7 n  c- d# ]
5377967a69d8334b1bbd7b99f41c9e23.png

, q$ u0 @- p5 V! ]8 {2 Q, W) L, A0 P0 N) q% z3 q" q$ q' _4 M1 p
然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。" }3 |5 N3 n* F' |. k# z
+ K6 G5 w7 O7 }# o3 H9 T/ u
好了,代码主体部分如下:) n7 g$ B0 E* C+ n4 X4 ?0 ~0 m! V/ v
8 k8 E) \' A1 V: p8 `; {
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)5 G* |# O, S( n" s
  2. ; [3 w2 t* l7 B3 s5 ^
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =8 G* f; `6 j. z6 ]
  4. {
    + G9 x' [4 q8 V9 ^! o( Y) j; y* l+ Z4 _
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,, ^. D& X8 D2 s2 [- J' Z" o- f
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,. X  J7 M3 [. V+ I# l
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,  ]2 J! s  v9 f2 }
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,
    ) u1 g8 Q. Y, H9 v% D5 x
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    # {7 i/ B; w6 O5 Z$ R( ?6 S. `; k
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
    8 d) n5 N% ^7 e  ?
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,3 P* `. |6 c  y; n" p$ {
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80
    3 g" O8 u0 T( G* Q, W' Z
  13. };* U' |4 }9 k2 M% h! V

  14. 2 A4 W  {9 A0 O. _; j! {* V. x
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];2 l) b- ]6 W; o# `4 ]
  16. 9 o+ p/ W. g. G
  17. int main(void)
    & |2 Q+ z( L" b  a  C
  18. {
    + ?- q! M! O. x6 h) e5 Z$ d) S. s
  19.   uint32_t counter = 0;
    ) i: ~8 y" w) ?' L: x
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;8 w. E2 A, o5 v( C

  21. 5 B* B/ U# Q/ u% q' B
  22.   if (HAL_Init() != HAL_OK)  j0 F0 n6 @8 ]/ W
  23.   {
    $ o3 ?- H/ R% h. x1 N( e
  24.     Error_Handler();
    ' E1 A  u: R1 g8 Y; E) [
  25.   }
    3 l9 n8 I: z% M, A3 I# h* B" g

  26. 7 h. E# F$ }7 y2 N5 p: t  J2 E
  27.   /* Initialize LEDs */
    $ M* G* G/ x; w2 @7 y* M
  28.   BSP_LED_Init(LED1);& _" s# k& o/ W8 G
  29. & |7 P7 W9 P' Y( o) N
  30.   /* Configure the system clock to 216 MHz */. @/ A. A" r3 `" f
  31.   SystemClock_Config();0 B" R6 A" F3 p$ A/ \3 x& f
  32.   BSP_LCD_Config();
    9 S4 j! T6 ]2 p8 I5 F  p
  33. 5 x/ ?, \! U, ?
  34.   /* Set to 1 if an transfer error is detected */
    0 b. D+ L# i' ^- l
  35.   transferErrorDetected = 0;
    8 l6 k4 ]: |; T/ K8 [# Y; {! Q
  36.         1 i8 \% [7 ^! @
  37.   /* Fill 128 bytes with 0x55 pattern */
    7 K8 Q; v/ s9 c: F* k
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));( R1 q% t% r  u+ v5 g' i
  39. . Z, M$ d* ~8 J  @, m* ?) C
  40.   /* TODO:Enable MPU and change SRAM region attribute / ~3 q. [. s7 N9 Z0 e. ]0 |
  41.   * set write-back policy on SRAM */6 u! O0 M( Q1 u; v# @! {* Y
  42.   MPU_Config();
    & N3 t4 p1 c6 C+ Z/ e" c# ~' L
  43. ' `' a& [3 f: d8 h, c
  44.   /* Enable Data cache */
    * V4 w+ `) [/ ]! H$ f+ q! S
  45.   SCB_EnableDCache();
    0 f* b3 k# z3 Q

  46. 0 g( p0 M$ X1 l8 m1 N% }# c1 S* c
  47.   /* Copy data from Flash to SRAM by CPU */
    3 o6 P  a$ U5 k
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)6 T& l7 L; Y9 W2 s( _$ u
  49.   {
    ( Y9 E, \. K+ k0 v) g; E4 x1 b
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];
    - i7 P. D2 Q7 m
  51.   }
    . e3 P9 S; ~$ U  K# t) ^" h# M
  52.         ; D- O, B- `/ F. l! l
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    2 M& t- s/ p$ v4 @7 k7 f0 ?
  54.   DMA_Config();
    0 f, N! A* q/ |$ U3 @

  55. / ]% z. D. P' t3 V' @. I& B
  56.   /* Wait for DMA end-of-transfer */% H$ y. G! i2 J: r4 l( s& \7 i

  57. # ^. e1 ?, t% O  o9 k
  58.   while(TransferCompleteFlag == RESET)
    % z# q7 w+ S& C* h, @
  59.   {
    % @* w+ l, w% D" u6 o& j4 {0 }
  60.   }
    0 D# H# z, U" M) [+ F7 D. w. N6 @
  61. : [7 p0 D6 j- `0 ?
  62.   /* Check data integrity*/
    6 b( i: V/ {3 o( |% P/ ~) ~
  63.   pBuffer = (uint32_t*)&aDST_Buffer;1 L2 M7 r7 K; k# U
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)) |& [8 S  @: X7 @
  65.   {
      l' X* y- f8 _( g( C3 L
  66.                
    8 p5 {" R5 l, t! L/ l
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)' c- {- _7 P/ n" n3 Q* z
  68.     {
    4 u9 C0 m' f$ z2 p: Y
  69.         compareErrorDetected++;
    ' Q. z0 n6 ]' h1 {+ R9 o9 L5 s
  70.     }
    . S6 Z: P& @+ T+ D2 ?: w; w! k
  71.     pBuffer++;
    4 h' f+ J. ?6 L2 X' C
  72.   }* }2 L5 v8 p$ X: Z
  73.         ! \7 e; O3 s4 {; A) s
  74.   if (compareErrorDetected != 0)
    0 c( |5 X2 p& M. {
  75.   {3 U9 m7 l% C1 D7 I. ^0 C" c% M
  76.       /* Toggle LED1 */
    / C) V1 L* H7 R' N& u
  77.       BSP_LED_Off(LED1);
    * |5 u; P* h- w* X$ d
  78.       compareErrorDetected = 0;        ) M2 q+ L* Z) f
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");" h3 Q/ [  B' Z9 ^, {
  80.   }+ x5 D6 R+ `. c+ t
  81.   else1 G0 s9 G: H) A/ g
  82.   {
    : Q; d" p7 d5 B  p2 q4 K# R/ D
  83.       /* Turn LED1 on */
      F) a' O$ V, Q1 ^5 X' l
  84.       BSP_LED_On(LED1);7 m( y7 v2 x0 c0 n4 i9 x( ]8 Q
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");
    4 {8 ~7 h! H. y4 r6 ?0 d  O8 j
  86.   }
    ' v( f" r) m; P$ l
  87.   w9 Y! e6 a+ k. G2 @  L
  88.   while (1)% P7 F! o  g4 t" u7 a
  89.   {( m  m. p: ^" u/ u0 D% ?* D

  90. * V3 c* g3 y8 _" L
  91.   }
    + z# G6 |7 C/ b2 n; z( R5 n
  92. }- G2 o) m/ u2 `" w6 |1 N" o
  93. ' g) H# K9 R& F1 H8 a
  94. static void MPU_Config(void)
    : D1 G7 Y! r  U& p- I- Z/ I
  95. {
    ' }+ X' X! r3 e: Q) w/ w
  96.   /* Disable MPU */
    ) Z- @$ t8 A" ~* ]7 C
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;3 ?, M8 y. |+ x& |4 s
  98. / F2 J0 e/ `* a
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    9 H$ a) k# F% F; {$ B7 w  A5 q
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;
    & ~$ r1 C; x4 o  W5 L
  101.   MPU->RBAR = SRAM1_ADDRESS_START;$ R" C- {' ?# p5 ^
  102.          + q7 r9 ~" _; Q# c+ F2 q/ G
  103.    /* Write-Back policy */3 H& H/ u! Z4 g
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;
    : f' N; M) ?  L3 v* N. |2 q5 I/ }

  105. ) I0 c. D, u2 t0 @2 Q0 j
  106.   /* Enable MPU */: w7 h+ V7 |5 l* j- e' Z, a. \* W
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    . O4 V  S& n" ^" ~: ], Z4 t- [+ k3 U; G
  108. }
    ( x7 A) W. D, C- ]' ~2 u. |$ G
复制代码

& H# A8 e1 X: t& `) k2 p为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:' \; \6 }  }4 F- F( f
. e0 M3 D( h$ j/ I3 v
d4c481b36d81bb11f17b07a56ac1f054.png

, f! Y& X/ v  w' Y: f, W* v1 J/ m* J% `! |4 T4 V
图3.4 检查常量和变量分配情况

* {5 A6 T* ^* i) t
, E% j4 V3 X) R7 x( X1 O下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:8 Z' H  _/ q% _% {! d6 @
9 u; X5 U$ S+ ^9 t9 M/ N+ }
bd661d50dcd8f45abeeabdd2ac3c0289.jpg

  O) h& Q, m: K0 {. W6 a! T/ e
/ \7 B% i7 }4 J* U: Z
图3.5 Cache 数据不一致

# w+ y5 d8 s% _* ]& y9 Z; W) F, ?8 |9 `
3.3.3 解决方案
  H3 y, E8 r) `/ y(1)不启动 D-Cache9 ?+ y/ y% q( {! `3 r
0 X2 J8 L. l3 f
注释掉 SCB_EnableDCache();
- Z5 G: L4 v, b3 t8 ~! H
2 P- s8 K- @% _8 Z* E9 q; C不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~
* Q' v' }* f/ E  g0 j0 W+ Z+ I* t4 |
(2)将 SRAM1 相应区域设置为 shareable
; M; s) H( _2 U0 `: }) Y# i8 d' b2 P8 n9 o& W; E9 d
通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:9 U& v+ T& c4 V7 [( \, o; G& T& Y: |
  1. static void MPU_Config(void)" j' b: F! r8 a% D" w
  2. {$ M% C/ N8 }& y' s: c2 K# m3 D
  3.   /* Disable MPU */" C: D0 M6 w* @1 K& h
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;6 m4 G0 ~" q2 X% n$ F: a

  5. ' `; c$ n1 l2 V5 R  r
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */# U. B, d! G0 p5 O4 f2 C3 B
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    ! s8 k) q! y9 M3 y  C
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    3 ]* Z$ P& Q4 h* _# t( t

  9. : ~. E! h$ J7 u
  10.   /* Shareable */5 n& b, V6 H0 Z: _- v$ N
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;. M' p; |# f; k* ?$ A$ A

  12. , i. a9 c+ O) W7 x- _3 M
  13.   /* Enable MPU */' [! O: J2 Z/ ~
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    - B; J. G5 K& N' j( ?8 E; Z
  15. }
复制代码

% b3 d- h: M. ~8 q$ k6 F0 o* E5 j  W(3)DMA 访问 SRAM1 前先 Clean cache
) w' Q# k# i/ a$ {  t/ C5 `6 V1 E
在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。4 f: Z: V" }: J7 {- U

  c8 D; q. e: p在本示例中,可以在 DMA_Config(); 前调用:
( l3 `% T0 |3 K0 n/ c( D
  1. SCB_CleanDCache();
复制代码
或者3 ^. [$ M  A, r
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码

) [5 \  a* _4 ]' X(4)将 SRAM1 相应区域设置为 Write-through 策略- G" w& C4 s; h4 M4 J% z) C

1 l" p9 Q& v0 Q6 t" s# [: g4 }通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:) ~* \( |1 R; y, r
9 k6 f. v; O7 I' g" w) I
  1. static void MPU_Config(void). `8 a& R9 g% t0 o; B& y4 }0 |
  2. {/ o4 m7 m1 C1 ~# @
  3.   /* Disable MPU */, s+ }4 i$ w2 Y1 s3 V* F+ S
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;% c- d( v) P$ u% y

  5. - C4 D% n( f5 r& E; ?/ J7 x& c. M/ X
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */( w/ Y5 d5 s% R) c# N7 U, r$ f8 x
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    3 L2 x- T' b/ b1 U7 W' W/ }1 G
  8.   MPU->RBAR = SRAM1_ADDRESS_START;" b# V6 l; P2 j

  9. ) n/ R" ?1 @8 [2 S1 v! d  a- H
  10.   /*Write Through policy*/8 ]- ]: [# s1 a6 o
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;
    9 G% O' ?- t) ?1 s
  12. 1 K1 g4 O1 u) Q' \
  13.   /* Enable MPU */
    7 ~9 W8 G! P* g  j7 }/ q, t9 [
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;( ?2 o  h7 W0 m; [9 R. M) C
  15. }
复制代码

; Q& m# E( U" `- e4 n( z(5)将所有 cacheable 的空间全部强制 Write-though
, x" [( \" R# j4 P) p* m1 S, {8 Y6 c: ~; ~! e
通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。
$ h" Q( [3 u. m' {) N1 x: l
, z# q; s, A' j" y; A$ H
e131d05081f8e30ba2296e50f3e9f392.png

  e5 J7 A( G/ W8 B9 ?( x8 q1 K- ^
图3.6 CACR 寄存器(来自 PM0253)
2 W. @) g0 n# C! X+ W5 Q% Z5 o' u
& \3 h: x7 I% b- f7 X
在初始化的时候进行设置:. y, J4 p0 u4 b) L0 D. U
  1. __FORCE_WRITE_THROUGH();
复制代码

7 R: i/ v8 s$ n- ~4 I' ~& x$ F1 z宏定义为:9 t. p" G8 ?8 p
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码

# P! _; d3 {( _  C/ P& w( c4 X6 d以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!
. C) I2 u7 C5 Q! ]
" k% X: X" n) a- f  ~! u值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。
( ^* L7 W/ e* a7 j7 J+ G' k; o# O3 T# v
9dffde7b310ed170c1b45f9dd7f75abe.jpg

* {. {; o, k% _+ D9 R1 w+ L* }; Z2 T: @& R9 Q
图3.7 Cache 数据一致

5 t3 R6 X$ `9 f% _( h7 b' X' A5 K7 z
好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~
& B% V/ H: r# z
9 X. ~1 _- i% {/ m* e7 e) j5 Y+ f* j
: b! Y8 m+ ?7 o1 o; y; F2 }6 |% N3 Y, U1 D" z/ B
赞 收藏 评论0 发布时间:2021-12-13 23:02

举报

0个回答

所属标签

相似技术帖

官网相关资源

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