您的位置:首页 > 运维架构 > Linux

linux 的TIMER0 中断例子

2013-03-09 09:35 232 查看
一般的书籍都是 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");
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: