From 976d3a40172f2b4085e38376b9d920c99fd4fc9b Mon Sep 17 00:00:00 2001 From: yanguangshaonian Date: Tue, 18 Apr 2023 12:10:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=9B=A0=E4=B8=BA=E9=97=B9=E9=92=9F=E4=B8=AD?= =?UTF-8?q?=E6=96=AD=E6=97=A0=E6=B3=95=E5=BC=80=E5=90=AF,=20=E6=9C=AA?= =?UTF-8?q?=E7=9F=A5bug,=20=E6=89=80=E4=BB=A5=E7=94=A8=E5=91=A8=E6=9C=9F?= =?UTF-8?q?=E4=B8=AD=E6=96=AD=E5=AE=9E=E7=8E=B0=E4=BA=86=E4=B8=80=E4=B8=AA?= =?UTF-8?q?=E4=BC=AA=E9=97=B9=E9=92=9F=E4=B8=AD=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 3 +- bochs/bochsrc | 2 +- bochs/bochsrc.gdb | 2 +- src/Makefile | 1 + src/include/onix/interrupt.h | 2 +- src/include/onix/onix.h | 1 + src/include/onix/rtc.h | 28 +++++++++++ src/include/onix/time.h | 16 ++---- src/kernel/main.c | 3 ++ src/kernel/rtc.c | 97 ++++++++++++++++++++++++++++++++++++ src/kernel/schdule.asm | 2 +- src/kernel/time.c | 8 +-- 12 files changed, 140 insertions(+), 25 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ae61e82..62a002c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,6 +26,7 @@ "cassert": "c", "*.inc": "c", "clock.h": "c", - "time.h": "c" + "time.h": "c", + "rtc.h": "c" } } \ No newline at end of file diff --git a/bochs/bochsrc b/bochs/bochsrc index f32dd4d..9526470 100644 --- a/bochs/bochsrc +++ b/bochs/bochsrc @@ -41,7 +41,7 @@ debugger_log: - magic_break: enabled=1 port_e9_hack: enabled=0 private_colormap: enabled=0 -clock: sync=none, time0=local, rtc_sync=0 +clock: sync=realtime, time0=local, rtc_sync=1 # no cmosimage log: - logprefix: %t%e%d diff --git a/bochs/bochsrc.gdb b/bochs/bochsrc.gdb index 24564af..0e26a8d 100644 --- a/bochs/bochsrc.gdb +++ b/bochs/bochsrc.gdb @@ -36,7 +36,7 @@ print_timestamps: enabled=0 gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0 port_e9_hack: enabled=0 private_colormap: enabled=0 -clock: sync=none, time0=local, rtc_sync=0 +clock: sync=realtime, time0=local, rtc_sync=1 # no cmosimage log: - logprefix: %t%e%d diff --git a/src/Makefile b/src/Makefile index 123ce38..a2833f7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -54,6 +54,7 @@ $(BUILD_PATH)/kernel.bin:$(BUILD_PATH)/kernel/start.o \ $(BUILD_PATH)/lib/stdlib.o\ $(BUILD_PATH)/kernel/clock.o\ $(BUILD_PATH)/kernel/time.o\ + $(BUILD_PATH)/kernel/rtc.o\ $(shell mkdir -p $(dir $@)) ld -m elf_i386 -static $^ -o $@ -Ttext $(KERNEL_ENTRY_POINT) diff --git a/src/include/onix/interrupt.h b/src/include/onix/interrupt.h index 82e5126..c06c1b9 100644 --- a/src/include/onix/interrupt.h +++ b/src/include/onix/interrupt.h @@ -9,7 +9,7 @@ #define IDT_SIZE 256 #define ENTRY_SIZE 0x30 // 我们实现的中断数量 -#define LOGK(fmt, args...) DEBUGK(fmt, ##args) +// #define LOGK(fmt, args...) DEBUGK(fmt, ##args) #define PIC_M_CTRL 0x20 // 主片的控制端口 #define PIC_M_DATA 0x21 // 主片的数据端口 diff --git a/src/include/onix/onix.h b/src/include/onix/onix.h index 021ecfe..a38c8c3 100644 --- a/src/include/onix/onix.h +++ b/src/include/onix/onix.h @@ -13,6 +13,7 @@ #include > #include > #include > +#include > void kernel_init(); diff --git a/src/include/onix/rtc.h b/src/include/onix/rtc.h index 3abcebf..11fdf0e 100644 --- a/src/include/onix/rtc.h +++ b/src/include/onix/rtc.h @@ -2,11 +2,39 @@ #define ONIX_RTC_H #include #include +#include +#include +#include +#include + + +#define CMOS_ADDR 0x70 // CMOS 地址寄存器 +#define CMOS_DATA 0x71 // CMOS 数据寄存器 + + +// 下面是 CMOS 信息的寄存器索引 +#define CMOS_SECOND 0x00 // (0 ~ 59) +#define CMOS_MINUTE 0x02 // (0 ~ 59) +#define CMOS_HOUR 0x04 // (0 ~ 23) +#define CMOS_WEEKDAY 0x06 // (1 ~ 7) 星期天 = 1,星期六 = 7 +#define CMOS_DAY 0x07 // (1 ~ 31) +#define CMOS_MONTH 0x08 // (1 ~ 12) +#define CMOS_YEAR 0x09 // (0 ~ 99) +#define CMOS_CENTURY 0x32 // 可能不存在 +#define CMOS_NMI 0x80 + +#define CMOS_A 0x0a +#define CMOS_B 0x0b +#define CMOS_C 0x0c +#define CMOS_D 0x0d + + u8 cmos_read(u8 addr); void cmos_write(u8 addr, u8 value); +void rtc_init(); #endif \ No newline at end of file diff --git a/src/include/onix/time.h b/src/include/onix/time.h index c4726cb..c9e77cc 100644 --- a/src/include/onix/time.h +++ b/src/include/onix/time.h @@ -2,20 +2,10 @@ #define ONIX_TIME_H #include #include +#include + + -#define CMOS_ADDR 0x70 // CMOS 地址寄存器 -#define CMOS_DATA 0x71 // CMOS 数据寄存器 - -// 下面是 CMOS 信息的寄存器索引 -#define CMOS_SECOND 0x00 // (0 ~ 59) -#define CMOS_MINUTE 0x02 // (0 ~ 59) -#define CMOS_HOUR 0x04 // (0 ~ 23) -#define CMOS_WEEKDAY 0x06 // (1 ~ 7) 星期天 = 1,星期六 = 7 -#define CMOS_DAY 0x07 // (1 ~ 31) -#define CMOS_MONTH 0x08 // (1 ~ 12) -#define CMOS_YEAR 0x09 // (0 ~ 99) -#define CMOS_CENTURY 0x32 // 可能不存在 -#define CMOS_NMI 0x80 #define MINUTE 60 // 每分钟的秒数 #define HOUR (60 * MINUTE) // 每小时的秒数 diff --git a/src/kernel/main.c b/src/kernel/main.c index c4007fa..e1568ca 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -22,6 +22,9 @@ void kernel_init(){ // 初始化时间 // time_init(); + // 闹钟中断 + rtc_init(); + asm volatile("sti\n"); hang(); diff --git a/src/kernel/rtc.c b/src/kernel/rtc.c index e69de29..fec8056 100644 --- a/src/kernel/rtc.c +++ b/src/kernel/rtc.c @@ -0,0 +1,97 @@ +#include + +// 从cmos芯片中读取到时间 +u8 cmos_read(u8 addr){ + out_8(CMOS_ADDR, CMOS_NMI | addr); + return in_8(CMOS_DATA); +} + + +// 写 cmos 寄存器的值 +void cmos_write(u8 addr, u8 value) +{ + out_8(CMOS_ADDR, CMOS_NMI | addr); + out_8(CMOS_DATA, value); +} + +int counter = 0; +static u32 next_time = 0xffffffff; +// 实时时钟中断处理函数 +void rtc_handler(int handle_num) +{ + // 实时时钟中断向量号 + assert(handle_num == 0x28); + + // 向中断控制器发送中断处理完成的信号 + send_eoi(handle_num); + + // 读 CMOS 寄存器 C,允许 CMOS 继续产生中断 + cmos_read(CMOS_C); + + tm time; + time_read(&time); + u32 now_time = mktime(&time); + if (next_time <= mktime(&time)) { + DEBUGK("rtc handler %d... %d %d \n", counter++, now_time, next_time); + next_time = 0xffffffff; + set_alarm(1); + } +} + + +// 设置 secs 秒后发生实时时钟中断 +void set_alarm(u32 secs) +{ + tm time; + time_read(&time); + + u8 sec = secs % 60; + secs /= 60; + u8 min = secs % 60; + secs /= 60; + u32 hour = secs; + + time.tm_sec += sec; + if (time.tm_sec >= 60) + { + time.tm_sec %= 60; + time.tm_min += 1; + } + + time.tm_min += min; + if (time.tm_min >= 60) + { + time.tm_min %= 60; + time.tm_hour += 1; + } + + time.tm_hour += hour; + if (time.tm_hour >= 24) + { + time.tm_hour %= 24; + } + + next_time = mktime(&time); +} + + + +void rtc_init() +{ + cmos_write(CMOS_B, 0b01000010); // 打开周期中断 + // cmos_write(CMOS_B, 0b00100010); // 打开闹钟中断 + cmos_read(CMOS_C); // 读 C 寄存器,以允许 CMOS 中断 + + // 设置中断频率 + out_8(CMOS_A, (in_8(CMOS_A) & 0xf) | 0b1110); + + set_alarm(3); + + // 设置自定义中断处理函数 + set_interrupt_handler(IRQ_RTC, rtc_handler); + + // 打开从片上的实时时钟中断控制器 + set_interrupt_mask(IRQ_RTC, true); + // 从片和主片和这个接口相连接 + set_interrupt_mask(IRQ_CASCADE, true); +} diff --git a/src/kernel/schdule.asm b/src/kernel/schdule.asm index b674667..f236621 100644 --- a/src/kernel/schdule.asm +++ b/src/kernel/schdule.asm @@ -31,5 +31,5 @@ task_switch: pop ebx pop ebp - ; 此时 栈顶是 call task_switch 的下一行代码的位置, ret即可 + ; 此时 栈顶是 call task_switch 的下一行代码的位置(如果是第一次调用则是函数指针的位置), ret即可 ret diff --git a/src/kernel/time.c b/src/kernel/time.c index bcb4c99..9aefceb 100644 --- a/src/kernel/time.c +++ b/src/kernel/time.c @@ -136,12 +136,6 @@ u32 get_yday(tm *time) return res; } -// 从cmos芯片中读取到时间 -u8 cmos_read(u8 addr) - { - out_8(CMOS_ADDR, CMOS_NMI | addr); - return in_8(CMOS_DATA); - }; void time_read_bcd(tm *time) { @@ -192,6 +186,6 @@ void time_init() // 计算得到时间戳 startup_time = mktime(&time); - DEBUGK("时间戳 time: %d", startup_time); + DEBUGK("now time: %d", startup_time); } \ No newline at end of file