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 cortex_m_rt::exception;
use bare_metal::CriticalSection; use bare_metal::CriticalSection;
const SYSTICK_RATE: u32 = 250;
static mut TIME: Mutex<RefCell<u64>> = Mutex::new(RefCell::new(0)); 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)] #[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_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.clear_current();
syst.enable_interrupt(); syst.enable_interrupt();
syst.enable_counter(); syst.enable_counter();
@ -20,14 +27,17 @@ pub fn init(cs: &CriticalSection) {
#[exception] #[exception]
unsafe fn SysTick() { unsafe fn SysTick() {
let interval = u64::from(1000 / SYSTICK_RATE);
cortex_m::interrupt::free(|cs| { 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 { pub fn get_time() -> u64 {
cortex_m::interrupt::free(|cs| { let base = cortex_m::interrupt::free(|cs| {
*unsafe { &mut TIME }.borrow(cs).borrow() *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 // if a socket has sent the latest data
let mut socket_pending = [false; 8]; let mut socket_pending = [false; 8];
loop { loop {
adc.data_ready() let _ = adc.data_ready()
.and_then(|channel| .and_then(|channel|
channel.map(|channel| channel.map(|channel|
adc.read_data().map(|new_data| { adc.read_data().map(|new_data| {
@ -199,7 +199,6 @@ fn main() -> ! {
for p in socket_pending.iter_mut() { for p in socket_pending.iter_mut() {
*p = true; *p = true;
} }
}); });
for (&tcp_handle, pending) in handles.iter().zip(socket_pending.iter_mut()) { for (&tcp_handle, pending) in handles.iter().zip(socket_pending.iter_mut()) {
let socket = &mut *sockets.get::<TcpSocket>(tcp_handle); let socket = &mut *sockets.get::<TcpSocket>(tcp_handle);
@ -223,7 +222,7 @@ fn main() -> ! {
*pending = false; *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(_) => (), Ok(_) => (),
Err(e) => println!("poll error: {}", e) Err(e) => println!("poll error: {}", e)
} }