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

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

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题- @% S4 m$ s! ]# e% [- g& o
3.1 什么是 cache 一致性问题/ ~! W) @4 y# Z& c  A% k$ s2 h
所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。
2 h* y9 c1 X$ c1 w; r( h5 K' s; A; {1 q9 T  s0 `* q$ j
在实际应用中,有以下两种情况:
8 _1 H3 \- [: A) i& H, D
) U  d& f  {3 e: Q6 c3 f7 y# V9 r第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。
/ h4 r9 _, g' v. K! m$ W4 a
: A: s9 l% \* C
516a4fcb212a09183f4c3f3efa77d170.png

+ y5 H2 \$ J8 D' G6 N, f1 O) g$ P
图3.1 Cache 一致性问题 第1种情况
$ o% Z' G, j( _5 \- U) {

! H- u0 H: W# a9 v第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。6 i+ ?0 n, V! P. q! u

6 E# ~% |3 z! ^# g& W
ba3341c9a0e0ddc198b5fe0466a465dc.png
$ C/ H( G3 T; ^( E

5 z& v; i2 L, t# e
图3.2 Cache 一致性问题 第2种情况

2 ^% V9 L( I9 e( [9 u. Q
. s2 X- l1 T0 l2 q) R# c3.2 如何处理 cache 一致性问题

9 d* L$ ]( X7 z8 b6 [7 d我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。
3 d8 _0 w6 P( G4 x9 a4 C9 `4 z$ o+ n% R; a1 P
因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。4 s4 s  `9 p  U, e

* V7 p) N3 h0 K1 q. U好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:
; {; j3 \5 e& o0 F$ v. V. A7 g3 B  Q' G  L5 t8 L7 `
所有的共享存储器都定义为共享属性
  V3 D& J  h+ O+ O+ o- Q) b. t# J% W% K, u
这些区域将默认不被缓存到 D-Cache。
: {1 a& {; k4 S+ Z3 J+ l8 r* q所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。+ r( h4 }( m& V/ q4 D* B
因为缓存对这些区域是透明的,写软件更容易。
" k* A6 a; |$ \; F0 i+ {% a
, c# s4 _; g# l, ?2 R; L' j通过软件进行cache的维护
* V( H9 G/ _5 P+ A1 b1 Q' C(1)Cortex-M7 的写操作要是全局可见的6 F; V2 z2 z' t; s! P) }3 Q8 {

6 Q) A2 }8 Z+ Y0 z' _使用透写属性(通过 MPU 设置)。
% s! G4 W& F: v% E! n% |% [使用 SIWT@CACR(Shared = Write Through)。
" z9 t1 X7 N" _: \通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。
, P4 X+ b# v. R. ]" _(2)其他主设备的写操作要对 Cortex-M7 可见
' C* f% z# M9 P/ d
- w- x' @+ a! [8 \) W+ Y  i比如作废 Cortex-M7 Dache 中数据。5 f* j6 F7 N3 b4 a% D
3.3 示例2 ~+ B$ l8 g+ q/ s- F2 \
3.3.1 程序描述  x: h; S- C; V" c- w
(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。2 o2 K$ g8 l- L
(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。- M9 {* ~/ C- S  ~
(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。
2 L( b' y. E5 q(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。
9 f; h) ?/ w. R" g% H' S
- v3 Y2 u8 k- k1 _" Z! ?, x, [显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
* `& a) y3 ?( W2 Z3 E5 ]4 \9 z& B+ |( y+ a0 a
程数据的传输流程和路径如下图所示:5 k6 ?$ J0 L4 N9 t/ q

  Z. V9 m& f2 [
d0db73574a58707717ae26695e9dc302.png

; T0 V. R0 W6 b% k3 v  l, @3 R/ X8 I8 k
图3.3 Cache 示例数据传输框图

% K, j+ m- O  X: C  L
9 [3 {: d* E, D+ q6 w7 H# D7 z+ W3.3.2 复现 cache 一致性问题
# ^! v0 j* n! N) ^( c) N# a我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。
, M  N* B4 E! ~: d! W, Y# W
% G0 _+ i# V- X) H( l本文所使用的环境是 IAR,其链接文件 *.icf 如下:. \" v  `) f- G& V3 @5 y

; T1 x" T$ e2 Z1 F4 W
5377967a69d8334b1bbd7b99f41c9e23.png
) A* P5 n( l. S7 {9 @& w5 j
/ @& Q" l; J$ d! _" d
然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。6 u0 p9 P, O- }' ^

. E& Q( b' i) v8 o/ Q2 n3 q/ Q7 ]3 ?好了,代码主体部分如下:' L2 X7 J. L! j4 e8 r9 g- J5 i

7 G3 Z+ F1 `' ^7 X. `' Z
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)7 X1 Z0 y! K% Z4 ~! |! W  r1 `
  2.   Z0 y3 i5 \2 [5 m6 P' t" m3 {
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
    : t' I- G1 q0 H, m- g
  4. {
    9 b$ g; s( P" U; _
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,. N- y# q3 ?6 V' w3 n/ j" e: H
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,
    7 h; k' {  A; t: @
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30," U$ W5 [; x: B% }
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,8 M1 F; N7 t4 z
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,
    ! K2 a( _) r0 c6 {; b+ M, A
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,
    7 O6 T5 R1 Y6 _' b4 c- g! |9 R
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,
    7 X8 @0 n0 k- }! ?, l! T) B, `2 l
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80+ _1 F9 m8 T  E8 G/ O# g
  13. };% `# p* d/ u4 C! T

  14. : Y: ]+ F7 {4 e1 S/ s  m  @
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];
    4 D0 @- K* X; `4 l3 Q5 }1 N

  16. 2 |1 T/ S  {- |% W' x" O
  17. int main(void)
    / e  I! L' i5 ]
  18. {
    - m: e9 L# \% v' V% n* B: R; q
  19.   uint32_t counter = 0;
    $ a4 i" U9 {7 ^- i+ v$ F2 r
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;" R  t$ n' J$ r$ _7 `- h0 Q
  21. 2 O: b, c5 C% D0 ?) {
  22.   if (HAL_Init() != HAL_OK)
    4 z! c! n; J8 W' w
  23.   {
    ! E+ e' x" }- `+ Z: O& e; O
  24.     Error_Handler();
    ; y  O# n7 i4 Q0 L+ s( f
  25.   }, L9 w# W2 [! Y2 p. Z; L
  26. ! k) W/ Y- U% a  [+ }( O1 t
  27.   /* Initialize LEDs */
    & i- I, @  T' V/ ]/ O
  28.   BSP_LED_Init(LED1);* S$ a; L% }5 D! |
  29. % E5 E7 G1 S1 ?$ J% g
  30.   /* Configure the system clock to 216 MHz */
    8 E& T, E% [" o* [4 `8 g
  31.   SystemClock_Config();; N9 F9 z7 O! I5 T( X
  32.   BSP_LCD_Config();
    $ S6 v" N1 m) e9 E$ @. B% F2 s
  33. + _' ^( {  m( k; G, a# j
  34.   /* Set to 1 if an transfer error is detected */
    0 l2 M. A& t$ W0 P  W6 H6 a
  35.   transferErrorDetected = 0;/ ?  J  h& ?5 P0 L
  36.         6 }+ L/ q6 A/ Z& V7 W
  37.   /* Fill 128 bytes with 0x55 pattern */3 _' [' @2 s/ x6 N; [8 V" {3 Z
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
    2 j! j( {1 p2 X  j: k

  39. - Z+ m+ S1 W# b' `+ h0 \" v& g6 m
  40.   /* TODO:Enable MPU and change SRAM region attribute
    , ?5 x4 }1 x, w" Q2 _; E0 K) z
  41.   * set write-back policy on SRAM */0 S8 |2 F  C4 ]' B
  42.   MPU_Config();+ a6 E% `4 k+ @5 R+ K6 j5 C6 d* |
  43. ) `+ a1 Z; t$ q$ O# p* h
  44.   /* Enable Data cache */# X  h6 S  A7 d* W* K' P
  45.   SCB_EnableDCache();( T6 g1 a/ ^+ ]& `- a% `
  46. : B# i  N$ P# G5 l: o! b
  47.   /* Copy data from Flash to SRAM by CPU *// J, y( v: _1 X; u% R
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)) l" e4 }6 [0 D: i" y
  49.   {. y6 b, x9 u% h. c4 D
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];/ Z8 D  a; ^# e% s4 M& J/ F
  51.   }, K) A1 Q1 y, o8 h3 U) g
  52.         5 ?# N  a: h" ~4 k/ X! V3 J% y% X+ A
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    . }' L. w5 p+ [1 T  u" j
  54.   DMA_Config();
    : T5 O1 [& ]* H: X+ y* O
  55. " s, R3 Z8 Q' u' H) P
  56.   /* Wait for DMA end-of-transfer */
    6 A  ^1 J/ l% T

  57. * s9 O$ H3 _! c) ]! u% `1 o8 ]- l
  58.   while(TransferCompleteFlag == RESET)7 S# {; k' R! t- T, U
  59.   {
    + p( v$ m7 @# z1 A+ x
  60.   }& q. x- }) j9 }% _) H- s, E
  61. * @' L6 }; P  [1 m8 t
  62.   /* Check data integrity*/' }& ?. U) `8 d* ]3 J
  63.   pBuffer = (uint32_t*)&aDST_Buffer;
    " y* v/ D% t; M2 X, `$ ?) c6 G
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)2 _& S. ]1 Q$ e4 X* O
  65.   {
    . C0 _- m" `* _7 @1 z1 q& q; q' u
  66.                
    ' s/ l; e& ]! T7 }  {
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)! P: O" Q- S1 `& M+ Q
  68.     {
    $ i. a0 x  a' K5 ~- K* ?& U- \% t
  69.         compareErrorDetected++;
    $ I  t! U" h- a; |
  70.     }0 y+ _( h9 p3 r" Q8 \
  71.     pBuffer++;+ I! A. Z- j8 W% u  d$ U
  72.   }' }  m, Z6 x3 L: p  j+ w( J( m
  73.         
    / I( r0 u& p0 O2 u
  74.   if (compareErrorDetected != 0)5 G# @8 O; F/ B  X
  75.   {
    ! B& |( _% Q# t# T4 x( P% Z6 v
  76.       /* Toggle LED1 */9 d: ^9 \+ ]. Q, w7 g9 ~
  77.       BSP_LED_Off(LED1);% ~7 o7 X3 r7 A% G! m2 c& L
  78.       compareErrorDetected = 0;        
    8 Z4 b$ e, T- ?/ S7 s
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");! t. C6 D& C, n4 Q9 K
  80.   }
    . y# D5 K1 D( K+ [
  81.   else& `7 }8 J) @2 G! P: @. m- P
  82.   {& R1 t& I2 K; a
  83.       /* Turn LED1 on */
    3 c) [) [$ f2 ?, ]8 s6 n
  84.       BSP_LED_On(LED1);8 d- h# P$ {9 S  I3 V$ O
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");# P! C/ ~% P' J4 t9 x
  86.   }
    7 X2 R, X+ J: m# u: A' [- h

  87. # |  D8 K5 u3 b$ T+ `2 j
  88.   while (1)
    * n3 t9 ^  z: V3 [7 ~: n/ B
  89.   {) N$ h5 K% j% M) e+ n' W0 t

  90. : K) k% M  G- ~: n3 M
  91.   }, c. z! {/ u9 i! s- j3 k
  92. }( H( ]* h! {2 `- j2 [' D2 p
  93. : ?) x7 O% j! ]) T9 Z! T
  94. static void MPU_Config(void)& s1 p3 t# A3 D: O
  95. {  m. w& A, ?$ r- N( {/ H: k
  96.   /* Disable MPU */* x0 d" f5 }4 O- j. f$ j
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;7 U; q$ w9 I. h- f, N
  98. " j, c) _" O2 [- Z- P! }6 I
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */9 X* E% h3 m0 _9 b0 }0 C
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;* |# i% l3 Q. p
  101.   MPU->RBAR = SRAM1_ADDRESS_START;/ {" s# k- A0 b8 _9 Q8 \$ l
  102.          
    % {8 i  @  O+ K
  103.    /* Write-Back policy */! y* P7 Z( O! p* y
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;. {0 L: h4 C6 q$ ]; _2 X( K

  105. / X  T' v% o% X( `, X/ \$ ?
  106.   /* Enable MPU */
    - F8 U5 M* ]4 e" f6 e* w0 d
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    5 N  O7 U& n5 w
  108. }
    : E1 J: V+ `' o$ p1 b1 g. f
复制代码
4 b# ^4 t( H2 f! Z
为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:: p- c: W8 k8 {& K* b0 w) U# `/ i  t
4 N' M  J! d# G+ a/ M  I" ?' n- d
d4c481b36d81bb11f17b07a56ac1f054.png

( {$ p3 A3 E. o
- b. [& B; D9 r- y, G
图3.4 检查常量和变量分配情况

1 C- R& e2 m6 w: u2 R  V7 z; }) Q3 q+ V  e( ?7 q
下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:2 x& L- p* t5 s( W3 p

  ~) Z2 G) w/ X
bd661d50dcd8f45abeeabdd2ac3c0289.jpg

7 \, d0 M, }4 ]7 v9 t8 z% x4 \* r" T) F6 Q+ g7 P8 {
图3.5 Cache 数据不一致
) z  E! L2 I* V* p1 v& N# A% G+ c
: |$ N4 e+ E( W' p2 A
3.3.3 解决方案: J3 u: {' i( {
(1)不启动 D-Cache0 e% p) Y+ q2 n8 j# P3 X5 `

4 S5 g4 k% C( o4 E" n. e注释掉 SCB_EnableDCache();* ]- w6 p3 `7 c9 H5 j
5 _/ q2 D0 u! h" `% s+ b# t
不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~; W( i0 t/ ~8 B
4 F* ]  ^+ f% l% u
(2)将 SRAM1 相应区域设置为 shareable( T( G+ D4 |7 L6 I3 [3 H- u) N& @
. v2 |8 i+ }& r( c; |6 `, f
通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:
8 J% s- q* }, @4 `$ W
  1. static void MPU_Config(void)
    & g9 x% Y7 b* K3 Z, `2 a" k$ M: O, O
  2. {4 B& @% k" x- u. j  m' o
  3.   /* Disable MPU */
    ) F0 `  @4 b( e& b. o% p9 r& y
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    4 O  o. A  d4 l  u  N

  5. ( y0 n5 j+ M# V6 K$ C- T/ i" K
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */$ l! F/ p' V: v+ @5 j
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;
    ' h. `- N8 O5 z+ c# R
  8.   MPU->RBAR = SRAM1_ADDRESS_START;
    3 @" [) K) h4 @. C

  9. 9 b# W7 f4 L" X8 ]( _8 F7 o
  10.   /* Shareable */
    ! {5 ~# ^4 b* z. n8 m
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;
    ! P/ }7 f% q1 r& ^
  12. + t1 [2 Z* R* t' n9 w
  13.   /* Enable MPU */- c4 `/ U( {0 X* T* K, G
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;2 j8 T! E5 v# e
  15. }
复制代码

% C0 ]7 A% E2 f1 V$ \; u(3)DMA 访问 SRAM1 前先 Clean cache5 h* T+ E0 {* p! P8 E
9 g. g; `: _* h, R; H  `0 J0 o2 q
在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。
5 b7 x3 o) }) x! S! l; L/ T/ K2 P: Z
在本示例中,可以在 DMA_Config(); 前调用:8 ^2 \- H& d$ \! k) v
  1. SCB_CleanDCache();
复制代码
或者/ u6 g  A- E# X$ J4 l' l6 n3 W6 r1 g
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码
1 W* `' x: e( d9 P& k/ ]6 S/ {
(4)将 SRAM1 相应区域设置为 Write-through 策略
; O6 f" n7 o4 y1 d- k
2 w4 z% u3 y% @/ s4 i+ `/ ?通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:, ~" a1 P" `0 O- B: {

6 [. n: @6 R' t% _+ E4 h
  1. static void MPU_Config(void)
    ( i; S8 ~1 G( I# X& D* v5 y
  2. {
    ( p1 r8 ^4 Y! k# `
  3.   /* Disable MPU */4 R3 H4 {! v! n1 u* J5 d3 W
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;- C: @& H$ u$ v- \: l

  5. ' o' T) s4 A# h7 @+ }! O" f
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */' |& g5 w- p) g* N
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;" `0 w% D2 v4 n% l
  8.   MPU->RBAR = SRAM1_ADDRESS_START;9 q7 r5 U* d( j+ g! K; w1 t. o: M: a

  9. + t7 L9 A' w& }7 @
  10.   /*Write Through policy*/8 z4 H' Y. n( E1 D9 V
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;
    3 `+ _2 u0 z* F- n6 D5 E( o6 c

  12. $ H0 s1 j: _! n. P$ @2 a' ^
  13.   /* Enable MPU */) ^9 G0 ]; d* z) H
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;
    : |  `5 S- v( d2 J! W
  15. }
复制代码

* j9 a% I$ B, a6 D7 W' h) L2 c(5)将所有 cacheable 的空间全部强制 Write-though
& j0 m: s# O; b9 T# G9 [$ E& J( E
通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。
1 K( Y7 `. v- p' Y" l
7 I0 T  [: N* l8 m
e131d05081f8e30ba2296e50f3e9f392.png
# C5 z8 b1 U; l0 l8 M- E, |
; n3 u8 O9 L  K: q7 l( g# c! a: g
图3.6 CACR 寄存器(来自 PM0253)

. N! b3 W( f% \) x6 f/ }; y/ t( G0 J4 q
在初始化的时候进行设置:9 H4 m. `5 T) y: V3 o1 T
  1. __FORCE_WRITE_THROUGH();
复制代码

! `' i# V% {8 m# t7 ]宏定义为:
. I* t% g. ~/ L. D0 e. }+ [5 o
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码

" h3 i+ s4 X1 R- N以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!
# J" N# j: A* C0 Q; T. m7 L5 e3 m4 B( O. _6 C
值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。1 Y) j0 K! o, Y& S) U0 w- ^7 |

; U8 f% M6 s, G7 ]- d& |
9dffde7b310ed170c1b45f9dd7f75abe.jpg

8 k# u5 l2 X; U# x0 C! r. R( T: w2 N% z* f- z0 L% n
图3.7 Cache 数据一致

: f' A2 i  H5 C- D3 P5 L0 w+ Y! Q) {8 f* `$ U) z
好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~
+ {% r& T+ W! @- G; n4 S% r$ j; e, j. a9 d: v
& Y; p, c: U% y$ g
$ {9 _# s+ p) e3 L1 ^2 G/ K% i7 c
收藏 评论0 发布时间:2021-12-13 23:02

举报

0个回答

所属标签

相似技术帖

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版