第10章 时钟中断(PIT编程)

设置时钟中断就是给操作系统加上心跳。设置时钟中断就是是设置PIT(8253/54芯片),可参考 《IBM-PC汇编语言程序设计 第2版》p384。

PIT有一个控制寄存器(0x43)和三个计数寄存器(0x40~0x42)。三个计数寄存器是16位的,有两种表示形式(BCD和二进制),有6种模式。控制寄存器中bit7~bit6用来选择计数寄存器,bit5~bit4用来选择写入方式,bit3~bit1用来选择计数模式,bit0用来选择表示形式。

PIT

设置计数器的方法:

  1. 先将控制字写入控制寄存器(选择哪个计数寄存器,选择写入方式,选择计数模式,选择表示方式)。
  2. 向选定的计数寄存器写入计数初值

当计数值是8位时,只用1条输出指令写入初值

当计数值是16位时,用2条输出指令写入初值(因为8253/54的数据总线是8位的)

CLK0、CLK1、CLK2的输入频率都是 1.1931817Mhz。计数器0作为定时器为系统时钟提供计时基准。计数器0的输出端OUT0与中断控制器8259A的中断请求IRQ0相连。假如需要计数器0的中断频率为M每秒,则divisor = 1193180/M。设定计数器0为模式3,输出频率为M。

设置计数器0的程序如下所示

outportb(0x43, 0x36);              //选择计数器0,输出模式3
outportb(0x40, divisor&0xff);      //把初始值的低字节写入LSB中
outportb(0x40, (divisor>>8)&0xff); //把初始值的高字节写入MSB中   
outportb(M_IMR, inportb(M_IMR)&0xfe);    //打开PIC1中的IRQ0中断(时钟中断)

timer.h文件的源代码如下所示

#ifndef        _TIMER_H_
#define     _TIMER_H_

#define     CLOCK_RATE    1193180
void init_timer(unsigned int  hz);
void do_timer(void);

#endif 

timer.c文件的源代码如下所示

#include "asm.h"
#include "io.h"
#include "idt.h"
#include "video.h"
#include "kernel.h"
#include "8259.h"
#include "timer.h"


void init_timer(unsigned int hz)
{
    unsigned int divisor = CLOCK_RATE/hz;
    outportb(0x43, 0x36);        //选择计数器0,输出模式3
    outportb(0x40, divisor&0xff);   //把初始值的低字节写入LSB中
    outportb(0x40, (divisor>>8)&0xff);    //把初始值的高字节写入MSB中
}

volatile unsigned int timer_ticks = 0;
void do_timer(void)
{
    outportb(M_PIC, EOI);   //告诉PIC1,中断处理函数已经结束,可以处理新来的中断。
                            //因为定时器是连接到PIC1的IRQ0上,所以不许要通知PIC2
    scheduler();
} 

Leave a Reply

Your email address will not be published. Required fields are marked *