linux 的TIMER0 中断例子
一般的书籍都是 EINT0 等外部按键中断,但是没有提及其他中断,这几天在看中断的原理,勉强看懂了个大概,细节还是有点蒙。结合昨天做的实验,发现申请中断还真的不难,因为底层都做好了,只需要申请就行了,然后昨天一直试验都失败,实在没办法今天继续搞,意外的发现成功 了,发现问题出在TIMER0 的初始化上面。之前在裸机上试验一般都是对TCON等直接赋值,但是在系统上面就出问题了,因为TIMER4被内核
·
一般的书籍都是 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");
更多推荐
已为社区贡献3条内容
所有评论(0)