SimpleKernel 1.17.0
Loading...
Searching...
No Matches
interrupt_main.cpp
Go to the documentation of this file.
1
5#include <cpu_io.h>
6
7#include "arch.h"
8#include "basic_info.hpp"
9#include "interrupt.h"
10#include "kernel.h"
11#include "kernel_log.hpp"
12#include "kstd_cstdio"
13
14namespace {
16
17// 定义 APIC 时钟中断向量号(使用高优先级向量)
18static constexpr uint8_t kApicTimerVector{0xF0};
19static constexpr uint32_t kApicTimerFrequencyHz{100};
20
27auto ApicTimerHandler(uint64_t cause, cpu_io::TrapContext* context)
28 -> uint64_t {
29 // APIC 时钟中断处理
30 static uint64_t tick_count = 0;
31 tick_count++;
32
33 // 每100次中断打印一次信息(减少日志输出)
34 if (tick_count % 100 == 0) {
35 klog::Info("APIC Timer interrupt {}, vector {:#x}", tick_count,
36 static_cast<uint32_t>(cause));
37 }
38
39 // 发送 EOI 信号给 Local APIC
40 InterruptSingleton::instance().apic().SendEoi();
41 return 0;
42}
43
50auto KeyboardHandler(uint64_t cause, cpu_io::TrapContext* context) -> uint64_t {
51 klog::Info("Keyboard interrupt received, vector {:#x}",
52 static_cast<uint32_t>(cause));
53 // 读取键盘扫描码
54 // 8042 键盘控制器的数据端口是 0x60
55 uint8_t scancode = cpu_io::In<uint8_t>(0x60);
56
57 // 简单的扫描码处理 - 仅显示按下的键(忽略释放事件)
58 if (!(scancode & 0x80)) { // 最高位为0表示按下
59 klog::Info("Key pressed: scancode {:#x}", scancode);
60
61 // 简单的扫描码到ASCII的映射(仅作为示例)
62 static constexpr char scancode_to_ascii[] = {
63 0, 27, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
64 '-', '=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',
65 'o', 'p', '[', ']', '\n', 0, 'a', 's', 'd', 'f', 'g', 'h',
66 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', 'v',
67 'b', 'n', 'm', ',', '.', '/', 0, '*', 0, ' '};
68
69 if (scancode < sizeof(scancode_to_ascii) && scancode_to_ascii[scancode]) {
70 char ascii_char = scancode_to_ascii[scancode];
71 klog::Info("Key: '{}'", ascii_char);
72 }
73 }
74
75 // 发送 EOI 信号给 Local APIC
76 InterruptSingleton::instance().apic().SendEoi();
77 return 0;
78}
79
80} // namespace
81
82auto InterruptInit(int, const char**) -> void {
83 InterruptSingleton::create();
84
85 // 初始化 APIC(从 ArchInit 移至此处)
86 InterruptSingleton::instance().InitApic(
87 BasicInfoSingleton::instance().core_count);
88 InterruptSingleton::instance().apic().InitCurrentCpuLocalApic().or_else(
89 [](Error err) -> Expected<void> {
90 klog::Err("Failed to initialize APIC: {}", err.message());
91 while (true) {
93 }
94 return std::unexpected(err);
95 });
96
97 InterruptSingleton::instance().SetUpIdtr();
98
99 // 注册 APIC Timer 中断处理函数(Local APIC 内部中断,不走 IO APIC)
100 InterruptSingleton::instance().RegisterInterruptFunc(
101 kApicTimerVector, InterruptDelegate::create<ApicTimerHandler>());
102
103 // 通过统一接口注册键盘外部中断(IRQ 1 = PS/2 键盘,先注册 handler 再启用 IO
104 // APIC)
105 static constexpr uint8_t kKeyboardIrq = 1;
106 InterruptSingleton::instance()
107 .RegisterExternalInterrupt(kKeyboardIrq, cpu_io::GetCurrentCoreId(), 0,
108 InterruptDelegate::create<KeyboardHandler>())
109 .or_else([](Error err) -> Expected<void> {
110 klog::Err("Failed to register keyboard IRQ: {}", err.message());
111 return std::unexpected(err);
112 });
113
114 // 启用 Local APIC 定时器
115 InterruptSingleton::instance().apic().SetupPeriodicTimer(
116 kApicTimerFrequencyHz, kApicTimerVector);
117 // 开启中断
118 cpu_io::Rflags::If::Set();
119
120 klog::Info("Hello InterruptInit");
121}
122
123auto InterruptInitSMP(int, const char**) -> void {
124 InterruptSingleton::instance().SetUpIdtr();
125
126 // 初始化当前 AP 核的 Local APIC
127 InterruptSingleton::instance().apic().InitCurrentCpuLocalApic().or_else(
128 [](Error err) -> Expected<void> {
129 klog::Err("Failed to initialize APIC for AP: {}", err.message());
130 while (true) {
132 }
133 return std::unexpected(err);
134 });
135
136 // 启用 Local APIC 定时器
137 InterruptSingleton::instance().apic().SetupPeriodicTimer(
138 kApicTimerFrequencyHz, kApicTimerVector);
139 cpu_io::Rflags::If::Set();
140 klog::Info("Hello InterruptInit SMP");
141}
auto InterruptInit(int, const char **) -> void
体系结构相关中断初始化
InterruptBase::InterruptDelegate InterruptDelegate
auto InterruptInitSMP(int, const char **) -> void
从核的体系结构相关中断初始化
etl::delegate< uint64_t(uint64_t, cpu_io::TrapContext *)> InterruptDelegate
类型安全的中断处理委托
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
void Pause()
Definition cpu_io.h:20
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
错误类型,用于 std::expected
Definition expected.hpp:343
constexpr auto message() const -> const char *
Definition expected.hpp:358