2017-01-02 01:23:27 +08:00
|
|
|
use csr;
|
2016-09-30 04:36:04 +08:00
|
|
|
|
|
|
|
const INIT: u64 = ::core::i64::MAX as u64;
|
2016-12-16 21:28:25 +08:00
|
|
|
const FREQ: u64 = csr::CONFIG_CLOCK_FREQUENCY as u64;
|
2016-09-30 04:36:04 +08:00
|
|
|
|
|
|
|
pub fn init() {
|
|
|
|
unsafe {
|
2016-10-01 15:56:34 +08:00
|
|
|
csr::timer0::en_write(0);
|
|
|
|
csr::timer0::load_write(INIT);
|
|
|
|
csr::timer0::reload_write(INIT);
|
|
|
|
csr::timer0::en_write(1);
|
2016-09-30 04:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 02:28:29 +08:00
|
|
|
pub fn get_us() -> u64 {
|
|
|
|
unsafe {
|
|
|
|
csr::timer0::update_value_write(1);
|
|
|
|
(INIT - csr::timer0::value_read()) / (FREQ / 1_000_000)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-09-30 04:36:04 +08:00
|
|
|
pub fn get_ms() -> u64 {
|
|
|
|
unsafe {
|
2016-10-01 15:56:34 +08:00
|
|
|
csr::timer0::update_value_write(1);
|
|
|
|
(INIT - csr::timer0::value_read()) / (FREQ / 1_000)
|
2016-09-30 04:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn spin_us(interval: u64) {
|
|
|
|
unsafe {
|
2016-10-01 15:56:34 +08:00
|
|
|
csr::timer0::update_value_write(1);
|
|
|
|
let threshold = csr::timer0::value_read() - interval * (FREQ / 1_000_000);
|
|
|
|
while csr::timer0::value_read() > threshold {
|
|
|
|
csr::timer0::update_value_write(1)
|
2016-09-30 04:36:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
struct Watchdog {
|
|
|
|
active: bool,
|
|
|
|
threshold: u64
|
|
|
|
}
|
|
|
|
|
|
|
|
pub const MAX_WATCHDOGS: usize = 16;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct WatchdogSet {
|
|
|
|
watchdogs: [Watchdog; MAX_WATCHDOGS]
|
|
|
|
}
|
|
|
|
|
|
|
|
impl WatchdogSet {
|
|
|
|
pub fn new() -> WatchdogSet {
|
|
|
|
WatchdogSet {
|
|
|
|
watchdogs: [Watchdog { active: false, threshold: 0 }; MAX_WATCHDOGS]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_ms(&mut self, interval: u64) -> Result<usize, ()> {
|
|
|
|
for (index, watchdog) in self.watchdogs.iter_mut().enumerate() {
|
|
|
|
if !watchdog.active {
|
|
|
|
watchdog.active = true;
|
|
|
|
watchdog.threshold = get_ms() + interval;
|
|
|
|
return Ok(index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear(&mut self, index: usize) {
|
|
|
|
if index < MAX_WATCHDOGS {
|
|
|
|
self.watchdogs[index].active = false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn expired(&self) -> bool {
|
|
|
|
self.watchdogs.iter()
|
|
|
|
.filter(|wd| wd.active)
|
|
|
|
.min_by_key(|wd| wd.threshold)
|
|
|
|
.map_or(false, |wd| get_ms() > wd.threshold)
|
|
|
|
}
|
|
|
|
}
|