在VIP群里,大家讨论热烈,完全可以看得出来大家都Linux技术和嵌入式技术等渴望和热诚,欢迎大家加入笨叔的VIP私密群,一起研究技术,一起奔跑,一起成长。
关于DMA
有朋友问有关DMA的相关问题,那么大家在编写驱动的时候需要额外小心敬慎。因为DMA的问题主要会影响cache的一致性。那linux内核里面提供了不少的API来帮助大家实现DMA的操作。
我们知道DMA使用的物理内存,那么在内核中主要有两类的接口来分配物理内存
* __get_free_page()和alloc_page()来分配以页为单位的物理内存
* kmalloc() 和 kmem_cache_alloc()来分配以字节为单位的物理内存
上述两个接口分配的内存都可以作为DMA buffer的原材料。但是我们系统分配的物理内存都是cachable的,也就是打开cache功能的。另外DMA engine在做DMA传输的时候是不需要CPU参与的,所以从这个角度来看,同一个cache line有可能CPU和DMA engine都能访问到,那就会导致cache line被破坏了,那如何去保证DMA操作的时候,cache这个捣蛋鬼不来捣乱呢?
一个简单的想法就是,我们在做DMA传输的时候,这段buffer我把cache给关闭了,这个就是kernel实现的一致性的DMA buffer mapping的(英文叫做:Consistent DMA mappings)。这里consistent的意思是synchronize或者conherent的意思,CPU和DMA这两个哥们都能同时看到数据的改变,不需要软件做额外的一些flush动作。核心函数是:
dma_addr_t dma_handle;
cpu_addr = dma_alloc_coherent(dev, size, &dma_handle, gfp);
-
这个函数返回两个值,其中cpu_addr是虚拟地址,CPU可以通过这个地址来访问这段buffer