Chinaunix首页 | 论坛 | 博客
  • 博客访问: 536993
  • 博文数量: 70
  • 博客积分: 3162
  • 博客等级: 中校
  • 技术积分: 850
  • 用 户 组: 普通用户
  • 注册时间: 2006-03-23 13:30
文章分类
文章存档

2013年(1)

2012年(4)

2011年(1)

2010年(7)

2009年(9)

2008年(20)

2007年(3)

2006年(25)

分类: LINUX

2008-12-10 00:17:51

http://blog.ednchina.com/thinkker/133244/message.aspx
arm开发板买了大半年了一直都没怎么用,趁着这些天回家不能上网,每天研究一点点,也算小有所得,便就记录下来,以备后忘.(不能上网虽然有很多不便,但也确实更能合理分配业余时间).

S3C2410_gpio_button.c
    模块初始化module_init(init_gpio_button)
    init_gpio_button
        循环处理gpio_buttons数组, 这个数组是在gpio_button_smdk2410_meri.c或者gpio_button_smdk2410_aiji.c中定义的,meri与 aiji是两个不同的开发板开发公司,所以他们的按键定义会有所不同,需要根据自己所采用的板子来配置(在内核编译里配置), 我们这里分析meri公司的.
        如果当前按键有对应的irq,
            设置此按键对应的irq的触发方式(set_external_irq). 包括上升沿/下降沿触发, 是否允许内部上拉电阻. 这两个参数是在gpio_buttons数组里已经作为常量定义好了的,这里只要读出来就行了
            申请中断(request_irq). 注册中断处理函数gpio_button_interrupt, 设置中断属性为FIQ(SA_INTERRUPT), 注册按键名, 设置gpio_buttons数组的地址作为dev_id(其实是gpio_button_interrupt的第二个参数)
        如果当前按键没有对应的irq
            如果当前按键有对应的pm_callback(就是按键对应的电源管理的回调函数), 就初始化请求(PM_MZ_INIT)作为参数调用这个函数
        打印一些信息
        重复循环过程
        如果定义了了CONFIG_PM, 即内核有电源管理模块
             初始化一个定时器双向链表的结构体,这里结构提里主要是设置了回调函数pwButton_timer_callback
             向电源管理模块注册按键的回调函数(pm_register). 注册的是设备类型(PM_USER_DEV, 在这个enum的定义后面有这么一句话: when wakeup, user must be handle this), 设备ID(PM_USER_INPUT), 以及回调函数(gpio_button_pm_callback)
             gpio_button_pm_callback
                如果当前新状态是休眠
                   如果此按键有对应的pm_callback, 则以睡眠状态为参数运行此函数
                   若此按键无对应的pm_callback
                      若此按键使用irq, 则禁止之
                如果当前新状态是唤醒
                    如果此按键有对应的pm_callback, 则以唤醒状态做参数运行此函数
                   若此按键无对应的pm_callback
                      若此按键使用irq, 则开放之                
        如果定义了CONFIG_S3C2410_SMDK, 也就是基于SMDK2410构架的实现
             初始化2410按键(s3c2410tk_button_init). 这里的按键指非特殊按键(不是Ctrl, Alt, shift等)
             s3c2410tk_button_init
                设置GPIO的B5为输入模式并禁止上拉(set_gpio_ctrl)
                设置GPIO的B6为输入模式并禁止上拉(set_gpio_ctrl)
                设置GPIO的E11为输入模式并禁止上拉(set_gpio_ctrl)
                设置GPIO的E12为输入模式并禁止上拉(set_gpio_ctrl) 
                初始化一个定时器(init_timer(&button_check_timer))并设置回调函数为tk_button_check_timer_handler, 超时时间为BUTTON_DELAY
                将定时器加入定时器链表(即现在开始这个定时器开始工作, 并在BUTTON_DELAY毫秒后第一次调用函数tk_button_check_timer_handler)
                    tk_button_check_timer_handler:这个函数每隔BUTTON_DELAY毫秒运行一次,并扫描gpio_buttons_tk数组中的按键
                    禁止中断(cli). 为了防止在扫描期间有按键中断进来,因为handle_scancode不是可重入函数
                    开始循环检测gpio_buttons_tk数组中每个按键是否有改变
                       暂存按键的原状态(按下还是未按)
                       读取按键的现状态(read_gpio_bit), 也就是读此按键对应的IO口电平
                       若现状态与原状态同,则表示此按键未改变,继续下一按键的检测
                       若状态有改变,则将按键的扫描值与按键状态发送给系统处理(handle_scancode). 在handle_scancode内主要是做长按的autorepeat处理, 将scancode转换成keycode, 唤醒等待进程, 将键加入队列等. 在这里有个函数比较有意思: handle_scancode->add_keyboard_randomness->add_timer_randomness->int_ln_12bits. 这个函数分析看附录.
                       重复循环
                    循环结束
                    开放中断
                    修改定时器的下次触发时间
    模块初始化结束

我们再来看按键的中断响应部分gpio_button_interrupt
    循环寻找当前irq对应的按键结构
    读取此按键状态(按下还是松开)
    判断此按键是否有对应的按键处理函数, 如果有,则以按键状态和一个私有成员(BUTTON_TYPE::priv, 其实就是当前按键在gpio_buttons数组中的索引)作为参数调用处理函数. 我们查看gpio_buttons数组中的各个按键对应的处理函数可以发现,除了电源键外,其他所有按键对应的处理函数都是keypad_handler
        keypad_handler:(普通功能键的处理函数)
           根据传入的priv(实际上是索引值)取得按键信息结构
           根据传入的按键状态, 将从按键信息结构体中取得的按键值和按键状态给系统处理(handle_scancode).这里与上面定时扫描部分相同
           (这里有点不大明白的是,为什么不直接传按键值或按键信息结构指针而是要传索引号呢?)
        pwButtonHandler:(电源键的处理函数)
           如果电源键之前未被按下
              打印一条信息
              任务调度power_button_task::power_button_task_handler, 这里函数将调用pm_user_suspend使系统进入休眠状态
           如果电源建之前已经被按下
              设置电源键新状态为未按
    如果没有处理函数,则将按键的扫描值与按键状态发送给系统处理(handle_scancode).

    模块卸载exit_gpio_button就是将一些申请的资源释放掉

总结: S3C2410的按键驱动模块分两部分:功能键(包括电源键)和普通键
功能键全部用irq来实现,这样就可以实现同时按多个功能键以及功能键与普通键的组合. 其主数据结构数组为gpio_buttons
普通键用定时扫描的方法取得按键值.其初始化函数为s3c2410tk_button_init, 扫描算法函数为tk_button_check_timer_handler, 其数据结构数组为gpio_buttons_tk

阅读(1941) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~