challenge6.3:interrupt clock

完善trap.c中的中断处理函数trap,在对时钟中断进行处理的部分填写trap函数中处理时钟中断的部分,使操作系统每遇到100次时钟中断后,调用print_ticks子程序,向屏幕上打印一行文字”100 ticks”。

先看一下print_ticks子程序;

#define TICK_NUM 100
static void print_ticks()
{
cprintf("%d ticks\n", TICK_NUM); // 打印了TICK_NUM变量
#ifdef DEBUG_GRADE
cprintf("End of Test.\n");
panic("EOT: kernel seems ok.");
#endif
}

再看一下kern/driver/clock.c:

#include <x86.h>
#include <trap.h>
#include <stdio.h>
#include <picirq.h>

/* *
* Support for time-related hardware gadgets - the 8253 timer,
* which generates interruptes on IRQ-0.
* */

#define IO_TIMER1 0x040 // 8253 Timer #1

/* *
* Frequency of all three count-down timers; (TIMER_FREQ/freq)
* is the appropriate count to generate a frequency of freq Hz.
* */

#define TIMER_FREQ 1193182
#define TIMER_DIV(x) ((TIMER_FREQ + (x) / 2) / (x))

#define TIMER_MODE (IO_TIMER1 + 3) // timer mode port
#define TIMER_SEL0 0x00 // select counter 0
#define TIMER_RATEGEN 0x04 // mode 2, rate generator
#define TIMER_16BIT 0x30 // r/w counter 16 bits, LSB first

volatile size_t ticks;

/* *
* clock_init - initialize 8253 clock to interrupt 100 times per second,
* and then enable IRQ_TIMER.
* */
void
clock_init(void) {
// set 8253 timer-chip
outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
outb(IO_TIMER1, TIMER_DIV(100) % 256);
outb(IO_TIMER1, TIMER_DIV(100) / 256);

// initialize time counter 'ticks' to zero
ticks = 0;

cprintf("++ setup timer interrupts\n");
pic_enable(IRQ_TIMER);
}


可以看到,在clock_init()中里定义了ticks,根据要求,当ticks每次+1,直到100时即调用print_ticks()函数打印信息;

于是填充代码,在kern/trap/trap.c中有:

/* trap_dispatch - dispatch based on what type of trap occurred */
static void
trap_dispatch(struct trapframe *tf)
{
char c;

switch (tf->tf_trapno)
{
case IRQ_OFFSET + IRQ_TIMER:
/* LAB1 YOUR CODE : STEP 3 */
/* handle the timer interrupt */
/* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
* (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
* (3) Too Simple? Yes, I think so!
*/
ticks++;
while(ticks % 100 == 0) // 100也可以用已经定义的TICK_NUM来替换
print_ticks();
break;
break;
case IRQ_OFFSET + IRQ_COM1:
c = cons_getc();
cprintf("serial [%03d] %c\n", c, c);
break;
case IRQ_OFFSET + IRQ_KBD:
c = cons_getc();
cprintf("kbd [%03d] %c\n", c, c);
break;
//LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
case T_SWITCH_TOU:
case T_SWITCH_TOK:
panic("T_SWITCH_** ??\n");
break;
case IRQ_OFFSET + IRQ_IDE1:
case IRQ_OFFSET + IRQ_IDE2:
/* do nothing */
break;
default:
// in kernel, it must be a mistake
if ((tf->tf_cs & 3) == 0)
{
print_trapframe(tf);
panic("unexpected trap in kernel.\n");
}
}
}

/* *
* trap - handles or dispatches an exception/interrupt. if and when trap() returns,
* the code in kern/trap/trapentry.S restores the old CPU state saved in the
* trapframe and then uses the iret instruction to return from the exception.
* */
void trap(struct trapframe *tf)
{
// dispatch based on what type of trap occurred
trap_dispatch(tf);
}

make qemu查看结果;

...
100 ticks
100 ticks
100 ticks
100 ticks
100 ticks
100 ticks
100 ticks
100 ticks
...