Просмотр исходного кода

从键盘获取输入 scancode

simon 1 год назад
Родитель
Сommit
e133150bc5
8 измененных файлов с 112 добавлено и 39 удалено
  1. 29 0
      device/keyboard.c
  2. 18 0
      device/keyboard.h
  3. 7 5
      kernel/init.c
  4. 30 4
      kernel/interrupt.c
  5. 0 23
      kernel/interrupt.h
  6. 17 1
      kernel/kernel.S
  7. 6 5
      kernel/main.c
  8. 5 1
      makefile

+ 29 - 0
device/keyboard.c

@@ -0,0 +1,29 @@
+#include "keyboard.h"
+#include "../kernel/global.h"
+#include "stdint.h"
+#include "../lib/kernel/io.h"
+#include "../lib/kernel/print.h"
+#include "../kernel/interrupt.h"
+
+// 键盘中断处理程序
+static void intr_keyboard_handler(void);
+
+void keyboard_init(void)
+{
+    put_str("keyboard init start\n");
+    // todo: 1. 打开 8042 键盘控制器
+
+    // 2. 注册键盘中断处理程序
+    register_handler(0x21, intr_keyboard_handler);
+    put_str("keyboard init done\n");
+    return;
+}
+
+// 键盘中断处理程序
+static void intr_keyboard_handler(void)
+{
+    uint8_t scancode = inb(KBD_DATA_PORT); // 必须要读取输出缓冲寄存器,否则 8042 不再继续响应键盘中断
+    put_int(scancode);
+    put_char(' ');
+    return;
+}

+ 18 - 0
device/keyboard.h

@@ -0,0 +1,18 @@
+#ifndef __DEVICE_KEYBOARD_H
+#define __DEVICE_KEYBOARD_H
+
+/******************************
+ * IO Port	Access Type	Purpose
+ * 0x60	Read/Write	Data Port
+ * 0x64	Read	Status Register
+ * 0x64	Write	Command Registe
+ ******************************/
+
+#define KBD_DATA_PORT 0x60
+#define KBD_STATUS_PORT 0x64
+
+#define KBD_STATUS_MASK 0x02
+
+void keyboard_init(void);
+
+#endif // !__DEVICE_KEYBOARD_H

+ 7 - 5
kernel/init.c

@@ -3,15 +3,17 @@
 #include "interrupt.h"
 #include "../device/timer.h"
 #include "../device/console.h"
+#include "../device/keyboard.h"
 #include "memory.h"
 #include "../thread/thread.h"
 
 void init_all(void)
 {
     put_str("init_all\n");
-    itd_init();     // 初始化中断
-    mem_init();     // 初始化内存管理系统
-    thread_init();  // 初始化线程管理系统
-    timer_init();   // 初始化定时器
-    console_init(); // 初始化 console
+    itd_init();      // 初始化中断
+    mem_init();      // 初始化内存管理系统
+    thread_init();   // 初始化线程管理系统
+    timer_init();    // 初始化定时器
+    console_init();  // 初始化 console
+    keyboard_init(); // 键盘初始化
 }

+ 30 - 4
kernel/interrupt.c

@@ -4,13 +4,38 @@
 #include "../lib/kernel/print.h"
 #include "../lib/kernel/io.h"
 
-char *intr_name[IDT_DESC_CNT];        // 用于保存异常的名字
-intr_handler idt_table[IDT_DESC_CNT]; // 中断处理函数数组
+#define IDT_DESC_CNT 0x30 // 目前支持的中断数
+#define PIC_M_CTRL 0x20   // 主片的控制端口是 0x20
+#define PIC_M_DATA 0x21   // 主片的数据端口是 0x21
+#define PIC_S_CTRL 0xA0   // 从片的控制端口是 0xA0
+#define PIC_S_DATA 0xA1   // 从片的数据端口是 0xA1
 
 #define EFLAGS_IF 0x200 // eflags寄存器中的if位为1
 #define GET_EFLAGS(EFLAG_VAR) asm volatile("pushfl; popl %0" : "=g"(EFLAG_VAR))
 
-static gate_desc idt[IDT_DESC_CNT]; // 中断描述符表,本质上就是个中断门描述符数组
+/* 中断门描述符结构体 */
+// Example type_attributes values that people are likely to use (assuming DPL is 0):
+// 32-bit Interrupt Gate: 0x8E (p=1, dpl=0b00, type=0b1110 => type_attributes=0b1000_1110=0x8E)
+// 32-bit Trap Gate: 0x8F (p=1, dpl=0b00, type=0b1111 => type_attributes=1000_1111b=0x8F)
+// Task Gate: 0x85 (p=1, dpl=0b00, type=0b0101 => type_attributes=0b1000_0101=0x85)
+typedef struct
+{
+    uint16_t offset_low;  // 16位 偏移量的低 16 位 (0..15)
+    uint16_t selector;    // 选择器 acode segment selector in GDT or LDT
+    uint8_t dcount;       // 置 0
+    uint8_t attribute;    // 述符类型 (bit 7:0)  gate type, dpl, and p fields
+    uint16_t offset_high; // 16 位 偏移量的高 16 位 (16..31)
+} __attribute__((packed)) gate_desc;
+
+char *intr_name[IDT_DESC_CNT]; // 用于保存异常的名字
+/****************************** 定义中断数组 **********************
+ * 在 kernel.S 中定义的 intrXXentry 只是中断处理程序的入口,
+ * 最终调用的 idt_table 中的处理程序*/
+intr_handler idt_table[IDT_DESC_CNT]; // 中断处理函数数组
+/***************************************************************/
+
+static gate_desc idt[IDT_DESC_CNT];                 // 中断描述符表,本质上就是个中断门描述符数组
+extern intr_handler intr_entry_table[IDT_DESC_CNT]; // 声明引用定义在 kernel.S 中的中断处理函数入口数组
 
 /*创建中断门描述符*/
 static void make_idt_desc(gate_desc *p_gdesc, uint8_t attr, intr_handler function)
@@ -48,7 +73,8 @@ static void pic_init(void)
     outb(PIC_S_DATA, 0x01); // ICW4: 8086 模式, 正常 EOI
 
     /* 打开主片上 IR0, 也就是目前只接受时钟产生的中断*/
-    outb(PIC_M_DATA, 0xfe);
+    // outb(PIC_M_DATA, 0xfe);
+    outb(PIC_M_DATA, 0xfd); // 测试键盘,只打开键盘中断,其他全部关闭
     outb(PIC_S_DATA, 0xff);
 
     put_str("   pic_init done\n");

+ 0 - 23
kernel/interrupt.h

@@ -4,12 +4,6 @@
 #include "stdint.h"
 #include "global.h"
 
-#define IDT_DESC_CNT 0x21 // 目前支持的中断数
-#define PIC_M_CTRL 0x20   // 主片的控制端口是 0x20
-#define PIC_M_DATA 0x21   // 主片的数据端口是 0x21
-#define PIC_S_CTRL 0xA0   // 从片的控制端口是 0xA0
-#define PIC_S_DATA 0xA1   // 从片的数据端口是 0xA1
-
 typedef void *intr_handler;
 void itd_init(void);
 
@@ -26,23 +20,6 @@ enum intr_status intr_set_status(enum intr_status);
 enum intr_status intr_enable(void);
 enum intr_status intr_disable(void);
 
-/* 中断门描述符结构体 */
-// Example type_attributes values that people are likely to use (assuming DPL is 0):
-// 32-bit Interrupt Gate: 0x8E (p=1, dpl=0b00, type=0b1110 => type_attributes=0b1000_1110=0x8E)
-// 32-bit Trap Gate: 0x8F (p=1, dpl=0b00, type=0b1111 => type_attributes=1000_1111b=0x8F)
-// Task Gate: 0x85 (p=1, dpl=0b00, type=0b0101 => type_attributes=0b1000_0101=0x85)
-typedef struct
-{
-    uint16_t offset_low;  // 16位 偏移量的低 16 位 (0..15)
-    uint16_t selector;    // 选择器 acode segment selector in GDT or LDT
-    uint8_t dcount;       // 置 0
-    uint8_t attribute;    // 述符类型 (bit 7:0)  gate type, dpl, and p fields
-    uint16_t offset_high; // 16 位 偏移量的高 16 位 (16..31)
-} __attribute__((packed)) gate_desc;
-
-// 定义中断处理程序数组.在 kernel.S 中定义的intrXXentry只是中断处理程序的入口,最终调用的是ide_table中的处理程序
-extern intr_handler intr_entry_table[IDT_DESC_CNT];
-
 /// @brief 注册中断处理函数
 /// @param vector_no  中断号
 /// @param function  中断处理函数

+ 17 - 1
kernel/kernel.S

@@ -1,5 +1,6 @@
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; kernel.S - 中断处理程序
+; 功能: 存储各个中断入口程序的地址,形成 intr_entry_table 数组
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 [bits 32]
 %define ERROR_CODE nop 
@@ -82,4 +83,19 @@ VECTOR 0x1c, ZERO
 VECTOR 0x1d, ZERO
 VECTOR 0x1e, ERROR_CODE
 VECTOR 0x1f, ZERO
-VECTOR 0x20, ZERO
+VECTOR 0x20, ZERO ; 时钟中断对应的入口
+VECTOR 0x21, ZERO ; 键盘中断对应的入口
+VECTOR 0x22, ZERO ; 级联用的
+VECTOR 0x23, ZERO ; 串口 2 对应的入口
+VECTOR 0x24, ZERO ; 串口 1 对应的入口
+VECTOR 0x25, ZERO ; 并口 2 对应的入口
+VECTOR 0x26, ZERO ; 软盘对应的入口
+VECTOR 0x27, ZERO ; 并口 1 对应的入口
+VECTOR 0x28, ZERO ; 实时时钟对应的入口
+VECTOR 0x29, ZERO ; 重定向
+VECTOR 0x2a, ZERO ; 保留
+VECTOR 0x2b, ZERO ; 保留
+VECTOR 0x2c, ZERO ; ps/2 鼠标
+VECTOR 0x2d, ZERO ; fpu 浮点单元异常
+VECTOR 0x2e, ZERO ; 硬盘
+VECTOR 0x2f, ZERO ; 保留

+ 6 - 5
kernel/main.c

@@ -21,15 +21,16 @@ int main(void)
     // put_int((uintptr_t)addr);
     // put_str("\n");
 
-    thread_start("thread_a", 31, thread_a_func, "argA ");
-    thread_start("thread_b", 8, thread_b_func, "argB ");
+    // thread_start("thread_a", 31, thread_a_func, "argA ");
+    // thread_start("thread_b", 8, thread_b_func, "argB ");
 
     intr_enable(); // 打开中断,使时钟中断起作用
     // 主线程会一直执行, 直到被中断或被其他线程强制结束
     while (1)
-    {
-        console_put_str("Main ");
-    }
+        ;
+    // {
+    //     console_put_str("Main ");
+    // }
     return 0;
 }
 

+ 5 - 1
makefile

@@ -14,7 +14,8 @@ OBJS = $(BUILD_O_DIR)/main.o $(BUILD_O_DIR)/init.o $(BUILD_O_DIR)/interrupt.o  \
 	$(BUILD_O_DIR)/timer.o $(BUILD_O_DIR)/kernel.o $(BUILD_O_DIR)/print.o   \
 	$(BUILD_O_DIR)/debug.o $(BUILD_O_DIR)/string.o $(BUILD_O_DIR)/bitmap.o  \
 	$(BUILD_O_DIR)/memory.o $(BUILD_O_DIR)/thread.o $(BUILD_O_DIR)/list.o  \
-	$(BUILD_O_DIR)/switch.o $(BUILD_O_DIR)/sync.o $(BUILD_O_DIR)/console.o
+	$(BUILD_O_DIR)/switch.o $(BUILD_O_DIR)/sync.o $(BUILD_O_DIR)/console.o \
+	$(BUILD_O_DIR)/keyboard.o
 
 ################################ C 代码编译 ################################
 $(BUILD_O_DIR)/main.o: kernel/main.c lib/kernel/print.h lib/stdint.h kernel/init.h
@@ -53,6 +54,9 @@ $(BUILD_O_DIR)/sync.o: thread/sync.c thread/sync.h
 $(BUILD_O_DIR)/console.o: device/console.c device/console.h
 	$(CC) $(CFLAGS) $< -o $@
 
+$(BUILD_O_DIR)/keyboard.o: device/keyboard.c device/keyboard.h
+	$(CC) $(CFLAGS) $< -o $@
+
 ################################ 汇编代码编译 ################################
 $(BUILD_O_DIR)/kernel.o: kernel/kernel.S
 	$(AS) $(ASFLAGS) $< -o $@