微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM-Linux驱动--DMA驱动分析(一)

ARM-Linux驱动--DMA驱动分析(一)

时间:11-20 来源:互联网 点击:

  1. *sysdev)
  2. {
  3. interror;
  4. structsysdev_class*cls=sysdev->cls;/*所属的系统设备类*/
  5. if(!cls)
  6. return-EINVAL;
  7. pr_debug("Registeringsysdeviceofclass%s\n",
  8. kobject_name(&cls->kset.kobj));
  9. /*initializethekobjectto0,incaseithadpreviouslybeenused*/
  10. memset(&sysdev->kobj,0x00,sizeof(structkobject));
  11. /*Makesuretheksetisset*/
  12. sysdev->kobj.kset=&cls->kset;
  13. /*Registertheobject*/
  14. error=kobject_init_and_add(&sysdev->kobj,&ktype_sysdev,NULL,
  15. "%s%d",kobject_name(&cls->kset.kobj),
  16. sysdev->id);
  17. if(!error){
  18. structsysdev_driver*drv;
  19. pr_debug("Registeringsysdevice%s\n",
  20. kobject_name(&sysdev->kobj));
  21. mutex_lock(&sysdev_drivers_lock);
  22. /*Genericnotificationisimplicit,becauseitsthat
  23. *codethatshouldhavecalledus.
  24. */
  25. /*Notifyclassauxillarydrivers*/
  26. list_for_each_entry(drv,&cls->drivers,entry){
  27. if(drv->add)
  28. drv->add(sysdev);/*遍历该设备所属同一个设备类的所有设备,并执行相应的add函数*/
  29. }
  30. mutex_unlock(&sysdev_drivers_lock);
  31. kobject_uevent(&sysdev->kobj,KOBJ_ADD);
  32. }
  33. returnerror;
  34. }

那DMA系统设备驱动中的add函数中到底是什么呢?

(1)首先看第一个函数int __init s3c2410_dma_init(void),在./arch/arm/plat-s3c24xx/dma.c

[cpp]view plaincopy

  1. int__inits3c2410_dma_init(void)
  2. {
  3. returns3c24xx_dma_init(4,IRQ_DMA0,0x40);
  4. }

实际上就是初始化DMA为4通道,设置中断号,设置寄存器的覆盖范围

下面是该函数的实现

  1. int__inits3c24xx_dma_init(unsignedintchannels,unsignedintirq,
  2. unsignedintstride)/*参数分别为通道个数、中断号、寄存器的覆盖范围*/
  3. {
  4. structs3c2410_dma_chan*cp;/*通道的结构体表示*/
  5. intchannel;
  6. intret;
  7. printk("S3C24XXDMADriver,Copyright2003-2006SimtecElectronics\n");
  8. dma_channels=channels;
  9. dma_base=ioremap(S3C24XX_PA_DMA,stride*channels);
  10. if(dma_base==NULL){
  11. printk(KERN_ERR"dmafailedtoremapregisterblock\n");
  12. return-ENOMEM;
  13. }
  14. /*分配DMA告诉缓冲区*/
  15. dma_kmem=kmem_cache_create("dma_desc",
  16. sizeof(structs3c2410_dma_buf),0,
  17. SLAB_HWCACHE_ALIGN,
  18. s3c2410_dma_cache_ctor);
  19. if(dma_kmem==NULL){
  20. printk(KERN_ERR"dmafailedtomakekmemcache\n");
  21. ret=-ENOMEM;
  22. gotoerr;
  23. }
  24. for(channel=0;channel
  25. cp=&s3c2410_chans[channel];
  26. memset(cp,0,sizeof(structs3c2410_dma_chan));
  27. /*dmachannelirqsareinorder..*/
  28. cp->number=channel;
  29. cp->irq=channel+irq;
  30. cp->regs=dma_base+(channel*stride);
  31. /*pointcurrentstatssomewhere*/
  32. cp->stats=&cp->stats_store;
  33. cp->stats_store.timeout_shortest=LONG_MAX;
  34. /*basicchannelconfiguration*/
  35. cp->load_timeout=1<18;
  36. printk("DMAchannel%dat%p,irq%d\n",
  37. cp->number,cp->regs,cp->irq);
  38. }
  39. return0;
  40. /*异常处理*/
  41. err:
  42. kmem_cache_destroy(dma_kmem);
  43. iounmap(dma_base);
  44. dma_base=NULL;
  45. returnret;
  46. }

(2)然后是函数s3c24xx_dma_order_set(&s3c2440_dma_order);

  1. int__inits3c24xx_dma_order_set(structs3c24xx_dma_order*ord)
  2. {
  3. structs3c24xx_dma_order*nord=dma_order;
  4. if(nord==NULL)
  5. nord=kmalloc(sizeof(structs3c24xx_dma_order),GFP_KERNEL);
  6. if(nord==NULL){
  7. printk(KERN_ERR"nomemorytostoredmachannelorder\n");
  8. return-ENOMEM;
  9. }
  10. dma_order=nord;
  11. memcpy(nord,ord,sizeof(structs3c24xx_dma_order));
  12. return0;
  13. }

我们注意到函数中使用了kmalloc给结构体重新分配了内存,这是由于__initdata修饰的变量表示初始化用的变量,初始化完毕后空间自动释放,所以需要将其存储起来。

(3)最后一个函数s3c24xx_dma_init_map(&s3c2440_dma_sel)

该函数功能是建立DMA源与硬件通道的映射图

  1. int__inits3c24xx_dma_init_map(structs3c24xx_dma_selection*sel)
  2. {
  3. structs3c24xx_dma_map*nmap;
  4. size_tmap_sz=sizeof(*nmap)*sel->map_size;
  5. intptr;
  6. nmap=kmalloc(map_sz,GFP_KERNEL);
  7. if(nmap==NULL)
  8. return-ENOMEM;
  9. memcpy(nmap,sel->map,map_sz);
  10. memcpy(&dma_sel,sel,sizeof(*sel));
  11. dma_sel.map=nmap;
  12. for(ptr=0;ptrmap_size;ptr++)
  13. s3c24xx_dma_check_entry(nmap+ptr,ptr);
  14. return0;
  15. }

这里的kmalloc函数的作用同上面的作用一样。

注:由于内核实在是太深了,这里只是表面上按流程大体了解了子同设备的注册和系统设备驱动的注册以及DMA设备的注册和初始化,函数中有很多细节有待进一步研究。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top