Files
riscv64-kernel/src/time.rs

68 lines
1.9 KiB
Rust

use core::time::Duration;
use alloc::format;
use log::info;
use crate::{
process::ExecutionContext, scheduler::scheduler, set_csr, vga::{Color, FONT_WIDTH, Vga, WIDTH}
};
pub const IRQ_M_TIMER: u8 = 1 << 7;
pub const IRQ_S_TIMER: u8 = 1 << 5;
const CLINT_TIMER_CMP: *mut u64 = 0x02004000 as *mut u64;
const CLINT_TIMER: *const u64 = 0x0200bff8 as *const u64;
const TIMER_FREQUENCY: u64 = 10000000; // 10MHz
const INTERRUPT_FREQUENCY: u64 = 20; // 20Hz
static mut START_TIME: Instant = Instant(0);
pub fn setup_timer_interrupt() {
unsafe { START_TIME = Instant::now() };
set_csr!(sie, IRQ_S_TIMER);
setup_next_timer_interrupt();
}
pub fn setup_next_timer_interrupt() {
unsafe {
core::ptr::write_volatile(
CLINT_TIMER_CMP,
Instant::now().0 + TIMER_FREQUENCY / INTERRUPT_FREQUENCY,
);
}
}
pub fn timer_interrupt(interrupt_state: ExecutionContext) -> usize {
let current_time = elapsed_time_since_startup();
let seconds = current_time.as_secs();
let minutes = seconds / 60 % 60;
let hours = seconds / 3600 % 60;
let seconds = seconds % 60;
let formated_time = format!("{:02}:{:02}:{:02}", hours, minutes, seconds);
unsafe {
Vga::draw_string(
(WIDTH - formated_time.len() * FONT_WIDTH) as u16,
0,
formated_time,
Color::WHITE,
Color::BLACK,
)
};
scheduler(interrupt_state)
}
pub fn elapsed_time_since_startup() -> Duration {
unsafe { START_TIME.elapsed() }
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Instant(u64);
impl Instant {
pub fn now() -> Self {
Instant(unsafe { core::ptr::read_volatile(CLINT_TIMER) })
}
pub fn elapsed(&self) -> Duration {
let now = Self::now();
Duration::from_nanos((now.0 - self.0) * (1_000_000_000 / TIMER_FREQUENCY))
}
}