定时器设定

一、前言 #

一般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}