参考了友善之臂的按键驱动程序和韦东山写的《嵌入式Linux应用开发完全手册》【下载见http://www.linuxidc.com/Linux/2011-01/31114.htm】一书的第20章—Linux异常处理体系结构部分的按键驱动程序,修改了部分内容,学习了嵌入式Linux下按键驱动程序。
按照习惯,先看原理,对所学习的知识结构有了大致的了解了开始阅读别人的代码,仔细分析代码实现的每个过程。由于时间有限,我只了解了一些概念性的理论和内核代码中部分数据结构,学习的过程还有待深入。对于我这样的初学者来说,想把资料中所介绍的每个原理和具体的实现方法都完全掌握,恐怕不止是时间的问题,我所追求的是一种快速上手的方法,先学会用再深入学习。
下面是经我改动后的按键驱动程序:
/*buttons_driver.c*/
#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define DEVICE_NAME 'buttons' struct button_irq_desc { int irq; int pin; int pin_setting; int number; char *name; }; static struct button_irq_desc button_irqs [] = { {IRQ_EINT8 , S3C2410_GPG0 , S3C2410_GPG0_EINT8 , 0, 'KEY0'}, {IRQ_EINT11, S3C2410_GPG3 , S3C2410_GPG3_EINT11 , 1, 'KEY1'}, {IRQ_EINT13, S3C2410_GPG5 , S3C2410_GPG5_EINT13 , 2, 'KEY2'}, {IRQ_EINT15, S3C2410_GPG7 , S3C2410_GPG7_EINT15 , 3, 'KEY3'}, {IRQ_EINT14, S3C2410_GPG6 , S3C2410_GPG6_EINT14 , 4, 'KEY4'}, {IRQ_EINT19, S3C2410_GPG11, S3C2410_GPG11_EINT19, 5, 'KEY5'}, }; static volatile char key_values [] = {'0', '0', '0', '0', '0', '0'}; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); static volatile int ev_press = 0; static irqreturn_t buttons_interrupt(int irq, void *dev_id) { struct button_irq_desc *button_irqs = (struct button_irq_desc *)dev_id; if ('0'== key_values[button_irqs->number]) { // Changed key_values[button_irqs->number] = '1'; } else if('1' == key_values[button_irqs->number]){ key_values[button_irqs->number] = '0'; } ev_press = 1; wake_up_interruptible(&button_waitq); return IRQ_RETVAL(IRQ_HANDLED); } static int s3c24xx_buttons_open(struct inode *inode, struct file *file) { int i; int err; //set the interrupt to falling //友善的是上升沿和下降沿都中断,这里改成下降沿中断 for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { err = request_irq(button_irqs[i].irq, buttons_interrupt, IRQ_TYPE_EDGE_FALLING, button_irqs[i].name, (void *)&button_irqs[i]); if (err) break; } if (err) { i--; for (; i >= 0; i--) { disable_irq(button_irqs[i].irq); free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); } return -EBUSY; } ev_press = 1; return 0; } static int s3c24xx_buttons_close(struct inode *inode, struct file *file) { int i; for (i = 0; i < sizeof(button_irqs)/sizeof(button_irqs[0]); i++) { free_irq(button_irqs[i].irq, (void *)&button_irqs[i]); } return 0; } static int s3c24xx_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp) { unsigned long err; if (!ev_press) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; else wait_event_interruptible(button_waitq, ev_press); } ev_press = 0; err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count)); return err ? -EFAULT : min(sizeof(key_values), count); } #if 0 static unsigned int s3c24xx_buttons_poll( struct file *file, struct poll_table_struct *wait) { unsigned int mask = 0;
上一篇:u-boot-2011.03在mini2440/micro2440上的移植 在RAM中运行
下一篇:mini2440_buttons.c驱动程序解读
推荐阅读最新更新时间:2024-11-13 06:24
设计资源 培训 开发板 精华推荐
- ADV3221-EVALZ,ADV3221 800 MHz、4:1模拟多路复用器评估板
- 【训练营_进阶班】物联网插座
- AD9954PCBZ,AD9954 评估板,400 MSPS,14 位,1.8 V CMOS 直接数字合成器
- STLQ50C33R 50mA、3uA 电源电流低压降线性稳压器的典型(固定版本)应用
- AM2LS-1215SH30-NZ 15V 2瓦DC-DC转换器的典型应用
- EVAL-ADXRS623Z,用于评估 ADXRS623、±150 度/秒、单芯片速率陀螺仪的评估板
- ADP2230 双路 2 MHz、800mA、同步低静态电流降压稳压器的典型应用
- LT3663EMS8E-5、1.2V 降压转换器的典型应用
- 电子名片
- EVAL-ADM1185EBZ,评估套件展示了 ADM1185 如何在多电源系统中提供四路电压监控和排序