内容参照 野火文档,增加了使用过程中遇到的实际问题
在RT1052与FPGA联调过程中,因为D-Cache问题出现了无法访问FPGA外设的情况,在此记录问题现象和解决办法
M7内核新增了I-cache(指令缓存),D-cache(数据缓存)
,Cache通过高速总线与内核相连,访问速度最快,可以大大提高CPU新能,但是使用不当就会造成令人头疼的问题。
为了提高CPU访问存储空间的速度,D-Cache中会根据一定规则(不清楚什么规则)保存经常访问或者刚刚访问过的数据,起的是一个外设和CPU内核之间桥梁的作用。如果CPU访问的数据在D-Cache中存在,就会直接使用D-cache中的数据,不再花费时间去读取外部存储器件。这样会大大提高处理速度。但是这样也会带来一个问题,就是D-cache中的数据可能会和外设中的数据不同步,造成读写异常。
先看我遇到的一个问题:
硬件环境,使用FlexSPI接口与FPGA连接,使用AHB方式直接访问方式,访问FPGA,FPGA映射在0x6200_0000~0x6600_0000地址上,FPGA端逻辑经过验证可以正常读写FlexSPI接口,无问题。
软件使用的是官方2.8.2版本的SDK,初始化的时候忘记关闭芯片D-Cache功能,并且使能了flexSPI接口的 enableAHBCachable 选项。
我的操作是
- 先用AHB方式向0x6200_0000地址写入0xFFFF_FFFF;
- 然后没有做其他任何操作,再去读0x6200_0000 地址;
- 正常情况下,因为有FPGA的存在,0x6200_0000地址处的数据会被改变为0x00~0x1FFC之间的值;
- 但是我读出的0x6200_0000地址数据却仍然是0xFFFF_FFFF;
-
使用FPGA内部的逻辑分析仪发现,
读0x6200_0000的指令根本没有被执行
; -
CPU没有去执行读0x6200_0000的AHB指令,而是
直接从D-Cache中读取了上一条指令写入的0xFFFF_FFFF值
。
问题基本上算是找到了,
又查看了2.3版本的SDK和2.8.2版本的SDK例程发现,2.3版本中直接在初始化时禁用了芯片D-Cache功能,
软件改到2.8.2SDK时,没有禁用D-cache,而是在读写外设前后使用了刷新D-cache的函数,使D-cache内原有的数据无效。
DCACHE_InvalidateByRange();
/*!
* brief Invalidates all data caches by range.
*
* Both cortex-m7 L1 cache line and L2 PL310 cache line length is 32-byte.
*
* param address The physical address.
* param size_byte size of the memory to be invalidated.
* note address and size should be aligned to cache line size
* 32-Byte due to the cache operation unit is one cache line. The startAddr here will be forced
* to align to the cache line size if startAddr is not aligned. For the size_byte, application should
* make sure the alignment or make sure the right operation order if the size_byte is not aligned.
*/
void DCACHE_InvalidateByRange(uint32_t address, uint32_t size_byte)
{
#if defined(FSL_FEATURE_SOC_L2CACHEC_COUNT) && FSL_FEATURE_SOC_L2CACHEC_COUNT
#if defined(FSL_SDK_DISBLE_L2CACHE_PRESENT) && !FSL_SDK_DISBLE_L2CACHE_PRESENT
L2CACHE_InvalidateByRange(address, size_byte);
#endif /* !FSL_SDK_DISBLE_L2CACHE_PRESENT */
#endif /* FSL_FEATURE_SOC_L2CACHEC_COUNT */
L1CACHE_InvalidateDCacheByRange(address, size_byte);
}
刷新D-cache后再去读写外设,读回的数据应该就是正常的了。
再看野火文档里最后一章的描述,也提及了同样的问题,并给出了解决办法,之前没看完整,没有意识到存在的问题。