Supervisor mode
This commit is contained in:
66
src/time.rs
Normal file
66
src/time.rs
Normal file
@@ -0,0 +1,66 @@
|
||||
use core::time::Duration;
|
||||
|
||||
use alloc::format;
|
||||
|
||||
use crate::{
|
||||
set_csr,
|
||||
vga::{Color, Vga, FONT_WIDTH, 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() {
|
||||
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,
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user