《30天自制操作系统》笔记----Day17

闲置任务

在前文说到,通过采用LEVEL的结构运行系统,但当高层任务A休眠,而下层LEVEL中不存在其他的任务,因此程序就找不到任务而导致运行出行异常,所以优秀的操作系统应该能自动在适当的LEVEL运行适当的任务。
创建一个闲置任务:
这个任务的功能只是执行HTL。

void task_idle(void)
{
		for(;;){
				io_hlt();
		}
}

所以即使高层任务A进入sleep,系统也能自动切换到上面这个闲置任务。移动鼠标,FIFO有数据写入,任务A就会被唤醒,系统自动切换到A继续工作。
所以改写一下HariMain:

void HariMain(void)
{
		(passing)
		/*sht_win_b*/
		for(i=0; i<3;i++){
				(passing)
				*((int*)(task_b[i]->tss.esp+4)) = (int) sht_win_b[i];
		}
		(passing)
}

创建命令行窗口

命令行窗口当作任务操作

void console_task(struct SHEET *sheet)
{
		struct FIFO32 fifo;
		struct TIMER *timer;
		struct TASK *task = task_now();
		int i, fifobuf[128], cursor_x = 8, cursor_c = COL8_000000;
		fifo32_init(&fifo, 128, fifobuf, task);
		timer = timer_alloc();
		timer_init(timer, &fifo, 1);
		timer_settime(timer, 50);
		for (;;) {
				io_cli();
				if (fifo32_status(&fifo) == 0) {
						task_sleep(task);
						io_sti();
				} else {
						i = fifo32_get(&fifo);
						io_sti();
						if (i <= 1) { /*光标用定时器*/
								if (i != 0) {
										timer_init(timer, &fifo, 0); /*下次置0 */
										cursor_c = COL8_FFFFFF;
										} else {
												timer_init(timer, &fifo, 1); /*下次置1 */
												cursor_c = COL8_000000;
												}
							timer_settime(timer, 50);
							boxfill8(sheet->buf, sheet->bxsize, cursor_c, cursor_x, 28,cursor_x + 7, 43);
						sheet_refresh(sheet, cursor_x, 28, cursor_x + 8, 44);
					}
			}
		}
}

实现字符输入

实现字符输入,需要在键盘被按下的时候向console_task的FIFO发送数据,即需要知道struct FIFO的内存地址才行。

struct TASK{
		int sel,flags;/*sel 代表*/
		int level,priority;
		struct FIFO32 fifo;
		struct TSS32 tss;
};

符号的输入

为了能够实现输入“!”和“%”,我们必须要处理Shift键。
左Shift : 0x2a(按下) 0xaa(抬起)
右Shift : 0x36 0xb6
所以准备一个key_shift变量:左Shift按下置1,右Shift按下置2,俩个都不按下置为0,俩个都按下置为3。
当key_shift为0时,我们用keytable0[]将按键编码转换为字符编码,而当key_shift不为0时,则使用keytable1[]进行转换。

大写字母与小写字母

要实现区分大小写字母的输入,我们必须要同时判断Shift键的状态以及CapsLock的状态。
CapsLock为OFF & Shift键为OFF → 小写英文字母
CapsLock为OFF & Shift键为ON → 大写英文字母
CapsLock为ON & Shift键为OFF → 大写英文字母
CapsLock为ON & Shift键为ON → 小写英文字母
即实现小写字母需要满足如下:
①输入的字符为英文字母
②“CapsLock为OFF&Shift键位OFF”或者“CapsLock为ON&Shift键为ON”
而CapsLock信息存储在BIOS中,在asmhead.nas中,通过BIOS获取键盘状态,并保存在binfo->leds中。
binfo->leds的第4位→ ScrollLock状态
binfo->leds的第5位 → NumLock状态
binfo->leds的第6位 → CapsLock状态

对各种锁定键的支持

我们通过上文可知:
CapsLock:0x3a
NumLock:0x45
ScrollLock:0x46

关于LED的控制:

对于NumLock和CapsLock等LED的控制,可采用下面的方法向键盘发送指令和数据。
1.读取状态寄存器,等待bit 1的值变为0。
2.向数据输出(0060)写入要发送的1个字节数据。
3.等待键盘返回1个字节的信息,这和等待键盘输入所采用的方法相同(用IRQ等待或者用轮询状态寄存器bit 1的值直到其变为0都可以)。
4.返回的信息如果为0xfa,表明1个字节的数据已成功发送给键盘。如为0xfe则表明发送失败,需要返回第1步重新发送。

首先,我们创建了一个叫keycmd的FIFO缓冲区,它不是用来接收中断请求的,而是用来管理由任务A向键盘控制器发送数据的顺序的。如果有数据要发送到键盘控制器,首先会在这个keycmd中累积起来。keycmd_wait变量,用来表示向键盘控制器发送数据的状态。当keycmd_wait的值为-1时,表示键盘控制器处于通常状态,可以发送指令;当值不为-1时,表示键盘控制器正在等待发送的数据,这时要发送的数据被保存在keycmd_wait变量中。在for循环的开头,当keycmd中有数据,且keycmd_wait为-1时,向键盘发送1个字节的数据,在开始发送数据的同时,keycmd_wait变为非-1的值。随后,当从键盘接收到0xfa返回信息时,keycmd_wait恢复为-1,继续发送下一个数据。当从键盘接收到的返回信息为0xfe时,则重新发送刚才的数据。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不吃人的坤坤坤坤坤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值