您的位置:首页 > 运维架构 > Linux

linux驱动学习--第二十天:第十一章:CPU 与内存和I/O(三):I/O 内存静态映射 和 DMA

2013-06-24 23:02 816 查看
I/O 内存静态映射

在将Linux 移植到目标电路板的过程中,通常会建立外设I/O 内存物理地址到虚拟地址的静态映射,

这个映射通过在电路板对应的map_desc 结构体数组中添加新的成员来完成,

DMA

DMA 是一种无须CPU 的参与就可以让外设与系统内存之间进行双向数据传输的硬件机制。使用DMA

可以使系统CPU 从实际的I/O 数据传输过程中摆脱出来,从而大大提高系统的吞吐率。DMA 通常与硬件

体系结构特别是外设的总线技术密切相关。

DMA 方式的数据传输由DMA 控制器(DMAC)控制,在传输期间,CPU 可以并发地执行其他任务。

当DMA 结束后,DMAC 通过中断通知CPU 数据传输已经结束,然后由CPU 执行相应的中断服务程序进

行后处理。

DMA 与Cache 一致性

这个属于小技巧,这两个地方的改变的数据不通知CPU,这个时候就会引起数据错误。

需要特别注意的是,Cache 与内存的一致性问题经常被初学者遗

忘。在发生Cache 与内存不一致性错误后,驱动将无法正常运行。如

果没有相关的背景知识,工程师几乎无法定位错误的原因,因为看

起来所有的程序都是完全正确的。

解决由于DMA 导致的Cache 一致性问题的最简单方法是直接禁

止DMA 目标地址范围内内存的Cache 功能。当然,这将牺牲性能,

但是却更可靠,图11.12 所示为Cache 和DMA 在考虑性能和易用两

个方面时处于跷跷板两端的比重。

Cache 的不一致问题并发只是发生在DMA 的情况下,实际上,还存在于其他情况。

例如,对于带MMU 功能的ARM 处理器,在开启MMU 之前,需要先置Cache 无

效,TLB 也是如此,代码清单11.16 所给出的一段汇编被用来完成此任务。

代码清单11.16 置ARM 的Cache 无效

1 /* 使cache 无效 */

2 "mov r0, #0\n"

3 "mcr p15, 0, r0, c7, c7, 0\n" /* 使数据和指令cache 无效 */

4 "mcr p15, 0, r0, c7, c10, 4\n" /* 放空写缓冲 */

5 "mcr p15, 0, r0, c8, c7, 0\n" /* 使TLB 无效 */

Linux 下的DMA 编程

首先 DMA 本身不属于一种等同于字符设备、块设备和网络设备的外设,它只是外设与内存交互数据的一

种方式。因此,本节的标题不是“Linux 下的DMA 驱动”而是“Linux 下的DMA 编程”。

内存中用于与外设交互数据的一块区域被称做DMA 缓冲区,在设备不支持scatter/gather CSG,分散/

聚集操作的情况下,DMA 缓冲区必须是物理上连续的。

对于ISA 设备而言,其DMA 操作只能在16MB 以下的内存中进行,因此,在使用kmalloc()和_

_get_free_pages()及其类似函数申请DMA 缓冲区时应使用GFP_DMA 标志,这样能保证获得的内存是具备

DMA 能力的(DMA-capable)。

总结

外设可处于CPU 的内存空间和I/O 空间,除X86 外,嵌入式处理器一般只存在内存空间。在Linux

系统中,为I/O 内存和I/O 端口的访问提高了一套统一的方法,访问流程一般为“申请资源→映射→访

问→去映射→释放资源”。

对于有MMU 的处理器而言,Linux 系统的内部布局比较复杂,可直接映射的物理内存称为常规内存,

超出部分为高端内存。kmalloc()和_ _get_free_pages()申请的内存在物理上连续,而vmalloc()申请的内存在物

理上不连续。

DMA 操作可能导致Cache 的不一致问题,因此,对于DMA 缓冲,应该使用dma_alloc_coherent()等方

法申请。在DMA 操作中涉及总线地址、物理地址和虚拟地址等概念,区分这3 类地址非常重要。Linux

内核中对DMA 通道的申请和释放采用了和中断类似的方法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: