只有简单的描述了,本来写得很详细的。
ret = request_irq(IRQ_ADC, adcdone_int_handler, IRQF_RANDOM, DEVICE_NAME, &adcdev);
注册中返回错误16 ,即EBUSY,说明中断重复定义,内核中可能之前已经申请了中断。
发现两种设置寄存器的方式,值得参考:
static void __iomem *base_addr;
#define ADCCON (*(volatile unsigned long *)(base_addr + S3C2410_ADCCON)) //ADC control
base_addr=ioremap(S3C2410_PA_ADC,0x20);
ADCTSC = 0;
void __iomem *reg_base;
reg_base = ioremap(S3C2410_PA_ADC, 0x20);
iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF), reg_base + S3C2410_ADCCON);
data_debug = ioread32(reg_debug_base + 0x1c);
两种方法效果一样。
调试触摸屏驱动,中断一直不能进入,后来发现添加另一个adc中断就可以进入中断,一切正常。分析原因可以是中断开启或设置有问题,
分析中断硬件结构系统, 中断分为两级, 一级中断源, 由intmask寄存器控制, 其中有些一级中断源又由子中断源组成, 即二级中断源,其中二级中断源由intsubmask寄存器控制。
为了找出不能进入触摸屏中断原因,使用排除方法测试:
1. 内核添加ADC中断,查看触摸屏驱动在注册tc中断前后的 掩码寄存器值。
intsubmask 5bfe -> 59fe intmask 635c3d8f, 触屏中断正常。
2. 内核去掉ADC中断,
intsubmask 5ffe -> 5dfe intmask 635c3d8f, 触屏无法进入中断。
3 简单看了一下ADC中断发现里面开启了adc中断。所以修改代码, 内核去掉ADC中断,在触屏驱动里面开启adc中断,
intsubmask 5ffe -> 59fe intmask 635c3d8f, 触屏无法进入中断。
从掩码寄存器和注册程序返回成功可以看出中断方面应该没有什么问题。
关于中断注册:
ret = request_irq(IRQ_TC, irq_isr, IRQF_SAMPLE_RANDOM | IRQF_SHARED, "sharpzou$$!!!!-ts", ts_devp));
注册成功返回0值。函数调用完成后需要注意一下几点:
1 用户的中断处理函数已经链入到了 irq_desc[irq] (irq_desc[iIRQ_TC] )结构中的action链表中。
2 中断的触发方式已经设置完毕。
3 中断已经被使能并能够被处理调用。
ps: 全局数组irq_desc[]中的每一项代表一个中断, 当然中断是可以被共享的,irq_desc结构中有一个action链表,每一次用户注册中成功后中断处理函数就会被加入到链表中, 共享也就是如此执行。当中断发生时,该action链表中的所以注册的中断处理函数都会执行。
irq_desc结构里有 irq_chip结构,irq_chip结构里包括了底层硬件访问函数,包括使能、失能、设置掩码、启动、关闭,依此定义知道以后设置中断是不需要自己设置相应的中断控制寄存器,request_irq函数已经打包完成了很多功能。
关于触摸屏不能中断的原因, 经过简单分析ADC中断代码后,并且隔离代码发现了以下一段代码产生实际作用。
static struct clk *adc_clock;
adc_clock = clk_get(NULL, "adc");
if (!adc_clock) {
printk(KERN_ERR "failed to get adc clock source/n");
return -ENOENT;
}
clk_enable(adc_clock);
可以知道是因为ADC&TC硬件模块时钟源没有设置。(即clkcon寄存器相应位)。
疑惑为什么内核初始化没有使能时钟源呢。
ADC驱动存在? 当使用ad功能时这个驱动正好可以使用,平台把时钟源关闭可以节能估计, 存在即合理!