首先介绍s3c2410与DMA相关的寄存器。
s3c2410共有4通道的dma,每通道9个寄存器,共36个。
1、DISRCn 该寄存器保存待传送数据的源地址。
2、DISRCCn 源控制寄存器。位1表示数据源的总线类型,位0表示地址是否自动增减。
3、DIDSTn 该寄存器保存待传送数据的目的地址。
4、DIDSTCn 目的控制寄存器。位1表示目的地址的总线类型,位0表示地址是否自动增减。
5、DCON DMA控制寄存器。
6、DSTATn DMA状态寄存器。
7、DCSRCn 当前源地址寄存器。
8、DCDSTn 当前目的地址寄存器。
9、DMASKTRIGn DMA MASK寄存器。
下面是linux-2.6.24.4中和dma有关的函数的分析:
首先定义了几个变量:
static int dma_channels ;//被设定为4
static struct s3c24xx_dma_selection dma_sel ;
struct s3c2410_dma_chan s3c2410_chans [S3C2410_DMA_CHANNELS];
static struct s3c24xx_dma_order * dma_order ;
有关的结构体定义如下:
struct s3c24xx_dma_selection {
struct s3c24xx_dma_map * map ;
unsigned long map_size;
unsigned long dcon_mask;
void ( * select ) ( struct s3c2410_dma_chan * chan,
struct s3c24xx_dma_map * map ) ;
} ;
struct s3c24xx_dma_map {
const char * name;
struct s3c24xx_dma_addr hw_addr;
unsigned long channels[ S3C2410_DMA_CHANNELS] ;
} ;
struct s3c2410_dma_chan {
/* channel state flags and information * /
unsigned char number; /* number of this dma channel * /
unsigned char in_use; /* channel allocated * /
unsigned char irq_claimed; /* irq claimed for channel * /
unsigned char irq_enabled; /* irq enabled for channel * /
unsigned char xfer_unit; /* size of an transfer * /
/* channel state * /
enum s3c2410_dma_state state;
enum s3c2410_dma_loadst load_state;
struct s3c2410_dma_client * client;
/* channel configuration * /
enum s3c2410_dmasrc source;
unsigned long dev_addr;
unsigned long load_timeout;
unsigned int flags; /* channel flags * /
struct s3c24xx_dma_map * map; /* channel hw maps * /
/* channel
struct s3c24xx_dma_order {
struct s3c24xx_dma_order_ch channels[ DMACH_MAX] ;
} ;
struct s3c24xx_dma_order_ch {
unsigned int list [ S3C2410_DMA_CHANNELS] ; /* list of channels */
unsigned int flags; /* flags */
} ;
然后分析各个函数。
int s3c2410_dma_request( unsigned int channel,
struct s3c2410_dma_client * client,
void * dev)
{
struct s3c2410_dma_chan * chan;
unsigned long flags;
int err;
pr_debug( "dma%d: s3c2410_request_dma: client=%s, dev=%p/n" ,
channel, client- > name, dev) ;
local_irq_save( flags) ;
chan = s3c2410_dma_map_channel( channel) ; //获得dma通道
if ( chan = = NULL ) {
local_irq_restore( flags) ;
return - EBUSY;
}
dbg_showchan( chan) ;
chan- > client = client;
chan- > in_use = 1; //占用该dma通道
if ( ! chan- > irq_claimed) {
pr_debug( "dma%d: %s : requesting irq %d/n" ,
channel, __FUNCTION__ , chan- > irq) ;
chan- > irq_claimed = 1;
local_irq_restore( flags) ;
err = request_irq( chan- > irq, s3c2410_dma_irq, IRQF_DISABLED, //申请中断
client- > name, ( void * ) chan) ;
local_irq_save( flags) ;
if ( err) { //中断申请失败
chan- > in_use = 0; //释放申请的通道和其他资源
chan- > irq_claimed = 0;
local_irq_restore( flags) ;
printk( KERN_ERR "%s: cannot get IRQ %d for DMA %d/n" ,
client- > name, chan- > irq, chan- > number) ;
return err;
}
chan- > irq_enabled = 1; //使能中断
}
local_irq_restore( flags) ;
/* need to setup */
pr_debug( "%s: channel initialised, %p/n" , __FUNCTION__ , chan) ;
return 0;
}
可见,该函数向内核申请了资源,即dma通道,然后就可以对申请的通道进行设置了。下面继续。
int s3c2410_dma_config( dmach_t channel, //通道号,和申请时使用的通道号要一致
int xferunit, //发送时位的设置,可以是1、2、或者4,分别对应8、16和32位方式
int dcon) //特别重要,就是dcon寄存器的值
{
struct s3c2410_dma_chan * chan = lookup_dma_channel( channel) ; //得到申请的dma通道
pr_debug( "%s: chan=%d, xfer_unit=%d, dcon=%08x/n" ,
__FUNCTION__ , channel, xferunit, dcon) ;
if ( chan = = NULL )
return - EINVAL;
pr_debug( "%s: Initial dcon is %08x/n" , __FUNCTION__ , dcon) ;
dcon | = chan- > dcon & dma_sel. dcon_mask; //这步的作用是清除dcon寄存器中除了24~26的其他位,从datasheet中知道这三位
//决定dma的中断源
pr_debug( "%s: New dcon is %08x/n" , __FUNCTION__ , dcon) ;
switch ( xferunit) { //设置字节传送的方式
case 1:
dcon | = S3C2410_DCON_BYTE;
break ;
case 2:
dcon | = S3C2410_DCON_HALFWORD;
break ;
case 4:
dcon | = S3C2410_DCON_WORD;
break ;
default :
pr_debug( "%s: bad transfer size %d/n" , __FUNCTION__ , xferunit) ;
return - EINVAL;
}
dcon | = S3C2410_DCON_HWTRIG; //使24~26位的选择有效
dcon | = S3C2410_DCON_INTREQ; //使传送完成的时候产生中断
pr_debug( "%s: dcon now %08x/n" , __FUNCTION__ , dcon) ;
chan- > dcon = dcon;
chan- > xfer_unit = xferunit;
return 0;
}
由以上分析可以知道,该函数完成的主要功能就是设置对应通道的dcon寄存器。关于更细节的东西,可以查看datasheet。
int s3c2410_dma_devconfig( int channel,
enum s3c2410_dmasrc source, //dma传送源的类型,可以是S3C2410_DMASRC_HW和S3C2410_DMASRC_MEM
int hwcfg,
unsigned long devaddr) //传送的目的地址
{
struct s3c2410_dma_chan * chan = lookup_dma_channel( channel) ;
if ( chan = = NULL )
return - EINVAL;
pr_debug( "%s: source=%d, hwcfg=%08x, devaddr=%08lx/n" ,
__FUNCTION__ , ( int ) source, hwcfg, devaddr) ;
chan- > source = source;
chan- > dev_addr = devaddr;
switch ( source) {
case S3C2410_DMASRC_HW: //dma传送源是外围硬件
/* source is hardware */
pr_debug( "%s: hw source, devaddr=%08lx, hwcfg=%d/n" ,
__FUNCTION__ , devaddr, hwcfg) ;
dma_wrreg( chan, S3C2410_DMA_DISRCC, hwcfg & 3) ; //设置源控制寄存器
dma_wrreg( chan, S3C2410_DMA_DISRC, devaddr) ; //设置传送源的地址
dma_wrreg( chan, S3C2410_DMA_DIDSTC, ( 0< < 1) | ( 0< < 0) ) ; //目的地址一般是内存
chan- > addr_reg = dma_regaddr( chan, S3C2410_DMA_DIDST) ; //得到传送目的地址寄存器的地址
return 0;
case S3C2410_DMASRC_MEM: //dma传送源是内存
/* source is memory */
pr_debug( "%s: mem source, devaddr=%08lx, hwcfg=%d/n" ,
__FUNCTION__ , devaddr, hwcfg) ;
dma_wrreg( chan, S3C2410_DMA_DISRCC, ( 0< < 1) | ( 0< < 0) ) ; //传送源控制器
dma_wrreg( chan, S3C2410_DMA_DIDST, devaddr) ; //传送的目的地址
dma_wrreg( chan, S3C2410_DMA_DIDSTC, hwcfg & 3) ; //目的地址控制器
chan- > addr_reg = dma_regaddr( chan, S3C2410_DMA_DISRC) ; //得到传送源地址寄存器的地址
return 0;
}
printk( KERN_ERR "dma%d: invalid source type (%d)/n" , channel, source) ;
return - EINVAL;
}
整个系统中dma的建立过程如下:
首先调用了s3c2410_dma_init(),该函数只有一句:
return s3c24xx_dma_init(4, IRQ_DMA0, 0x40);
其中第一个参数就是通道号,第二个参数为dma的中断号的基数,第三个参数表示各个通道占用的空间的大小。
在函数s3c24xx_dma_init中,主要做了以下几件事情:
1、调用ioremap,将dma控制器的地址做一个映射。
2、为dma分配内核空间。
3、将上面提到的s3c2410_chans数组的内容全部清零。
4、初始化4个s3c2410_dma_chan结构的变量,对其中的一部分成员赋值。
成功结束时,该函数返回0。
第二步,系统调用s3c24xx_dma_order_set函数,如下:
s3c24xx_dma_order_set(&s3c2410_dma_order);
s3c2410_dma_order定义于arch/arm/mach-s3c2410/dma.c文件中,是一个s3c24xx_dma_order类型的结构体。
该函数主要为该结构体分配空间,然后将s3c2410_dma_order的内容copy到dma_order中。
第三步,系统调用s3c24xx_dma_init_map,完成dma通道的映射:
return s3c24xx_dma_init_map(&s3c2410_dma_sel);
下面重点分析一下该函数。
传给该函数的参数定义如下:
static struct s3c24xx_dma_selection __initdata s3c2410_dma_sel = {
. select = s3c2410_dma_select,
. dcon_mask = 7 < < 24,
. map = s3c2410_dma_mappings,
. map_size = ARRAY_SIZE( s3c2410_dma_mappings) ,
} ;
该函数首先为各个通道分配内存空间,分配的总的大小为sizeof(struct s3c24xx_dma_map ) * s3c2410_dma_sel.map_size。
然后,函数把s3c2410_dma_sel的所有内容全部赋给上面提到的dma_sel结构体,该结构体就包含了所有的dma可以申请的通道。
用户申请dma通道的时候,内核就可以在dma_sel的map表中查找,并决定是否可以使用该dma通道。
上一篇:s3c2410_i2c总线驱动及at24c02设备驱动实例
下一篇:linux 2.6.24.4在S3C2410上的移植(CS8900网卡驱动)(基于GEC2410)
推荐阅读最新更新时间:2024-11-16 21:01
推荐帖子
- MC1413的应用
- 【不懂就问】MC1413芯片的DATASHEET的等效电路如下图,但是不知道输出口和PIN9脚怎么外接datasheet说7路输入7路输出,PIN9是公共端,看起来是个集电极开路电路看到一种接法,如下图,可以这样接吗?如果上图是正确的,那么输出的电压,是依靠上拉电阻拉倒Vcc的吗?在DATASHEET中规定的输出最大不超过50V,是指这个vcc吗?此外PIN9接一个电源,这里是3.3V,是怎么起保护作用的?它只是能让输出钳位在3.3+0.7V处把这是找的一个应用图,右边的两个
- shaorc 模拟电子
- 数据存储技术与实践
- 分享一本华为的新书《数据存储技术与实践》pdf第一篇企业存储概述第1章存储工业演进历史31.1高端存储系统的演进41.2中端存储兴起61.3SAN外置存储阵列71.4NAS外置存储阵列91.5块、文件统一存储系统101.6全Flash外置存储阵列101.7ServerSAN融合存储11第2章存储产品架构演进趋势132.1高端存储架构演进142.2中端存储架构演进15第3章企业存储
- 白丁 FPGA/CPLD
- 储存搬运对静电敏感的元器件有什么方法?
- 静电敏感元件在储存和运输过程中会暴露于有静电的区域中,用静电屏蔽的方法可削弱外界静电对电子元件的影响。最通常的方法是用静电屏蔽袋和防静电周转箱作为防护用。另外防静电衣对人体的静电具有一定的屏蔽作用。 所以我们要求在周转搬运过程中,工人必须佩带无绳静电环和手套,穿防静电服装和防静电鞋等,同时应使用防静电料箱、PCB防静电料架、不锈钢周转车等专业设备,尽量避免人体直接接触周转。 要说明的是:由于防静电服,是用特殊合成纤维织成布料,一般情况下揉搓磨擦不会产生静
- ESD技术咨询 安防电子
- 暴力拆解特斯拉电池组,探究美帝黑科技!(惊呆了!)
- 时尚的外形、百公里加速3.2秒、续航440公里,这些都是特斯拉ModelS作为一款纯电动汽车所展示给人们的数据。ModelS之所以能够拥有不逊于传统燃油车的性能表现,除了电动机技术之外,还要得益于特斯拉先进的电池技术。那么,特斯拉到底在电动车最核心技术之一的电池组研发方面有何独特建树呢?据介绍,ModelS的电池板总重高达900公斤,被放置在驾驶舱正下方的底盘当中,在为电动机提供能量的同时,也起到了稳定车辆重心的作用。
- 木犯001号 电源技术
- 好东东共享,Cadence SPB15.7 视频教程第1-7讲(于博士版)
- 可在线观看,也可以下载。文件太大,传不上来。给个地址,自己去下载吧。http://www.sig007.com/videoclass/107.htmlhttp://www.sig007.com/videoclass/108.htmlhttp://www.sig007.com/videoclass/109.htmlhttp://www.sig007.com/videoclass/110.htmlhttp://www.sig007.com/videoclass/111.htm
- cheeta PCB设计
- 做了一个电容屏的IIC接口转USB
- 实现的功能:电容屏的触控芯片一般对外接口为IIC接口,无法在windows/linux等电脑主机上直接使用,通过增加一颗转接芯片实现IIC接口转免驱USB接口,可以直接在通用电脑上免驱使用触控屏。实现框图如下:目前转接方案已支持汇顶(如GT911/GT9110/GT928等)、墩泰(如FT5406/FT5446等)、集创北方(如ICNT88X6)等主流触控IC的IIC接口转USB接口。有需求或技术探讨的可直接联系球球1258305301.应用场景:1、中
- 明天会更好124 51单片机
设计资源 培训 开发板 精华推荐
- DER-173 - 非隔离 14 W LED 驱动器
- ARG81800 EVB,用于 ARG81800 超低 IQ 同步降压稳压器的评估板,具有 SYNCIN、CLKOUT 和 PGOOD 3.5 至 36 Vin、3.3 Vout、1A、2.15 MHz
- DC143A-D,使用 LTC1475CMS8 3.3V @ 300mA 高效降压 DC/DC 转换器的演示板
- LT1764AET-1.8 3.3 VIN 至 2.5 VOUT LDO 稳压器的典型应用
- 用于微功率 A/D 转换器的 LT1634BIS8-5 电压基准的典型应用
- DER-745 - 基于InnoSwitch3-EP 900V的10W双输出电源
- LT3755EUD-1 50W 白色汽车 LED 前照灯驱动器的典型应用电路
- LT1634BCS8-2.5 单节锂离子电池监控电路的典型应用 (IQ = 20uA)
- LT3487EDD 演示板、升压型 DC/DC 转换器
- FPAB30BH60B前端整流智能功率模块(SPM)典型应用电路