动手写操作系统 -- 定时器中断


上一节写了个单任务系统,下面当然就是多任务了,这里就先用2个任务吧。

任务多了,就需要调度,前面说了,需求就是写个支持多任务,分时调度的操作系统。

怎样实现分时调度呢?PC机有颗8254计时器芯片,设置好计数后,可实现每秒(18-1193180)次的中断。

可以在每次定时器中断中轮流调度任务,这样就能让多任务运行起来。是不是有点小激动。。。。。

想法是美好的,还需要一步步实现,先能够实现周期性的定时器中断再说。

先上图吧,在每次定时器中断中输出显示字符’a’:

pic

代码下载: funnyos_time_interrupt.7z

定时器中断实现代码如下,

#include "pc.h"
void testtest();
void TickISR(void);
void (*PC_TickISR)(void);

void  main (void) {
	PC_DispClrScr(DISP_FGND_WHITE + DISP_BGND_BLACK);      /* Clear the screen                         */

	PC_DispStr( 0,  0, "                              Funny OS Demo                                     ", DISP_FGND_WHITE + DISP_BGND_RED + DISP_BLINK);
	PC_SetTickRate(18);                      /* Reprogram tick rate                      */
	PC_TickISR = &TickISR;
	PC_VectSet(0x8, PC_TickISR); 
	testtest();
	for(;;);
}

void testtest() {
	static int i = 97;
	i++;
	PC_DispChar( 0,  i-95, i, DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
}

void TickISR(void) {
	static int i = 0;
	static int j = 0;
	PC_DispChar( (i++)%78,  (j++)/78 + 1, 'a'+(j/78), DISP_FGND_BLACK + DISP_BGND_LIGHT_GRAY);
	asm cli;
	outp(0x20,  0x20); 
	asm sti;
	//asm iret;
}

基础知识:

定时器芯片8254的控制寄存器IO 地址为0x43,寄存器操作方式如下图:


这里设置每秒18次中断,PC_SetTickRate(18)。

还有定时器中断向量号为0x8,即内存地址0x20-0x23处的值为中断处理函数TickISR()的地址。
在TickISR()函数中除了暑促字符'a',还设置了outp(0x20,  0x20); 
这句汇编代码,是使能中断控制芯片(PIC)——8259A的定时器的掩码,即重新使能定时器中断,因为每次
产生定时器中断是,掩码都是自动置0,去使能的。

上篇: 动手写操作系统 -- 单任务系统 下篇: 动手写操作系统 -- 任务切换(共享栈)