ImageVerifierCode 换一换
格式:DOCX , 页数:17 ,大小:21.88KB ,
资源ID:11214312      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/11214312.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux DMA驱动构架分析.docx)为本站会员(b****7)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux DMA驱动构架分析.docx

1、Linux DMA驱动构架分析Linux DMA驱动构架分析 以linux2.6.32中的S3C2440驱动为例进行分析,DMA驱动所对应的源码为linux-2.6.32.2archarmmach-s3c2440dma.c,代码入口为:arch_initcall(s3c2440_dma_init);205 static int _init s3c2440_dma_init(void) 206 207 return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver);208 DMA驱动作为系统驱动由sysdev_drive

2、r_register来向内核注册,这里只关注s3c2440_dma_driver相关的内容,即调用drive中的add方法,其他的kobject对象略过。201 static struct sysdev_driver s3c2440_dma_driver = 202 .add = s3c2440_dma_add,203 ; s3c2440_dma_add做了一系列的初始化工作,相应的代码如下:194 static int _init s3c2440_dma_add(struct sys_device *sysdev) 195 196 s3c2410_dma_init();197 s3c24xx

3、_dma_order_set(&s3c2440_dma_order);198 return s3c24xx_dma_init_map(&s3c2440_dma_sel);199 下面就其中出的三个函数一一进行分析。一、 s3c2410_dma_init首先s3c2410_dma_init()调用了plat-s3c24xx平台公共的函数s3c24xx_dma_init(4, IRQ_DMA0, 0x40);1306 int _init s3c24xx_dma_init(unsigned int channels, unsigned int irq, 1307 unsigned int strid

4、e) 1308 1309 struct s3c2410_dma_chan *cp; 1310 int channel; 1311 int ret; 1312 1313 printk(S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronicsn); 1314 1315 dma_channels = channels; 1316 1317 dma_base = ioremap(S3C24XX_PA_DMA, stride * channels); 1318 if (dma_base = NULL) 1319 printk(KERN_ERR d

5、ma failed to remap register blockn); 1320 return -ENOMEM; 1321 1322 1323 dma_kmem = kmem_cache_create(dma_desc, 1324 sizeof(struct s3c2410_dma_buf), 0,1325 SLAB_HWCACHE_ALIGN,1326 s3c2410_dma_cache_ctor);1327 1328 if (dma_kmem = NULL) 1329 printk(KERN_ERR dma failed to make kmem cachen); 1330 ret =

6、-ENOMEM; 1331 goto err; 1332 1333 1334 for (channel = 0; channel number = channel; 1341 cp-irq = channel + irq; 1342 cp-regs = dma_base + (channel * stride); 1343 1344 /* point current stats somewhere */ 1345 cp-stats = &cp-stats_store; 1346 cp-stats_store.timeout_shortest = LONG_MAX; 1347 1348 /* b

7、asic channel configuration */ 1349 1350 cp-load_timeout = 1number, cp-regs, cp-irq); 1354 1355 1356 return 0; 1357 1358 err: 1359 kmem_cache_destroy(dma_kmem); 1360 iounmap(dma_base); 1361 dma_base = NULL; 1362 return ret; 1363 1364 首先来关注一下函数传递的参数:unsigned int channels:s3c2440平台对应的DMA通道总数,为4unsigned

8、 int irq:起始DMA中断的中断号unsigned int stride:每通道DMA所占寄存器资源数1309行struct s3c2410_dma_chan记录dma通道信息,内容如下:151 struct s3c2410_dma_chan 152 /* channel state flags and information */ 153 unsigned char number; /dma通道号, 154 unsigned char in_use; /当前通道是否已经使用 155 unsigned char irq_claimed; / 有无dma中断156 unsigned cha

9、r irq_enabled; /是否使能了dma中断 157 unsigned char xfer_unit; /传输块大小 158 159 /* channel state */ 160 161 enum s3c2410_dma_state state; 162 enum s3c2410_dma_loadst load_state; 163 struct s3c2410_dma_client *client; 164 165 /* channel configuration */ 166 enum s3c2410_dmasrc source; 167 enum dma_ch req_ch;

10、168 unsigned long dev_addr; 169 unsigned long load_timeout; 170 unsigned int flags; /* channel flags */171 172 struct s3c24xx_dma_map *map; /* channel hw maps */ 173 174 /* channels hardware position and configuration */ 175 void _iomem *regs; /* channels registers */176 void _iomem *addr_reg; /* da

11、ta address register */ 177 unsigned int irq; 中断号178 unsigned long dcon; /默认控制寄存器的值179 180 /* driver handles */ 181 s3c2410_dma_cbfn_t callback_fn; 传输完成回调函数 182 s3c2410_dma_opfn_t op_fn; 操作完成回调函数*/ 183 184 /* stats gathering */ 185 struct s3c2410_dma_stats *stats; 186 struct s3c2410_dma_stats stats_s

12、tore; 187 188 /* buffer list and information */ 189 struct s3c2410_dma_buf *curr; /* current dma buffer */ 190 struct s3c2410_dma_buf *next; /* next buffer to load */ 191 struct s3c2410_dma_buf *end; /* end of queue */dma缓冲区链表192 193 /* system device */ 194 struct sys_device dev; 195 ; 1315行dma_chan

13、nels是全局变量记录了当前系统dma通道总数1317-1321行映射dma控制寄存器1323-1332行为struct s3c2410_dma_buf分配cache,并利用函数s3c2410_dma_cache_ctor初始化为0。1334-1354行的循环就是初始化全局数组struct s3c2410_dma_chan s3c2410_chansS3C_DMA_CHANNELS;,其中包括通道编号、中断号以及寄存器基地址等信息。这个数组是针对实际的硬件信息建立的,每个硬件的dma通道唯一对应一个struct s3c2410_dma_chan的数据结构。与之对应的还有一个虚拟的dma通道,其

14、实质是将不同dma请求源区分开来,然后用一个虚拟的通道号与之一一对应,然后与实际的dma通道通过一张map表关联起来。关于map的相关内容后面将会分析。二、 s3c24xx_dma_order_set首先这个函数的意义是预定一些目标板要用的dma通道,使用的是上文提到的虚拟的dma通道号。1475 int _init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord) 1476 1477 struct s3c24xx_dma_order *nord = dma_order; 1478 1479 if (nord = NULL) 1480 n

15、ord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);1481 1482 if (nord = NULL) 1483 printk(KERN_ERR no memory to store dma channel ordern);1484 return -ENOMEM;1485 1486 1487 dma_order = nord; 1488 memcpy(nord, ord, sizeof(struct s3c24xx_dma_order); 1489 return 0; 1490 1477行dma_order是个全局变量,其作

16、用是记录下目标板的dma预定信息。这里使用的是s3c2440_dma_order为其赋值,数据如下:51 static struct s3c24xx_dma_order _initdata s3c2440_dma_order = 52 .channels = 53 DMACH_SDI = 54 .list = 55 0 = 3 | DMA_CH_VALID,56 1 = 2 | DMA_CH_VALID,57 2 = 1 | DMA_CH_VALID,58 3 = 0 | DMA_CH_VALID,59 , 60 , 61 DMACH_I2S_IN = 62 .list = 63 0 = 1

17、| DMA_CH_VALID,64 1 = 2 | DMA_CH_VALID,65 , 66 , 67 DMACH_I2S_OUT = 68 .list = 69 0 = 2 | DMA_CH_VALID,70 1 = 1 | DMA_CH_VALID,71 , 72 , 73 DMACH_PCM_IN = 74 .list = 75 0 = 2 | DMA_CH_VALID,76 1 = 1 | DMA_CH_VALID,77 , 78 , 79 DMACH_PCM_OUT = 80 .list = 81 0 = 1 | DMA_CH_VALID,82 1 = 3 | DMA_CH_VALI

18、D,83 , 84 , 85 DMACH_MIC_IN = 86 .list = 87 0 = 3 | DMA_CH_VALID,88 1 = 2 | DMA_CH_VALID,89 , 90 , 91 , 92 ; DMACH_SDI、 DMACH_I2S_IN等是系统为dma所分配的虚拟dma通道号,犹如中断子系统为中断分配的中断号一样,与具体硬件的中断向量号是不一致的。后面我们在系统中使用的dma通道号,都将是内核虚拟出来的, s3c2410_dma_request函数将为用户找到硬件对应的dma通道号。提取上面DMACH_SDI 虚拟通道来分析一下:DMACH_SDI = 54 .li

19、st = 55 0 = 3 | DMA_CH_VALID,56 1 = 2 | DMA_CH_VALID,57 2 = 1 | DMA_CH_VALID,58 3 = 0 | DMA_CH_VALID,59 , 60 , List这个结构列出的是实际dma通道的可用信息,这里表面对于sdi所能够使用的dma通道包含通道3,2,1,0一共四个通道,为什么从大到小排列是因为某些dma请求只能使用dma0,dma1等较小的通道号,比如外部总线dma只能使用dma0,为了避免sdi占用,这里就采用了这种排列。三、 s3c24xx_dma_init_map 上面提到过一个map,这里就是为这个map的初

20、始化函数了。他实际是根据硬件情况为一个全局变量赋值。与前面的初始化一样,这里主要是为了统一管理plat24xx这个平台下的dma资源,所以不同的芯片必须将自己硬件有关的dma信息初始化到相应的全局变量中。再说函数之前先来关注一下struct s3c24xx_dma_map这个数据结构,他提供了dma虚拟通道与实际的dma通道直接的关联:struct s3c24xx_dma_map const char *name;/虚拟dma通道名称 struct s3c24xx_dma_addr hw_addr; unsigned long channelsS3C_DMA_CHANNELS;/实际dma通道

21、信息 unsigned long channels_rxS3C_DMA_CHANNELS;上面的结构只提供了单个虚拟通道的dma视图,整个芯片的虚拟dma通道的分配情况是靠struct s3c24xx_dma_map数组完成的。在这里由struct s3c24XX_dma_selection来统一管理。struct s3c24xx_dma_selection struct s3c24xx_dma_map *map;/记录了struct s3c24xx_dma_map数组的首地址 unsigned long map_size;/ struct s3c24xx_dma_map数组的成员个数 uns

22、igned long dcon_mask;/dma控制器掩码 void (*select)(struct s3c2410_dma_chan *chan, struct s3c24xx_dma_map *map);/虚拟通道选择函数 void (*direction)(struct s3c2410_dma_chan *chan, struct s3c24xx_dma_map *map, enum s3c2410_dmasrc dir);/dma方向;有了上面的背景以后下面函数就是简单的数据拷贝了,函数比较简单不在展开说明。1454 int _init s3c24xx_dma_init_map(s

23、truct s3c24xx_dma_selection *sel) 1455 1456 struct s3c24xx_dma_map *nmap; 1457 size_t map_sz = sizeof(*nmap) * sel-map_size; 1458 int ptr; 1459 1460 nmap = kmalloc(map_sz, GFP_KERNEL); 1461 if (nmap = NULL) 1462 return -ENOMEM;1463 1464 memcpy(nmap, sel-map, map_sz); 1465 memcpy(&dma_sel, sel, sizeo

24、f(*sel); 1466 1467 dma_sel.map = nmap; 1468 1469 for (ptr = 0; ptr map_size; ptr+) 1470 s3c24xx_dma_check_entry(nmap+ptr, ptr);1471 1472 return 0; 1473 初始化的任务比较简单,就是(1)建立硬件dma通道信息即:struct s3c2410_dma_chan s3c2410_chansS3C_DMA_CHANNELS;(2)建立目标板虚拟dma通道与硬件的dma通道的关联:static struct s3c24xx_dma_order *dma_

25、order;(3)建立芯片本身的虚拟dma通道与硬件dma通道的视图:static struct s3c24xx_dma_selection dma_sel;完成上述工作以后,基本的dma框架就已经建立起来了。接下分析dma使用过程中相关的函数:(一) s3c2410_dma_request715 int s3c2410_dma_request(unsigned int channel, 716 struct s3c2410_dma_client *client, 717 void *dev) 718 719 struct s3c2410_dma_chan *chan; 720 unsigne

26、d long flags; 721 int err; 722 723 pr_debug(dma%d: s3c2410_request_dma: client=%s, dev=%pn, 724 channel, client-name, dev); 725 726 local_irq_save(flags); 727 728 chan = s3c2410_dma_map_channel(channel); 729 if (chan = NULL) 730 local_irq_restore(flags); 731 return -EBUSY; 732 733 734 dbg_showchan(c

27、han); 735 736 chan-client = client; 737 chan-in_use = 1; 738 739 if (!chan-irq_claimed) 740 pr_debug(dma%d: %s : requesting irq %dn, 741 channel, _func_, chan-irq); 742 743 chan-irq_claimed = 1; 744 local_irq_restore(flags); 745 746 err = request_irq(chan-irq, s3c2410_dma_irq, IRQF_DISABLED, 747 client-name, (void *)chan);748 749 local_irq_save(flags); 750 751 if (err) 752 chan-in_use = 0; 75

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1