完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
本帖最后由 charles_jinbao 于 2016-8-2 22:05 编辑
最近几天学习了初级字符设备驱动:按键中断。 学习了3种方式: 1. 查询方式: 应用程序不断查询按键是否按下,应用程序占用CPU,不可取 2. poll机制: 首先声明一个等待队列 static DECLARE_WAIT_QUEUE_HEAD(button_waitq),作用是将当前进程挂到该队列中,执行调度休眠,这是前提; 然后就写一个poll函数了,将fop->poll指向它,供应用程序sys_poll调用,该函数有两个作用,一是将当前进程挂到事先声明的等待队列中,二是需要该函数的返回值mask,mask不为零,sys_poll函数就会跳出,返回不为零的值,应用程序根据该值进行下一步的操作,mask为零时,进程进入休眠,休眠函数在sys_poll里调用。注意ev_press是判断中断是否发生的标志位,初始值为0。 unsigned int mask=0; poll_wait(file, &button_waitq, wait); if (ev_press) mask |= POLLIN | POLLRDNORM; return mask; 最后就是按键中断了,当按键按下,中断发生,进入中断程序,读取按键值,置位ev_press,从等待队列中唤醒休眠的进程: ev_press = 1; wake_up_interruptible(&button_waitq); 最后ev_press在执行read函数后被清零。 3.不使用poll: 同样的,需要先声明等待队列,和上面一样 然后在read函数中调用休眠函数wait_event_interruptible(button_waitq, ev_press); 最后也一样中断程序中唤醒 ev_press = 1; wake_up_interruptible(&button_waitq); 这样如果中断不发生,应用程序一执行read函数就休眠,直到中断发生。 驱动程序: #include #include #include #include #include #include #include #include #include #include #include #include static struct class *keysint_class; static struct class_device *keysint_class_dev; volatile unsigned long *gpgcon; volatile unsigned long *gpgdat; static DECLARE_WAIT_QUEUE_HEAD(button_waitq); /* 中断事件标志, 中断服务程序将它置1,keysint_read将它清0 */ static volatile int ev_press = 0; struct pin_desc{ unsigned int pin; unsigned int key_val; }; /* 键值: 按下时, 0x01, 0x02, 0x03, 0x04 */ /* 键值: 松开时, 0x81, 0x82, 0x83, 0x84 */ static unsigned char key_val; struct pin_desc pins_desc[4] = { {S3C2410_GPG0, 0x01}, {S3C2410_GPG3, 0x02}, {S3C2410_GPG5, 0x03}, {S3C2410_GPG6, 0x04}, }; /* * 确定按键值 */ static irqreturn_t buttons_irq(int irq, void *dev_id) { struct pin_desc * pindesc = (struct pin_desc *)dev_id; unsigned int pinval; pinval = s3c2410_gpio_getpin(pindesc->pin); if (pinval) { /* 松开 */ key_val = 0x80 | pindesc->key_val; } else { /* 按下 */ key_val = pindesc->key_val; } ev_press = 1; /* 表示中断发生了 */ wake_up_interruptible(&button_waitq); /* 唤醒休眠的进程 */ return IRQ_RETVAL(IRQ_HANDLED); } static int keysint_open(struct inode *inode, struct file *file) { request_irq(IRQ_EINT8, buttons_irq, IRQT_BOTHEDGE, "K1", &pins_desc[0]); request_irq(IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "K2", &pins_desc[1]); request_irq(IRQ_EINT13, buttons_irq, IRQT_BOTHEDGE, "K3", &pins_desc[2]); request_irq(IRQ_EINT14, buttons_irq, IRQT_BOTHEDGE, "K4", &pins_desc[3]); return 0; } ssize_t keysint_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) { if (size != 1) return -EINVAL; /* 如果没有按键动作, 休眠 */ wait_event_interruptible(button_waitq, ev_press); /* 如果有按键动作, 返回键值 */ copy_to_user(buf, &key_val, 1); ev_press = 0; return 1; } int keysint_close(struct inode *inode, struct file *file) { free_irq(IRQ_EINT8, &pins_desc[0]); free_irq(IRQ_EINT11, &pins_desc[1]); free_irq(IRQ_EINT13, &pins_desc[2]); free_irq(IRQ_EINT14, &pins_desc[3]); return 0; } static struct file_operations keysint_fops = { .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */ .open = keysint_open, .read = keysint_read, .release = keysint_close, }; int major; static int keysint_init(void) { major = register_chrdev(0, "keysint", &keysint_fops); keysint_class = class_create(THIS_MODULE, "keysint"); keysint_class_dev = class_device_create(keysint_class, NULL, MKDEV(major, 0), NULL, "buttons"); /* /dev/buttons */ gpgcon = (volatile unsigned long *)ioremap(0x56000060, 16); gpgdat = gpgcon + 1; return 0; } static void keysint_exit(void) { unregister_chrdev(major, "keysint"); class_device_unregister(keysint_class_dev); class_destroy(keysint_class); iounmap(gpgcon); return 0; } module_init(keysint_init); module_exit(keysint_exit); MODULE_LICENSE("GPL"); 应用程序: #include #include #include #include #include int main(int argc, char **argv) { int fd; unsigned char key_val; fd = open("/dev/buttons", O_RDWR); if (fd < 0) { printf("can't open!n"); } while (1) { read(fd, &key_val, 1); } return 0; } |
|
相关推荐
|
|
你正在撰写讨论
如果你是对讨论或其他讨论精选点评或询问,请使用“评论”功能。
飞凌嵌入式ElfBoard ELF 1板卡-i2c与从设备通讯编程示例之开发板测试
1006 浏览 0 评论
ubuntu ping 开发板存在严重的丢包情况,请问该怎么解决?
2061 浏览 1 评论
12G-SDI高清视频开发案例,让4K视频采集更便捷!基于Xilinx MPSoC高性能平台
1822 浏览 0 评论
全志T507-H国产平台Ubuntu系统正式发布,让您的应用开发更便捷!
1264 浏览 0 评论
全志T507-H国产平台Ubuntu系统正式发布,让您的应用开发更便捷!
29 浏览 0 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-5 12:19 , Processed in 0.359632 second(s), Total 34, Slave 27 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号