tasklet_schedule(&keyboard_tasklet);
tasklet使用模板 /**定义tasklet和底半部函数并关联*/ struct tasklet_struct xxx_tasklet; void xxx_do_tasklet(unsigned long); DECLARE_TASKLET(xxx_tasklet, xxx_do_tasklet, 0); /**中断处理底半部*/ void xxx_do_tasklet(unsigned long) { } /**中断处理顶半部*/ irqreturn_t xxx_interrupt(int irq, void *dev_id) { ... taklet_schedule(&xxx_tasklet); ... return IRQ_HANDLED; } /**设备驱动模块加载函数*/ int __init xxx_init(void) { ... /**申请中断*/ result = request_irq(xxx_irq, xxx_interrupt, IRQF_DISABLED, "xxx", NULL); ... } /**设备驱移除函数*/ void __exit xxx_exit(void) { ... /**释放中断*/ free_irq(dev->irq, dev); ... }
2)工作队列 tasklet运行于中断上下文 工作队列运行于进程上下文 tasklet处理函数中不能睡眠,而工作队列处理函数中允许睡眠 I)定义一个工作队列结构 struct work_struct my_wq; II)定义一个处理函数 void my_wq_func(unsigned long); III)初始化这个工作队列并将工作队列与函数绑定 INIT_WORK(&my_wq, (void(*)(void *))my_wq_func, NULL); IV)调度工作队列执行schedule_work() schedule_work(&my_wq); ----------------------------------------------------- 工作队列使用模板 /**定义工作队列和关联函数*/ struct work_struct xxx_wq; void xxx_do_work(unsigned long); /**中断处理底半部*/ void xxx_do_work(unsigned long) { ... } /**中断处理顶半部*/ irqreturn_t xxx_interrupt(int irq, void *dev_id) { ... schedule_work(&xxx_wq); ... return IRQ_HANDLED; } /**设备驱动模块加载函数*/ int __init xxx_init(void) { ... /**申请中断*/ result = request_irq(xxx_irq, xxx_interrupt, IRQF_DISABLED, "xxx", NULL); ... /**初始化工作队列*/ INIT_WORK(&xxx_wq, (void(*)(void*))xxx_do_work, NULL); ... } /**设备驱动移除函数*/ void xxx_exit(void) { ... /**释放中断*/ free_irq(&dev->irq, dev); ... }
5. 中断例子 /** *interrupt key kernel 2.6.35.7 */ #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/fs.h> #include <mach/gpio.h> #define KEY_MAJOR 233 #define DEVICE_NAME "gpio_key1" struct work_struct work; static void gpio_key_work_func(struct work_struct *work) { printk("the code is 101\n"); } static irqreturn_t gpio_key_isr(int irq, void *dev_id) { schedule_work(&work); return IRQ_HANDLED; } int key_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { return 0; } static const struct file_operations key_ops = { .owner = THIS_MODULE, .ioctl = key_ioctl, }; static int __init gpio_keys_init(void) { int ret = 0; int irq;//中断号 unsigned long irqflags; ret = register_chrdev(KEY_MAJOR, DEVICE_NAME, &key_ops); if (ret < 0) { printk("can't register gpio_keys_number\n"); return -1; } //申请管脚 gpio_request(S3C64XX_GPN(0), "HOME"); //设置为输入 gpio_direction_input(S3C64XX_GPN(0)); irq = gpio_to_irq(S3C64XX_GPN(0)); printk("the gpio_key irq is [%d]\n ", irq); irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; ret = request_irq(irq, gpio_key_isr, irqflags, "HOME", NULL); if (ret) { printk("can't get gpio irq\n"); return -1; } INIT_WORK(&work, gpio_key_work_func); printk("gpio_keys init\n"); return 0; } static void __exit gpio_keys_exit(void) { unregister_chrdev(KEY_MAJOR, DEVICE_NAME); } module_init(gpio_keys_init); module_exit(gpio_keys_exit); MODULE_LICENSE("GPL"); ------------------------------- 测试,按键 # the code is 101 # cat /proc/interrupts 101: 6 s3c-eint HOME 中断被用了6次