CeDOS - Commit 66f9711e

Merge branch 'experimental/rtc-alarm' into develop
Celina Sophie Kalus
Tue, 02 Jan 2024 19:56:13 +0100
10 files changed, 95 insertions(+), 23 deletions(-)
M kernel/main.ckernel/main.c

@@ -2,6 +2,7 @@ #include "drivers/console.h"

#include "drivers/keyboard.h" #include "drivers/graphics.h" +#include "time.h" #include "sched/sched.h" #include "sched/process.h"

@@ -61,6 +62,10 @@ printk("done.\n");

printk("Installing syscalls..."); syscall_init(); + printk("done.\n"); + + printk("Initializing RTC..."); + time_init(); printk("done.\n"); printk("Initializing scheduler...");
M kernel/pic.ckernel/pic.c

@@ -26,9 +26,12 @@ outb(0x01, PIC1_DATA);

outb(0x01, PIC2_DATA); nop(); nop(); nop(); nop(); - // mask all interrupts - outb(0xff, PIC1_DATA); + // mask all interrupts (except for cascade) + outb(~(1 << PIC_IRQ_CASCADE), PIC1_DATA); outb(0xff, PIC2_DATA); + + // EOI + pic2_eoi(); return 1; }
M kernel/pic.hkernel/pic.h

@@ -16,6 +16,9 @@ #define PIC2_OFFSET 0x28

#define PIC_END_OF_INTERRUPT 0x20 +// IRQ number of the slave interrupt cascade +#define PIC_IRQ_CASCADE 2 + #define PIC1_IRQ(n) (PIC1_OFFSET + n) #define PIC2_IRQ(n) (PIC2_OFFSET + n)
M kernel/sched/sched.ckernel/sched/sched.c

@@ -15,6 +15,7 @@ #include "pic.h"

#include "elf.h" #include "file.h" #include "alarm.h" +#include "time.h" #include "assembly.h" #include "assert.h"

@@ -129,8 +130,6 @@

void sched_interrupt_c(SCHED_FRAME * volatile frame, uint32_t volatile ebp) { PROCESS* current = get_process(current_pid); - alarm_tick(); - current->esp = (VIRT_ADDR)(frame); current->ebp = (VIRT_ADDR)(ebp); current->eip = (VIRT_ADDR)frame->eip;

@@ -222,13 +221,13 @@

crit_exit(); } -void sched_sleep(int ticks) { +void sched_sleep(int msec) { // block the process. unblocking is done by the alarm. PROCESS *process = get_process(current_pid); process->state = PSTATE_BLOCKED; // create a wakeup-alarm to unblock the process. - alarm_add(ticks, current_pid, ALARM_WAKEUP); + alarm_add(RTC_MSEC(msec), current_pid, ALARM_WAKEUP); sched_yield();
M kernel/sched/sched.hkernel/sched/sched.h

@@ -11,7 +11,7 @@

#include "mm/paging.h" // 11928 ~ 10ms per interval -#define SCHED_INTERVAL (1193) +#define SCHED_INTERVAL (11928) /*! * Structure of the process stack when the scheduler is executed.

@@ -70,11 +70,11 @@ */

void sched_yield(void); /** - * @brief Blocks the current process for the given number of ticks. + * @brief Blocks the current process for the given number of milliseconds. * - * @param ticks Number of ticks. + * @param msec Number of milliseconds. */ -void sched_sleep(int ticks); +void sched_sleep(int msec); /** * @brief Unblocks the process given by \p pid immediately.
M kernel/sched/sched.skernel/sched/sched.s

@@ -16,7 +16,6 @@ // pass process stack as arguments

push %ebx push %eax xor %eax, %eax - call time_tick call sched_interrupt_c pop %eax pop %ebx
M kernel/time.ckernel/time.c

@@ -1,5 +1,9 @@

#include "time.h" #include "assembly.h" +#include "interrupts.h" +#include "pic.h" +#include "core.h" +#include "alarm.h" #define RTC_COMMAND 0x70 #define RTC_DATA 0x71

@@ -9,6 +13,7 @@

#define RTC_REGISTER_A 0x0A #define RTC_REGISTER_B 0x0B #define RTC_REGISTER_C 0x0C +#define RTC_REGISTER_D 0x0D #define RTC_GET_SECONDS 0x00 #define RTC_GET_MINUTES 0x02

@@ -18,6 +23,11 @@ #define RTC_GET_DAY 0x07

#define RTC_GET_MONTH 0x08 #define RTC_GET_YEAR 0x09 +#define RTC_DISABLE_NMI 0x80 +#define RTC_ENABLE_NMI 0x00 + +#define RTC_ENABLE_INT8 0x40 + int ticks = 0; void time_tick(void) {

@@ -30,22 +40,66 @@ }

static uint8_t rtc_get(uint8_t reg) { outb(reg, RTC_COMMAND); + /*nop(); nop(); nop(); + nop();*/ + uint8_t res = inb(RTC_DATA); + return res; +} + +static uint8_t from_BCD(uint8_t bcd_value) { + return (bcd_value >> 4) * 10 + (bcd_value & 0x0F); +} + +static uint8_t rtc_set(uint8_t reg, uint8_t value) { + outb(reg, RTC_COMMAND); + /*nop(); nop(); nop(); - uint8_t res = inb(RTC_DATA); - return (res >> 4) * 10 + (res & 0x0F); + nop();*/ + outb(value, RTC_DATA); } int time_now(datetime_t *buffer) { - buffer->year = 2000 + rtc_get(RTC_GET_YEAR); - buffer->month = rtc_get(RTC_GET_MONTH); - buffer->day = rtc_get(RTC_GET_DAY); + buffer->year = 2000 + from_BCD(rtc_get(RTC_GET_YEAR)); + buffer->month = from_BCD(rtc_get(RTC_GET_MONTH)); + buffer->day = from_BCD(rtc_get(RTC_GET_DAY)); - buffer->hour = rtc_get(RTC_GET_HOURS); - buffer->minute = rtc_get(RTC_GET_MINUTES); - buffer->second = rtc_get(RTC_GET_SECONDS); + buffer->hour = from_BCD(rtc_get(RTC_GET_HOURS)); + buffer->minute = from_BCD(rtc_get(RTC_GET_MINUTES)); + buffer->second = from_BCD(rtc_get(RTC_GET_SECONDS)); return 0; -}+} + +INTERRUPT(rtc_interrupt, frame) { + time_tick(); + alarm_tick(); + + rtc_get(RTC_REGISTER_C); + + pic2_eoi(); +} + +int time_init(void) { + install_interrupt(PIC2_IRQ(0x00), rtc_interrupt, 0x18, INT_GATE); + + // disable all interrupts + cli(); + + uint8_t reg_a = rtc_get(RTC_REGISTER_A | RTC_DISABLE_NMI); + rtc_set(RTC_REGISTER_A | RTC_DISABLE_NMI, (reg_a & 0xF0) | RTC_INT_RATE); + + uint8_t reg_b = rtc_get(RTC_REGISTER_B | RTC_DISABLE_NMI); + rtc_set(RTC_REGISTER_B | RTC_DISABLE_NMI, reg_b | RTC_ENABLE_INT8); + + reg_b = rtc_get(RTC_REGISTER_B); + + rtc_get(RTC_REGISTER_C); + rtc_get(RTC_REGISTER_D); + // enable interrupts again + sti(); + + pic_unmask_interrupt(8); +}
M kernel/time.hkernel/time.h

@@ -1,6 +1,13 @@

#ifndef __TIME_H #define __TIME_H +// frequency = 32768 >> (rate-1); +// rate at least 2 (~8kHz) +#define RTC_INT_RATE 3 +#define RTC_FREQUENCY (32768 >> (RTC_INT_RATE - 1)) +#define RTC_MSEC(ms) ((RTC_FREQUENCY / 1000) * ms) +#define RTC_SEC(s) (RTC_FREQUENCY * s) + typedef struct { int year; int month;

@@ -10,6 +17,8 @@ int hour;

int minute; int second; } datetime_t; + +int time_init(void); void time_tick(void);
M libcedos/cedos.clibcedos/cedos.c

@@ -101,9 +101,9 @@ volatile uint32_t res = 0;

interrupt(0x30, res, 14, pid, 0, 0); } -void sleep(int ticks) { +void sleep(int msec) { volatile uint32_t res = 0; - interrupt(0x30, res, 15, ticks, 0, 0); + interrupt(0x30, res, 15, msec, 0, 0); } int time_now(datetime_t *buffer) {
M libcedos/cedos.hlibcedos/cedos.h

@@ -17,7 +17,7 @@ } datetime_t;

int sysprint(const char *fmt, int arg1, int arg2); int yield(); -void sleep(int ticks); +void sleep(int msec); int get_pid(); int process_spawn(const char *fname, const char *args); int process_spawn_pipe(const char *fname, const char *args, int stdin, int stdout);