我正在编写我的第一个linux设备驱动程序,我遇到了一个问题。我想阻止一个内存区域被缓存,所以我一直在尝试使用flush_cache_range()
和flush_tlb_range()
来刷新这个内存区域的缓存。一切都编译得很好,但是当我尝试加载内核模块时,我得到以下错误:
Unknown symbol flush_cache_range (err 0)
Unknown symbol flush_tlb_range (err 0)
我发现这很奇怪。它们不应该在内核中定义吗?
我知道,或者我也可以使用dma_alloc_coherent()
来分配非缓存的内存区域。但我没有设备结构,并且为此参数传递NULL不会导致任何错误,但我也看不到任何应该存在的数据。
关于我的系统的一些信息:我正试图在带有集成FPGA(Xilinx Zynq)的ARM微控制器上运行。 FPGA将一些数据复制到CPU指定的存储单元。现在我想访问这个内存而不从缓存中获取旧数据。
非常感谢任何帮助。
答案 0 :(得分:1)
您不能使用flush_cache_range()
等功能,因为它们不适合模块使用。
要分配可由DMA设备访问的内存,必须使用dma_alloc_coherent()
。
这需要有效的器件结构,以便它可以在存储器地址和总线地址之间进行适当的映射。
如果您的设备不在由现有框架(例如PCI)处理的总线上,则必须创建平台设备。
答案 1 :(得分:0)
一些注意事项:
1- flush_cache_range不会阻止一个内存区域被高速缓存" ..它只是简单地刷新(清理+无效)缓存。任何将来通过相同虚拟范围写入/读取此内存区域的内容都将再次通过缓存。
2-如果FPGA正在写入内存,然后CPU将从该内存中读取数据,那么刷新缓存可能不是正确的做法。通常,您需要做的是使存储区无效,然后告诉FPGA写入。
3-请查看" $ {kernel-src} /Documentation/DMA-API.txt"在内核中。它有大量关于如何安全地(缓存维护+ phys_to_dma转换)使用特定内存区域进行DMA的信息。