目录
概述
1 Cache 及其原理
2 结构及策略
2.1 Cache类型
2.2 Cache实例
3 Cache 及 MPU 属性
4 Cache 一致性问题
4.1 未Clean写Cache情况
4.2 DMA 更新物理内存情况
4.3 一个实例
4.3.1 功能描述
4.3.2 代码实现
4.3.3 结论
概述
本文主要从结构原理以及应用方面对 MPU 和 Cache 进行分析,通过对cache相关知识体系的学习,以Cache 有基本的了解。便于在具体的实际应用中, 使用带有一级 cache 的 MCU 时,避免出现一些不必要的错误。
1 Cache 及其原理
cache 是一种高速缓存,其位于CPU与memory之间的存储设备。
Cache是高速缓存,一般指的是 L1 cache,即和 Core 紧耦合的, 从 STM32F7 系列开始,基于 ARM cortex-M7 内核,增加了对 L1 Cache 的支持。
Cache分为两类:
1)指令 Cache(I-cache)
2)数据 Cache(D-cache)
从上图片可以看出来,无论是指令 Cache(I-cache)还是数据 Cache(D-cache), 一旦使能之后,
就分别与 Core 的 prefetch unit(I-cache)和 load-store unit(D-cache)相连。
Cache的特点:
以 D-cache 为例, 因为直接与 LSU 相连,访问速度会比直接访问 SRAM 或外部 RAM 快很多, 只要保证 cache 有足够高的命中率(由 cache 策略保证), 尽量少的 cache miss, 读/写的速度会有比较大的提高。
2 结构及策略
2.1 Cache类型
1)指令Cache
2)数据Cache
2.2 Cache实例
同样这里以 D-cache 为例, 看一下 D-cache 的构成:包括 Address 和 cache-line, Address 表明其地址, 对应一条包含 32bytes 的 cache-line。
1)读数据
当地址命中时即 cache-hit,便可以直接从 cache line 中取出相应的数据, 反之,当遍历address 都没有找到, 就会产生 cache-miss,这时便会从实际的内存单元(如 SRAM)中取出相应的数据,并更新到某一条 cache-line 中并修改相应的 cache-line 信息;
2)写数据: write-through 策略和 write-back 策略。
write-though策略
更新 cache-line 的同时, 同样会更新其对应的实际物理地址的区域。
write-back策略
更新cache-line 的同时,并不是马上去更新其对应的实际物理地址的内容,而是在其认为合适或者所有的cache-line 都 dirty 的时候才会去更新, 当然,也可以通过软件让其强制更新,即 clean 的动作, 这一块会在后面的 cache 一致性问题上也会有体现;
同样,对于为什么将 cache 拆分为 2-way 或是 4-way, 这和 cache 自身的策略如查找算法等相关。
3 Cache 及 MPU 属性
cache 一般是配合 MPU(memory protection unit)一起使用的, 首先需要通过 MPU配置相应 memory 的属性(normal, strongly-ordered, device, XN etc.), 如下表所示:
地址空间 | 描述 |
---|---|
0~0x1FFF_FFFF | flash 空间, 属性为 normal, cache 的属性为 Write-through, 即更新 cache 的同时,将数据同时写入相应的物理地址空间 |
0x2000_0000~0x3FFF_FFFF | SRAM 空间, 属性为 normal, cache 的属性为 write-back, 即仅更新cache, 在合适的时候(由 cache 策略决定或者软件强制更新)将数据更新到相应的SRAM 空间 |
0x4000_0000~0x5FFFF_FFFF | 芯片内部的外设空间,属性为 device,这一版是外设寄存器所处的位置,对其读写的过程中不会经过 cache |
4 Cache 一致性问题
4.1 未Clean写Cache情况
当写物理内存的指令时, core 会先去更新相应的 cache-line(Write-back 策略), 在没有clean 的情况下,会导致其对应的实际物理内存中的数据并没有被更新。如果这个时候有其它的 Host( 如 DMA) 访问这段内存时, 就会出现问题( 由于实际物理内存并未被更新,和 D-cache 中的不一致) , 这就是所谓的 cache 一致性的问题!
4.2 DMA 更新物理内存情况
在DMA 更新了某段物理内存( DMA 和 cache 直接没有直接通道)时 , 而这个时候 Core 再读取这段内存的时候,由于相对应地址的 cache-line 没有被 invalidate,导致 Core 读到的是 cache-line中的数据,而非被 DMA 更新过的实际物理内存的数据
4.3 一个实例
4.3.1 功能描述
执行流程:
step -1: SRAM1_Buffer 先全部写入 0x55
step -2: Core 将 Flash 中的 Const_Buffer 写入 SRAM1_Buffer( 这里会先经过 d-cache)
step -3:配置 DMA,将 SRAM1_Buffer 中的数据通过 DMA 写入另一段内存 DTCM_Buffer
step -4:比较 DTCM_Buffer 中的数据和 Flash 中的 Const_Buffer 数据, 看是否一致
4.3.2 代码实现
step -1: MPU 对 memory 的配置
参数 | 描述 |
---|---|
BaseAddress | 要配置的存储空间的起始地址; |
Size | 要配置的存储空间的大小 |
IsCacheable | 表明这段存储空间是否可以 cache |
IsBufferable | 使能 cache 之后, 策略是 write-through 还是 write-back(bufferable) 这里需要特别注意的 1 点:配置的 BaseAddress 需要被 Size 整除, 以上述配置为例, 即0x20010000 除以 256K 需要是整数! |
step- 2: 使能 Cache
step- 3: 初始化 SRAM1_Buffer 为 0x55
step- 4: Copy Flash 中的 Const_Buffer 到 SRAM1_Buffer
step- 5: 配置 DMA,将 SRAM1_Buffer 写入 DTCM_Buffer
step- 6: 比较 DTCM_Buffer 和 Const_Buffer, 看是否一致
4.3.3 结论
从结果上看,step- 6比较的结果并不一致, 原因比较简单, 由于设定的 WB 策略,所以在
step4 的时候, 数据会暂存在 D-cache 当中, 并没有更新到 SRAM1_Buffer, 所以当
SRAM1_Buffer 被 DMA 拷到 DTCM_Buffer 中的时候,有一部分可能还是初始值,导致最终
的比较不一样,而解决的方法有以下几个:
1)MPU 配置的代码,将属性改为 MPU_ACCESS_BUFFERABLE, 即使用 write-though 策略
2)通过 cache 控制寄存器,将所有 cacheable 的空间全部强制 write-though