#![no_std]
use cortex_m::peripheral::{DCB, DWT};
use cortex_m::interrupt::{self, Mutex};
use core::{cell::RefCell, ops::DerefMut};
use cortex_m::asm;
pub type Instant<const TIMER_HZ: u32> = fugit::TimerInstantU64<TIMER_HZ>;
pub type Duration<const TIMER_HZ: u32> = fugit::TimerDurationU64<TIMER_HZ>;
static DWT:Mutex<RefCell<Option<DWT>>> =
Mutex::new(RefCell::new(None));
static PREVIOUS_CYCCNT_VAL : Mutex<RefCell<usize>> = Mutex::new(RefCell::new(0));
static NB_CYCCNT_CYCLES : Mutex<RefCell<u32>> = Mutex::new(RefCell::new(0));
pub struct CYCCNTClock<const SYSCLK_HZ: u32>{
}
impl <const SYSCLK_HZ :u32 > CYCCNTClock<SYSCLK_HZ>{
const MAX_CYCCNT_VAL: u32 = core::u32::MAX;
pub fn now() -> Instant<SYSCLK_HZ> {
interrupt::free( |cs|{
Self::update();
let nb_cyccnt_cycles : u32 = *NB_CYCCNT_CYCLES.borrow(cs).borrow();
if let Some(ref mut dwt) = DWT.borrow(cs).borrow_mut().deref_mut().as_mut(){
let acc_cyccnt_val : u64 = (nb_cyccnt_cycles as u64) *(Self::MAX_CYCCNT_VAL as u64 +1) + (dwt.cyccnt.read() as u64);
Instant::from_ticks(acc_cyccnt_val)
}
else{
panic!("Counter not initialized");
}
})
}
pub fn delay(duration: Duration<SYSCLK_HZ>) {
let instant_init = Self::now();
while (Self::now() - instant_init) < duration{
asm::nop();
}
}
pub fn update(){
interrupt::free( |cs|{
if let Some(ref mut dwt) = DWT.borrow(cs).borrow_mut().deref_mut().as_mut(){
let cyccnt_val = dwt.cyccnt.read();
let mut previous_cyccnt_val = PREVIOUS_CYCCNT_VAL.borrow(cs).borrow_mut();
if *previous_cyccnt_val as u32 > cyccnt_val {
NB_CYCCNT_CYCLES.borrow(cs).replace_with(|&mut old| old +1);
}
*previous_cyccnt_val = cyccnt_val as usize;
}
});
}
pub fn init(dcb: &mut DCB, mut dwt : DWT){
interrupt::free( |cs|{
assert!(DWT::has_cycle_counter());
dcb.enable_trace();
DWT::unlock();
dwt.enable_cycle_counter();
dwt.set_cycle_count(0);
DWT.borrow(cs).borrow_mut().replace(dwt);
});
}
}