原创 【转】adc驱动基于mini2440

2011-10-16 20:28 1295 9 9 分类: EDA/ IP/ 设计与制造

在mini2440中只有一个ad转换器,为了和触摸屏共享资源,在adc驱动中声明了一个全局信号量

ADC_LOCK:DECLARE_MUTEX(ADC_LOCK)

在adc驱动中导出符号供触摸屏驱动使用:EXPORT_SYSBOL(ADC_LOCK);

 

这个信号量只是解决了不合触摸屏同时使用AD转换器,但是还需要一个变量来说明当前的驱动是否在使用这个资源:我们暂且用adc_own变量来表示。还定义了一个static volatile int ev_adc = 0; //用来标识adc事件是否发生

 

在init函数中首先应完成把虚拟地址映射到内存空间,这样直接写内存地址的时候就实现了对ad寄存器的操作。、

static void __iomem *base_addr;

base_addr=ioremap(S3C2410_PA_ADC,0x20);

 

通过clk_get(NULL,"adc")获取时钟,在s3c中设备的时钟在plat-s3c下有定义。具体位置可以使用soure-insight去定位

再 clk_enable();------>request_irq(IRQ_ADC, adcdone_int_handler, IRQF_SHARED, DEVICE_NAME, &adcdev);这里需要注意最后一个参数,由于该驱动要和触摸屏共享一个中断号IRQ_ADC,这里需要使用adcdev来加以区分

 

 

在adcdone_int_handler中断处理函数中,读取寄存器中转换后的数据,设adc时间标志为1,ev_adc = 1; 之后调用

wake_up_interruptible(&adcdev.wait); 唤醒wait等待队列上的进程

 

在s3c2410_adc_read函数中,通过wait_event_interruptible(adcdev.wait, ev_adc);函数等待ad转换的完成。下面看下该函数的

定义

  1. #define __wait_event_interruptible(wq, condition, ret)   
  2. do {   
  3. DEFINE_WAIT(__wait);   
  4.   
  5. for (;;) {   
  6. prepare_to_wait(&wq, &__wait, TASK_INTERRUPTIBLE);   
  7. if (condition) //只有当condition变为1了才会跳出!   
  8. break;   
  9. if (!signal_pending(current)) {   
  10. schedule();   
  11. continue;   
  12. }   
  13. ret = -ERESTARTSYS;   
  14. break;   
  15. }   
  16. finish_wait(&wq, &__wait);   
  17. while (0)   
  18.  
  19. #define wait_event_interruptible(wq, condition)   
  20. ({   
  21. int __ret = 0;   
  22. if (!(condition)) //只有当condition=0时才会进入等待!   
  23. __wait_event_interruptible(wq, condition, __ret);   
  24. __ret;   
  25. })   
  26.   
  27. 这样看,就是说必须确保condition在进入signal_pending之前都是0,之后变为1!   

这就解释了为什么开始初始化的时候设置ev_adc = 0,这个变量在adcdone_int_handler处理函数中ad转换完成就被设置成了1,这样就从wait_event_interruptible(adcdev.wait, ev_adc);函数中跳出了。。。。特别要注意condition的设置。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
我要评论
0
9
关闭 站长推荐上一条 /3 下一条