8042的输入缓冲区大小只有一个字节,所以当一个扫描码有不止一个字符时,实际上会产生不止一次中断。也就是说,如果我们按一下Shift+A,产生的0x2A0x1E0x9E0xAA是4次中断接收来的。这就给我们的程序实现带来了困难,因为第一次中断时收到的0x2A无法让我们知道用户最终会完成什么,说不定是按下Shift又释放,也可能是Shift+Z而不是Shift+A。
于是,当接收到类似0x2A这样的值的时候,需要先把它保存起来,在随后的过程中慢慢解析用户到底做了什么。
在这里,向前辈学习,建立一个缓冲区,让keyboard_handler将每次收到的扫描码放入这个缓冲区,然后建立一个新的任务专门用来解析它们并做相应处理。
键盘程序处理架构:
用户按下键盘-->触发键盘中断处理程序(把按键的扫描码存储到键盘缓冲区)
添加一个系统进程tty(操作系统会不停的调度到它)-->从键盘缓冲区读出数据
/*======================================================================*
init_keyboard
*======================================================================*/
PUBLIC void init_keyboard()
{
kb_in.count = 0;
kb_in.p_head = kb_in.p_tail = kb_in.buf;
put_irq_handler(KEYBOARD_IRQ, keyboard_handler);/*设定键盘中断处理程序*/
enable_irq(KEYBOARD_IRQ); /*开键盘中断*/
}
/*======================================================================*
keyboard_handler
*======================================================================*/
PUBLIC void keyboard_handler(int irq)
{
u8 scan_code = in_byte(KB_DATA);
if (kb_in.count < KB_IN_BYTES) {
*(kb_in.p_head) = scan_code;
kb_in.p_head++;
if (kb_in.p_head == kb_in.buf + KB_IN_BYTES) {
kb_in.p_head = kb_in.buf;
}
kb_in.count++;
}
}
/*======================================================================*
keyboard_read
*======================================================================*/
PUBLIC void keyboard_read()
{
u8 scan_code;
if(kb_in.count > 0){
disable_int();
scan_code = *(kb_in.p_tail);
kb_in.p_tail++;
if (kb_in.p_tail == kb_in.buf + KB_IN_BYTES) {
kb_in.p_tail = kb_in.buf;
}
kb_in.count--;
enable_int();
disp_int(scan_code);
}
}
/*======================================================================*
task_tty
*======================================================================*/
PUBLIC void task_tty()
{
while (1) {
keyboard_read(); //调用其他文件的函数处理
}
}