Browse Source

:new: rtc时钟驱动程序

fslongjin 2 years ago
parent
commit
401df84d51
4 changed files with 90 additions and 3 deletions
  1. 5 2
      kernel/Makefile
  2. 64 0
      kernel/driver/timers/rtc/rtc.c
  3. 20 0
      kernel/driver/timers/rtc/rtc.h
  4. 1 1
      run.sh

+ 5 - 2
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
 

+ 64 - 0
kernel/driver/timers/rtc/rtc.c

@@ -0,0 +1,64 @@
+#include "rtc.h"
+#include <common/kprint.h>
+
+/*置位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;
+}

+ 20 - 0
kernel/driver/timers/rtc/rtc.h

@@ -0,0 +1,20 @@
+#pragma once
+#include <common/glib.h>
+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);

+ 1 - 1
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    \