努力成为linux kernel hacker的人李万鹏原创作品,为梦而战。转载请标明出处
http://blog.csdn.net/woshixingaaa/archive/2011/06/02/6462089.aspx
首先介绍一下DMA,S3C2440A支持位于系统总线和外围总线之间的4通道DMA控制器,每个通道都可以在系统总线或外围总线上的设备之间传输数据。每个通道可以对下面4种情况进行传输:
1.源和目的都在系统总线上
2.源在系统总线而目的在外围总线
3.源在外围总线而目的在系统总线
4.源和目的都在外围总线
下图是请求源为硬件模式时的每个通道的请求源:
DMA使用3个状态的有限状态机:
1.初始状态,DMA等待DMA请求,一旦请求到达DMA进入状态2,DMA ACK与INT REQ为0。
2.在这个状态,DMA ACK置为1并且计数器CURR_TC的值被从DCON[19:0]载入,注意DMA ACK保持为1直到它被清除。
3.在这个状态,处理DMA原子操作的子状态机被初始化。子状态机从源地址读取数据,然后写入目的地址。在这个操作中,要考虑数据的大小和传输的大小(单个/突发),这个操作重复执行直到计数器(CURR_TC)变成0在全服务模式,而只执行一次在单服务模式。当子状态机结束每一次原子操作的时候主状态机减少CURR_TC的值。另外,主状态机发出INT REQ信号当CURR_TC变成0并且DCON[29]位被置位1时。并且,清除DMA ACK,如果下面两个条件之一满足的话:
1)在全服务模式下CURR_TC变成0
2)在单服务模式下结束原子操作
注意在单服务模式下,主有限状态机的3个状态被执行然后停止,等待另一个DMA REQ。如果DMA REQ到来,所有的3个状态被重复执行。所以在每次原子操作中DMA ACK被置位,然后又被清除。与之对比,在全服务模式,主有限状态机等在状态3直到CURR_TC变成0。所以,DMA ACK在传输期间被置位,到TC为0时被清除。
然而,不管哪个服务模式,INT REQ被发出只有当CURR_TC变成0时。
如下图,是基本的DMA时序:
nXDREQ生效后等待至少2个时钟周期,nXDACK响应并开始生效,但要知道延时至少3个时钟周期,DMA控制器才可获得总线的控制权,进行读写操作一次。
下面来分析内核DMA驱动源码:
首先来看一下DMA驱动是怎样注册的:
这里使用了系统设备的概念,通过内核中源码的注释我们看看什么是系统设备。系统设备与驱动模型有一点不同,他们不需要动态的驱动绑定,也不能被探测,并且不属于任何类型的外围总线。对系统设备我们仍然有驱动的概念,因为我们仍想执行在这些设备上执行基本的操作。
在arch/arm/plat-s3c24xx/s3c244x.c中,注册了系统设备的类:
在arch/arm/mach-s3c2410/dma.c中,注册了dma的驱动:
把dma驱动注册到设备类下:
先来看一下系统设备类:
这个结构体有一个drivers双向循环链表,注册到这个类的驱动都挂在这里。
下面分析一下dma驱动是怎样注册的:
在arch/arm/mach-s3c2440/s3c2440.c中,注册了一个系统设备s3c2440_sysdev,
注意系统设备这个结构体,里边封装了一个系统设备类。
下面来看一下系统设备的注册,系统设备是一个虚拟设备,这里的目的就是为了调用driver的add函数。
下面来分析一下这个add函数。看上边的那个dma驱动的结构体,指明了add函数为s3c2410_dma_add:
分别对s3c2410_dma_add中的3个函数进行分析:
(一)
这里使用到了一个s3c2410_dma_chan结构体,struct s3c2410_dma_chan记录dma通道信息,内容如下:
(二)
先看下边一个结构体,s3c2410_dma_order。这个是建立目标板dma源与硬件的dma通道的关联。
分析这里SDI可以是使用通道3,2,0,为什么从大到小排列,是因为某些dma请求只能使用dma0,dma1等较小的通道号,比如外部总线dma只能只用dma0,为了避免sdi占用,这里就采用的这种排列。
注意这个结构体是用__initdata修饰的,所以在初始化后会被释放掉。下边这个函数重新分配内存保存这个结构体就是这个原因。
(三)
建立芯片本身的dma源与硬件dma通道的视图。
更多内容请看:
Linux驱动修炼之道
分享到:
相关推荐
Linux驱动修炼之道-DMA框架源码分析(上).pdf Linux驱动修炼之道-DM9000A网卡驱动框架源码分析(中).pdf Linux驱动修炼之道-DM9000A网卡驱动框架源码分析(下).pdf Linux驱动修炼之道-DM9000A网卡驱动框架...
Linux驱动drm_dma源码分析
Linux DMA驱动构架分析 很好的DMA源代码分析
pg195-pcie-dma
STM32F4XX ADC模数转换应用多通道采集--DMA方式程序源码,有使用到STM32F4XX系列ADC多通道的可以参考!
Petalinux如何加载AXI-DMA驱动
W5500驱动,STM32-DMA-W5500驱动,使用LL库,下载直接可用,附带cubemx配置文件,注释详细,方便移植修改
xilinx-axidma petalinux2020,使用说明参见《xilinx_axidma 驱动移植与使用》 包含测试例程hello_dma
u-dma-buf是Linux设备驱动程序,用于在内核空间中分配连续的内存块作为DMA缓冲区,并使它们在用户空间中可用。 当用户应用程序使用UIO(用户空间I / O)在用户空间中实现设备驱动程序时,打算将这些存储块用作DMA...
DMA enabled Zynq PS-PL communication to implement high throughput data transfer between Linux applications and user IP core. (based on Xilinx UG873 chapter 6) This is a simple loop-back project in ...
此资源是我的博客下,《ZYNQ7000平台 - Linux环境下pl-ps使用AXI-DMA进行数据传输》文章对应的所有工程,可以按照此博客进行简单的测试和学习
xilinx-axidma-master DMA驱动
Xilinx-FPGA-PCIE-Linux驱动程序.rar
STM32CubeMX配置STM32F407的SDCard-DMA-FatFs
S32K144-PDB-ADC_backtoback-DMA-ISR-S32DS_s32k144pdb定时器ADCDMA_s32k144+ADC+PDB_s32kadc_s32k144adcdma_源码.zip
STM32F4xx ADC模数转换应用单通道采集--DMA方式程序源码,有使用到STM32FFxx系列ADC的可以参考!
基于zynq的AXI-DMA驱动,在linux驱动层做出注册、发送、读取等处理,基于原版哈佛版本驱动新增DMA中断处理
u-dma-buf(用户空间可映射 DMA 缓冲区)\n概述\nu-dma-buf介绍\nu-dma-buf 是一个 Linux 设备驱动程序,它在内核空间中分配连续的内存块作为 DMA 缓冲区,并使它们在用户空间中可用。当用户应用程序使用 UIO(用户...
ADC1独立模式,使用通道4,PA4(配置为模拟模式),使用DMA传输,采用外部触发ADC转换,触发源为TIM3的TRGO事件,TIM3的TRGO事件来源于其更新事件,TIM3每200ms更新一次,也就是ADC每200ms采样一次, 使用ADC1的规则...