缓存(Cache)
概述
各个 CPU 的缓存描述如下:
CPU |
类型 |
大小 |
Way |
缓冲行长度 |
---|---|---|---|---|
KM4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
KM0 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
CPU |
类型 |
大小 |
Way |
缓冲行长度 |
---|---|---|---|---|
KM4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
KR4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
CPU |
类型 |
大小 |
Way |
缓冲行长度 |
---|---|---|---|---|
KM4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
KR4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
DSP |
I-Cache |
32KB |
4 |
128B |
D-Cache |
48KB |
3 |
128B |
CPU |
类型 |
大小 |
Way |
缓冲行长度 |
---|---|---|---|---|
KM4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
KR4 |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
DSP |
I-Cache |
32KB |
4 |
128B |
D-Cache |
48KB |
3 |
128B |
CPU |
类型 |
大小 |
Way |
缓冲行长度 |
---|---|---|---|---|
KM4 |
I-Cache |
64KB |
4 |
32B |
D-Cache |
32KB |
4 |
32B |
|
KM0 |
I-Cache |
16KB |
2 |
32B |
D-Cache |
8KB |
2 |
32B |
|
CA32 |
L1 I-Cache |
32KB |
2 |
64B |
L1 D-Cache |
32KB |
4 |
64B |
|
L2 Cache |
256KB |
8 |
64B |
CPU |
Type |
Size |
Way |
Cache line length |
---|---|---|---|---|
KM4TZ |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
|
KM4NS |
I-Cache |
16KB |
4 |
32B |
D-Cache |
16KB |
4 |
32B |
片内缓存支持 Enable/Disable、Flush 和 Clean 操作。在 main()
函数之前,各个 CPU 均已调用 Cache_Enable()
启用了缓存。
操作 |
描述 |
I-Cache |
D-Cache |
---|---|---|---|
Enable/Disable |
启用或禁用缓存 |
√ |
√ |
Flush (Invalidate) |
|
√ |
√ |
Clean |
|
x |
√ |
备注
CA32 清空某个地址时,只有处于 clean 状态的缓存行才会执行清空操作,处于 dirty 状态的缓存行会执行 Clean & Invalidate 操作。
CA32 和 DSP 具有自动数据预取功能,当 CPU 预测未来将需要访问的数据时,CPU 会在后台执行行填充操作,自动将数据加载到缓存中。
对于 CA32 和 DSP,
DCache_Clean()
/DCache_CleanInvalidate()
操作会将整个缓存行写入内存。当两个 CPU(具有不同的缓存行大小)使用共享内存通信时,共享内存必须与较大的缓存行对齐,以避免数据覆盖问题。例如:如果共享内存只有 32 字节,缓存行大小为 32 字节的 CPU0 每次清理时只会写入 32 字节,而缓存行大小为 64 字节的 CPU1 每次清理时会写入 64 字节,可能会覆盖 CPU0 的其他数据。
API 参考
ICache_Enable
void ICache_Enable(void)
启用 I-Cache
ICache_Disable
void ICache_Disable(void)
禁用 I-Cache
ICache_Invalidate
void ICache_Invalidate(void)
清空 I-Cache
DCache_IsEnabled
u32 DCache_IsEnabled(void)
确认 D-Cache 是否启用,返回值:
1:启用
0:禁用
DCache_Enable
void DCache_Enable(void)
启用 D-Cache
DCache_Disable
void DCache_Disable(void)
禁用 D-Cache
DCache_Invalidate
void DCache_Invalidate(u32 Address, u32 Bytes)
通过地址清空 D-Cache,参数说明:
- Address:
失效地址(按缓存行长度对齐)
- Bytes:
内存块大小(单位:字节)
DCache_Clean
void DCache_Clean(u32 Address, u32 Bytes)
通过地址清理 D-Cache,参数说明:
- Address:
清理地址(按缓存行长度对齐)
- Bytes:
内存块大小(单位:字节)
DCache_CleanInvalidate
void DCache_CleanInvalidate(u32 Address, u32 Bytes)
通过地址清理和清空 D-Cache,参数说明:
- Address:
需清理并失效的地址(按缓存行长度对齐)
- Bytes:
内存块大小(单位:字节)
备注
Address
和Bytes
同时为 0xFFFFFFFF,表示清理或者清空全部 D-Cache。Address
和Bytes
必须按缓存行长度对齐。如果不对齐,例如缓存行长度为 32 字节,Address
为 0x20000003C,Bytes
为 0x00000008 时,那么操作的地址范围跨越了 2 个缓存行,实际操作的地址范围为0x200000020 ~ 0x20000003F
和0x200000040 ~ 0x20000005F
,此时会导致预期外的问题。
如何定义非缓存数据缓冲区
在缓冲区定义前添加宏 SRAM_NOCACHE_DATA_SECTION,可定义具有非缓存属性(Non-Cacheable)的数据缓冲区。
SRAM_NOCACHE_DATA_SECTION u8 noncache_buffer[DATA_BUFFER_SIZE];
在缓冲区定义前添加宏 SRAM_NOCACHE_DATA_SECTION,可定义具有非缓存属性(Non-Cacheable)的数据缓冲区。
SRAM_NOCACHE_DATA_SECTION u8 noncache_buffer[DATA_BUFFER_SIZE];
备注
对于 KR4:非缓存属性仅能通过 MCCA 寄存器 配置,因此无法直接通过宏定义实现非缓存缓冲区。
在缓冲区定义前添加宏 SRAM_NOCACHE_DATA_SECTION,可定义具有非缓存属性(Non-Cacheable)的数据缓冲区。
SRAM_NOCACHE_DATA_SECTION u8 noncache_buffer[DATA_BUFFER_SIZE];
备注
对于 KR4:非缓存属性仅能通过 MCCA 寄存器 配置,因此无法直接通过宏定义实现非缓存缓冲区。
对于 DSP:若需操作 DSP 缓存,请参考 Xtensa LX7 Microprocessor Data Book 和 Xtensa System Software Reference Manual 获取详细信息。
在缓冲区定义前添加宏 SRAM_NOCACHE_DATA_SECTION,可定义具有非缓存属性(Non-Cacheable)的数据缓冲区。
SRAM_NOCACHE_DATA_SECTION u8 noncache_buffer[DATA_BUFFER_SIZE];
备注
对于 KR4:非缓存属性仅能通过 MCCA 寄存器 配置,因此无法直接通过宏定义实现非缓存缓冲区。
对于 DSP:若需操作 DSP 缓存,请参考 Xtensa LX7 Microprocessor Data Book 和 Xtensa System Software Reference Manual 获取详细信息。
在缓冲区定义前添加宏 SRAM_NOCACHE_DATA_SECTION,可定义具有非缓存属性(Non-Cacheable)的数据缓冲区。
SRAM_NOCACHE_DATA_SECTION u8 noncache_buffer[DATA_BUFFER_SIZE];
备注
对于 CA32:非缓存属性通过 MMU 配置,配置的区间至少是 4KB 的整数倍。
在缓冲区定义前添加宏 SRAM_NOCACHE_DATA_SECTION,可定义具有非缓存属性(Non-Cacheable)的数据缓冲区。
SRAM_NOCACHE_DATA_SECTION u8 noncache_buffer[DATA_BUFFER_SIZE];
使用 DMA 时的缓存一致性
当使用 DMA 在内存缓冲区之间迁移数据时,缓冲区的起始地址和结束地址必须与缓存行对齐,以避免缓存数据与内存数据不一致。
例如:若某缓冲区的起始地址位于缓存行的中间位置,且前半部分已被其他程序占用,当其他程序对缓存行执行 Invalidate 或 Clean 操作时,该操作将影响整个缓存行,导致当前缓冲区的缓存数据与内存数据不一致。
备注
DMA 操作地址需独占一个完整的缓存行。可通过以下方式之一定义缓冲区:
malloc()
:该函数会返回一个起始地址为缓存行对齐,并且缓冲区长度也是缓存行对齐的地址。ALIGNMTO(CACHE_LINE_SIZE) u8 op_buffer[CACHE_LINE_ALIGMENT(op_buffer_size)]
:ALIGNMTO(CACHE_LINE_SIZE)
保证起始地址为缓存行对齐,CACHE_LINE_ALIGMENT(op_buffer_size)
保证长度也是缓存行对齐。
有关 DMA 数据传输时 Cache 的正确操作方法,可参考 DMA 与 Cache 。