中国触摸屏网
首页
触摸屏
一体机
触摸显示器
供求商机
产品展示
厂商资料
资讯中心
触摸软件
触摸论坛
触摸屏资讯 | 触控一体机 | 触摸屏屏幕 | 触摸屏机柜 | 触摸显示器 | 触摸控制器 | 自助终端 | 呼叫系统 | 触摸屏软件| 全国经销商
触摸屏外设 | 考勤排队机 | 触摸屏新品 | 解决之方案 | 选购与维护 | 驱动与软件 | 数字城市 | POS 系统 |LED电子大屏| 触摸屏论坛
导航: 首页 >> 触摸屏资讯 >> 电子显示屏 >> 正文 全国触摸屏销售热线:(点击查看)
全国触摸屏经销商 全国触摸屏经销商
·广东广州 ·广东深圳
·福建福州 ·福建厦门
·福建泉州 ·湖南长沙
·江西南昌 ·上 海 市
·江苏南京 ·江苏苏州
·北 京 市 ·山西太原
·山东济南 ·四川成都
·重 庆 市 ·云南昆明
·>>> 经销商加入指南
·>>> 经销商加入指南
s3c2410触摸屏在linux下的驱动分析 三  
s3c2410触摸屏在linux下的驱动分析 三
副标题:s3c2410触摸屏在linux下的驱动分析 三
日期:2008-3-24 22:22:42     来源:雪竹博客   编辑:51Touch 
由于上面这个wake_up_interruptible 函数的作用还不是很明确,所以需要分析一下打开设备文件这个函数。触摸屏打开设备文件函数定义如下: static int s3c2410_ts_open(struct inode *inode, struct file *filp) tsdev.head = tsdev.tail = 0; tsdev.penStatus = PEN_UP; 首先是最简单的将变量tsdev.head 和tsdev.tail 这两个表示buf 头尾位置的值清零,然后将变量tsdev.penStatus 的状态值初始化为笔抬起。 #ifdef HOOK_FOR_DRAG init_timer(&ts_timer); ts_timer.function = ts_timer_handler; #endif 如果定义了笔拖曳,先调用init_timer 函数来初始化一个定时器,变量ts_timer 为struct timer_list 数据结构,然后将定时调用的函数指针指向ts_timer_handler 函数。 tsEvent = tsEvent_raw; 将函数指针tsEvent 指向tsEvent_raw 函数。在/kernel/include/linux/wait.h 文件中: static inline void init_waitqueue_head(wait_queue_head_t *q) { #if WAITQUEUE_DEBUG if (!q) WQ_BUG(); #endif q->lock = WAITQUEUE_RW_LOCK_UNLOCKED; INIT_LIST_HEAD(&q->task_list); #if WAITQUEUE_DEBUG q->__magic = (long)&q->__magic; q->__creator = (long)current_text_addr(); #endif } 该函数初始化一个已经存在的等待队列头,它将整个队列设置为"未上锁"状态,并将链表指针prev和next指向它自身。 init_waitqueue_head(&(tsdev.wq)); 在这个s3c2410_ts_open 函数中,调用init_waitqueue_head 函数来初始化一个定义在变量tsdev 中的等待队列头的成员结构。 MOD_INC_USE_COUNT; return 0; 最后调用MOD_INC_USE_COUNT; 来对设备文件计数器加一计数,并返回再来分析一下用户层要调用的读取设备文件的接口函数: static ssize_t s3c2410_ts_read(struct file *filp, char *buffer, size_t count, loff_t *ppos) 这个函数实现的任务是将事件队列从设备缓存中读到用户空间的数据缓存中。实现的过程主要是通过一个循环,只有在事件队列的头、尾指针不重合时,才能成功的从tsdev.tail指向的队列尾部读取到一组触摸信息数据,并退出循环。否则调用读取函数的进程就要进入睡眠。 TS_RET ts_ret; retry: if (tsdev.head != tsdev.tail) { int count; count = tsRead(&ts_ret); if (count) copy_to_user(buffer, (char *)&ts_ret, count); return count; } 这个函数中,首先通过变量tsdev.head 和tsdev.tail 是否相等来判断环形缓冲区是否为空。若不相等则表示环形缓冲区中有触摸屏数据,调用tsRead 函数将触摸屏数据读入TS_RET 数据结构的ts_ret 变量中,该函数会在后面说明。 接下来调用copy_to_user 函数来把内核空间的数据复制到用户空间,在这里就是把驱动程序里的变量ts_ret 中的数据复制到用户程序的buffer 中,然后返回复制的数据长度。 else { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; interruptible_sleep_on(&(tsdev.wq)); if (signal_pending(current)) return -ERESTARTSYS; goto retry; } 若变量tsdev.head 和tsdev.tail 相等,则表示环形缓冲区为空,首先根据file->f_flags 与上O_NONBLOCK 值来进行判断,若为O_NONBLOCK 值,则表示采用非阻塞的文件IO方法,立即返回,否则才会调用interruptible_sleep_on 函数,调用该函数的进程将会进入睡眠,直到被唤醒。关于O_NONBLOCK 值的含义在我总结的《IIS音频驱动程序分析》一文中有详细说明。在/kernel/kernel/sched.c 文件中: void interruptible_sleep_on(wait_queue_head_t *q) { SLEEP_ON_VAR current->state = TASK_INTERRUPTIBLE; SLEEP_ON_HEAD schedule(); SLEEP_ON_TAIL } 常用的睡眠操作有interruptible_sleep_on和sleep_on。两个函数类似,只不过前者将进程的状态从就绪态(TASK_RUNNING)设置为TASK_INTERRUPTIBLE,允许通过发送signal唤醒它(即可中断的睡眠状态);而后者将进程的状态设置为TASK_UNINTERRUPTIBLE,在这种状态下,不接收任何singal。关于interruptible_sleep_on 和wake_up_interruptible 函数详细的用法可以参考一篇《关于linux内核中等待队列的问题》文档。如果进程被唤醒,则会继续跳到retry: 循环读取环形缓冲区,直到读取到一组触摸信息数据才会退出。 static int tsRead(TS_RET * ts_ret) 这个函数主要将环形缓冲区的x轴y轴坐标数据和笔的状态数据传入该函数形式参数所指的指针变量中。 spin_lock_irq(&(tsdev.lock)); 上文已经解释过了,调用该宏函数来禁止IRQ 中断。 ts_ret->x = BUF_TAIL.x; ts_ret->y = BUF_TAIL.y; ts_ret->pressure = BUF_TAIL.pressure; tsdev.tail = INCBUF(tsdev.tail, MAX_TS_BUF); 接着把变量tsdev 的环形缓冲区中相关数据赋值给该函数形式参数所指的指针变量中,并将表示环形缓冲区队列尾部的变量tsdev.tail 加一,这就意味着从环形队列中读取一组数据,尾指针加一。 spin_unlock_irq(&(tsdev.lock)); return sizeof(TS_RET); 上文已经解释过了,调用该宏函数来重新使能IRQ 中断,然后返回。再来看一个定时器定时调用的函数: #ifdef HOOK_FOR_DRAG static void ts_timer_handler(unsigned long data) { spin_lock_irq(&(tsdev.lock)); if (tsdev.penStatus == PEN_DOWN) { start_ts_adc(); } spin_unlock_irq(&(tsdev.lock)); } #endif 这个函数需要定义过笔拖曳才有效。首先调用宏函数spin_lock_irq 来禁止IRQ 中断。 然后在变量tsdev.penStatus 状态为笔按下的时候,调用宏函数start_ts_adc 来启动A/D转换,转换的是X轴的坐标。 最后再调用宏函数spin_unlock_irq 来重新使能IRQ 中断 最后再来看一个释放设备文件的函数: static int s3c2410_ts_release(struct inode *inode, struct file *filp) #ifdef HOOK_FOR_DRAG del_timer(&ts_timer); #endif MOD_DEC_USE_COUNT; return 0; 其实也很简单,在定义了笔拖曳的情况下,调用del_timer 函数来删除定时器,变量ts_timer 为struct timer_list 数据结构,然后调用MOD_DEC_USE_COUNT; 将设备文件计数器减一计数,并返回。经过对整个触摸屏驱动程序的流程,以及S3C2410 芯片数据手册里的相关章节进行分析后,下面来总结一下触摸屏驱动程序的大致流程。首先在驱动模块初始化函数中,除了对驱动的字符设备的注册外,还要对中断进行申请。这里申请了两个触摸屏相关的中断,一个是IRQ_TC 中断,查阅了数据手册后了解到,该中断在笔按下时,由XP 管脚产生表示中断的低电平信号,而笔抬起是没有中断信号产生的。另一个是IRQ_ADC_DONE 中断,该中断是当芯片内部A/D转换结束后,通知中断控制器产生中断,这时就可以去读取转换得到的数据。当触摸屏按下后,就会出发中断,这时会调用申请中断时附带的s3c2410_isr_tc 中断回调函数,该函数中判断若为笔抬起则启动x轴坐标的A/D转换。当转换完毕后就会产生ADC中断,这时就会调用申请中断时附带的s3c2410_isr_adc 中断回调函数,在该函数中进行判断,若x轴坐标转换结束马上进行y轴坐标的A/D转换转换;若y轴坐标转换结束,则重新回到等待中断模式,然后将坐标值写入环形缓冲区,并环形等待队列中的进程。
 
对这篇文章您有更多的想法? 请去论坛发表意见吧   
“s3c2410触摸屏在linux下的驱动分析 三 ” 的相关新闻
触摸屏及相关厂家
【触摸屏】台湾嵩达
【触摸屏】深圳深越
【触摸屏】台湾理义
【触摸屏】北京联控
【触摸屏】宇宙光电
【触摸屏】3M触控部
【触摸屏】南京华睿川
>> 触摸屏相关厂商加入
站内搜索 站内搜索
软件开发 软件开发
Toucher2.2在线演示
时代广场软件首页
荣威触摸屏查询软件首页
眉山经济贸易委员会软件首页
推荐新闻 推荐新闻
友达、华映将推新品,电
触摸屏浏览器Toucher V4
触控屏技术能否开启手机
专门为零售商开发的触摸
Toucher触摸屏浏览器V4.
触摸屏浏览器Toucher触摸
在便携设备中应用电容式
加入收藏网站地图友情链接联系我们  |  广告联系全国销售网络
    网站广告、经销商加盟、触摸屏软件销售:028-87439508 13183843395 028-66219290 联系人:张小姐 传真:028-87439508 全国各地经销商如下:
   广 州   020-87599875 深 圳   0755-21949677 福 州   0591-87818596 厦 门   0592-5615268 泉 州   0595-88150378
   湖 南   15863470449 江 西   0791-6283683 上 海   13916222245 南 京   025-83610010 苏 州   0512-65581867
   北 京   010-62631382 山 西   0351-8390152 济 南   13396407999 四 川   028-85450187 重 庆   023-68609756
   云 南   0871-5109466 其 他… 028-87439508   >>> 经销商加入指南    
电子邮件: 51touch(A)126.com 请将地址中的"(A)"改成"@",避免垃圾邮件出此下策,望谅
版权所有 Copyright© 2003-2008 中国触摸屏网 地址:成都市晋吉南路146号 电话:028-87439508  13183843395  028-66219290

在线咨询QQ: 

触摸屏、触摸屏软件、触控一体机咨询 43361182 触摸屏、触摸屏软件、触控一体机咨询 893008608 MSN 帐号: touch8(A)gmail.com 将"(A)"改成"@"即可