RT1052 M7 芯片 D-Cache使用问题和注意事项

内容参照 野火文档,增加了使用过程中遇到的实际问题

在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 选项。

我的操作是

  1. 先用AHB方式向0x6200_0000地址写入0xFFFF_FFFF;
  2. 然后没有做其他任何操作,再去读0x6200_0000 地址;
  3. 正常情况下,因为有FPGA的存在,0x6200_0000地址处的数据会被改变为0x00~0x1FFC之间的值;
  4. 但是我读出的0x6200_0000地址数据却仍然是0xFFFF_FFFF;
  5. 使用FPGA内部的逻辑分析仪发现,读0x6200_0000的指令根本没有被执行
  6. 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后再去读写外设,读回的数据应该就是正常的了。

再看野火文档里最后一章的描述,也提及了同样的问题,并给出了解决办法,之前没看完整,没有意识到存在的问题。

猜你喜欢

转载自blog.csdn.net/catshit322/article/details/108809781