星期三, 十月 31, 2007

S3C2410下的Linux键盘驱动分析

内核初始化的时候会调用chr_dev_init 之后会有这样的调用过程

0 && image.height>0){if(image.width>=510){this.width=510;this.height=image.height*510/image.width;}}" style="width: 184px; height: 239px;" src="http://docs.google.com/File?id=dcmkbdfm_40ctgbvcc2">
真正的键盘部分的初始化从kbd_init开始 kbd_init 初始化键盘状态结构体(struct kbd_struct), 这个结构体主要记录shift状态, led状态等. 将各个tty对应的struct kbd_struct全部初始化. 即每个tty都有自己的独立的struct kbd_struct 得到tty的结构体指针 键盘的硬件初始化(kbd_init) 允许键盘处理的后半部分(tasklet_enable)
调度键盘处理的后半部分(keyboard_tasklet),
keyboard_tasklet主要是处理键值(kbd_processkeycode)和处理led指示灯(kbd_leds)的动作.
kbd_processkeycode主要判断各种状态, 将扫描值映射成键值, 将其放入tty的键值队列,
以及autorepeat动作(如果键盘是处于raw mode就不会处理autorepeat, 因为控制台是希望得到键盘的原始状态).
autorepeat主要是通过一个timer来实现的,这个timer调用key_callback,这个函数又再次调用
keyboard_tasklet, 这样只要按着键就会不断有新键值进入tty的键值队列.
对于键盘处理的后半部分(keyboard_tasklet), 我们只要记住一点: 这部分操作时间可能会比较长, 所以需要与中断响应分开处理.
向电源管理模块注册(pm_register)
OK, 我们再来看看键盘的硬件初始化
kbd_init被定义成与(s3c2410_kbd_init)相同,s3c2410_kbd_init会调用HW_kbd_init,
设置键盘接口界面(这里使用的是SPI). 包括IO口控制,SPI触发模式,频率等.
写一些测试数据(SPI_WRITE)
将key_interrupt注册到EINT1.这里好像有点奇怪,怎么会注册到外部中断呢?分析可能是这个版本对应的外挂SPI键盘在有按键按下时,会产生一个中断,通知S3C2410去读SPI接口
key_interrupt
选通外挂键盘
等待外挂键盘准本就绪
写一个空数据到SPI总线上

待所有数据输出完成(在输出完成的同时,输入数据(即键盘的扫描值)也进入到S3C2410.
这一步其实是效率很低的,因为是在FIQ响应中,所以所有中断都被禁止,
而SPI总线的速率为99.12K,那么我们等待所有数据输出完成就需要(8/99.12)毫秒,也就是80.7uS,
而在这段时间里CPU是什么也干不了的.不过幸亏,没有几个人会用到SPI总线的外挂键盘吧.
对扫描值做一些判断与处理, 最后调度后半处理函数keyboard_tasklet

0 意見: