systick: implement nanosecond precision

This commit is contained in:
Astro 2019-09-08 02:34:59 +02:00
parent 4249addba2
commit 25dc3fb70c
2 changed files with 21 additions and 12 deletions

View File

@ -4,15 +4,22 @@ use cortex_m::peripheral::{SYST, syst::SystClkSource};
use cortex_m_rt::exception;
use bare_metal::CriticalSection;
const SYSTICK_RATE: u32 = 250;
static mut TIME: Mutex<RefCell<u64>> = Mutex::new(RefCell::new(0));
/// In HZ
const RATE: u32 = 10;
/// Period between to interrupts in ns
const INTERVAL: u64 = 1_000_000 / RATE as u64;
pub fn init(cs: &CriticalSection) {
fn syst() -> &'static mut SYST {
#[allow(mutable_transmutes)]
let syst: &mut SYST = unsafe { core::mem::transmute(&*SYST::ptr()) };
unsafe { core::mem::transmute(&*SYST::ptr()) }
}
pub fn init(_cs: &CriticalSection) {
let syst = syst();
// syst.set_clock_source(SystClkSource::Core);
syst.set_clock_source(SystClkSource::External);
syst.set_reload(100 * SYST::get_ticks_per_10ms() / SYSTICK_RATE);
syst.set_reload(100 * SYST::get_ticks_per_10ms() / RATE);
syst.clear_current();
syst.enable_interrupt();
syst.enable_counter();
@ -20,14 +27,17 @@ pub fn init(cs: &CriticalSection) {
#[exception]
unsafe fn SysTick() {
let interval = u64::from(1000 / SYSTICK_RATE);
cortex_m::interrupt::free(|cs| {
TIME.borrow(cs).replace_with(|time| *time + interval);
TIME.borrow(cs).replace_with(|time| *time + INTERVAL);
});
}
pub fn get_time() -> u64 {
cortex_m::interrupt::free(|cs| {
let base = cortex_m::interrupt::free(|cs| {
*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)
}

View File

@ -181,7 +181,7 @@ fn main() -> ! {
// if a socket has sent the latest data
let mut socket_pending = [false; 8];
loop {
adc.data_ready()
let _ = adc.data_ready()
.and_then(|channel|
channel.map(|channel|
adc.read_data().map(|new_data| {
@ -199,7 +199,6 @@ fn main() -> ! {
for p in socket_pending.iter_mut() {
*p = true;
}
});
for (&tcp_handle, pending) in handles.iter().zip(socket_pending.iter_mut()) {
let socket = &mut *sockets.get::<TcpSocket>(tcp_handle);
@ -223,7 +222,7 @@ fn main() -> ! {
*pending = false;
}
}
match iface.poll(&mut sockets, Instant::from_millis(get_time() as i64)) {
match iface.poll(&mut sockets, Instant::from_millis((get_time() / 1000) as i64)) {
Ok(_) => (),
Err(e) => println!("poll error: {}", e)
}