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

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

[复制链接]
STMCU小助手 发布时间:2021-12-13 23:02
3. Cache 一致性问题
  d5 J& r  b4 l7 H! n3.1 什么是 cache 一致性问题
8 m7 k+ j6 i* h8 ~: D; z2 [4 v所谓的 Cache 一致性问题, 主要指的是由于 D-cache 存在时,表现在有多个 Host(典型的如 MCU 的 Core, DMA 等)访问同一块内存时, 由于数据会缓存在 D-cache 中而没有更新实际的物理内存。
$ f) k- |6 p+ D( A, U% h1 C5 i: }/ |7 j% I+ f3 b7 Z5 F6 t
在实际应用中,有以下两种情况:) D" o# g6 t1 C! p- e) v( }' R1 z

7 B3 t% G8 W( X$ u( N$ @: R6 x; s第一种情况是当有写物理内存的指令时,Core 会先去更新相应的 cache-line(Write-back 策略),在没有 clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新,如果这个时候有其它的 Host(如 DMA)访问这段内存时,就会出现问题(由于实际物理内存并未被更新,和 D-cache 中的不一致),这就是所谓的 cache 一致性的问题。( y& P7 V" R( i( c
* D# G5 [4 C; ^0 ?4 L7 |. e1 z
516a4fcb212a09183f4c3f3efa77d170.png
. M# J) r2 `. x: t( y7 D) a

, `& \" N+ e4 V% k, Z# M
图3.1 Cache 一致性问题 第1种情况

2 @* L% {* ]  L4 j/ o; \1 k1 ]1 k) b$ H. r1 G: x" f
第二种情况是 DMA 更新了某段物理内存(DMA 和 cache 直接没有直接通道),而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line 中的数据,而非被 DMA 更新过的实际物理内存的数据。6 M0 b5 r  g* ^& R; D9 ~

% f# m! X0 _; h2 ^( D4 J0 a
ba3341c9a0e0ddc198b5fe0466a465dc.png
  ~6 O8 X. H, R; G; W  I5 g) |
6 e7 m% W% E8 p  o5 ]2 S
图3.2 Cache 一致性问题 第2种情况

+ H/ k' O' h. V+ ^' y. a2 N0 X: ^0 U- \- B3 R4 H" J1 k" C
3.2 如何处理 cache 一致性问题

. a6 g5 V/ A; m: i" C我们知道,Cache 机制是为了提高存储系统的平均读写性能而设计的,但是这种机制带来了数据一致性问题,然而,却没有对一致性的硬件支持。' P$ _# w" L# S% B

+ t/ f- D: K* l  j' O' g$ w因此为了解决一致性问题,一个办法就是禁用 Cache(cache 都禁用了,肯定不会有 cache 一致性的问题啦~)。但是如果你选择使用 STM32F7 这样高性能的微控制器,又不使用其带来的高性能特性,那你为什么要用 F7 呢,用 F3、F4 不就得了么?所以为了提高性能,还是使能 cache,并积极解决 cache 一致性问题吧。. E1 ]: m, B9 v3 C4 I

! F4 l4 h3 @' r* {3 p- t好吧,解决 STM32F7 的 cache 一致性问题,有两种可选方案:4 P9 P9 x/ G5 Z5 Y, Z8 t6 R2 o% I

' ~& J  Q5 E9 |3 I6 f所有的共享存储器都定义为共享属性) z# X/ S0 a7 @; q

' _- R- N0 K8 Y. A. ]这些区域将默认不被缓存到 D-Cache。) i% r' u7 ?6 F
所有的操作都直接针对二级存储器(内部Flash,外部存储器),性能降低。
' A7 ^7 j) S( G- ^因为缓存对这些区域是透明的,写软件更容易。
9 n# E0 y4 I8 K$ s% N8 f$ a( @5 S: B: g) g: d
通过软件进行cache的维护
2 n. ]; p0 x0 j(1)Cortex-M7 的写操作要是全局可见的9 V8 G/ p8 n8 s+ x

9 {7 }  l# j" U' ?2 l8 S5 h使用透写属性(通过 MPU 设置)。" v/ X1 g: \% N( G9 A: j/ R/ j* t
使用 SIWT@CACR(Shared = Write Through)。
* H" k. }& |  b0 s. h通过指令清 D-cache,然后所有更新位置禁止 D-Cache操作。
& I/ u$ k" \' H. n0 Y(2)其他主设备的写操作要对 Cortex-M7 可见8 B; D- ?* q: Z# G. ^/ A" M+ W

1 V- B- K+ Q- i1 L0 x7 ]6 `# e比如作废 Cortex-M7 Dache 中数据。
4 Z) F$ x3 H8 g: s+ C2 z, B3.3 示例( e4 u- M: x! F: Q4 \6 x/ `
3.3.1 程序描述2 t0 i- {: K& Q! _  n' `
(1)首先将地址 0x20020000(SRAM1)处开始的 128 字节初始化为 0x55。5 ~7 r$ f# |" B) n. o% C
(2)将 Flash 中的 128 字节的常量数组 aSRC_Const_Buffer 拷贝到 SRAM1 地址 0x20020000(pBuffer)。; a) T* q: t; b8 h, X
(3)配置并使能 DMA,通过 DMA 将数据从 SRAM1 的地址 0x20020000 处拷贝到 DTCM RAM 中的数组 aDST_Buffer 中。# C, ~. r- I% z4 [) H
(4)将 Flash 中的数组 aSRC_Const_Buffer 与 DMA 读出的数组 aDST_Buffer 进行比较。
' i" ?' \$ }0 [+ V  o) l/ i; F
: p4 D$ a; B1 ^1 }' b% `  N) u; i; q; W显然,这个例子中的 cache 一致性问题, 展示的是上面(图3.1)的第一种情况。也就是在 Write-back 策略下,CPU 先去更新相应的 cache-line,然后 DMA 去访问对应的内存,从而导致数据不一致的现象。
8 X7 N- D0 H& m3 s* J! T! `1 }
2 b% T' e3 A3 B2 ~' G程数据的传输流程和路径如下图所示:- n3 B. K) o; x6 ]6 y- N
0 E" q9 E1 r) x% {' C4 Z1 u
d0db73574a58707717ae26695e9dc302.png
" ^5 E2 v: D" K) `& q3 o$ s
* X: b: C4 j  ?2 Z7 [% o
图3.3 Cache 示例数据传输框图

" E$ Q1 j/ n+ J& Y( k+ Y9 O& [! F3 n, K7 N5 h- ]
3.3.2 复现 cache 一致性问题
# U' P/ R' `! Y( K; t' v我们先来按照示例要求编写代码,复现 cache 一致性问题。有些人可能会疑惑,变量数据怎么放到 Flash、SRAM1、DTCM?实际上,可以通过一些相关的配置文件进行设置,比如 icf 文件、scatter 文件等,当然,这跟所使用开发环境和编译工具链有关。9 c+ W/ k3 }1 @8 e2 ^
- e& J3 |5 L1 Q% o
本文所使用的环境是 IAR,其链接文件 *.icf 如下:
# P+ Q6 u; j; j# W* c+ B. l9 j" x! F1 b
5377967a69d8334b1bbd7b99f41c9e23.png
+ Y+ l+ H& I* [9 ^7 V; |7 u' n

: j6 K" R5 k! ^6 u5 D; g然后将 aSRC_Const_Buffer 数组定义为常量,即可分配到 RO 区域,aDST_Buffer 定义为普通的全局变量或静态变量即可,因为内存区域从 0x20000000 开始,也就是 DTCM RAM。
: I' U& `5 d# z, n+ g' \. z; u9 B) f& z# q( r- N* f- u7 j9 _
好了,代码主体部分如下:
" g5 @  S# J( ^: }0 i  f6 O& a( R/ P6 m: [$ Z9 Q
  1. #define SRAM1_ADDRESS_START   (0x20020000UL)
    3 h8 ]: s2 A( U5 I3 ^$ w: u1 ]
  2. ! \# e' Y1 `% U% h
  3. static const uint32_t aSRC_Const_Buffer[BUFFER_SIZE] =
    ) j4 }9 H$ m+ ^$ H2 J
  4. {
    ) K; ]0 Z, N8 Z& @. U* o/ [2 B
  5.   0x01020304, 0x05060708, 0x090A0B0C, 0x0D0E0F10,: X% `4 z( p8 \+ J6 x& o- _: d
  6.   0x11121314, 0x15161718, 0x191A1B1C, 0x1D1E1F20,1 e3 X. m( z6 ^4 r# O3 V1 c7 B
  7.   0x21222324, 0x25262728, 0x292A2B2C, 0x2D2E2F30,
    4 Z9 `% w! j6 O: F, d7 C: F
  8.   0x31323334, 0x35363738, 0x393A3B3C, 0x3D3E3F40,' V% L/ x5 C% V7 J! N+ F
  9.   0x41424344, 0x45464748, 0x494A4B4C, 0x4D4E4F50,2 O% I2 o0 y. O- o$ i+ j: B
  10.   0x51525354, 0x55565758, 0x595A5B5C, 0x5D5E5F60,0 a6 M, l5 u! C+ G* a9 A
  11.   0x61626364, 0x65666768, 0x696A6B6C, 0x6D6E6F70,' ~7 N3 U! u, m/ w* z( [5 v9 H  ~
  12.   0x71727374, 0x75767778, 0x797A7B7C, 0x7D7E7F80; S& W" \4 N5 z; Y4 Y3 `3 o" R3 a
  13. };
    : N' s# z, ]+ m) g( x

  14. 5 i* e; \' G8 N% {9 Y
  15. static uint32_t aDST_Buffer[BUFFER_SIZE];; o" S8 p" ^2 Y0 E
  16. $ u, f. E/ b# o
  17. int main(void)% _' M5 ^. j: R
  18. {
    : Q+ t) Q8 `& _4 `( t
  19.   uint32_t counter = 0;
    - S( @& H* S. u! H$ C
  20.   uint32_t *pBuffer = (uint32_t*)SRAM1_ADDRESS_START;! n& E! ^' C- f/ J5 I

  21. 2 Y3 l" w9 d. I/ j/ k/ [
  22.   if (HAL_Init() != HAL_OK)
    9 C4 k1 q" D9 H4 A( W  H% z4 t
  23.   {
    + R  I% h$ `6 C, i# g- A+ X3 S$ _
  24.     Error_Handler();
    ' f& R- u8 e. y
  25.   }! D3 D3 A+ ^0 r- _" m8 ?

  26. / v; z1 l" E/ Y) \
  27.   /* Initialize LEDs */
    , b( E7 K  w" \0 p
  28.   BSP_LED_Init(LED1);1 ~/ Z2 ^! K8 }, Z* J

  29. 3 G* X! k5 P0 C6 R2 U1 E5 F
  30.   /* Configure the system clock to 216 MHz */$ F$ L4 S% w  R5 S
  31.   SystemClock_Config();
    9 C  m' N- G9 ~+ L: G5 U: x) i
  32.   BSP_LCD_Config();- ?1 l# x+ p) T# |: G
  33. % o* T. r& O' h! I- k7 A
  34.   /* Set to 1 if an transfer error is detected */6 I6 u# I& |- S
  35.   transferErrorDetected = 0;! _( v8 W4 M5 V1 Z4 \
  36.         
    1 c4 l  y- a& K4 C
  37.   /* Fill 128 bytes with 0x55 pattern */
    4 Z' n, R* ?: k0 s6 F
  38.   memset((uint8_t*)SRAM1_ADDRESS_START, 0x55, sizeof(aSRC_Const_Buffer));
    $ z* |4 a# X: y; [4 Q  c
  39. 4 ^3 q8 M( m1 G- v4 A4 b* y
  40.   /* TODO:Enable MPU and change SRAM region attribute . q3 r2 p. @  j5 t  L- Z$ w
  41.   * set write-back policy on SRAM */
    * h) |/ P4 C  ?) i6 Q! j8 y8 a
  42.   MPU_Config();
    ' a6 I( J1 I# y

  43. 2 `6 R6 x2 I# C; v2 {: o9 a& {
  44.   /* Enable Data cache */
    ' e* r5 F; `$ b" U
  45.   SCB_EnableDCache();
    : R5 o+ J! |* E% n  F
  46. 9 h% j, G/ O# ^4 k# P3 `
  47.   /* Copy data from Flash to SRAM by CPU */
    $ q: |" ^5 b  j" M
  48.   for (counter = 0; counter < (sizeof(aSRC_Const_Buffer)/4); counter++)' m/ r: I% t% Q8 f$ |
  49.   {
    1 j+ F% U+ L$ W$ X4 V( P
  50.         *pBuffer++ = aSRC_Const_Buffer[counter];& M+ F. F- `  x% t6 U8 G# U+ I
  51.   }
    " P1 m' T4 G, v0 D( U& \6 c. m( [
  52.         1 d: Q3 }# ~& S% y
  53.   //* Configure and enable the DMA stream for Memory to Memory transfer */
    $ v" `, [4 V2 n3 M
  54.   DMA_Config();; O: Z5 X7 V4 p1 e# q

  55. / g# u7 D% j7 j9 o
  56.   /* Wait for DMA end-of-transfer */
    + |0 z6 T( S/ M. k

  57. 0 i7 L1 L- |+ k) r6 Y
  58.   while(TransferCompleteFlag == RESET)& f( @, w8 X3 H5 V
  59.   {* j& p5 a. j% ?9 x# [
  60.   }
    . G+ `) ~+ F) M7 s
  61. 1 `0 v" ~; P2 E
  62.   /* Check data integrity*/6 l0 e' j3 M; h+ P4 M% Y& Y8 n" L
  63.   pBuffer = (uint32_t*)&aDST_Buffer;
    . V" C- E! s5 s
  64.   for(counter = 0; counter <(sizeof(aSRC_Const_Buffer)/4); counter++)7 t0 [9 H! ?6 ?% P
  65.   {5 t0 l+ I0 H5 L7 j4 l% j
  66.                 , q# B$ y0 d! O9 j- m0 o
  67.     if(aSRC_Const_Buffer[counter] != *pBuffer)$ X% _, s3 m0 [( \* J! J
  68.     {
    0 m. e4 u# a% q( [# }4 D
  69.         compareErrorDetected++;
      ~3 T3 X5 m+ |
  70.     }
    5 Q% x: {% {3 H$ \
  71.     pBuffer++;' o, U3 g' ^9 M  K9 A. v
  72.   }
    & I; A# ]7 L4 t, A! i1 K* P
  73.         " t8 X5 ~. ?- |. _* @+ Q
  74.   if (compareErrorDetected != 0)+ T# K' t' t- ?" t6 \4 N
  75.   {
    + N% z6 Z5 L8 A) ^- F
  76.       /* Toggle LED1 */: b" `. d7 S% ~1 N9 B: w. \
  77.       BSP_LED_Off(LED1);( M) Q/ V4 F: F; w, F7 p6 a8 ^
  78.       compareErrorDetected = 0;        8 @& S  I) P. X/ e
  79.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation failed!      ");/ w/ I7 g1 J  f$ Q: k# p
  80.   }
    7 Y/ `$ V! j- |  J# u
  81.   else
    + L! y0 n2 J1 g
  82.   {$ q, J# E" Y& B! X! o( o
  83.       /* Turn LED1 on */$ n3 N2 T( L: s4 D* L+ ^
  84.       BSP_LED_On(LED1);
    % Q% l$ i4 `( V: I2 V
  85.       BSP_LCD_DisplayStringAtLine(10, (uint8_t *)"       Data comparation success!      ");
    7 l, N- O( B9 l" I+ |! }0 J
  86.   }
    ; h7 u6 v8 T6 b; }/ @9 G

  87. / D9 O- l: H/ Y& ~  r
  88.   while (1)7 S3 [1 ?& w# d# }, b
  89.   {# Z+ e8 }5 |1 X

  90. 3 g/ L! s. a3 P8 u, Y0 K! f
  91.   }2 o& |% A( }: H9 w( d; S' }
  92. }
    5 d# g4 J  E' [0 l
  93. % q9 A9 M; m6 L) c  Z- H7 F
  94. static void MPU_Config(void)% p! E  M9 ]# {
  95. {
    9 ^! x9 J6 o/ h5 I
  96.   /* Disable MPU */& {6 H! Q4 f. ]$ F' a6 ~" U
  97.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    . M! Q7 N% R: I: X$ x

  98. 3 V: J  P  |9 @; c
  99.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    7 i3 [: W! R8 _  \- x( j4 p
  100.   MPU->RNR  = SRAM1_REGION_NUMBER;
    ! R8 A% Y1 I) [8 ?; v
  101.   MPU->RBAR = SRAM1_ADDRESS_START;7 T2 C# ~9 v' C3 o# q/ F" `
  102.          ' M1 g( s# [% W! c/ O; p" f
  103.    /* Write-Back policy */, X" E* B0 j/ b9 G, h7 s' T
  104.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | MPU_RASR_B_Msk | SRAM1_ACCESS_PERMISSION | 1<<MPU_RASR_TEX_Pos;+ v$ b3 K/ V; i

  105. 2 |; n  Y0 t& S5 T1 a1 m
  106.   /* Enable MPU */3 z3 D( }/ ~- k, y& s
  107.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;* h0 a& k' h7 H6 m
  108. }- P: O+ \( g* t2 P) o
复制代码
: Q8 |( q- Y  V
为了确保 aSRC_Const_Buffer 在 Flash,aDST_Buffer 在 DTCM,我们可以在编译完之后查看 *.map 文件,如下:2 _9 e. d& W. t

/ l- `6 k8 T9 Y5 B* B. L. m
d4c481b36d81bb11f17b07a56ac1f054.png
2 e1 F, F, p; o
' C6 M+ |* T  p# |( k
图3.4 检查常量和变量分配情况

# H  Y: k( y, u9 s' P- U, d6 ?
4 G4 N& w# w1 @9 k2 {$ a( b! X下载到 STM32F769I-DISCO 板子上,显然,由于此时开启了 D-Cache,会出现数据不一致的现象,执行结果如下所示:' u+ g. |3 M2 k8 m* t5 {* w: g
' f4 o( _& I: Y9 `
bd661d50dcd8f45abeeabdd2ac3c0289.jpg
" r- Z" A; P1 U. |+ N' L$ \# {
  k1 s: I2 r* i$ H& _9 q
图3.5 Cache 数据不一致

* e- Z+ E2 @3 i( U0 q8 S7 z& T* S. R6 ^9 h' a9 Q5 |1 a
3.3.3 解决方案) ~- T/ V) h" S. z' \/ ~$ q/ c
(1)不启动 D-Cache9 b$ K* I5 h" m) Y& U0 ^9 p

) B4 Q' F3 k: A8 v5 Z/ u注释掉 SCB_EnableDCache();6 Q8 r# c# F! w2 ~2 A9 }. G

6 l( U* z* W' t4 \( R不启动 D-Cache,当然也就没有了 Cache 数据不一致的问题啦~
) K$ W! S% _) @5 e6 A  i- \1 C2 K7 c
(2)将 SRAM1 相应区域设置为 shareable' G, m5 V5 Q  q

4 i4 `7 x; _: s通过 MPU 将 SRAM1 相应区域设置为 shareable,MPU_Config() 函数处理如下:, I5 d6 J" K( n& L8 H& @
  1. static void MPU_Config(void)- F; f' |" p+ L& @
  2. {
    - x- l- i. B0 ]8 I9 S- R
  3.   /* Disable MPU */
    8 e' a  C7 V0 j& u( U. o/ O
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    8 c8 j4 k& Z, r' e1 [

  5. 7 \) p% @' x3 Z+ R, L5 a
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    # |, n: F2 U: X1 F9 F! S: U5 f
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;( C" s1 x) v3 Y2 W  p
  8.   MPU->RBAR = SRAM1_ADDRESS_START;8 |% T2 h1 E9 ~# k0 R+ O' u9 T
  9. 2 n* ?$ _( L) J, N& L/ L
  10.   /* Shareable */
    5 |& Z% Q, I, S8 U4 q6 w  I: [
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_S_Msk | SRAM1_ACCESS_PERMISSION;; R* L8 |9 \0 Z& ?: }
  12. , x2 h$ [- s. o2 ^) {
  13.   /* Enable MPU */6 e  e/ B& X1 u6 p. f) ?9 b
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;( `4 K+ q' @' K
  15. }
复制代码

9 z  n+ h% c6 `2 u) |! W% C: `(3)DMA 访问 SRAM1 前先 Clean cache
1 Y( |9 W3 @4 Y- a& n. Q( c# O+ C/ ]4 }$ b
在启动 DMA 访问之前,程序员需要在合适的地方将 D-Cache 数据回写到主内存中,也就是 Clean 的操作。
+ A) q/ W+ p+ j3 Y9 I+ A( b& @& S" @; T- r) |7 u; Z" P
在本示例中,可以在 DMA_Config(); 前调用:: n& Z  ~  h, l  M
  1. SCB_CleanDCache();
复制代码
或者
/ x, u  {( E4 S% Z4 z
  1. SCB_CleanDCache_by_Addr((uint32_t*)SRAM1_ADDRESS_START, sizeof(aSRC_Const_Buffer));
复制代码
: Z! m7 Z6 Y7 r6 I. L
(4)将 SRAM1 相应区域设置为 Write-through 策略5 X) N! c" C+ u: {4 o; W
, N% [$ B) T( ^5 X  A
通过 MPU 将 SRAM1 相应区域设置为透写模式(Write-through),MPU_Config() 函数处理如下:
' S: [, q! x9 w. k9 a. T1 |+ \+ E0 B/ l2 H" @
  1. static void MPU_Config(void)# s+ @4 K9 u! K
  2. {" P7 H4 i4 x2 Q% x
  3.   /* Disable MPU */
    & ~7 P( m$ Y' W- J
  4.   MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
    : e" ]( v) G3 b

  5. / z6 t. U  i# U" F7 i
  6.   /* Configure RAM region as Region N°0, 256kB of size and R/W region */
    8 @# B3 i( G1 D% k9 X5 |5 i  X" }
  7.   MPU->RNR  = SRAM1_REGION_NUMBER;# P; e% A" Z; L: Q, G' O. L+ t
  8.   MPU->RBAR = SRAM1_ADDRESS_START;( |+ X( `6 I$ O4 _' }0 d4 J& i
  9. * p/ |8 B0 m3 t
  10.   /*Write Through policy*/3 Z& X1 E- K5 p' r: ^4 F
  11.   MPU->RASR = SRAM1_SIZE | MPU_RASR_C_Msk | SRAM1_ACCESS_PERMISSION;- [4 Z' |! y. f& \3 O3 n) h0 b
  12. * b! G' }$ F0 i6 \
  13.   /* Enable MPU */
    1 {  x! M. g9 k* K: ]
  14.   MPU->CTRL |= MPU_CTRL_PRIVDEFENA_Msk | MPU_CTRL_ENABLE_Msk;6 _) B8 C7 @0 X# _, `
  15. }
复制代码
/ K8 Y" v: h; |5 u: ^6 g
(5)将所有 cacheable 的空间全部强制 Write-though5 P' f- x; |+ {

  V: q" B$ N& F- z/ w" }通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 Write-though 模式。
$ \( f& E8 Z2 f* p* C/ Z# c
' G, q2 g( V7 R9 B! q4 z; r
e131d05081f8e30ba2296e50f3e9f392.png

0 e0 E* e( p3 \& t
2 s8 f' i5 p  `7 X+ J8 f
图3.6 CACR 寄存器(来自 PM0253)
2 p: j7 ]) [2 {/ q5 V6 a; ^4 Z

, M9 v! B. q  Z  [+ e在初始化的时候进行设置:5 P8 R( y1 X7 l8 e( k' G
  1. __FORCE_WRITE_THROUGH();
复制代码
+ b' ~8 a6 e8 a& S8 A' @5 ]0 _1 b
宏定义为:# S  I7 h  M' G) ]
  1. #define __FORCE_WRITE_THROUGH()    *(__IO uint32_t *)0xE000EF9C = 1UL<<2
复制代码

; |- p+ W$ f9 i- A, |' R6 B以上这是都是较为常用的方法,在实际的开发过程中,为了提高性能,一般都会开启 cache,同时将其配置为 WB 策略,这就需要开发者在使用时特别小心!2 [5 n: t& e. |) ^' e! `5 b' q0 H& O
7 W: t3 o( N0 s9 a6 u" q
值得一提的是:对于第二种情况(图3.2),就不是 clean 操作了,而是 invalidate。需要先调用 SCB_InvalidateDCache() 或 SCB_InvalidateDCache_by_Addr() 去 invalidate 相应的 cache-line, 这样当 CPU 在读取时,会忽略 D-cache 中的内容,去真实的物理地址读取对应的数据。4 V6 I8 n& K% ~- y' M* D" F

6 A* \' M* V% N. G6 O0 _7 U+ u* M
9dffde7b310ed170c1b45f9dd7f75abe.jpg
8 N* L( z' n& Y
, |) J! x0 i/ p" F# t8 k
图3.7 Cache 数据一致

+ H0 f9 k* d' [; c7 y- A6 a
8 W- g) |9 ^5 o. p  Z好啦,通过上述几种方法,就可以解决 cache 数据一致性问题。当然,除了我这里提供的,还有其他方案,各种方案各有利弊,要根据实际应用场景去衡量,这就是嵌入式程序员展示才华的时候啦~" ?7 i' L7 _' F! U( B

5 |* y2 V7 z6 j! k7 _( n4 m
" t* X; m' _# W3 N; W
* V/ T. G0 \$ B% ~! l
收藏 评论0 发布时间:2021-12-13 23:02

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版