初始化定时器中断

5.10.4 初始化定时器中断

回到start_kernel,612行time_init函数:

void __init time_init(void)

{

       late_time_init = x86_late_time_init;

}

 

函数x86_late_time_init实际上是初始化tsc时钟源。在time_init中只是把该函数的地址赋给全局变量late_time_init,以后某个时刻肯定会调用它的,这里先提前详细分析一下他:

 

static __init void x86_late_time_init(void)

{

       x86_init.timers.timer_init();

       tsc_init();

}

 

x86_init.timers.timer_init实际是函数hpet_time_init,来自文件kernel/timer.c:

 

101 void __init hpet_time_init(void)

102 {

103        if (!hpet_enable())

104               setup_pit_timer();

105        setup_default_timer_irq();

106}

 

由于我们没有配置CONFIG_HPET_TIMER,所以103行hpet_enable返回0,调用104行的函数setup_pit_timer,位于arch/x86/kernel/i8253.c:

 

104void __init setup_pit_timer(void)

 105{

 106        /*

 107         * Start pit with the boot cpu mask and make it global after the

 108         * IO_APIC has been initialized.

 109         */

 110        pit_ce.cpumask = cpumask_of(smp_processor_id());

 111        pit_ce.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);

 112        pit_ce.max_delta_ns = clockevent_delta2ns(0x7FFF, &pit_ce);

 113        pit_ce.min_delta_ns = clockevent_delta2ns(0xF, &pit_ce);

 114

 115        clockevents_register_device(&pit_ce);

 116        global_clock_event = &pit_ce;

 117}

 

整个函数的115行之前都是在通过汇编指令初始化全局变量pit_ce,这个clock_event_device类型的变量在编译的时候已经被初始化成了:

 

static struct clock_event_device pit_ce = {

       .name             = "pit",

       .features  = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,

       .set_mode       = init_pit_timer,

       .set_next_event = pit_next_event,

       .shift              = 32,

       .irq         = 0,

};

 

我们看到它的irq号为0,也就是对应32号中断描述符表项,即interrupt[0]处理函数。115行把它注册到通知链和clockevent_devices链表中:

 

void clockevents_register_device(struct clock_event_device *dev)

{

       unsigned long flags;

……//一些调试代码

       raw_spin_lock_irqsave(&clockevents_lock, flags);

       list_add(&dev->list, &clockevent_devices);

       clockevents_do_notify(CLOCK_EVT_NOTIFY_ADD, dev);

       clockevents_notify_released();

       raw_spin_unlock_irqrestore(&clockevents_lock, flags);

}

 

最后将全局global_clock_event设置成这个定时器,然后回到hpet_time_init中,105行,调用setup_default_timer_irq():

 

void __init setup_default_timer_irq(void)

{

       setup_irq(0, &irq0);

}

static struct irqaction irq0  = {

       .handler = timer_interrupt,

       .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,

       .name = "timer"

};

 

很简单,调用setup_irq把interrupt[0]对应的处理函数设置成timer_interrupt。至于随后如何处理的,请查看博客“定时器中断”

http://blog.csdn.net/yunsongice/archive/2010/03/07/5354137.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值