Skip to content

Commit

Permalink
Refactor module
Browse files Browse the repository at this point in the history
  • Loading branch information
vinc committed Oct 21, 2024
1 parent 1e20614 commit c0e5b53
Show file tree
Hide file tree
Showing 10 changed files with 60 additions and 50 deletions.
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn init(boot_info: &'static BootInfo) {
sys::ata::init();
sys::fs::init(); // Require ATA

sys::clk::log_rtc(); // Require MEM
log!("RTC {}", sys::clk::date());
}

#[allow(dead_code)]
Expand Down
8 changes: 6 additions & 2 deletions src/sys/clk/boot.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use super::timer;

use crate::api::fs::{FileIO, IO};

#[derive(Debug, Clone)]
Expand Down Expand Up @@ -39,9 +41,11 @@ impl FileIO for BootTime {
}
}

// NOTE: This clock is monotonic
/// Returns the number of seconds since boot.
///
/// This clock is monotonic.
pub fn boot_time() -> f64 {
super::time_between_ticks() * super::ticks() as f64
timer::time_between_ticks() * timer::ticks() as f64
}

#[test_case]
Expand Down
9 changes: 6 additions & 3 deletions src/sys/clk/cmos.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Interrupt, RTC, Register, RTC_CENTURY};
use super::rtc::{Interrupt, RTC, Register, RTC_CENTURY};

use bit_field::BitField;
use core::hint::spin_loop;
Expand Down Expand Up @@ -107,10 +107,12 @@ impl CMOS {
self.write_register(Register::Year, year as u8);
}

#[allow(dead_code)]
pub fn enable_periodic_interrupt(&mut self) {
self.enable_interrupt(Interrupt::Periodic);
}

#[allow(dead_code)]
pub fn enable_alarm_interrupt(&mut self) {
self.enable_interrupt(Interrupt::Alarm);
}
Expand All @@ -119,8 +121,9 @@ impl CMOS {
self.enable_interrupt(Interrupt::Update);
}

/// Rate must be between 3 and 15
/// Resulting in the following frequency: 32768 >> (rate - 1)
// Rate must be between 3 and 15
// Resulting in the following frequency: 32768 >> (rate - 1)
#[allow(dead_code)]
pub fn set_periodic_interrupt_rate(&mut self, rate: u8) {
interrupts::without_interrupts(|| {
self.disable_nmi();
Expand Down
11 changes: 7 additions & 4 deletions src/sys/clk/epoch.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::CMOS;
use super::cmos::CMOS;
use super::timer;

use crate::api::fs::{FileIO, IO};

Expand Down Expand Up @@ -45,7 +46,9 @@ impl FileIO for EpochTime {
}
}

// NOTE: This clock is not monotonic
/// Returns the number of seconds since Unix epoch (1970-01-01 00:00:00 UTC).
///
/// This clock is not monotonic.
pub fn epoch_time() -> f64 {
let rtc = CMOS::new().rtc(); // Assuming GMT

Expand All @@ -56,8 +59,8 @@ pub fn epoch_time() -> f64 {
+ 60 * rtc.minute as u64
+ rtc.second as u64;

let fract = super::time_between_ticks()
* (super::ticks() - super::last_rtc_update()) as f64;
let fract = timer::time_between_ticks()
* (timer::ticks() - timer::last_rtc_update()) as f64;

(ts as f64) + fract
}
Expand Down
24 changes: 9 additions & 15 deletions src/sys/clk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,33 +5,27 @@ mod rtc;
mod sleep;
mod timer;

pub use boot::{boot_time, BootTime}; // TODO: Rename to boot_time
pub use epoch::{epoch_time, EpochTime}; // TODO: Rename to epoch_time
pub use cmos::CMOS;
pub use boot::{boot_time, BootTime};
pub use epoch::{epoch_time, EpochTime};
pub use rtc::RTC;
pub use sleep::{sleep, nanowait, halt};
pub use timer::{
ticks, time_between_ticks, pit_frequency, set_pit_frequency_divider,
last_rtc_update
};
pub use timer::{ticks, pit_frequency, set_pit_frequency};

use rtc::{Interrupt, Register, RTC_CENTURY};
use timer::{rdtsc, CLOCKS_PER_NANOSECOND};

use crate::api::clock::DATE_TIME_ZONE;
use crate::api;

use alloc::string::String;
use time::{Duration, OffsetDateTime};

pub fn init() {
timer::init();
}

pub fn log_rtc() {
let s = epoch_time();
/// Returns the current date and time.
pub fn date() -> String {
let s = epoch::epoch_time();
let ns = Duration::nanoseconds(
libm::floor(1e9 * (s - libm::floor(s))) as i64
);
let dt = OffsetDateTime::from_unix_timestamp(s as i64) + ns;
let rtc = dt.format(DATE_TIME_ZONE);
log!("RTC {}", rtc);
dt.format(api::clock::DATE_TIME_ZONE)
}
5 changes: 2 additions & 3 deletions src/sys/clk/rtc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use super::CMOS;
use super::cmos::CMOS;

use crate::sys;
use crate::api::clock::{DATE_TIME, DATE_TIME_LEN};
use crate::api::fs::{FileIO, IO};

Expand Down Expand Up @@ -84,7 +83,7 @@ impl FileIO for RTC {
return Err(());
}
CMOS::new().update_rtc(self);
sys::clk::log_rtc();
log!("RTC {}", super::date());
Ok(buf.len())
}

Expand Down
16 changes: 8 additions & 8 deletions src/sys/clk/sleep.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::sys;
use super::boot;
use super::timer;

use core::sync::atomic::Ordering;
use x86_64::instructions::interrupts;

pub fn halt() {
Expand All @@ -12,17 +12,17 @@ pub fn halt() {
}

pub fn sleep(seconds: f64) {
let start = sys::clk::boot_time();
while sys::clk::boot_time() - start < seconds {
let start = boot::boot_time();
while boot::boot_time() - start < seconds {
halt();
}
}

pub fn nanowait(nanoseconds: u64) {
let start = super::rdtsc();
let clock = super::CLOCKS_PER_NANOSECOND.load(Ordering::Relaxed);
let delta = nanoseconds * clock;
while super::rdtsc() - start < delta {
let start = timer::tsc();
let freq = timer::tsc_frequency();
let delta = nanoseconds * freq;
while timer::tsc() - start < delta {
core::hint::spin_loop();
}
}
31 changes: 19 additions & 12 deletions src/sys/clk/timer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use super::sleep;
use super::cmos::CMOS;

use crate::sys;
use crate::sys::clk::CMOS;

use core::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use x86_64::instructions::interrupts;
use x86_64::instructions::port::Port;
Expand All @@ -8,13 +11,13 @@ use x86_64::instructions::port::Port;
// which will result in about 54.926 ms between ticks.
// During init we will change the divider to 1193 to have about 1.000 ms
// between ticks to improve time measurements accuracy.
pub const PIT_FREQUENCY: f64 = 3_579_545.0 / 3.0; // 1_193_181.666 Hz
const PIT_FREQUENCY: f64 = 3_579_545.0 / 3.0; // 1_193_181.666 Hz
const PIT_DIVIDER: usize = 1193;
const PIT_INTERVAL: f64 = (PIT_DIVIDER as f64) / PIT_FREQUENCY;

static PIT_TICKS: AtomicUsize = AtomicUsize::new(0);
static LAST_RTC_UPDATE: AtomicUsize = AtomicUsize::new(0);
pub static CLOCKS_PER_NANOSECOND: AtomicU64 = AtomicU64::new(0);
static TSC_FREQUENCY: AtomicU64 = AtomicU64::new(0);

pub fn ticks() -> usize {
PIT_TICKS.load(Ordering::Relaxed)
Expand All @@ -32,8 +35,8 @@ pub fn pit_frequency() -> f64 {
PIT_FREQUENCY
}

/// The frequency divider must be between 0 and 65535, with 0 acting as 65536
pub fn set_pit_frequency_divider(divider: u16, channel: u8) {
// The frequency divider must be between 0 and 65535, with 0 acting as 65536
pub fn set_pit_frequency(divider: u16, channel: u8) {
interrupts::without_interrupts(|| {
let bytes = divider.to_le_bytes();
let mut cmd: Port<u8> = Port::new(0x43);
Expand All @@ -48,14 +51,18 @@ pub fn set_pit_frequency_divider(divider: u16, channel: u8) {
});
}

// Read Time Stamp Counter
pub fn rdtsc() -> u64 {
// Time Stamp Counter
pub fn tsc() -> u64 {
unsafe {
core::arch::x86_64::_mm_lfence();
core::arch::x86_64::_rdtsc()
}
}

pub fn tsc_frequency() -> u64 {
TSC_FREQUENCY.load(Ordering::Relaxed)
}

pub fn pit_interrupt_handler() {
PIT_TICKS.fetch_add(1, Ordering::Relaxed);
}
Expand All @@ -69,7 +76,7 @@ pub fn init() {
// PIT timmer
let divider = if PIT_DIVIDER < 65536 { PIT_DIVIDER } else { 0 };
let channel = 0;
set_pit_frequency_divider(divider as u16, channel);
set_pit_frequency(divider as u16, channel);
sys::idt::set_irq_handler(0, pit_interrupt_handler);

// RTC timmer
Expand All @@ -78,8 +85,8 @@ pub fn init() {

// TSC timmer
let calibration_time = 250_000; // 0.25 seconds
let a = rdtsc();
super::sleep(calibration_time as f64 / 1e6);
let b = rdtsc();
CLOCKS_PER_NANOSECOND.store((b - a) / calibration_time, Ordering::Relaxed);
let a = tsc();
sleep::sleep(calibration_time as f64 / 1e6);
let b = tsc();
TSC_FREQUENCY.store((b - a) / calibration_time, Ordering::Relaxed);
}
2 changes: 1 addition & 1 deletion src/sys/serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ impl fmt::Write for Serial {
}
}

/// See https://vt100.net/emu/dec_ansi_parser
// Source: https://vt100.net/emu/dec_ansi_parser
impl Perform for Serial {
fn csi_dispatch(&mut self, params: &Params, _: &[u8], _: bool, c: char) {
match c {
Expand Down
2 changes: 1 addition & 1 deletion src/usr/beep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const SPEAKER_PORT: u16 = 0x61;
fn start_sound(freq: f64) {
let divider = (sys::clk::pit_frequency() / freq) as u16;
let channel = 2;
sys::clk::set_pit_frequency_divider(divider, channel);
sys::clk::set_pit_frequency(divider, channel);

let mut speaker: Port<u8> = Port::new(SPEAKER_PORT);
let tmp = unsafe { speaker.read() };
Expand Down

0 comments on commit c0e5b53

Please sign in to comment.