2019-09-08 08:13:02 +08:00
|
|
|
use core::cell::RefCell;
|
|
|
|
use cortex_m::interrupt::Mutex;
|
2019-09-08 07:54:51 +08:00
|
|
|
use cortex_m::peripheral::{SYST, syst::SystClkSource};
|
2019-09-08 08:13:02 +08:00
|
|
|
use cortex_m_rt::exception;
|
|
|
|
use bare_metal::CriticalSection;
|
2019-09-08 07:54:51 +08:00
|
|
|
|
2019-09-08 08:13:02 +08:00
|
|
|
static mut TIME: Mutex<RefCell<u64>> = Mutex::new(RefCell::new(0));
|
2019-09-08 08:34:59 +08:00
|
|
|
/// In HZ
|
|
|
|
const RATE: u32 = 10;
|
2019-09-08 08:43:01 +08:00
|
|
|
/// Period between two interrupts in ns
|
2019-09-08 08:34:59 +08:00
|
|
|
const INTERVAL: u64 = 1_000_000 / RATE as u64;
|
2019-09-08 07:54:51 +08:00
|
|
|
|
2019-09-08 08:34:59 +08:00
|
|
|
fn syst() -> &'static mut SYST {
|
2019-09-08 07:54:51 +08:00
|
|
|
#[allow(mutable_transmutes)]
|
2019-09-08 08:34:59 +08:00
|
|
|
unsafe { core::mem::transmute(&*SYST::ptr()) }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn init(_cs: &CriticalSection) {
|
|
|
|
let syst = syst();
|
|
|
|
// syst.set_clock_source(SystClkSource::Core);
|
2019-09-08 08:13:02 +08:00
|
|
|
syst.set_clock_source(SystClkSource::External);
|
2019-09-08 08:34:59 +08:00
|
|
|
syst.set_reload(100 * SYST::get_ticks_per_10ms() / RATE);
|
2019-09-08 07:54:51 +08:00
|
|
|
syst.clear_current();
|
|
|
|
syst.enable_interrupt();
|
|
|
|
syst.enable_counter();
|
|
|
|
}
|
|
|
|
|
|
|
|
#[exception]
|
|
|
|
unsafe fn SysTick() {
|
2019-09-08 08:13:02 +08:00
|
|
|
cortex_m::interrupt::free(|cs| {
|
2019-09-08 08:34:59 +08:00
|
|
|
TIME.borrow(cs).replace_with(|time| *time + INTERVAL);
|
2019-09-08 08:13:02 +08:00
|
|
|
});
|
2019-09-08 07:54:51 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_time() -> u64 {
|
2019-09-08 08:34:59 +08:00
|
|
|
let base = cortex_m::interrupt::free(|cs| {
|
2019-09-08 08:13:02 +08:00
|
|
|
*unsafe { &mut TIME }.borrow(cs).borrow()
|
2019-09-08 08:34:59 +08:00
|
|
|
});
|
|
|
|
let syst_current = u64::from(SYST::get_current());
|
|
|
|
let syst_reload = u64::from(SYST::get_reload());
|
|
|
|
let precise = INTERVAL - (INTERVAL * syst_current / syst_reload);
|
|
|
|
base + u64::from(precise)
|
2019-09-08 07:54:51 +08:00
|
|
|
}
|