From 401df84d51a89e3abeef343fe7b2c99d6514a387 Mon Sep 17 00:00:00 2001 From: fslongjin Date: Fri, 8 Apr 2022 00:10:02 +0800 Subject: [PATCH] =?UTF-8?q?:new:=20rtc=E6=97=B6=E9=92=9F=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E7=A8=8B=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kernel/Makefile | 7 ++-- kernel/driver/timers/rtc/rtc.c | 64 ++++++++++++++++++++++++++++++++++ kernel/driver/timers/rtc/rtc.h | 20 +++++++++++ run.sh | 2 +- 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 kernel/driver/timers/rtc/rtc.c create mode 100644 kernel/driver/timers/rtc/rtc.h diff --git a/kernel/Makefile b/kernel/Makefile index 0f2101f7..94116600 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -109,16 +109,19 @@ pci.o: driver/pci/pci.c ahci.o: driver/disk/ahci/ahci.c gcc $(CFLAGS) -c driver/disk/ahci/ahci.c -o driver/disk/ahci/ahci.o +rtc.o: driver/timers/rtc/rtc.c + gcc $(CFLAGS) -c driver/timers/rtc/rtc.c -o driver/timers/rtc/rtc.o + all: kernel objcopy -I elf64-x86-64 -O elf64-x86-64 -R ".comment" -R ".eh_frame" kernel ../bin/kernel/kernel.elf # -kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o $(OBJ_LIST) +kernel: head.o entry.o main.o printk.o trap.o mm.o slab.o irq.o pic.o process.o syscall.o multiboot2.o cpu.o acpi.o ps2_keyboard.o ps2_mouse.o ata.o pci.o ahci.o smp.o apu_boot.o rtc.o $(OBJ_LIST) ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o mm/mm.o mm/slab.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \ common/cpu.o smp/smp.o smp/apu_boot.o \ - driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o \ + driver/acpi/acpi.o driver/interrupt/pic.o driver/keyboard/ps2_keyboard.o driver/mouse/ps2_mouse.o driver/disk/ata.o driver/pci/pci.o driver/disk/ahci/ahci.o driver/timers/rtc/rtc.o \ $(LD_LIST) \ -T link.lds diff --git a/kernel/driver/timers/rtc/rtc.c b/kernel/driver/timers/rtc/rtc.c new file mode 100644 index 00000000..239471d3 --- /dev/null +++ b/kernel/driver/timers/rtc/rtc.c @@ -0,0 +1,64 @@ +#include "rtc.h" +#include + +/*置位0x70的第7位,禁止不可屏蔽中断*/ +/* +#define read_cmos(addr) ({ \ + io_out8(0x70, 0x80 | addr); \ + io_in8(0x71); \ +}) +*/ +enum CMOSTimeSelector +{ + T_SECOND = 0x0, + T_MINUTE = 0x2, + T_HOUR = 0x4, + T_DAY = 0x7, + T_MONTH = 0x8, + T_YEAR = 0x9, +}; + +int read_cmos(uint8_t addr) +{ + io_out8(0x70, 0x80 | addr); + io_mfence(); + return (uint8_t)(io_in8(0x71) & 0xff); +} + +int rtc_get_cmos_time(struct time *t) +{ + // 为防止中断请求打断该过程,需要先关中断 + cli(); + + uint8_t status_register_B = read_cmos(0x0B); // 读取状态寄存器B + bool is_24h = ((status_register_B & 0x02) ? true : false); // 判断是否启用24小时模式 + bool is_binary = ((status_register_B & 0x04) ? true : false); // 判断是否为二进制码 + + do + { + t->year = read_cmos(0x09); + t->month = read_cmos(0x08); + t->day = read_cmos(0x07); + t->hour = read_cmos(0x04); + t->minute = read_cmos(0x02); + t->second = read_cmos(0x00); + } while (t->second != read_cmos(0x00)); // 若读取时间过程中时间发生跳变则重新读取 + // 使能NMI中断 + io_out8(0x70, 0x00); + + if (!is_binary) // 把BCD转为二进制 + { + t->second = (t->second & 0xf) + (t->second >> 4) * 10; + t->minute = (t->minute & 0xf) + (t->minute >> 4) * 10; + t->hour = ((t->hour & 0xf) + ((t->hour & 0x70) >> 4) * 10) | (t->hour & 0x80); + + t->month = (t->month & 0xf) + (t->month >> 4) * 10; + t->year = (t->year & 0xf) + (t->year >> 4) * 10; + } + t->year += 2000; + + if ((!is_24h) && t->hour & 0x80) // 将十二小时制转为24小时 + t->hour = ((t->hour & 0x7f) + 12) % 24; + sti(); + return 0; +} diff --git a/kernel/driver/timers/rtc/rtc.h b/kernel/driver/timers/rtc/rtc.h new file mode 100644 index 00000000..cae8224a --- /dev/null +++ b/kernel/driver/timers/rtc/rtc.h @@ -0,0 +1,20 @@ +#pragma once +#include +struct time +{ + int second; + int minute; + int hour; + int day; + int month; + int year; +}; + +/** + * @brief 从主板cmos中获取时间 + * + * @param t time结构体 + * @return int 成功则为0 + */ +int rtc_get_cmos_time(struct time*t); +int get_cmos_time(struct time *time); \ No newline at end of file diff --git a/run.sh b/run.sh index eee3cb61..4274c7c1 100644 --- a/run.sh +++ b/run.sh @@ -93,7 +93,7 @@ if [ $flag_can_run -eq 1 ]; then bochs -q -f ${bochsrc} -rc ./tools/bochsinit else qemu-system-x86_64 -cdrom ${iso} -m 512M -smp 2,cores=2,threads=1,sockets=1 \ - -monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu IvyBridge --enable-kvm \ + -monitor stdio -d cpu_reset,guest_errors,trace:check_exception,exec,cpu,out_asm,in_asm -s -S -cpu IvyBridge --enable-kvm -rtc clock=host,base=localtime \ -drive id=disk,file=bin/disk.img,if=none \ -device ahci,id=ahci \ -device ide-hd,drive=disk,bus=ahci.0 \