linux中断和异步通知 基于QT210
来源:互联网 发布:淘宝上哪里有秒杀 编辑:程序博客网 时间:2024/05/22 17:27
linux异步通知:
应用程序需要完成如下三个步骤:
1)signal(SIGIO, sig_handler);
调用signal函数,让指定的信号SIGIO与处理函数sig_handler对应。
2)fcntl(fd, F_SET_OWNER, getpid());
指定一个进程作为文件的“属主(filp->owner)”,这样内核才知道信号要发给哪个进程。
3)f_flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, f_flags | FASYNC);
在设备文件中添加FASYNC标志,驱动中就会调用将要实现的test_fasync函数。
三个步骤执行后,一旦有信号产生,相应的进程就会收到。
内核需要完成下面四个步骤:
1)定义结构体fasync_struct。
struct fasync_struct *async_queue;
2)实现test_fasync,把函数fasync_helper将fd,filp和定义的结构体传给内核。
int test_fasync (int fd, struct file *filp, int mode)
{
struct _test_t *dev = filp->private_data;
return fasync_helper(fd, filp, mode, &dev->async_queue);
}
3)当设备可写时,调用函数kill_fasync发送信号SIGIO给内核。
if (dev->async_queue){
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
}
4)完成ops
struct file_operations test_fops = {
.open = test_open,
.release = test_close,
.write = test_write,
.read = test_read,
.poll = test_poll,
.fasync = test_fasync
基于QT210和linux3.4.2设置如下:
配置内核:
参考原理图:
编译内核代码:
#include <linux/types.h>#include <linux/module.h>#include <linux/cdev.h>#include <linux/fs.h>#include <linux/device.h>#include <linux/gpio.h>#include <linux/irq.h>#include <linux/interrupt.h>#include <linux/sched.h> #include <linux/wait.h>#include <linux/uaccess.h>#include <mach/gpio.h>#include <asm/uaccess.h>#include <asm/irq.h>#include <asm/io.h>static dev_t devno;static struct cdev cdev;static struct class* buttons_class;static struct device* buttons_device;static wait_queue_head_t button_waitq;static struct timer_list buttons_timer;static volatile int pressed = 0;static unsigned int key_val;static struct fasync_struct *button_async;struct key_desc{unsigned int pin;unsigned char value;};static struct key_desc *irq_pd;static volatile unsigned long *gph3con;static volatile unsigned long *gph3dat;static struct key_desc key_descs[8] = {[0] = {.pin = S5PV210_GPH2(3),.value = 0x00,},[1] = {.pin = S5PV210_GPH2(4),.value = 0x01,},[2] = {.pin = S5PV210_GPH2(5),.value = 0x02,},[3] = {.pin = S5PV210_GPH2(6),.value = 0x03,},[4] = {.pin = S5PV210_GPH2(7),.value = 0x04,},};static void buttons_timer_function(unsigned long data){struct key_desc * pindesc = irq_pd;unsigned int pinval;if (!pindesc)return;pinval = gpio_get_value(pindesc->pin);if (pinval){/* 松开 */key_val = 0x80 | pindesc->value;}else{/* 按下 */key_val = pindesc->value;}pressed = 1;wake_up_interruptible(&button_waitq);kill_fasync (&button_async, SIGIO, POLL_IN);}static irqreturn_t buttons_irq(int irq, void *dev_id){printk("buttons_irq happen\n");/* 10ms后启动定时器 */irq_pd = (struct key_desc *)dev_id;mod_timer(&buttons_timer, jiffies+HZ/100);return IRQ_RETVAL(IRQ_HANDLED);}static int buttons_open(struct inode *inode, struct file *file){int ret;ret = request_irq(IRQ_EINT(19), buttons_irq, IRQ_TYPE_EDGE_BOTH, "key1", &key_descs[0]);if(ret)return ret;ret = request_irq(IRQ_EINT(20), buttons_irq, IRQ_TYPE_EDGE_BOTH, "key2", &key_descs[1]);if(ret)return ret; ret = request_irq(IRQ_EINT(21), buttons_irq, IRQ_TYPE_EDGE_BOTH, "key3", &key_descs[2]);if(ret)return ret; ret = request_irq(IRQ_EINT(22), buttons_irq, IRQ_TYPE_EDGE_BOTH, "key4", &key_descs[3]);if(ret)return ret;ret = request_irq(IRQ_EINT(23), buttons_irq, IRQ_TYPE_EDGE_BOTH, "key5", &key_descs[4]);if(ret)return ret;return 0;}static ssize_t buttons_read(struct file * file, char __user *data, size_t count, loff_t *loff){if (count != 1)return -EINVAL;if (file->f_flags & O_NONBLOCK){if (!pressed)return -EAGAIN;}wait_event_interruptible(button_waitq, pressed);pressed = 0;if(copy_to_user(data, &key_val, 1)){printk(KERN_ERR "The driver can not copy the data to user area!\n");return -ENOMEM;}return 0;}static int buttons_close(struct inode *inode, struct file *file){free_irq(IRQ_EINT(19), &key_descs[0]);free_irq(IRQ_EINT(20), &key_descs[1]);free_irq(IRQ_EINT(21), &key_descs[2]);free_irq(IRQ_EINT(22), &key_descs[3]);free_irq(IRQ_EINT(23), &key_descs[4]);return 0;}static int buttons_fasync (int fd, struct file *filp, int on){printk("driver: buttons_fasync\n");return fasync_helper (fd, filp, on, &button_async);}struct file_operations buttons_ops = {.open = buttons_open,.read = buttons_read,.release = buttons_close,.fasync = buttons_fasync,};int buttons_init(void){int ret;init_timer(&buttons_timer);buttons_timer.function = buttons_timer_function;//buttons_timer.expires = 0;add_timer(&buttons_timer); cdev_init(&cdev, &buttons_ops);cdev.owner = THIS_MODULE;ret = alloc_chrdev_region(&devno, 0, 1, "buttons");if(ret){printk(KERN_ERR "alloc char device region faild!\n");return ret;}ret = cdev_add(&cdev, devno, 1);if(ret){printk(KERN_ERR "add char device faild!\n");goto add_error;}buttons_class = class_create(THIS_MODULE, "buttonsdrv");if(IS_ERR(buttons_class)){printk(KERN_ERR "create class error!\n");goto class_error;}buttons_device = device_create(buttons_class, NULL, devno, NULL, "buttons");if(IS_ERR(buttons_device)){printk(KERN_ERR "create buttons device error!\n");goto device_error;}init_waitqueue_head(&button_waitq);gph3con = (volatile unsigned long *)ioremap(0xE0200C60, 16);gph3dat = gph3con + 1;*gph3con &= (~0x000000ff);*gph3con |=0x11;*gph3dat &= ~0x03;printk("buttons init\n");return 0;device_error:class_destroy(buttons_class);class_error:cdev_del(&cdev);add_error:unregister_chrdev_region(devno,1);return -ENODEV;}void buttons_exit(void){printk("buttons exit\n");device_destroy(buttons_class, devno);class_destroy(buttons_class);cdev_del(&cdev);unregister_chrdev_region(devno, 1);}module_init(buttons_init);module_exit(buttons_exit);MODULE_LICENSE("GPL");
编译用户测试代码:
#include <fcntl.h>#include <stdio.h>#include <poll.h>#include <signal.h>#include <sys/types.h>#include <unistd.h>#include <fcntl.h>int fd; void sig_handler(int signum){ unsigned char key_val; read(fd, &key_val, 1); printf("key_val: 0x%x\n", key_val);}int main(int argc, char **argv){ unsigned char key_val; int ret; int Oflags; signal(SIGIO, sig_handler); fd = open("/dev/buttons", O_RDWR | O_NONBLOCK); if (fd < 0){ printf("can't open!\n"); return -1; } fcntl(fd, F_SETOWN, getpid()); Oflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, Oflags | FASYNC);while(1); return 0;}
测试结果如下:
[210_Liujia]#insmod buttons.ko[210_Liujia]#./buttons_testkey_val: 0x1key_val: 0x81key_val: 0x0key_val: 0x80key_val: 0x2key_val: 0x82key_val: 0x3key_val: 0x83key_val: 0x4key_val: 0x84key_val: 0x1key_val: 0x81key_val: 0x2key_val: 0x82key_val: 0x4key_val: 0x84key_val: 0x3key_val: 0x83
- linux中断和异步通知 基于QT210
- linux中断和异步通知 基于QT210
- Linux中断异步通知笔记
- Linux内核中断引入用户空间(异步通知机制)
- Linux内核中断引入用户空间(异步通知机制)
- Linux内核中断引入用户空间(异步通知机制)
- Linux 电子书 (基于linux-3.9.7 QT210)
- linux-3.9.7 sdhci 驱动移植 基于QT210
- linux设备驱动--异步通知和异步I/O
- Linux设备驱动中的异步通知和异步IO
- QT210中断
- Linux异步通知fasync
- Linux异步通知fasync
- Linux异步通知编程
- linux 异步通知fasync
- Linux异步通知
- linux 信号异步通知
- Linux异步通知 fasync
- 游戏引擎与虚拟仿真系统
- 数据库表的命名规范
- 软件测试面试题及解析(四)
- 电容屏单点的tslib的使用
- 想放弃了吗?想想为什么当初坚持走到了这里。
- linux中断和异步通知 基于QT210
- B继承自A,A指针无法隐式转换为B指针,函数参数只管指针类型,与实际指向对象无关
- 自己动手编写CSDN博客备份工具-blogspider
- 拥有属于自己的SVN(Google SVN)(更新版)
- 电容屏改为单点触摸屏
- Linux FTP命令详解及使用技巧
- Structs深入研究(一)-----Struts framework的工作原理和组件
- linux 简单的mysql备份和导入,以及文件的备份和导入
- 学习日记-java基础语法