2. STM32F7 新特性——高速缓存. T, I- G" I( v; G: B0 C8 o 2.1 STM32F7 的存储系统 STM32F7 系列微控制器作为高性能微控制器,为我们带来了很多让人眼前一亮的新特性,其中之一就是独立的指令和数据高速缓冲存储器,也就是所谓的 L1-cache,包括 I-Cache 和 D-Cache。Cache 的大小根据不同型号有所差别,有 4Kbytes、8Kbytes 和 16Kbytes 几种容量。& q, a8 i7 F& K) N& ` ( U. t# Q' x4 {; e' |2 ~$ q# I3 b 实际上,这个 Cache 是放在 Cortex 内核里面的,半导体厂商(比如 ST)购买 IP 核的时候可以选择要多大的 cache,之后这款 MCU 的 cache 就已经固定了。这有点像我们去 4S 店买车,根据自身的需求和资金情况选择不同的配置。显然,cache 的容量越大,价格也就越高。本文所使用的 STM32F769I-DISCO 包含 16Kbytes 的 I-Cache 和 D-Cache。- @2 k8 C$ {: L5 A9 C4 u2 x/ f+ G. Y + ~- L1 A* x9 x5 [2 H ^" i+ n + B X7 ?6 S7 O3 H, M4 c* w* r 上图是 STM32F7 系列微控制器的系统架构框图,我们可以看到在 Cortex-M7 内核里面有一个 I-Cache 和一个 D-Cache,它们是实实在在的高速存储器。而 DTCM 和 ITCM 则是两个接口,对应 Data TCM 和 Instruction TCM,它们有利于数据和指令的快速读取,可实现内嵌 Flash 的零时延数据读取。但是要注意 TCM 接口是不经过缓存的!* f; D: [ S; }2 j * b2 E- {5 r- m% |- T5 N 上图的 F7 框图,包含 1 MB Flash 和 320 KB SRAM,其中的 320 KB 的 SRAM 是分离的,它包括 64 KB 的 DTCM RAM、240 KB SRAM1 以及 16 KB SRAM2,而 16 KB 的 ITCM RAM 和 4 KB 的备份 RAM 并不包含在内。 这几个 SRAM 的关系,我们来看下面这个图就比较明白了。2 ^5 z$ l5 m" J. |' x + `* P- W) W% ~( Q 可以看到,DTCM RAM、SRAM1 和 SRAM2 在地址映射上是连续的,比如从 0x20000000 到 0x2007FFFF。 我们还可以看到内嵌的 Flash 有两种接口,分别是 AXIM 和 ITCM 接口,对应于地址 0x08000000 和 0x00200000。那怎么通过不同的接口操作 Flash 呢?——只要操作对应的地址即可。 ' R# T- B, t* s 2.2 Cache 的组织: n0 g9 o. i" v! h* B: ?$ ?3 _ 在前面我们说过,绝大多数控制器的 Cache 都是采用组关联(set-associative)的映射方式,STM32F7 当然也不例外。那么,F7 的 Cache 是如何组织的呢? 1 Q' v7 f2 }8 [, j/ K! ?2 V 通过文档 AN4839,我们可以了解到:5 ?9 Q! ]/ u O5 _( O) j // 第5页 A cache is normally implemented using sets of lines where a line is just a short segment of memory. The number of lines in a set is called x-way associative. This property is set in the hardware design. // 第6页' U* _; Q1 f3 e \7 I) {( Y8 R The L1-caches on all Cortex®-M7s are divided into lines of 32 bytes. Each line is tagged with an address. The data cache is 4-way set associative (four lines per set) and the instruction cache is 2-way set associative. This is a hardware compromise to keep from having to tag each line with an address. # r0 X; N- P5 w! [ 也就是说,D-Cache 和 I-Cache 的块大小(cache line)为 32 bytes,采用组关联映射方式。对于 D-Cache,每组(set)包含 4 个缓冲行(line);对于 I-Cache,每组(set)包含 2 个缓冲行(line)。' B7 j3 G2 U, T% u& A( x6 K 以 16 KBytes 的 D-Cache 来计算,一共 512 个缓冲行(lines),128 个组(sets),每组包含 4 个 line,每个 line 包含 8 个字,也就是 32 个字节。5 N+ ]2 e5 l* {" t5 o5 I- \% P& i3 x& C 2 U3 H9 i' [1 |7 P, w 2.3 存储器默认映射和属性 STM32F7 系列微控制器的存储器的默认映射和属性如下图所示。 ) u( d5 D2 D8 L n ^' p% e# {5 A # u0 K, F0 T2 ^ e3 } n “默认”的意思就是如果没有启动 MPU,并且没有对某些特殊寄存器进行配置,那么存储器的映射地址及其属性就如上图所示。+ C1 a( b7 x7 M, a1 M ! k. ]! l7 y: y0 g2 L. Z$ }3 ^ 其中,WT 表示 Write-through(透写),WB 表示 Write-back(回写),WA 表示 Write-allocate(写分配),没有明确标注 WA 的就是 RA(读分配)。XN 的意思是 Execute-Never, 其含义为如果相应的地址空间是 XN,是绝不允许执行代码的。 存储器类型为 Normal 的才能使用 cache,并且 TCM 接口是 not cacheable 的。5 |" v- s: Q9 c6 \: }3 i0 w 6 o- Y/ r5 }5 C/ ]6 b/ S5 Q) U 当然,这只是默认值,部分存储器地址映射和属性是可以通过 MPU 来配置的。 ; h/ k- o6 \9 z! r- Z. A, r 选取几个有特点的区域稍微讲解一下吧:7 R8 N+ |4 L% t : w" b9 y& ~: O8 E3 P0 H 0x00000000~0x1FFFFFFF:flash 空间, 属性为 normal, cache 的属性为 Write-through, 即更新 cache 的同时,将数据同时写入相应的物理地址空间。 q" B$ e k. N* e9 | }6 E4 Q1 m# M. p; z( P* i: _ 0x20000000~0x3FFFFFFF:SRAM 空间, 属性为 normal, cache 的属性为 write-back, 即仅更新 cache, 在合适的时候(由 cache 策略决定或者软件强制更新)将数据更新到相应的 SRAM 空间。 9 p1 q% [$ U0 [. n' Q( k& e 0x40000000~0x5FFFFFFFF:芯片内部的外设空间,属性为 device,这一区域是外设寄存器所处的位置,对其读写的过程中不会经过 cache。% x" z* M0 Z: ]+ ?* |$ I( \ 2.4 CMSIS 函数' `* s" Q" _" \7 a0 J n" F 前面说了那么多,我自己都有点晕了。。。对于用户来说,如何正确使用 Cache 才是关键!2 o5 c7 p3 b. I- h' L: U1 x 下面这张图是在文档 PM0253 中截取的,Cache 相关操作的函数在 cmsis/include/core_cm7.h 头文件中声明。从函数名中可以知道,包括四种 cache 操作:enable、disable、clean 和 invalidate。. A4 n9 S0 u) c6 i) l6 [ q 7 K U) ?+ m0 X0 S% h' R 查看源代码发现,除了表中的8个函数,还有以下3个函数(都是以 _by_Addr 结尾):) f6 ?. R6 J8 P+ l+ { 9 m5 P9 s0 c4 @9 ]
好,那下面我们一一来了解这些函数吧。 SCB_EnableICache() 和 SCB_EnableDCache() 使能 I-cache 或 D-cache。 SCB_DisableICache() 和 SCB_DisableDCache() * w6 N+ ^/ ?$ o 禁用 I-cache 或 D-cache。 3 B3 \# r2 B" ~" t" z5 q8 _3 B SCB_InvalidateICache() 使 I-cache 无效,I-cache 被 invalidate 之后,当读取指令时,会忽略相应的 cache-line 中的内容(因为被 validate 了),而从真实的物理地址中去获取相应的指令。+ M/ F. ?: W6 H9 A. G m# V! k0 M' U SCB_InvalidateDCache()8 X- k0 c0 o7 ^+ j 使 D-cache 无效,D-cache 被 invalidate 之后,当有 Host(如 core,DMA 等)读取数据时,会忽略相应的 cache-line 中的内容( 因为被 validate 了),从真实的物理地址中去获取相应的数据。; D/ x5 r+ [: {* f& d, D ) z/ {0 `+ {+ _1 a; r% a! k2 k4 j( } SCB_InvalidateDCache_by_Addr(): Z- B& }$ {' J9 q1 u+ O* s g 根据地址信息无效其对应的 cache-line。7 J5 h4 m3 E, i( e( m: w- W 8 y8 ~2 E% m4 l& s! ~, q7 C SCB_CleanDCache() Clean 所有的 cache-line,即将 dirty 的 cache-line 全部写到 cache line 对应的真实的物理地址中所谓的 drity 属性,即写操作时, 更新了相应的 cache-line,但是没有更新到真实的物理地址,而这个 clean 的动作, 就是将 cache 中的内容更新到真实的物理地址中。% e% a8 s# I4 G6 W! U1 {# Q SCB_CleanDCache_by_Addr() 根据地址信息 clean 其对应的 cache-line。- a! ]/ D/ ^! p, Y) K" @ SCB_CleanInvalidateDCache_by_Addr()% f. y3 U4 s9 ?/ P) G. @0 ]: E 根据地址信息 clean 并 invalidate 其对应的 cache-line。 " e0 h& F2 T( A |
基于STM32F746G-Discover的扩展电路板
【合集】STM32F7教程、资料大集合
F769 Discovery实现播放U盘音乐的播放器
STM32 VS Code Extension (在Ubuntu上开发STM32,ST官方vscode插件使用指南)
STM32F765@216MHz跑NES模拟器【代码】【视频】
基于STM32F7实现ADC软件触发+轮询采集
基于STM32F7进行ADC采集解决更新问题
基于STM32F7使用定时器经验分享
实现基于STM32F7中周期采集
基于STM32F7中实现采集和中断