一般的书籍都是 EINT0 等外部按键中断,但是没有提及其他中断,这几天在看中断的原理,勉强看懂了个大概,细节还是有点蒙。结合昨天做的实验,发现申请中断还真的不难,因为底层都做好了,只需要申请就行了,然后昨天一直试验都失败,实在没办法今天继续搞,意外的发现成功 了,发现问题出在TIMER0 的初始化上面。之前在裸机上试验一般都是对TCON等直接赋值,但是在系统上面就出问题了,因为TIMER4被内核占用了,如果强制改变 TCON 的值,系统崩溃了。所以正确的办法应该是读-修改-写,

先将TCON读出来,只修改TIMER0对应的几个位,不能改变其他位,这点以后一定要注意。至于申请中断就很容易了,request_irq 而已。

代码如下

/*
 * basic char driver
 * Etual <Etual@163.com>
 * 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 <Etual@163.com>"); 
MODULE_DESCRIPTION("Timer0 IRQ Driver");
MODULE_LICENSE("GPL");



Logo

更多推荐