Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

all platforms: update Mycelium dependencies #343

Merged
merged 14 commits into from
Dec 27, 2024
33 changes: 22 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

43 changes: 25 additions & 18 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,22 @@ default-members = [
# this isn't actually a crate
exclude = ["source/notes"]

### workspace dependencies ###

[workspace.package]
edition = "2021"
repository = "https://github.com/tosc-rs/mnemos"
homepage = "https://mnemos.dev"
license = "MIT OR Apache-2.0"

[workspace.dependencies]
cordyceps = { version = "0.3", default-features = false }
hal-core = { version = "0.1.0" }
maitake = { version = "0.1.0", default-features = false }
miette = "7.2"
mycelium-alloc = { version = "0.1.0", features = ["buddy", "bump"] }
mycelium-bitfield = { version = "0.1.5" }
mycelium-util = { version = "0.1.0" }

### profile settings ###

Expand Down Expand Up @@ -150,13 +158,12 @@ debug = "line-tables-only"
### patches ###

[patch.crates-io.maitake]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"

[patch.crates-io.mycelium-util]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"

[patch.crates-io.mycelium-alloc]
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"
# Use the `mycelium-bitfield` crate from the Mycelium monorepo rather than
# crates.io.
# NOTE: this patch, unlike the patches for `maitake` and `mycelium-util`, (which
Expand All @@ -165,24 +172,24 @@ rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"
# since it's already in our dependency tree as a transitive dep of `maitake` ---
# having both a Git dep and a crates.io dep seems unfortunate.
[patch.crates-io.mycelium-bitfield]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"

[patch.crates-io.mycelium-util]
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"

[patch.crates-io.cordyceps]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"

[patch.crates-io.hal-core]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"

[patch.crates-io.hal-x86_64]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"

[patch.crates-io.mycelium-alloc]
git = "https://github.com/hawkw/mycelium.git"
rev = "13d0722429ef201f38e4ea47ea22d88f3f72c10e"
git = "https://github.com/hawkw/mycelium"
rev = "ba56bb4d02f46fb59754b7b88bddc2e8ca99c1f5"

[patch.crates-io.bbq10kbd]
git = "https://github.com/hawkw/bbq10kbd"
Expand Down
1 change: 0 additions & 1 deletion platforms/allwinner-d1/board-configs/lichee-rv.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
[kernel]
max_drivers = 16
timer_granularity = { secs = 0, nanos = 333 }

[services.spawnulator]
enabled = true
Expand Down
79 changes: 79 additions & 0 deletions platforms/allwinner-d1/d1-core/src/timer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,92 @@
use crate::plic::{Plic, Priority};
use core::sync::atomic::{AtomicU32, Ordering};
pub use d1_pac::timer::tmr_ctrl::{
TMR_CLK_PRES_A as TimerPrescaler, TMR_CLK_SRC_A as TimerSource, TMR_MODE_A as TimerMode,
};
use d1_pac::TIMER;
use kernel::maitake::time::Clock;

pub struct Timers {
pub timer0: Timer0,
pub timer1: Timer1,
}

static TIMER0_ROLLOVERS: AtomicU32 = AtomicU32::new(0);

impl Timer0 {
const INITIAL_VALUE: u32 = u32::MAX;

pub fn into_maitake_clock(mut self, plic: &Plic) -> Clock {
use d1_pac::Interrupt;
self.set_prescaler(TimerPrescaler::P8); // 24M / 8: 3.00M ticks/s
self.set_mode(TimerMode::PERIODIC);
Comment on lines +21 to +22
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same prescaler and mode configuration we set in the older code, so that's presumably not the problem...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UPDATE: indeed it was not! #343 (comment)


// Clear any previous interrupt flag.
let _ = self.get_and_clear_interrupt();

// Register the interrupt handler for when the timer rolls over.
unsafe {
plic.register(Interrupt::TIMER0, Self::maitake_timer_interrupt);
plic.activate(Interrupt::TIMER0, Priority::P1).unwrap();
}

// Start the timer counting down from u32::MAX;.
self.reset();

Clock::new(core::time::Duration::from_nanos(333), || {
let timer0 = unsafe {
// Safety: we are just reading the current value and will not be
// concurrently mutating the timer.
Self::steal()
};
// Since timer 0 is counting *down*, we have to subtract its current
// value from the intial value to get an i[ncreasing timestamp for
// Maitake. As timer 0 is a 32-bit timer, this forms the lower half
// of our 64-bit timestamp.
let lo = (Self::INITIAL_VALUE - timer0.current_value()) as u64;
// The higher half of the 64-bit timestamp is the current value of
// the 32-bit timer rollover counter --- i.e. the number of times
// that timer 0 has counted down to 0.
let hi = TIMER0_ROLLOVERS.load(Ordering::Relaxed) as u64;
// Combine the two halves to form the full 64-bit timestamp.
(hi << 32) | lo
})
.named("CLOCK_D1_TIMER0")
}

fn reset(&mut self) {
self.start_counter(Self::INITIAL_VALUE);
// N.B. that we probably don't *have* to reset the IRQ_EN bit every time
// it fires, but let's make sure it's enabled just in case...
self.set_interrupt_en(true);
}

/// Handle a TIMER0 interrupt when TIMER0 is used as the maitake timer.
fn maitake_timer_interrupt() {
let mut timer0 = unsafe {
// Safety: we need to do this to be an ISR lol
Self::steal()
};

// Clear the interrupt flag
let _ = timer0.get_and_clear_interrupt();

// Increment the rollover counter
TIMER0_ROLLOVERS.fetch_add(1, Ordering::Relaxed);

// Wait for the interrupt to clear to avoid repeat interrupts
let timers = unsafe { &*TIMER::PTR };
while timers.tmr_irq_sta.read().tmr0_irq_pend().bit_is_set() {}

// RESET THE CLOCK!
timer0.reset();
}

unsafe fn steal() -> Self {
Self { _x: () }
}
}

mod sealed {
use d1_pac::{
generic::Reg,
Expand Down
36 changes: 11 additions & 25 deletions platforms/allwinner-d1/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ pub fn kernel_entry(config: mnemos_config::MnemosConfig<PlatformConfig>) -> ! {

pub struct D1 {
pub kernel: &'static Kernel,
pub timers: Timers,
pub timer1: mnemos_d1_core::timer::Timer1,
pub plic: Plic,
pub dmac: Dmac,
_uart: Uart,
Expand Down Expand Up @@ -192,10 +192,13 @@ impl D1 {
kernel_settings: KernelSettings,
service_settings: KernelServiceSettings,
) -> Self {
let timer0_clock = timers.timer0.into_maitake_clock(&plic);
let k = unsafe {
Box::into_raw(Kernel::new(kernel_settings).expect("cannot initialize kernel"))
.as_ref()
.unwrap()
Box::into_raw(
Kernel::new(kernel_settings, timer0_clock).expect("cannot initialize kernel"),
)
.as_ref()
.unwrap()
};

k.initialize_default_services(service_settings);
Expand Down Expand Up @@ -240,7 +243,7 @@ impl D1 {
kernel: k,
_uart: uart,
_spim: spim,
timers,
timer1: timers.timer1,
plic,
dmac,
i2c0_int,
Expand Down Expand Up @@ -293,7 +296,7 @@ impl D1 {
pub fn run(self) -> ! {
let Self {
kernel: k,
timers,
mut timer1,
plic,
dmac: _,
_uart,
Expand All @@ -308,19 +311,9 @@ impl D1 {
//
// In the future, we probably want to rework this to use the RTC timer for
// both purposes, as this will likely play better with sleep power usage.
let Timers {
mut timer0,
mut timer1,
} = timers;

// NOTE: if you change the timer frequency, make sure you update
// initialize_kernel() below to correct the kernel timer wheel
// granularity setting!
timer0.set_prescaler(TimerPrescaler::P8); // 24M / 8: 3.00M ticks/s
timer1.set_prescaler(TimerPrescaler::P8);
timer0.set_mode(TimerMode::PERIODIC);
timer1.set_mode(TimerMode::SINGLE_COUNTING);
let _ = timer0.get_and_clear_interrupt();
let _ = timer1.get_and_clear_interrupt();

unsafe {
Expand All @@ -344,22 +337,16 @@ impl D1 {
}
}

timer0.start_counter(0xFFFF_FFFF);
hawkw marked this conversation as resolved.
Show resolved Hide resolved

loop {
// Tick the scheduler
let start = timer0.current_value();
let tick = k.tick();

// Timer is downcounting
let elapsed = start.wrapping_sub(timer0.current_value());
let turn = k.timer().force_advance_ticks(elapsed.into());
let turn = k.timer().turn();

// If there is nothing else scheduled, and we didn't just wake something up,
// sleep for some amount of time
if turn.expired == 0 && !tick.has_remaining {
let wfi_start = timer0.current_value();

// TODO(AJM): Sometimes there is no "next" in the timer wheel, even though there should
// be. Don't take lack of timer wheel presence as the ONLY heuristic of whether we
// should just wait for SOME interrupt to occur. For now, force a max sleep of 100ms
Expand All @@ -384,8 +371,7 @@ impl D1 {
timer1.stop();

// Account for time slept
let elapsed = wfi_start.wrapping_sub(timer0.current_value());
let _turn = k.timer().force_advance_ticks(elapsed.into());
let _turn = k.timer().turn();
}
}
}
Expand Down
Loading
Loading