关注+星标公众号,及时获取更多技术分享~
作者 | 冰茶奥利奥
微信公众号 | 嵌入式电子创客街
最近在使用一款Cortex-A7芯片时,出现了一个让人比较困惑的问题。ARM和FPGA通过DDR3进行数据通信,FPGA会把数据定时存放进DDR3里面,然后ARM通过读取DDR3获取数据。
我们知道,在ARM架构体系下,一切皆地址。一片512MB的DDR3对应的不过也是一串长度为512M字节的地址。比如我的板子上,DDR3分配的地址就是从0x00100000—>0x1FFFFFFF,大小为512M。
我们知道,CPU和外设之间有多级的缓存结构,其模型就如同金字塔一般,如下图所示,最顶层的就是CPU的寄存器了,越往下存储量越大同时读写更慢。我们的DDR在L4那一层,属于DRAM主存。
当然,在ARMv7架构里一般只有两级高速缓存,即L1和L2。
存储器层次结构
在一般的计算机系统中,为了实现更快的访问速度,通常会采取这种数据缓存的方式。当然,像stm32这种Cortex-M3内核的芯片,CPU和外设总线之间是没有任何缓存的,这也是为什么stm32开发时候从来不需要考虑这种问题,这样设计的好处当然是使程序的行为更可预测,但是缺点就是速度被大大限制了。
CPU通过高速缓存更快的工作
话说回来,CPU和FPGA都在独立运行,CPU通过DDR控制器来对DDR存储器进行访问,为了加速,常常将一些数据缓存(Cache),而且不是针对一个数据缓存,而是针对一批(有些芯片称为一行,即Line,一行长度为32)。这样好处很明显,下一次访问速度会加快;但坏处也很明显,就是Cache里的数据如果发生了改变,不能迅速反映到DDR3实际数据中,反之亦然。因此,当FPGA通过DMA修改了DDR3数据时,CPU可能还不知道发生了些什么,拿到的数据仍然是Cache中的没有改过的数据。
在裸机开发时,规避Cache最简单的方法就是禁用Cache。
DCacheDisable(void);
这样操作后,CPU将直接访问DDR内存,读写都是直接的。由于FPGA非常频繁的再往DDR3里面写数,就会不断的触发CPU去刷新映射的数据。这样显然会降低CPU性能,但简化了数据传输操作,属于极端的方法。
另外一种操作要多加一道手续,通常ARM芯片的驱动里有Cache Flush和Cache Invalidate的操作。从字面理解,Flush就是把Cache里的数据流放出去,清空Cache,也就是将Cache的内容推到DDR中去;而Cache Invalidate表示当场宣布Cache里的内容无效,需要从DDR中重新加载,即把数据从DDR中拉到Cache中来。理解了这个原理,在编程的时候心里就非常有底气了!
每当我们的程序想要从DDR里面获取数据时,只需要调用CacheInvalidate就可以使CPU立即获取一次最新的DDR数据。
反之,如果我们的程序想往DDR里面送数据时,只需要调用CacheFlush就可以使CPU立即将数据送至DDR。
如果您觉得这篇文章帮到了你,请点赞或者留下您的评论,您的鼓励是我前进的动力~
关注博主公众号 “嵌入式电子创客街” 获取更多及时技术分享~
关注+星标公众号,及时获取更多技术分享~