DMA缓存解耦的一点见解
扫描二维码
随时随地手机看文章
DMA(英文全称:Direct Memory Access,中文:直接内存访问)是一种不经过CPU而直接从内存存取数据的数据交换模式。在DMA模式下,CPU只须向DMA控制器下达指令,让DMA控制器来处理数据的传送,数据传送完毕再把信息反馈给CPU,这样就很大程度上减轻了CPU资源占有率,可以大大节省系统资源。
DMA的传输模型结构见下图:
Figure 1 DMA传输模型
从上图可知,使用DMA从源地址传输数据到目的地址,数据都必须通过DMA控制器内部的寄存器或FIFO作缓存,而不是在源和目的地之间直接传输,这是因为源和目的所在设备的传输速度不一样,接口也不一样,要适应这些情况,数据在DMA控制器内的缓存是必不可少的,这样可使在低速设备传输数据时,高速设备可被释放并可被重新利用,这可看作是一种解耦,使低速设备和高速都能高效工作而不相互影响。
笔者在工作过程中,曾遇到一个有关DMA的issue,具体如下:在某个应用使用DMA进行大数据量传输过程中,经常出现数据传输异常,检查系统的调试打印信息,发现DMA在阶段性传输结束(会产生相应的中断)后,重新启动新阶段的DMA传输(使用相同的通道)时,有时会出现申请的DMA通道还在活动状态的情况,导致后面的数据传输无法正常启动。按照一般的思路,驱动程序设置好参数,启动DMA后,就可以去做其他工作,中断的到来就意味着该次的DMA传输结束了,但矛盾的是有时发现传输结束的DMA通道却不在空闲状态,要说明的是,所有的DMA通道资源都是预先分配好的,不同驱动程序使用各自不同的通道,不会互相干扰。开始认为是驱动程序没有设计好,出现竞争导致函数重入,但阅读整个驱动源码后,没有发现这方面的问题。
重新分析整个DMA传输过程:数据从源设备到目标设备,中间是要经过DMA controller Data transfer register或FIFO这个中转站暂存,而中断产生的条件是只要源或目的地址更新到与通知地址相同,这样当中断发生时,最后的数据可能还在中转站内,传输还在进行当中,由于最后的数据传输什么时候能真正结束,取决于目标器件以及当时的总线仲裁等情况,时间比较随机,此时中断服务函数重新启动新阶段传输前检查该通道时就有可能查询到DMA通道还处于忙状态,这样就会导致重新启动DMA通道失败而无法继续进行数据传输。
初步认为issue的产生是由于真正的数据传输结束滞后于DMA中断的产生(这个应该是硬件设计的一个bug),因此解决的方法就是加入等待,这可以通过多次重复查询来实现。按照这个思路,修改驱动程序,重新进行测试,问题没有复现,数据传输正常,这说明以上的分析推断是正确的。
通过上面的例子可以看到,充分理解DMA设计的一些硬件基本机理,对我们在工作当中解决一些实际问题还是很有帮助的。