在使用atsama5d27这款mpu芯片编写裸机程序,用dma时第一次遇到cache这个坑,dma传输时记得调用clean和invalidate刷新一下啊!!!
简述一下cache是什么
cpu的工作速度很快,甚至比读写ram中数据的速度还快。比如读取一个存储在DDR RAM芯片中的变量,耗时可以达到几十上百个cpu工作周期。为了减少ram读写比cpu慢太多导致的等待,便设计出了cache(高速缓存)机制。比如我正在使用的这个芯片,有L1(64k)和L2(128k)两级缓存,这是两块容量小,但读写速度很快的内存区域。
cpu想访问RAM中的哪个地址的数据,缓存控制器就会读取RAM,将对应地址的数据加载进缓存区,然后cpu就使用缓存区内的这份数据进行工作。当然,缓存区的大小有限,每次载入新数据都会挑一个使用率最低的数据写回到RAM。
cache会导致dma传输数据出问题
问题在于,L1L2缓存是特供cpu使用的,而DMA是绕过cpu和缓存直接操作RAM。
只有当缓存满了,又有新数据需要载入缓存,才会挑选一些不常用数据写回到RAM。
便会出现下图这种场景,我的程序明明往buffer数组赋值了,但RAM中的数组并没有更新,导致串口一直发送无效数据。
只有当缓存内没有载入这个RAM地址的数据时,才会从RAM载入。
便会出现下图这种场景,虽然DMA修改了RAM中的buffer数组,但因为buffer数组之前已经被载入缓存了,所以cpu的视角里buffer数组一直没有改变过。
使用clean和invalidate解决问题
clean和invalidate是两个对于cache的基础操作,一般厂商提供的函数库内都会有这个。
clean:将对应的数据清出缓存区,即把数据写回到RAM中
实际使用时,就是在dma传输前,调用clean函数将buffer数组的缓存清除,触发写回。就可以解决DMA发送时RAM中的buffer数组没更新的问题
invalidate:标记缓存中的数据为无效,cpu下次使用该数据时,就会从RAM中重新载入
实际使用时,在每次dma传输完成后,就要调用invalidate函数,将buffer数组标记为无效,这样程序再读取buffer数组,缓存就会重新载入RAM中的内容。
文章来源:https://www.toymoban.com/news/detail-769278.html
文章来源地址https://www.toymoban.com/news/detail-769278.html
到了这里,关于[踩坑] dma传输时要注意cache的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!