Linux 内核空间与用户空间异步通信机制
2016-09-22 10:36
267 查看
/* * @file exirq.c * @author fzs * @date 2016-12-13 */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/nmi.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/irqreturn.h> #include <linux/spinlock.h> #include <asm/io.h> #include <asm/irq.h> volatile unsigned int *pic_vaddr6 = NULL, *pic_vaddr5 = NULL; extern void open_softirq(int nr, void (*action)(struct softirq_action *)); extern phys_addr_t get_immrbase(void); static atomic_t ex_interrupt_has_happen = ATOMIC_INIT(0); static wait_queue_head_t ex_interrupt; #define MPC85xx_PIC_EIVPR6 0x500c0 #define WAIT_FOR_EXTERN_INTERRUPT 0x1 #if 1 static irqreturn_t exirq_process ( int irq, void *dev_id ) { int handled = 0; u32 regdata; // printk("come in irq_process \n"); #if 1 regdata = in_be32(pic_vaddr6); //printk("pic_eivpr6 value = %x \n", regdata); if(regdata & 0x40000000) { atomic_set(&ex_interrupt_has_happen, 1); wake_up_interruptible(&ex_interrupt); } #endif //spin_lock(&i->lock); handled = 1; //spin_unlock(&i->lock); return IRQ_RETVAL(handled); } #endif static long exirq_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case WAIT_FOR_EXTERN_INTERRUPT: //printk("wait for extern interrupt\n"); wait_event_interruptible(ex_interrupt, atomic_read(&ex_interrupt_has_happen)!=0); atomic_set(&ex_interrupt_has_happen, 0); //printk("get an interrupt\n"); break; default: printk("cmd=%d error\n",cmd); break; } return 0; } #if 0 static struct timer_list test_timer; static void timer_action(unsigned long aa) { atomic_set(&ex_interrupt_has_happen, 1); wake_up_interruptible(&ex_interrupt); test_timer.expires = jiffies+(HZ*10); add_timer(&test_timer); } #endif static struct file_operations exirq_fops = { .owner = THIS_MODULE, .unlocked_ioctl = exirq_ioctl }; struct cdev exirq_cdev; int major; int exirq_int_init(void) { unsigned int regdata = 0; int ret = 0; init_waitqueue_head(&ex_interrupt); atomic_set(&ex_interrupt_has_happen, 0); #if 1 pic_vaddr6 = ioremap(get_immrbase() + MPC85xx_PIC_EIVPR6, 64); /* init EIVPR4 to 0x80000 */ regdata = 0x80000; /* priority=8; vector=0 */ // regdata |= 1<<22; out_be32(pic_vaddr6, regdata); /* init EIDR4 to let core process the int*/ regdata = 2; out_be32((pic_vaddr6+4), regdata); #endif /* we must use IRQF_SHARED mode. here IRQF_SHARED=0x80 */ ret = request_irq(16, exirq_process, 0x80, "IRQ4",1); if (ret < 0) printk("irq4 request fail.\n"); else printk("irq4 request success.\n"); #if 0 init_timer(&test_timer); test_timer.function = timer_action; test_timer.expires = jiffies + (HZ * 10); add_timer(&test_timer); #endif return 0; } static struct class *exirq_cls; dev_t dev_id; static int __init exirq_init(void) { printk("exirq init...\n"); exirq_int_init(); alloc_chrdev_region(&dev_id, 0, 1, "exirq"); major = MAJOR(dev_id); cdev_init(&exirq_cdev, &exirq_fops); cdev_add(&exirq_cdev, dev_id, 1); exirq_cls = class_create(THIS_MODULE, "exirq"); device_create(exirq_cls, NULL, dev_id, NULL, "exirq"); /* for test */ /* fpga_int_register_callback(0,test1); fpga_int_register_callback(1,test2); */ return 0; } static void __exit exirq_exit(void) { printk(KERN_ALERT "exirq driver exit\n"); device_destroy(exirq_cls, MKDEV(major, 0)); class_destroy(exirq_cls); /* 3.3 删除cdev*/ cdev_del(&exirq_cdev); /* 3.4 释放设备号*/ unregister_chrdev_region(MKDEV(major, 0), 1); free_irq(16,1); } module_init(exirq_init); module_exit(exirq_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("fzs");
/* * @file exirq.c * @author fzs * @date 2016-12-13 */ #include <linux/module.h> #include <linux/moduleparam.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/console.h> #include <linux/sysrq.h> #include <linux/delay.h> #include <linux/platform_device.h> #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/nmi.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/interrupt.h> #include <linux/irqreturn.h> #include <linux/spinlock.h> #include <asm/io.h> #include <asm/irq.h> volatile unsigned int *pic_vaddr6 = NULL, *pic_vaddr5 = NULL; extern void open_softirq(int nr, void (*action)(struct softirq_action *)); extern phys_addr_t get_immrbase(void); static atomic_t ex_interrupt_has_happen = ATOMIC_INIT(0); static wait_queue_head_t ex_interrupt; #define MPC85xx_PIC_EIVPR6 0x500c0 #define WAIT_FOR_EXTERN_INTERRUPT 0x1 #if 1 static irqreturn_t exirq_process ( int irq, void *dev_id ) { int handled = 0; u32 regdata; // printk("come in irq_process \n"); #if 1 regdata = in_be32(pic_vaddr6); //printk("pic_eivpr6 value = %x \n", regdata); if(regdata & 0x40000000) { atomic_set(&ex_interrupt_has_happen, 1); wake_up_interruptible(&ex_interrupt); } #endif //spin_lock(&i->lock); handled = 1; //spin_unlock(&i->lock); return IRQ_RETVAL(handled); } #endif static long exirq_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { switch (cmd) { case WAIT_FOR_EXTERN_INTERRUPT: //printk("wait for extern interrupt\n"); wait_event_interruptible(ex_interrupt, atomic_read(&ex_interrupt_has_happen)!=0); atomic_set(&ex_interrupt_has_happen, 0); //printk("get an interrupt\n"); break; default: printk("cmd=%d error\n",cmd); break; } return 0; } #if 0 static struct timer_list test_timer; static void timer_action(unsigned long aa) { atomic_set(&ex_interrupt_has_happen, 1); wake_up_interruptible(&ex_interrupt); test_timer.expires = jiffies+(HZ*10); add_timer(&test_timer); } #endif static struct file_operations exirq_fops = { .owner = THIS_MODULE, .unlocked_ioctl = exirq_ioctl }; struct cdev exirq_cdev; int major; int exirq_int_init(void) { unsigned int regdata = 0; int ret = 0; init_waitqueue_head(&ex_interrupt); atomic_set(&ex_interrupt_has_happen, 0); #if 1 pic_vaddr6 = ioremap(get_immrbase() + MPC85xx_PIC_EIVPR6, 64); /* init EIVPR4 to 0x80000 */ regdata = 0x80000; /* priority=8; vector=0 */ // regdata |= 1<<22; out_be32(pic_vaddr6, regdata); /* init EIDR4 to let core process the int*/ regdata = 2; out_be32((pic_vaddr6+4), regdata); #endif /* we must use IRQF_SHARED mode. here IRQF_SHARED=0x80 */ ret = request_irq(16, exirq_process, 0x80, "IRQ4",1); if (ret < 0) printk("irq4 request fail.\n"); else printk("irq4 request success.\n"); #if 0 init_timer(&test_timer); test_timer.function = timer_action; test_timer.expires = jiffies + (HZ * 10); add_timer(&test_timer); #endif return 0; } static struct class *exirq_cls; dev_t dev_id; static int __init exirq_init(void) { printk("exirq init...\n"); exirq_int_init(); alloc_chrdev_region(&dev_id, 0, 1, "exirq"); major = MAJOR(dev_id); cdev_init(&exirq_cdev, &exirq_fops); cdev_add(&exirq_cdev, dev_id, 1); exirq_cls = class_create(THIS_MODULE, "exirq"); device_create(exirq_cls, NULL, dev_id, NULL, "exirq"); /* for test */ /* fpga_int_register_callback(0,test1); fpga_int_register_callback(1,test2); */ return 0; } static void __exit exirq_exit(void) { printk(KERN_ALERT "exirq driver exit\n"); device_destroy(exirq_cls, MKDEV(major, 0)); class_destroy(exirq_cls); /* 3.3 删除cdev*/ cdev_del(&exirq_cdev); /* 3.4 释放设备号*/ unregister_chrdev_region(MKDEV(major, 0), 1); free_irq(16,1); } module_init(exirq_init); module_exit(exirq_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("fzs");
相关文章推荐
- linux用户空间和内核空间之细说
- Linux 系统内核空间与用户空间通信的实现与分析
- 在 Linux 下用户空间与内核空间数据交换的方式: procfs、seq_file、debugfs和relayfs
- linux用户空间和内核空间延时函数
- Linux 系统内核空间与用户空间通信的实现与分析
- 在 Linux 下用户空间与内核空间数据交换的方式
- 对Linux用户空间与内核空间数据传递的几点理解和总结(ZZ)
- 转载: Linux 系统内核空间与用户空间通信的实现与分析
- Linux 系统内核空间与用户空间通信的实现与分析(转)
- linux内存布局的内核实现--用户空间的映射方式
- 在 Linux 下用户空间与内核空间数据交换的方式,第 1 部分: 内核启动参数、模块参数与sysfs、sysctl、系统调用和netlink
- linux用户空间和内核exit的语义--linux没有线程
- linux 内核与用户空间通信之netlink使用方法
- 在 Linux 下用户空间与内核空间数据交换的方式,第 2 部分: procfs、seq_file、debugfs和relayfs
- linux内存布局的内核实现--用户空间的映射方式
- Linux 系统内核空间与用户空间通信的实现与分析
- Linux 系统内核空间与用户空间通信的实现与分析
- 在 Linux 下用户空间与内核空间数据交换的方式
- Linux 系统内核空间与用户空间通信的实现与分析
- 在 Linux 下用户空间与内核空间数据交换的方式