30天自制操作系统——第七天FIFO缓冲区与鼠标控制

本文详细介绍了在操作系统开发中如何处理键盘和鼠标中断,通过建立FIFO缓冲区提升中断处理速度,并解决键盘输入多字节编码问题。接着,文章讲解了鼠标控制电路的初始化和激活过程,最后实现从鼠标接收数据的功能。
摘要由CSDN通过智能技术生成

昨天鼠标不动的问题,是因为相关的设定还没到位。鼠标和键盘的情况很类似,在解决鼠标问题之前,先拿键盘练练手。

获取按键编码(hiarib04a)

现在在键盘上按一个键,就在屏幕上显示出信息。我们把程序修改成,键盘按下一个键后不直接结束,可以接着在屏幕上显示按键的值,其他就先不做了。

需要修改的是int.c中的inthandler21函数:

#define PORT_KEYDAT		0x0060

void inthandler21(int *esp)
{
	struct BOOTINFO *binfo = (struct BOOTINFO *) ADR_BOOTINFO;
	unsigned char data, s[4];
	io_out8(PIC0_OCW2, 0x61);	/* 通知PIC"IRQ-01"已经受理完毕 */
	data = io_in8(PORT_KEYDAT);

	sprintf(s, "%02X", data);
	boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
	putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);

	return;
}

io_out8(PIC0_OCW2, 0x61);这句是告知PIC已经发生了IRQ1中断,如果是IRQ3,则写成0x63,即将“0x60+IRQ号码”输出给OCW2就可以了。执行这句后,PIC继续监视IRQ1中断是否发生。

应该注意的是从编号为0x0060的设备输入的8位信息是按键编码,编号为0x0060的设备是键盘。

那么现在将接收到的按键编码显示在画面上,然后处理中断。

我们现在运行以下make run,看一下结果——

随便按下一个按键,屏幕上就会显示出一个十六进制的数字,这里我们发现键盘按下去会显示一个数字,松开会显示另一个数字,其中原因我们后面再说。

在这里插入图片描述

加快中断处理(hiarib04b)

现在程序里有一个问题,就算字符显示的内容也放在了中断处理的程序之中。由于中断处理本身是打断CPU正在执行的工作,强行加入请求进行处理,中断期间也不再接受别的中断。

而且在计算机看来字符显示是要花很多时间处理的,中断处理速度过慢就会出现鼠标卡顿的等问题,因此字符显示的内容最好不要加在中断函数里。

那么应该怎么处理呢?

方法很简单,将按键的编码先接收下来,保存在变量中,之后由HariMain偶尔去查看这个变量。如果有了新数据,就把它显示出来。

int.c节选:

#define PORT_KEYDAT		0x0060

struct KEYBUF keybuf;

void inthandler21(int *esp)
{
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61);	/* 通知PIC IRQ-01已经受理完毕 */
	data = io_in8(PORT_KEYDAT);
	if (keybuf.flag == 0) {
		keybuf.data = data;
		keybuf.flag = 1;
	}
	return;
}

由于键盘输入时需要缓冲区,我们定义了一个结构体,命名为keybuf。keybuf中的flag变量用于表示这个缓冲区是否为空,如果flag是0,表示缓冲区为空;如果flag是1,就表示缓冲区中存有数据。 若果缓冲区中存有数据,这时来了一个中断该怎么处理了,这里我们先不做处理,把这个数据丢掉。

我们对bootpack.c的HariMain函数里的无线循环for(;;)模块进行修改。

HariMain函数节选:

for (;;) {
		io_cli();
		if (keybuf.flag == 0) {
			io_stihlt();
		} else {
			i = keybuf.data;
			keybuf.flag = 0;
			io_sti();
			sprintf(s, "%02X", i);
			boxfill8(binfo->vram, binfo->scrnx, COL8_008484, 0, 16, 15, 31);
			putfonts8_asc(binfo->vram, binfo->scrnx, 0, 16, COL8_FFFFFF, s);
		}
	}

循环开始时,先用io_cli指令屏蔽中断。

为什么这时要屏蔽中断呢?

这是因为在执行后面的处理时,要是中断突然闯进来,可就乱套了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值