Linux驱动技术(三) _DMA编程
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);//映射流式DMA
dma_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);//去映射流式DMA
dma_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);
Linux驱动技术(三) _DMA编程相关推荐
- Android应用程序访问linux驱动第三步:实现并向系统注册Service
在学习Android应用程序访问linux驱动时,原博主在第一.二步写得具体详细,但我学到第三步实现并向系统注册Service时,发觉内迷惑和发现几处错误,这里我将我的理解和修改记录下来和大家分享.希 ...
- 详解Linux驱动技术(五) _设备阻塞/非阻塞读写
在Linux驱动程序编写过程中,设备阻塞/非阻塞读写是一种非常重要的技术.它可以实现高效的数据传输和事件处理,提高系统的性能和响应速度.在本文中,我们将深入探讨Linux驱动技术(五) _设备阻塞/非 ...
- linux 模块化编译,手把手教Linux驱动1-模块化编程 module
大家好,从本篇起,一口君将手把手教大家如何来学习Linux驱动,预计会有20篇关于驱动初级部分知识点.本专题会一直更新,有任何疑问,可以留言或者加我微信. Linux的开发者,遍布世界各地,他们相互之 ...
- 手把手教Linux驱动1-模块化编程
大家好,从本篇起,一口君将手把手教大家如何来学习Linux驱动,预计会有20篇关于驱动初级部分知识点.本专题会一直更新,有任何疑问,可以留言或者加我微信. 什么是模块化编程? Linux的开发者,遍布 ...
- Linux 驱动开发 三:字符设备驱动框架
一.参考 (3条消息) Linux 字符设备驱动结构(一)-- cdev 结构体.设备号相关知识解析_知秋一叶-CSDN博客 (3条消息) linux设备驱动框架_不忘初心-CSDN博客_linux设 ...
- Linux 驱动开发 三十五:Linux 内核时钟管理
参考: linux时间管理,时钟中断,系统节拍_u010936265的博客-CSDN博客_系统节拍时钟中断 Linux内核时钟系统和定时器实现_anonymalias的专栏-CSDN博客_linux内 ...
- linux服务器开发三(网络编程)
转载自:http://www.cnblogs.com/zfc2201/archive/2017/05/04/6804990.html 作者:水之原 网络基础 协议的概念 什么是协议 从应用的角度出发, ...
- Linux 驱动开发 三十四:Linux 内核定时器原理
参考文档: <Cortex -A7 MPCore Technical Reference Manual> 中 Chapter 9:Generic Timer. <ARM ® Arch ...
- Linux驱动技术(六) _内核中断
在硬件上,中断源可以通过中断控制器向CPU提交中断,进而引发中断处理程序的执行,不过这种硬件中断体系每一种CPU都不一样,而Linux作为操作系统,需要同时支持这些中断体系,如此一来,Linux中就提 ...
最新文章
- 皮一皮:别人都那么努力,你还有什么理由不努力...
- WPF DatePicker 默认显示当前时间
- JavaScript入门(part2)--JS书写方式及注释
- 牙齿间隙变大怎么办_牙齿之间的间隙越来越大怎么办?
- git ignore 怎么添加和删除_Git删除已追踪文件,上传大文件到Github
- ie浏览器怎么取消代理浏览器_微软和IE渐行渐远,IE浏览器终将成为回忆
- 乐pad平板电脑_2020年双十一高性价比平板电脑推荐(包含苹果ipad,安卓华为,微软surface)...
- 《HTML5移动Web开发实战》—— 1.6 在移动网站中使用HTML5
- LINQ to SQL之使用Lambda Expression批量删除数据
- flash json php,php - codeigniter数组json和flashdata - 堆栈内存溢出
- paip.c++ bcb string 转换操作大总结.
- qt 定义一个长度的数组_6.8 C++字符数组
- flush和evit
- Aspose.word Java实现html转word,word转html
- Zynga公布2020年第四季度及全年财务业绩
- 笔记本损耗60 计算机提示,笔记本电池损耗60%多怎么处理!
- Tomcat服务器日志输出格式设置
- 真假金士顿U盘大拆解
- 【开发工具】【memtester】内存测试工具(memtester)的使用
- 装好虚拟机后,打开系统有黑屏的一些解决策略