DMA机制

前言

我很早就接触到DMA这个词,但是现在才感觉真正的认识DMA。这种认识来的太迟,还好是来了。

之前的认识

“DMA是一种硬件,帮助CPU搬运buffer,降低CPU loading。”
现在看来,除了最基本的“硬件”、“降低CPU loading”还算正确,其他全部乱套了。

什么是DMA

DMA是一种硬件,用于“外设和内存”之间的数据搬运。

外设

可以认为是除CPU和内存(或DDR)外的所有设备;常见的有网卡、ISP、GPU等。
一个最常见的举例,就是网卡的数据,搬运到内存,其实读取网卡某些寄存器,然后拷贝到内存中;这个数据量相当大,因此使用DMA可以大幅降低CPU loading。

数据搬运,而不是buffer搬运!

外设和内存之间的数据搬运,除了buffer等大量数据外,还可以指一些提前准备好的寄存器数据,甚至是任意数据。
比如CPU会根据3A算法往ISP刷大量寄存器,如果可以使用DMA,就会降低CPU loading —— 这就是cammand DMA(CDMA);
比如ISP某模块触发中断,也会设置某些寄存器,正常情况下,都是CPU来实现;即使数据量不大,考虑到Linux对中断的响应有延迟,也可以使用DMA。
这也是CDMA使用的一种场景,特别是在图像流实时处理中很有用。

Reader和Writer

我一直很好奇,为什么D公司设计的ISP中,除了Cammand DMA,没有使用DMA搬运buffer?
我还很好奇,为什么C公司设计的ISP,大家一直提DMA buffer,讲道理ISP模块内部的buffer轮转,不需要DMA硬件啊!
现在就完全讲通了:
再次强调:DMA用来外设(除CPU和DDR)和内存之间的buffer搬运。
D ISP中的reader/writer,就是通过AXI 总线读写DDR数据,这和DMA的工作机制完全一致!
实际上,reader/writer就是一种特殊的DMA,具有额外数据对齐、裁剪等图像处理功能。
C ISP中肯定有很多可以读写buffer的模块,设计文档上命名为DMA read/writer engine,是否读写只是一个寄存器配置,不作为一个单独reader/writer模块理解。
因此,大家都在讨论DMA buffer,而没有讨论DMA模块,也没有讨论reader和writer,实际上确实使用了DMA机制。

DMA内存

DMA内存特性

  • 物理地址连续:DMA可没有MMU,没有办法处理物理地址不连续的情况
  • 缓存一致性:也就是DMA访问到的内存和CPU访问到的一致;正常情况下,CPU会从cache访问数据而不是DDR中
  • 不可换出:DMA内存必须是常驻内存

两种方案

  • 采用Android常用的ION buffer(专门为DMA设计,满足以上所有要求 + 用户态/内核态共享)
  • 内核预分配大块连续物理内存,采用mmap映射以便用户态/内核态共享
posted @ 2025-09-28 11:03  moonのsun  阅读(58)  评论(0)    收藏  举报