欢迎进入IT技术社区论坛,与200万技术人员互动交流 >>进入
现在主要谈谈编写s3c2410的触摸屏驱动的收获。模仿已有的驱动自己也写了一个驱动,实现同样的功能。同时为了完成这个驱动,把LDD2 这本书相关部分好好的读了一遍,获益匪浅。
先看看为了完成一个驱动,需要作的事吧。
1. 看datasheet,说白了芯片user manual,对于触摸屏,那些寄存器是主要的关注点,如ADCCON,ADCTSC…..,这些寄存器均会在驱动中使用,驱动也是全凭这些寄存器才完成与硬件的通信。这步很关键的说,虽然只用了了几笔!
2. 接下来应该先熟悉一下驱动中都需要定义些什么接口,如read,write,open,release,这些是基本的。见多了就不怪了,其实就是那些为上层(用户层)预留了访问内核数据的接口,比如此驱动,我在用户层调用用户层的read函数读取数据时,实际上就是在调用内核层(驱动属于内核层)的read来完成读操作。
3. 中断,中断,上课时看似没用的东西,现在用到了吧。啥叫中断,在此不表。怎么实现中断?还记得中断服务程序吗,就是它了。在程序的初始化函数(init)中,先使用ret=request_irq(IRQ_ADC_DONE,adc_isr_handler,SA_INTERRUPT,DEVICE_NAME,NULL);申请一个ADC中断,然后调用adc_isr_handler这个中断服务程序,这个程序完成了触摸屏控制器的模数转换,取得寄存器中的x,y值。不过千万别忘了在模块卸载(exit)的时候将中断释放掉,否则的话,很快中断申请线的资源就被占尽了。
4. 调试程序,呵呵,print啊,不过这里是在编驱动,千万别用printf啊,为啥?丢不起这个人啊!内核编程怎能用C函数库的函数?应该用printk!使用打印信息的方法方便实用,再加上一些宏定义开启关闭调试信息的功能,perfect!还有其他的调试方法,不过看过书了不知所云,有待钻研。
5. 还用高级的字符驱动需要的阻塞型I/O,就是等待队列,休眠进程,唤醒进程。。。(偶还没太明白,先写这么几句!)
6. 看似简单的驱动阿,学问咋那么多呢。要真正完成触摸屏的驱动还需要时间流着部分知识,咋地也要让咱的屏屏能进行个识别输入的字母吧。现在我还在调他,本打算调通之后再来完成此篇文章,看来是奢望了。继续调~~
下面我的驱动和测试程序就要粉墨登场了,鉴于驱动只完成到可以挂载到内核之上,并不能实现最终的功能,在此就只展出部分,等到全部完成时,就是它与大家见面之曰。
程序片断1:触摸屏驱动
触摸屏的设备数据结构:
typedef struct{
unsigned int penStatus;
TS_RET buf[MAX_TS_BUF];
unsigned int head,tail;
wait_queue_head_t wq;
spinlock_t lock;
}TS_DEV;
下面这两个函数是双胞胎阿,一读一写,文武双全。。。
static int read_xy(TS_RET * ts_ret)
{
spin_lock_irq(&(tsdev.lock));
ts_ret->x = tsdev.buf[tsdev.tail].x;
ts_ret->y = tsdev.buf[tsdev.tail].y;
ts_ret->pressure = tsdev.buf[tsdev.tail].pressure;
tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF);
spin_unlock_irq(&(tsdev.lock));
return sizeof(TS_RET);
}
static void ts_write_buf(void)
{
if(tsdev.penStatus==PEN_DOWN)
{
tsdev.buf[tsdev.head].x = x;
tsdev.buf[tsdev.head].y = y;
tsdev.buf[tsdev.head].pressure = PEN_DOWN;
}else{
tsdev.buf[tsdev.head].x = 0;
tsdev.buf[tsdev.head].y = 0;
tsdev.buf[tsdev.head].pressure = PEN_UP;
}
}
[1][2][3]
对于旅行,从来都记忆模糊。记不得都去了哪些地方,