use crate::{sync::Value, task::WakerSet};
use core::{
future::{poll_fn, Future},
sync::atomic::Ordering,
task::Poll,
};
pub fn millis() -> usize {
MILLIS.load(Ordering::Relaxed)
}
pub fn sleep_millis(mut duration: usize) -> impl Future<Output = ()> {
let mut start = millis();
poll_fn(move |ctx| {
let current = millis();
let elapsed = current.wrapping_sub(start);
if elapsed >= duration {
Poll::Ready(())
} else {
duration -= elapsed;
start = current;
TIMER_WAKERS.add(ctx.waker().clone());
Poll::Pending
}
})
}
static MILLIS: Value = Value::new(0);
static FRACT: Value = Value::new(0);
static TIMER_WAKERS: WakerSet = WakerSet::new();
pub extern "C" fn timer_intr() {
#[cfg(mcu = "fe310g002")]
unsafe {
const MTIMELO: *mut u32 = 0x0200_BFF8 as _;
asm!("amoadd.w {}, {}, ({})", out(reg) _, in(reg) -33, in(reg) MTIMELO);
}
let mut millis = MILLIS.load(Ordering::Relaxed);
millis = millis.wrapping_add(1);
let mut fract = FRACT.load(Ordering::Relaxed);
fract += 33000 - 32768;
if fract >= 1000 {
millis = millis.wrapping_add(1);
fract -= 1000;
}
FRACT.store(fract, Ordering::Relaxed);
MILLIS.store(millis, Ordering::Relaxed);
TIMER_WAKERS.wake();
}