Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3010641
  • 博文数量: 674
  • 博客积分: 17881
  • 博客等级: 上将
  • 技术积分: 4849
  • 用 户 组: 普通用户
  • 注册时间: 2010-03-17 10:15
文章分类

全部博文(674)

文章存档

2013年(34)

2012年(146)

2011年(197)

2010年(297)

分类: LINUX

2010-03-30 14:25:04

在linux/arch/arm/mach-s3c2410/time.c 里
内核的主要工作是初始化了这样一个结构
struct sys_timer s3c24xx_timer = {
.init = s3c2410_timer_init,
.offset = s3c2410_gettimeoffset,
.resume = s3c2410_timer_setup
};
下面是s3c2410_timer_init的实现
static void __init s3c2410_timer_init (void)
{
s3c2410_timer_setup(); //这里做了一些时钟初始化设置,但是针对timer4的
setup_irq(IRQ_TIMER4, &s3c2410_timer_irq); //设置中断处理函数
}

s3c24xx_timer又在linux/arch/arm/mach-s3c2410/mach-smdk2410.c中被调用
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
* to SMDK2410 */
MAINTAINER("Jonas Dietsche")
BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, (u32)S3C24XX_VA_UART)
BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
MAPIO(smdk2410_map_io)
INITIRQ(smdk2410_init_irq)
.timer = &s3c24xx_timer, //这里!!!
MACHINE_END

我觉得执行完上述代码后时钟就应该设置好了。所以我想先在s3c2410_timer_setup()里参照timer4的加入对timer1的初始化,然后在s3c2410_timer_init里再添加一个setup_irq()
我正好打算写一个PWM的驱动,所以也就试了timer,结果是可以的,没问题。这是我用来测试的驱动程序,你可以参考一下。加载这个ko后,在timer0中断时会在console打印一个字符串。

#include
#include
#include
#include
#include
#include

#include
#include

#include
#include
#include
#include

MODULE_LICENSE("Dual BSD/GPS");

int timer_major = 0;
int timer_minor = 0;

static DECLARE_WAIT_QUEUE_HEAD(timer0_wait);
struct cdev cdev;

static int timer_ioctl(struct inode* node, struct file* f, unsigned int cmd, unsigned long arg)
{
return 0;
}

struct file_operations timer_fops = {
.owner = THIS_MODULE,
.ioctl = timer_ioctl,
};

static irqreturn_t timer0_irq(int irq, void* dev_id, struct pt_regs* reg)
{
printk(KERN_ALERT "timer0 irq ");
wake_up_interruptible(&timer0_wait);
return IRQ_HANDLED;
}

static void setup_led_ios(void)
{
s3c2410_gpio_cfgpin(S3C2410_GPB7, S3C2410_GPB7_OUTP);
s3c2410_gpio_pullup(S3C2410_GPB7, 1);
}

static void setup_timer0(void)
{
unsigned long nTCON;
unsigned long nTCNT;
unsigned long nTCFG0;
unsigned long nTCFG1;

nTCON = __raw_readl(S3C2410_TCON);
nTCFG0 = __raw_readl(S3C2410_TCFG0);
nTCFG1 = __raw_readl(S3C2410_TCFG1);

nTCFG1 &= ~S3C2410_TCFG1_MUX0_MASK;
nTCFG1 |= S3C2410_TCFG1_MUX0_DIV16;

nTCFG0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
nTCFG0 |= 0xFF;

nTCNT = 0xFFFF;

__raw_writel(nTCFG1, S3C2410_TCFG1);
__raw_writel(nTCFG0, S3C2410_TCFG0);
__raw_writel(nTCNT--, S3C2410_TCNTB(0));

nTCON &= ~(0xF);
nTCON |= S3C2410_TCON_T0RELOAD;
nTCON |= S3C2410_TCON_T0MANUALUPD;

__raw_writel(nTCON, S3C2410_TCON);
__raw_writel(nTCNT, S3C2410_TCNTB(0));
__raw_writel(nTCNT, S3C2410_TCMPB(0));

nTCON |= S3C2410_TCON_T0START;
nTCON &= ~S3C2410_TCON_T0MANUALUPD;

__raw_writel(nTCON, S3C2410_TCON);
}

static int sbc2410_timer_init(void)
{
int result;
dev_t dev = 0;

printk(KERN_ALERT "sbc2410 timer-led driver ");

result = alloc_chrdev_region(&dev, timer_minor, 1, "timerled");
timer_major = MAJOR(dev);

if (request_irq(IRQ_TIMER0, timer0_irq, SA_INTERRUPT, "timer0", NULL))
{
printk(KERN_ALERT "request_irq error ");
return -1;
}

setup_led_ios();
setup_timer0();

cdev_init(&cdev, &timer_fops);
cdev_add(&cdev, dev, 1);

return 0;
}

static void sbc2410_timer_exit(void)
{
dev_t dev = MKDEV(timer_major, timer_minor);
cdev_del(&cdev);
unregister_chrdev_region(dev, 0);

printk(KERN_ALERT "sbc2410 timer driver exit. ");
}

module_init(sbc2410_timer_init);
module_exit(sbc2410_timer_exit);
阅读(815) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~