ARM Linux驱动–ADC驱动(中断方式)

本网站用的阿里云ECS,推荐大家用。自己搞个学习研究也不错

<

div id=”content”>硬件平台:FL2440

内核版本:2.6.28

主机平台:Ubuntu 11.04

内核版本:2.6.39

这个驱动写了好久,因为原来的Linux内核编译的时候将触摸屏驱动编译进内核了,而触摸屏驱动里的ADC中断在注册的时候类型选择的是

IRQF_SAMPLE_RANDOM,不是共享类型,所以,自己写的ADC驱动在每次open的时候,总提示ADC中断注册失败。

解决方案:

重新配置内核,选择触摸屏驱动以模块的形式编译,而不是直接编译进内核,这样Linux在启动的时候不会自动加载触摸屏驱动,当然,IRQ_ADC中断号不会被占用。这样可以测试自己写的ADC驱动了。

以下是驱动源代码:

  1. #include    
  2. #include    
  3. #include    
  4. #include  /*创建设备节点*/   
  5. #include    
  6. #include  /*定义DECLARE_WAIT_QUEUE_HEAD*/   
  7. #include  /*定义了irqreturn_t等*/   
  8. #include  /*request_irq disable_irq enable_irq*/   
  9. #include    
  10. #include    
  11. #include   /*其中包含了#include “mach/irqs.h” */   
  12. #include    
  13. #include    
  14. #define ADC_MAJOR 102   
  15. #define ADC_NAME “my_adc”   
  16. #define SUCCESS 0   
  17. static int adc_open(struct inode *,struct file *);   
  18. static int adc_release(struct inode *,struct file *);   
  19. static int __init adc_init(void);   
  20. static int __exit adc_exit(void);   
  21. static ssize_t adc_read(struct file *,char *,size_t,loff_t *);   
  22. volatile unsigned long adc_con;   
  23. unsigned long adc_dat0;   
  24. int flag;//等待任务完成标志   
  25. unsigned long buf;//存放转换完成的数据   
  26. //声明等待队列   
  27. DECLARE_WAIT_QUEUE_HEAD(adc_wait);   
  28. struct clk *adc_clk;    
  29. static irqreturn_t adc_interrupt(int irq,void * dev_id)//中断处理程序   
  30. {   
  31.     if(flag==0)   
  32.     {   
  33.         buf=(readw(adc_dat0) & 0x3ff );//读取转换完成的数据   
  34.         flag=1;   
  35.         wake_up_interruptible(&adc_wait);//唤醒等待其上的进程   
  36.         printk(“Read value is %ld\n”,buf);   
  37.     }   
  38.     return IRQ_HANDLED;   
  39. }   
  40. struct file_operations  adc_ops =   
  41. {   
  42.     .owner  =   THIS_MODULE,   
  43.     .read       =   adc_read,   
  44.     .open   =   adc_open,   
  45.     .release    =   adc_release,   
  46. };   
  47. static int __init adc_init(void)   
  48. {   
  49.     int ret;   
  50.     adc_clk = clk_get(NULL,“adc”);//获取时钟   
  51.     clk_enable(adc_clk);//使能时钟   
  52.        
  53.     ret=register_chrdev(ADC_MAJOR,ADC_NAME,&adc_ops); //注册设备   
  54.     if(ret<0)   
  55.     {   
  56.         printk(“register device fail\n”);   
  57.         return ret;   
  58.     }   
  59.     adc_con=(unsigned long)ioremap(0x58000000,4);   
  60.     adc_dat0=(volatile unsigned long)ioremap(0x58000000+S3C2410_ADCDAT0,4);   
  61.     if( !(adc_con & adc_dat0) )   
  62.     {   
  63.         printk(“Failed to ioremap\n”);   
  64.         goto handle;   
  65.     }   
  66.     printk(“Initialized…\n”);   
  67.     return SUCCESS;   
  68. handle:   
  69.     unregister_chrdev(ADC_MAJOR,ADC_NAME);   
  70.     return -1;   
  71. }   
  72. static int adc_open(struct inode * inode,struct file * file) //打开设备函数   
  73. {   
  74.     //注册中断   
  75.     int ret;   
  76.     //disable_irq(IRQ_ADC);   
  77.     //enable_irq(IRQ_ADC);   
  78.     ret=request_irq(IRQ_ADC,adc_interrupt,IRQF_SHARED,ADC_NAME,1);//注册中断 IRQ_ADC在 mach/irqs.h中定义   
  79.     if(ret<0)   
  80.     {   
  81.         printk(“IRQ %d can not request\n”,IRQ_ADC);   
  82.         return ret;   
  83.     }   
  84.     return SUCCESS;   
  85. }   
  86. static int adc_release(struct inode * inode,struct file * file) //关闭设备函数   
  87. {   
  88.     free_irq(IRQ_ADC,1);//释放中断   
  89.     return SUCCESS;   
  90. }   
  91. static ssize_t adc_read(struct file *file,   
  92.                             char * buffer,   
  93.                             size_t length,   
  94.                             loff_t * offset)//设备读取函数   
  95. {   
  96.        
  97.     writew((1<<14)|(0x31<<6),adc_con);       //设置ADCCON   
  98.     writew((readw(adc_con) | 0x1),adc_con);  //启动AD转换   
  99.     wait_event_interruptible(adc_wait,flag);   
  100.     flag=0;   
  101. }   
  102. static int __exit adc_exit(void//驱动卸载函数   
  103. {   
  104.     iounmap(adc_con);   
  105.     iounmap(adc_dat0);   
  106.     unregister_chrdev(ADC_MAJOR,ADC_NAME);   
  107.     clk_disable(adc_clk);   
  108.     clk_put(adc_clk);   
  109.     printk(“The adc is unintialized\n”);   
  110.     return SUCCESS;   
  111. }   
  112. module_init(adc_init);      

未经允许不得转载:演道网 » ARM Linux驱动–ADC驱动(中断方式)

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册