use core::sync::atomic::{AtomicU32, Ordering};
static CHECKIN_TIMEOUT_US: AtomicU32 = AtomicU32::new(0);
pub fn init(period: crate::time::Duration) {
crate::port::board::wdt_init(period.as_micros() as u32);
}
pub fn feed() {
crate::port::board::wdt_feed();
}
pub fn on_tick() {
crate::port::board::wdt_check();
check_task_checkins();
}
pub fn checkin() {
if CHECKIN_TIMEOUT_US.load(Ordering::Acquire) == 0 {
return;
}
if let Some(id) = crate::preempt::sched::current() {
if let Some(t) = crate::preempt::tcb::get(id) {
t.last_checkin
.store(crate::port::board::now_us() as u32, Ordering::Release);
}
}
}
pub fn enable_checkins(timeout: crate::time::Duration) {
CHECKIN_TIMEOUT_US.store(timeout.as_micros() as u32, Ordering::Release);
}
fn check_task_checkins() {
let timeout = CHECKIN_TIMEOUT_US.load(Ordering::Acquire);
if timeout == 0 {
return;
}
let now = crate::port::board::now_us() as u32;
for (id, t) in crate::preempt::tcb::TASKS.iter().enumerate() {
if !t.used.load(Ordering::Acquire) {
continue;
}
let last = t.last_checkin.load(Ordering::Acquire);
if last != 0 && now.wrapping_sub(last) > timeout {
crate::console::write_str("RIVET TASK CHECKIN TIMEOUT task=");
print_dec(id);
crate::console::write_str("\n");
crate::port::board::reset();
}
}
}
fn print_dec(mut n: usize) {
if n == 0 {
crate::console::write_str("0");
return;
}
let mut digits = [0u8; 10];
let mut i = 0;
while n > 0 {
digits[i] = b'0' + (n % 10) as u8;
n /= 10;
i += 1;
}
let mut out = [0u8; 10];
for j in 0..i {
out[j] = digits[i - 1 - j];
}
if let Ok(s) = core::str::from_utf8(&out[..i]) {
crate::console::write_str(s);
}
}
#[cfg(feature = "test-support")]
pub(crate) fn reset_for_test() {
CHECKIN_TIMEOUT_US.store(0, Ordering::Release);
}