偷得浮生半桶水(半日闲), 好记性不如抄下来(烂笔头). 信息爆炸的时代, 学习是一项持续的工作.
全部博文(1750)
分类: LINUX
2009-02-06 17:28:47
int request_irq(unsigned int irq, void (*handler)(int irq, void *dev_id, struct pt_regs *regs), unsigned long irqflags, const char * devname, void *dev_id); |
void free_irq(unsigned int irq,void *dev_id); |
void my_tasklet_func(unsigned long); //定义一个处理函数: DECLARE_TASKLET(my_tasklet,my_tasklet_func,data); //定义一个tasklet结构my_tasklet,与my_tasklet_func(data)函数相关联 |
tasklet_schedule(&my_tasklet); |
DECLARE_TASKLET_DISABLED(name,function,data); //与DECLARE_TASKLET类似,但等待tasklet被使能 tasklet_enable(struct tasklet_struct *); //使能tasklet tasklet_disble(struct tasklet_struct *); //禁用tasklet tasklet_init(struct tasklet_struct *,void (*func)(unsigned long),unsigned long); //类似DECLARE_TASKLET() tasklet_kill(struct tasklet_struct *); // 清除指定tasklet的可调度位,即不允许调度该tasklet |
#include … //定义与绑定tasklet函数 void test_tasklet_action(unsigned long t); DECLARE_TASKLET(test_tasklet, test_tasklet_action, 0); void test_tasklet_action(unsigned long t) { printk("tasklet is executing\n"); } … ssize_t globalvar_write(struct file *filp, const char *buf, size_t len, loff_t *off) { … if (copy_from_user(&global_var, buf, sizeof(int))) { return - EFAULT; } //调度tasklet执行 tasklet_schedule(&test_tasklet); return sizeof(int); } |
static struct fasync_struct *rtc_async_queue; static int __init rtc_init(void) { misc_register(&rtc_dev); create_proc_read_entry("driver/rtc", 0, 0, rtc_read_proc, NULL); #if RTC_IRQ if (rtc_has_irq == 0) goto no_irq2; init_timer(&rtc_irq_timer); rtc_irq_timer.function = rtc_dropped_irq; spin_lock_irq(&rtc_lock); /* Initialize periodic freq. to CMOS reset default, which is 1024Hz */ CMOS_WRITE(((CMOS_READ(RTC_FREQ_SELECT) &0xF0) | 0x06), RTC_FREQ_SELECT); spin_unlock_irq(&rtc_lock); rtc_freq = 1024; no_irq2: #endif printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n"); return 0; } static void __exit rtc_exit(void) { remove_proc_entry("driver/rtc", NULL); misc_deregister(&rtc_dev); release_region(RTC_PORT(0), RTC_IO_EXTENT); if (rtc_has_irq) free_irq(RTC_IRQ, NULL); } static void rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs) { /* * Can be an alarm interrupt, update complete interrupt, * or a periodic interrupt. We store the status in the * low byte and the number of interrupts received since * the last read in the remainder of rtc_irq_data. */ spin_lock(&rtc_lock); rtc_irq_data += 0x100; rtc_irq_data &= ~0xff; rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) &0xF0); if (rtc_status &RTC_TIMER_ON) mod_timer(&rtc_irq_timer, jiffies + HZ / rtc_freq + 2 * HZ / 100); spin_unlock(&rtc_lock); /* Now do the rest of the actions */ wake_up_interruptible(&rtc_wait); kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); } static int rtc_fasync (int fd, struct file *filp, int on) { return fasync_helper (fd, filp, on, &rtc_async_queue); } static void rtc_dropped_irq(unsigned long data) { unsigned long freq; spin_lock_irq(&rtc_lock); /* Just in case someone disabled the timer from behind our back... */ if (rtc_status &RTC_TIMER_ON) mod_timer(&rtc_irq_timer, jiffies + HZ / rtc_freq + 2 * HZ / 100); rtc_irq_data += ((rtc_freq / HZ) << 8); rtc_irq_data &= ~0xff; rtc_irq_data |= (CMOS_READ(RTC_INTR_FLAGS) &0xF0); /* restart */ freq = rtc_freq; spin_unlock_irq(&rtc_lock); printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", freq); /* Now we have new data */ wake_up_interruptible(&rtc_wait); kill_fasync(&rtc_async_queue, SIGIO, POLL_IN); } |