【读书笔记-《30天自制操作系统》-11】Day12

从本篇内容开始讲解定时器。本篇内容比较简单,首先介绍定时器的概念与设置方法,然后介绍超时的中断处理,并对中断处理函数进行了优化。
在这里插入图片描述

1. 定时器

定时器是操作系统中十分重要的功能。它的原理很简单,只是每隔一段时间发送一个中断给CPU。如果想要知道过了多长时间,只需要在中断处理程序中记录中断的次数就可以计算得到。

管理定时器也很简单,只需要对PIT(Programmable Interval Timer的缩写)进行设置即可。通过对PIT的设置,可以设置定时器每隔多长时间发送一次中断。PIT连接着IRQ的0号中断。设置PIT需要的命令如下:

  • AL = 0x34;OUT(0x43, AL);
  • AL = 中断周期的低8位;OUT(0x40, AL)
  • AL = 中断周期的高8位;OUT(0x40, AL)

实际设置的中断频率 = 单位时间时钟周期数(主频)/设定的数值
根据当前的主频,如果设定11932,则中断频率位100Hz,即10ms发生一次中断。把11932换算为16进制,则是0x2e9c。

设置PIT相关程序如下:

#define PIT_CTRL	0x0043
#define PIT_CNT0	0x0040

void init_pit(void)
{
   
   
	io_out8(PIT_CTRL, 0x34);
	io_out8(PIT_CNT0, 0x9c);
	io_out8(PIT_CNT0, 0x2e);
	return;
}

在主程序中调用init_pit函数:

struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	char s[40], keybuf[32], mousebuf[128];
	int mx, my, i;
	unsigned int memtotal, count = 0;
	struct MOUSE_DEC mdec;
	struct MEMMAN *memman = (struct MEMMAN *) MEMMAN_ADDR;
	struct SHTCTL *shtctl;
	struct SHEET *sht_back, *sht_mouse, *sht_win;
	unsigned char *buf_back, buf_mouse[256], *buf_win;

	init_gdtidt();
	init_pic();
	……

涉及到了中断,则需要将中断处理函数注册到IDT中,这些也是前面讲过的内容了。

	/* 注册IDT*/
	set_gatedesc(idt + 0x20, (int) asm_inthandler20, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x21, (int) asm_inthandler21, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x27, (int) asm_inthandler27, 2 * 8, AR_INTGATE32);
	set_gatedesc(idt + 0x2c, (int) asm_inthandler2c, 2 * 8, AR_INTGATE32);
_asm_inthandler20:
		PUSH	ES
		PUSH	DS
		PUSHAD
		MOV		EAX,ESP
		PUSH	EAX
		MOV		AX,SS
		MOV		DS,AX
		MOV		ES,AX
		CALL	_inthandler20
		POP		EAX
		POPAD
		POP		DS
		POP		ES
		IRETD
void inthandler20(int *esp)
{
   
   
	io_out8(PIC0_OCW2, 0x60);	/* 通知PIC, IRQ-00中断受理完毕 */
	/* 暂时无内容 */
	return;
}

这样定时器的中断处理就完成了。接下来就在中断处理中进行计时:

struct TIMERCTL {
   
   
	unsigned int count;
};

struct TIMERCTL timerctl;

void inthandler20(int *esp)
{
   
   
	io_out8(PIC0_OCW2, 0x60);	
	timerctl.count++;
	return;
}

新建了timerctl结构体,每次进入中断处理函数时就对其中的count变量增加1。在主程序中将count实时显示出来,根据之前的设置,每秒钟显示的数值会增加100。

	for (;;) {
   
   
		sprintf(s, "%010d", timerctl.count);
		boxfill8(buf_win, 160, COL8_C6C6C6, 40, 28, 119, 43);
		putfonts8_asc(buf_win, 160, 40, 28, COL8_000000, s);
		sheet_refresh(sht_win, 40, 28, 120, 44);
		……

这样就可以测量一段

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值