一、前言 #
一般IRQ0作为定时器中断,cpu有一个旁路芯片或者内置触发此中断。
二、定时器中断设置 #
1// arch/x86/kernel/time.c
2/*
3 * Default timer interrupt handler for PIT/HPET
4 */
5static irqreturn_t timer_interrupt(int irq, void *dev_id)
6{
7 global_clock_event->event_handler(global_clock_event);
8 return IRQ_HANDLED;
9}
10
11static void __init setup_default_timer_irq(void)
12{
13 unsigned long flags = IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER;
14
15 /*
16 * Unconditionally register the legacy timer interrupt; even
17 * without legacy PIC/PIT we need this for the HPET0 in legacy
18 * replacement mode.
19 */
20 if (request_irq(0, timer_interrupt, flags, "timer", NULL))
21 pr_info("Failed to register legacy timer interrupt\n");
22}
23
24/* Default timer init function */
25void __init hpet_time_init(void)
26{
27 if (!hpet_enable()) {
28 if (!pit_timer_init())
29 return;
30 }
31
32 setup_default_timer_irq();
33}
三、定时器芯片设置 #
1. 定时器芯片频率和计数器相关计算 #
芯片频率定义如下
1// include/linux/timex.h
2/* The clock frequency of the i8253/i8254 PIT */
3#define PIT_TICK_RATE 1193182ul
根据CONFIG_HZ计算出要设置到定时器的计数器的值
1// include/linux/i8253.h
2#define PIT_LATCH ((PIT_TICK_RATE + HZ/2) / HZ)
2. 设置i8253的PIT #
1// include/linux/i8253.h
2/* i8253A PIT registers */
3#define PIT_MODE 0x43
4#define PIT_CH0 0x40
5#define PIT_CH2 0x42
6
7// drivers/clocksource/i8253.c
8static int pit_set_periodic(struct clock_event_device *evt)
9{
10 raw_spin_lock(&i8253_lock);
11
12 /* binary, mode 2, LSB/MSB, ch 0 */
13 outb_p(0x34, PIT_MODE);
14 outb_p(PIT_LATCH & 0xff, PIT_CH0); /* LSB */
15 outb_p(PIT_LATCH >> 8, PIT_CH0); /* MSB */
16
17 raw_spin_unlock(&i8253_lock);
18 return 0;
19}