dma即direct memory access,是一种允许外设直接存取内存数据而没有cpu参与的技术,当外设对于该块内存的读写完成之后,dmac通过中断通知cpu,这种技术多用于对数据量和数据传输速度都有很高要求的外设控制,如显示设备等。
dma和cache一致性
我们知道,为了提高系统运行效率,现代的cpu都采用多级缓存结构,其中就包括使用多级cache技术来缓存内存中的数据来缓解cpu和内存速度差异问题。在这种前提下,显而易见,如果dma内存的数据已经被cache缓存了,而外设又修改了其中的数据,这就会造成cache数据和内存数据不匹配的问题,即dma与cache的一致性问题。为了解决这个问题,最简单的办法就是禁掉对dma内存的cache功能,显然,这会导致性能的降低
虚拟地址 vs 物理地址 vs 总线地址
在有mmu的计算机中,cpu看到的是虚拟地址,发给mmu后转换成物理地址,虚拟地址再经过相应的电路转换成总线地址,就是外设看到的地址。所以,dma外设看到的地址其实是总线地址。linux内核提供了相应的api来实现三种地址间的转换:
//虚拟->物理virt_to_phys()//物理->虚拟ioremap()//虚拟->总线virt_to_bus()//总线->虚拟bus_to_virt()
dma地址掩码
dma外设并不一定能在所有的内存地址上执行dma操作,此时应该使用dma地址掩码
int dma_set_mask(struct device *dev,u64 mask);
比如一个只能访问24位地址的dma外设,就使用dma_set_mask(dev,0xffffff)
编程流程
下面是在内核程序中使用dma内存的流程:
一致性dma
如果在驱动中使用dma缓冲区,可以使用内核提供的已经考虑到一致性的api:
/** * request_dma - 申请dma通道 * on certain platforms, we have to allocate an interrupt as well... */int request_dma(unsigned int chan, const char *device_id);/** * dma_alloc_coherent - allocate consistent memory for dma * @dev: valid struct device pointer, or null for isa and eisa-like devices * @size: required memory size * @handle: bus-specific dma address * * allocate some memory for a device for performing dma. this function * allocates pages, and will return the cpu-viewed address, and sets @handle * to be the device-viewed address. */void * dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)//申请pci设备的dma缓冲区void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle)//释放dma缓冲区void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle )//释放pci设备的dma缓冲区void pci_free_consistent()/** * free_dma - 释放dma通道 * on certain platforms, we have to free interrupt as well... */void free_dma(unsigned int chan);
流式dma
如果使用应用层的缓冲区建立的dma申请而不是驱动中的缓冲区,可能仅仅使用kmalloc等函数进行申请,那么就需要使用流式dma缓冲区,此外,还要解决cache一致性的问题。
/** * request_dma - 申请dma通道 * on certain platforms, we have to allocate an interrupt as well... */int request_dma(unsigned int chan, const char *device_id);//映射流式dmadma_addr_t dma_map_single(struct device *dev,void *buf, size_t size, enum dma_datadirection direction);//驱动获得dma拥有权,通常驱动不该这么做void dma_sync_single_for_cpu(struct device *dev,dma_addr_t dma_handle_t bus_addr,size_t size, enum dma_data_direction direction);//将dma拥有权还给设备void dma_sync_single_for_device(struct device *dev,dma_addr_t dma_handle_t bus_addr,size_t size, enum dma_data_direction direction);//去映射流式dmadma_addr_t dma_unmap_single(struct device *dev,void *buf, size_t size, enum dma_datadirection direction);/** * free_dma - 释放dma通道 * on certain platforms, we have to free interrupt as well... */void free_dma(unsigned int chan);
SLA4100构成的录放电路图
智慧物联网云平台开发,工业物联网平台开发需要多少钱?
泰利特于Broadband TAIWAN展出无线通讯模组
BGA返修台类别总结
在精密控制应用设计中实现高精度和零延迟转换的解决方案
Linux驱动技术技术之一:DMA编程
JDI研发出透明彩色屏幕面板!透明iPhone即将来袭?
英创信息技术WinCE系统多串口扩展方案简介
机器学习是大数据走向嵌入式智能化应用的捷径
AS-LLE点液位传感器专为远程油位感测而设计
通信系统相控电源改造解决方案
NI推出第二款向量信号收发器NI PXIe-5645R
教你如何分析芯片损坏的原因
库克或将终结苹果黄金时代 与乔布斯比差在哪
揭秘:RCFile高效存储结构
一加5什么时候上市?一加5最新消息:一加5今年发两款机?一加5配置曝光,新机配色致敬锤子科技!
反馈的概念与分类
iPhone8会采用隔空充电,国内IC推出隔空充电方案
机器视觉——工业4.0的关键技术
工信部:4G用户占比近七成 100Mbps接入用户数达1.2亿