一般的书籍都是 EINT0 等外部按键中断,但是没有提及其他中断,这几天在看中断的原理,勉强看懂了个大概,细节还是有点蒙。结合昨天做的实验,发现申请中断还真的不难,因为底层都做好了,只需要申请就行了,然后昨天一直试验都失败,实在没办法今天继续搞,意外的发现成功 了,发现问题出在TIMER0 的初始化上面。之前在裸机上试验一般都是对TCON等直接赋值,但是在系统上面就出问题了,因为TIMER4被内核占用了,如果强制改变 TCON 的值,系统崩溃了。所以正确的办法应该是读-修改-写,
先将TCON读出来,只修改TIMER0对应的几个位,不能改变其他位,这点以后一定要注意。至于申请中断就很容易了,request_irq 而已。
代码如下
/* * basic char driver * Etual <[email protected]> * 2013-03-09 * linux 2.6.22.6 * sbc2440 */ #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/errno.h> #include <linux/fcntl.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/cdev.h> #include <linux/interrupt.h> #include <asm/irq.h> #include <asm/uaccess.h> #include <asm/arch/regs-gpio.h> #include <asm/arch/regs-timer.h> #include <asm/arch/regs-irq.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/mach/irq.h> #include <asm/arch/regs-irq.h> int blink = 0; static irqreturn_t timer0_interrupt(int irq, void *dev_id) { if (blink) { blink = 0; s3c2410_gpio_setpin(S3C2410_GPB5, 0); }else{ blink = 1; s3c2410_gpio_setpin(S3C2410_GPB5, 1); } //printk("timer0_interrupt\n"); return IRQ_HANDLED; } static int __init leds_init(void) { int err; unsigned long tcfg0, tcfg1, tcon, msk; tcfg0 = __raw_readl(S3C2410_TCFG0); tcfg1 = __raw_readl(S3C2410_TCFG1); tcon = __raw_readl(S3C2410_TCON); tcon &= 0xffffff00; // stop timer0 __raw_writel(tcon, S3C2410_TCON); tcfg0 = (tcfg0&0xfffffff0) + 99; // PRESCALER 99, bit0~7 used for TIMER 0 1 tcfg1 = (tcfg1&0xfffffff0) + 0x03; //16div // setup hardware __raw_writel(tcfg0, S3C2410_TCFG0); __raw_writel(tcfg1, S3C2410_TCFG1); // 16DIV __raw_writel(31250, S3C2410_TCNTB(0)); // counter // manual update tcon |= 1<<1; __raw_writel(tcon, S3C2410_TCON); // start tcon = (tcon & 0xffffff00) + 0x09; __raw_writel(tcon, S3C2410_TCON); // intmsk msk = __raw_readl(S3C2410_INTMSK); msk &= (~(1<<10)); __raw_writel(msk, S3C2410_INTMSK); err = request_irq(IRQ_TIMER0, timer0_interrupt, IRQF_DISABLED, "sbc2440-timer0", 0); if (err) { printk("request irq error \n"); return err; } // led pin out s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPB5_OUTP); printk("Timer0 IRQ initialized\n"); return 0; } static void __exit leds_exit(void) { free_irq(IRQ_TIMER0, NULL); } module_init(leds_init); module_exit(leds_exit); MODULE_AUTHOR("Etual <[email protected]>"); MODULE_DESCRIPTION("Timer0 IRQ Driver"); MODULE_LICENSE("GPL");