首先简单介绍下什么是DMAC(Direct Memory Access Controller),DMAC 是一个自适应先进的微控制器总线体系的控制器,它由ARM公司设计并基于PrimeCell技术标准,DMAC提供了一个AXI接口用来执行DMA传输,以及两个APB接口用来控制这个操作,DMAC在安全模式技术下用一个APB接口执行TrustZone技术,其他操作则在非安全模式下执行。DMAC包括了一个小型的指令集,用来提供一些灵活便捷的操作,为了缩小内存需求,DMAC则使用了变长指令。
不同于ARM11以及以前系列的芯片,S5PV210使用了基于PrimeCell技术标准的PL330(DMA控制器核心)有了很大的变化,从编程方式上看,它提供了灵活的指令集,使得你有更多的组合方式用来操作DMA,从硬件上看,它实现了硬件上的多线程管理,一次编写代码即可让它正常的完成所需的工作,因此这个DMA的开发是有一定困难的。
DMAC包含了一个执行指令的模块,并且控制了数据的传输,DMAC通过AXI接口来存取这些存储在了内存中的指令,DMAC还可以将一些临时的指令存放在Cache中,我们能够配置行宽度以及深度。
当然,DMAC的8个通道都是可配置的,且每个都可支持单个并发线程的操作,除此之外,还有一个管理线程专门用来初始化DMA通道的线程。它是用来确保每个线程都在正常工作,它使用了round-robin来处理当选择执行下一个活动期的DMA通道。
DMAC使用了变长指令集,范围在1到6字节之间,并还为每个通道提供了单独的PC寄存器,当一个线程需要执行一条指令时,将先从Cache中搜索,如果匹配上则立刻供给数据,另外,线程停止的话,DMAC将使用AXI接口来执行一次Cache线填充。
当一个DMA通道线程执行一次load/store指令,DMAC将添加指令到有关的读队列和写队列中,DMAC使用这些队列作为一个指令存储区,它用来优先执行存储在其中的指令,DMAC还有包含了一个MFIFO数据缓存区,它用来存储DMA传输中读/写的数据。
DMAC还提供多个中断输出,在微处理器的不干扰下,外设的request接口还有内存到外设和外设到内存的传输能力,双APB接口支持安全以及非安全两种模式,编程时,可通过APB接口来访问状态寄存器和直接执行DMAC指令。
下面是它的指令集。
下面是它的框图。
在s5pv210中,总共有两种类型的DMA。一种是存储器到存储器的,另一种是外设到存储器或存储器到外设的。
其中,存储器到存储器的DMA(简称DMA_mem)采用了一个PL330。
而,外设到存储器和存储器到外设的DMA(简称DMA_prei)采用了两个PL330组成,这种有外设参与的,真正的组成可以使用的还需要dma_map用来把外设的地址和dma传输进行映射。
其中DMA_mem同一时间,最多支持8个通道的传输,最多每次传输8个字节,16次爆发。
DMA_peri,同一时刻支持16个通道的传输,每次最大传输4字节。
对于普通外设的,MDA,是由硬件+寄存器配置决定如何让使用的。比较外设很多,通道比较少。
可以看到两个外设的DMA,基本都是串行总线在使用。
当然,一个SOC中,很外设其是自带DMA控制器的,比如LCD控制器,USB控制器等。
使用DMA控制器进行输出数据传输,需要理解下面四个问题。
1.数据源在哪。
2.数据目的在哪。
3.如何启动传输。
4.传输结束如何通知。
这里已比较简单的DMA_mem来举例。
对于内存,源数据肯定就是内存地址了。这里要说明大的是DMA传输时,源必须是物理地址,不能是虚拟地址。
在s5pv210中,每个通道的源地址寄存器如下。
对于内存,目的数据也肯定就是内存地址了。这里要说明大的是DMA传输时,目的必须是物理地址,不能是虚拟地址。
如何启动传输?
这个主要是一些硬件操作,配置具体某个通道的控制器寄存中的某些位使能就可以了。
当然,通常对这些通道还是需要进行配置之后再使能的。
具体的配置,看一下具体的寄存器说明就知道了。
传输结束,如何通知?
最常用的方式是,使用中断。
可以看到,除了外部中断,优先级最高的就是DMA的中断了。
只需要在相关的配置寄存器中设置好,传输结束,自动会执行中断函数。
当然,一个DMA是支持多个通道的,所以通常这个中断也是共享中断。
中断发生后,只需要查询对应的通道的状态寄存器就可以知道是那个通道的传输结束了。
当然也可以通过查询方式,查询状态寄存器来判断是否传输成功。
具体的要学习这个控制器的所有知识可以看一下官方文档。
CSDN上好像网友的要积分才能下载,我这边在github上传一份,有需要的可以直接下载。
https://github.com/To-run-away/PL330-DMA