购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.3 键盘中断的处理过程

本节以按下按键<a>为例分析键盘中断处理的整体流程。当在键盘上按下按键<a>后,7A桥片中断控制器接收到向量号为3的键盘中断信号。与此同时,按键<a>的扫描码0x1c被存放到7A桥片寄存器L7A_I8042_DATA中。之后,7A桥片中断控制器通过HT总线,向3A处理器的HT控制器发送HT消息包。3A处理器中的扩展I/O中断控制器接收到HT控制器发送的中断向量号为0的HT中断信号后,将该中断信号转发给处理器核。

此时,ESTAT寄存器的IS字段中的HWI0位被设置为1,并且ECFG寄存器的LIE字段中的HWI0位在键盘中断初始化过程中被设置为1(设置过程详见代码清单3.6的第27行),CRMD寄存器中的IE字段被设置为1(在main函数中调用int_on函数实现)。因此,处理器将CRMD寄存器中的IE和PLV字段保存到PRMD寄存器后,将IE字段设置为0(关中断)。处理器将中断返回地址保存到ERA寄存器后,跳转到EENTRY寄存器中存放的中断处理函数exception_handler的入口地址处。exception_handler函数将中断现场保存到内核初始化栈后,调用do_exception函数进行中断处理,do_exception函数(第2版)的实现详见代码清单3.7。

代码清单3.7 do_exception函数(第2版)

下面对代码清单3.7进行说明。

·第20~28行: 本章实验code3中的do_exception函数的第2版在第1版的基础上增加了对键盘中断的处理。

·第22行: 获取扩展IO中断状态寄存器IOCSR_EXT_IOI_SR的值。如前所述,3A处理器的扩展I/O中断控制器共支持256个HT中断。256位3A处理器寄存器IOCSR_EXT_IOI_SR用于记录256个HT中断的状态。此时,因为键盘中断的HT中断向量号为0,所以IOCSR_EXT_IOI_SR寄存器中位0的值为1,表示产生了键盘中断。

·第23~27行: 对键盘中断进行处理。 第25行 表示调用keyboard_interrupt函数处理键盘中断,keyboard_interrupt函数的实现详见代码清单3.8。在 第26行 中,IOCSR_EXT_IOI_SR寄存器除了用于记录中断状态,也可以通过写该寄存器来清除中断标记。因此,通过调用write_iocsr库函数,向IOCSR_EXT_IOI_SR寄存器的第0位写1,从而清除键盘中断标记。

代码清单3.8 keyboard_interrupt函数(第1版)

下面对代码清单3.8进行说明。

·第8行: 从7A桥片寄存器L7A_I8042_DATA中读取键盘扫描码。

·第9~13行: 当按下和松开键盘按键时,都会产生键盘中断。当按下按键后,只需进行1次L7A_I8042_DATA寄存器读操作,并且读到的内容为该按键的扫描码;松开按键时,需要进行2次读操作,第1次读到的值为0xf0,第2次读到的内容为该按键的扫描码。MaQueOS只对按下键盘按键的中断进行处理。若从L7A_I8042_DATA寄存器中读取的值为0xf0,则说明是松开按键产生的键盘中断。因此,在 第11行 中,从L7A_I8042_DATA寄存器中读取按键的扫描码后,不进行处理,直接返回。

·第14行: 调用do_keyboard函数,对按键的扫描码进行处理。do_keyboard函数的实现详见代码清单3.9。

代码清单3.9 do_keyboard函数

下面对代码清单3.9进行说明。

·第15行: 用按键的扫描码作为keys_map数组的索引,获取按键的ASCII值。keys_map数组的定义在第1~8行中。因为按键<a>的扫描码为0x1c,所以获取到的按键<a>的ASCII值保存在keys_map[28]中。

·第16~21行: 若按下的按键为<a>,且stack数组未满,则在 第18行 中调用get_page函数申请一页空闲物理页,并将其保存至stack数组中。在 第19行 中,调用print_debug显示该空闲物理页的起始地址,print_debug函数的实现详见代码清单3.10。在 第20行 中,索引号index加1,指向stack数组的下一个空闲项。

·第22~27行: 若按下的按键为<s>,且stack数组不为空,则在 第24行 中,索引号index减1,指向stack数组的上一个保存物理页的项。在 第25行 中,调用free_page函数释放该物理页。在 第26行 中,调用print_debug显示被释放的物理页的起始地址。

代码清单3.10 print_debug函数

下面对代码清单3.10进行说明。

·第8行: 调用printk函数,显示参数中的字符串str。

·第9~17行: 将参数中的变量val的值转化为十六进制。其中,在 第11~15行 中,以4比特为单位,循环遍历val的值,将利用digits_map数组转化为十六进制的val的值保存到buffer数组中。

·第18行: 调用printk函数,显示完成转化后的十六进制的val的值。 DDR5Yl96QKah3Ydv54kCYHdaAqVIY/IZis3E4R4+zsTVKKZSxL6vh+B6BZmGJ0v/

点击中间区域
呼出菜单
上一章
目录
下一章
×