IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【操作系统】30天自制操作系统--(6)FIFO缓冲区与鼠标控制 -> 正文阅读

[系统运维]【操作系统】30天自制操作系统--(6)FIFO缓冲区与鼠标控制

? ? ? ? 上一章的最后,实现了键盘的中断反馈,但是鼠标依然没有反应,所以承上启下,本章要做这么几个事情,(1)将中断接收到的数据,拿到中断外面来处理,以减少中断中的操作,加快程序运行(这边很好理解,不再赘述);(2)建立FIFO缓冲区,以便快速稳定地读写键盘/鼠标的活动数据;(3)键盘控制电路的初始化,并激活鼠标,应用建立的FIFO缓冲区读写鼠标的活动数据;

一 建立FIFO缓冲区

????????缓冲区是一个队列结构,先进先出,队列长度可以在初始化中自行定义。这边主要构建了以下几个操作函数:

【1】FIFO缓冲区初始化----fifo8_init:

? ? ? ? 这个函数用于初始化一个缓冲区结构体,缓冲区的读写采用双指针的控制方法,所以这边用p、q两个指针来指代缓冲区数组下标。长度可以根据情况自行定义(键盘操作少一点,定义的长度为32,鼠标的操作多一点,定义的长度为128):

void fifo8_init(struct FIFO8 *fifo, int size, unsigned char *buf)
/* FIFO缓冲区初始化 */
{
	fifo->buf   = buf;  //缓冲数据区
    fifo->p     = 0;    //缓冲区写指针
    fifo->q     = 0;    //缓冲区读指针
    fifo->size  = size; //缓冲区总长度
    fifo->free  = size; //缓冲区剩余长度
    fifo->flags = 0;    //缓冲区溢出标志位
    
	return;
}

【2】FIFO缓冲区写数据----fifo8_put:

int fifo8_put(struct FIFO8 *fifo, unsigned char data)
/* 向FIFO传送数据并保存 */
{
    if(fifo->free == 0)
    {
        /* 如果缓冲区满,则溢出标志位置1,写不进新的数据 */
        fifo->flags |= FLAGS_OVERRUN;
        return -1;
    }
	fifo->buf[fifo->p] = data;
    fifo->p ++;
    fifo->free --;
    if(fifo->p == fifo->size)
    {
        fifo->p = 0;
    }
	return 0;
}

【3】FIFO缓冲区读数据----fifo8_get:

int fifo8_get(struct FIFO8 *fifo)
/* 从FIFO取一个数据 */
{
    int data;
    if(fifo->free == fifo->size)
    {
        /* 如果缓冲区为空,则直接返回,读不到数据 */
        return -1;
    }
	data = fifo->buf[fifo->q];
    fifo->q ++;
    fifo->free ++;
    if(fifo->q == fifo->size)
    {
        fifo->q = 0;
    }
    
	return data;
}

【4】FIFO缓冲区状态查询----fifo8_status:

int fifo8_status(struct FIFO8 *fifo)
/* 查询使用了多少数据 */
{
	return fifo->size - fifo->free;
}

? ? ? ? 有了上面的几个FIFO操作函数,就可以在主函数以及中断处分别添加读、写操作:

? ? ? ? 中断处写FIFO:

void inthandler21(int *esp)
{
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61);	/* 通知PIC,IRQ1受理完成 */
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&keyfifo, data);  /* 将接收到的键盘操作符,写缓冲区 */
	return;
}

? ? ? ? 主函数处读FIFO:

void HariMain(void)
{
    //display...
	fifo8_init(&keyfifo, 32, keybuf);

	for (;;) {
		io_cli();
		if (fifo8_status(&keyfifo) == 0) {
            //缓冲区为空则等待
			io_stihlt();
		} else {
            //读缓冲区一个字节
			i = fifo8_get(&keyfifo);
			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);
		}
	}
}

二 鼠标控制

????????上一章的最后,实现了键盘的中断反馈,但是鼠标依然没有反应,原因在于,主板上虽然做了鼠标用的电路,但只要不执行激活鼠标的指令,就不产生鼠标的中断信号。

? ? ? ? 鼠标的使用包含两个部分,一个是控制电路的激活,第二个是鼠标操作符的接收。

????????【1】鼠标的控制电路包含在键盘的控制电路中,鼠标的激活需要键盘控制电路的初始化

#define PORT_KEYDAT				0x0060
#define PORT_KEYSTA				0x0064
#define PORT_KEYCMD				0x0064
#define KEYSTA_SEND_NOTREADY	0x02
#define KEYCMD_WRITE_MODE		0x60
#define KBC_MODE				0x47

void wait_KBC_sendready(void)
{
	/* 等待键盘控制电路准备完毕 */
	for (;;) {
		if ((io_in8(PORT_KEYSTA) & KEYSTA_SEND_NOTREADY) == 0) {
			break;
		}
	}
	return;
}

void init_keyboard(void)
{
	/* 初始化键盘控制电路 */
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD, KEYCMD_WRITE_MODE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT, KBC_MODE);
	return;
}

#define KEYCMD_SENDTO_MOUSE		0xd4
#define MOUSECMD_ENABLE			0xf4

void enable_mouse(void)
{
	/* 激活鼠标控制 */
	wait_KBC_sendready();
	io_out8(PORT_KEYCMD, KEYCMD_SENDTO_MOUSE);
	wait_KBC_sendready();
	io_out8(PORT_KEYDAT, MOUSECMD_ENABLE);
	return; /* 顺利的话,键盘控制其会返回ACK(0xfa) */
}

? ? ? ? 【2】鼠标操作符的接收

? ? ? ? 与键盘操作相比,鼠标这部分区别不大。区别在于中断中的处理(这边为了方便对比,把键盘的处理也一并贴出来):

? ? ? ? 键盘的处理如下:

struct FIFO8 keyfifo;

void inthandler21(int *esp)
{
    /* 来自PS/2键盘的中断 */
	unsigned char data;
	io_out8(PIC0_OCW2, 0x61);	/* 通知PIC0 IRQ-01的受理已经完成 */
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&keyfifo, data);
	return;
}

? ? ? ? 鼠标的处理如下:

struct FIFO8 mousefifo;

void inthandler2c(int *esp)
/* 来自PS/2鼠标的中断 */
{
	unsigned char data;
	io_out8(PIC1_OCW2, 0x64);	/* 通知PIC1 IRQ-12的受理已经完成 */
	io_out8(PIC0_OCW2, 0x62);	/* 通知PIC0 IRQ-02的受理已经完成 */
	data = io_in8(PORT_KEYDAT);
	fifo8_put(&mousefifo, data);
	return;
}

? ? ? ? 由上面可以看出,键盘因为是IRQ1中断,只需要通知一次PIC0即可。然而鼠标是IRQ12中断,IRQ12是由PIC1控制,而PIC1是由PIC0上的IRQ2控制,所以这边需要分别通知

? ? ? ? ?主函数中的处理与键盘没有区别,所以这边不再赘述(设定的键盘缓冲区是32,鼠标缓冲区是128)。

? ? ? ? 至此,鼠标和键盘的初始化、激活以及操作符的反馈已经完成。

? ? ? ? 但是目前鼠标的操作符返回的东西看不懂,还不能实际使用,对其的解读下一章会介绍。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-15 00:46:32  更:2022-04-15 00:47:42 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 21:28:49-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码