From c0e5b53a3b2bab397f49b4813e76c36347adc30d Mon Sep 17 00:00:00 2001 From: Vincent Ollivier Date: Mon, 21 Oct 2024 11:23:13 +0200 Subject: [PATCH] Refactor module --- src/lib.rs | 2 +- src/sys/clk/boot.rs | 8 ++++++-- src/sys/clk/cmos.rs | 9 ++++++--- src/sys/clk/epoch.rs | 11 +++++++---- src/sys/clk/mod.rs | 24 +++++++++--------------- src/sys/clk/rtc.rs | 5 ++--- src/sys/clk/sleep.rs | 16 ++++++++-------- src/sys/clk/timer.rs | 31 +++++++++++++++++++------------ src/sys/serial.rs | 2 +- src/usr/beep.rs | 2 +- 10 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d0123b31..b76c3a64 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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)] diff --git a/src/sys/clk/boot.rs b/src/sys/clk/boot.rs index ab2c52ab..ff633d30 100644 --- a/src/sys/clk/boot.rs +++ b/src/sys/clk/boot.rs @@ -1,3 +1,5 @@ +use super::timer; + use crate::api::fs::{FileIO, IO}; #[derive(Debug, Clone)] @@ -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] diff --git a/src/sys/clk/cmos.rs b/src/sys/clk/cmos.rs index fcd5d551..624bb0c6 100644 --- a/src/sys/clk/cmos.rs +++ b/src/sys/clk/cmos.rs @@ -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; @@ -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); } @@ -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(); diff --git a/src/sys/clk/epoch.rs b/src/sys/clk/epoch.rs index c0798591..7512b444 100644 --- a/src/sys/clk/epoch.rs +++ b/src/sys/clk/epoch.rs @@ -1,4 +1,5 @@ -use super::CMOS; +use super::cmos::CMOS; +use super::timer; use crate::api::fs::{FileIO, IO}; @@ -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 @@ -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 } diff --git a/src/sys/clk/mod.rs b/src/sys/clk/mod.rs index 827b9a60..8993d681 100644 --- a/src/sys/clk/mod.rs +++ b/src/sys/clk/mod.rs @@ -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) } diff --git a/src/sys/clk/rtc.rs b/src/sys/clk/rtc.rs index eb30dbe6..511ccefc 100644 --- a/src/sys/clk/rtc.rs +++ b/src/sys/clk/rtc.rs @@ -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}; @@ -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()) } diff --git a/src/sys/clk/sleep.rs b/src/sys/clk/sleep.rs index 86b708ad..f76af0e2 100644 --- a/src/sys/clk/sleep.rs +++ b/src/sys/clk/sleep.rs @@ -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() { @@ -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(); } } diff --git a/src/sys/clk/timer.rs b/src/sys/clk/timer.rs index d0fd2b10..6db40185 100644 --- a/src/sys/clk/timer.rs +++ b/src/sys/clk/timer.rs @@ -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; @@ -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) @@ -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 = Port::new(0x43); @@ -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); } @@ -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 @@ -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); } diff --git a/src/sys/serial.rs b/src/sys/serial.rs index 184b5b3b..8ea0a443 100644 --- a/src/sys/serial.rs +++ b/src/sys/serial.rs @@ -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 { diff --git a/src/usr/beep.rs b/src/usr/beep.rs index 4fe8d256..fd049d87 100644 --- a/src/usr/beep.rs +++ b/src/usr/beep.rs @@ -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 = Port::new(SPEAKER_PORT); let tmp = unsafe { speaker.read() };