use crate::{register::Register, sync::Flag};
use bit_field::BitField;
use core::sync::atomic::Ordering;
#[repr(C)]
struct SysTickRegs {
ctrl: Register<u32>,
load: Register<u32>,
val: Register<u32>,
calib: Register<u32>,
}
pub struct SysTick {
regs: &'static mut SysTickRegs,
}
static SYSTICK_LOCK: Flag = Flag::new(false);
impl SysTick {
pub fn get() -> Option<Self> {
unsafe {
if SYSTICK_LOCK.swap(true, Ordering::AcqRel) {
None
} else {
Some(Self {
regs: &mut *(0xE000E010 as *mut _),
})
}
}
}
pub fn set_reload_value(&mut self, value: u32) {
self.regs.load.write(value);
}
pub fn set_current_value(&mut self, value: u32) {
self.regs.val.write(value);
}
pub fn enable(&mut self, enabled: bool) {
self.regs.ctrl.update(|ctrl| {
ctrl.set_bit(0, enabled);
});
}
pub fn enable_interrupt(&mut self, enabled: bool) {
self.regs.ctrl.update(|ctrl| {
ctrl.set_bit(1, enabled);
});
}
pub fn use_core_clock(&mut self, core: bool) {
self.regs.ctrl.update(|ctrl| {
ctrl.set_bit(2, core);
});
}
}
impl Drop for SysTick {
fn drop(&mut self) {
SYSTICK_LOCK.store(false, Ordering::Release);
}
}