ionpak-thermostat/firmware/src/board/systick.rs

44 lines
1.3 KiB
Rust
Raw Normal View History

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));
/// In HZ
const RATE: u32 = 10;
2019-09-08 08:43:01 +08:00
/// Period between two interrupts in ns
const INTERVAL: u64 = 1_000_000 / RATE as u64;
2019-09-08 07:54:51 +08:00
fn syst() -> &'static mut SYST {
2019-09-08 07:54:51 +08:00
#[allow(mutable_transmutes)]
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);
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| {
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 {
let base = cortex_m::interrupt::free(|cs| {
2019-09-08 08:13:02 +08:00
*unsafe { &mut TIME }.borrow(cs).borrow()
});
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
}