ticktimer: implement hosted version of ticktimer

This gets the basic ticktimer server working in a hosted environment.

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
Sean Cross 2020-10-28 11:14:26 +08:00
parent 4334e7c23e
commit 0bce0eeb53

View file

@ -1,61 +1,94 @@
#![cfg_attr(target_os = "none", no_std)]
#![cfg_attr(target_os = "none", no_main)]
#[cfg(target_os = "none")]
#[macro_use]
mod debug;
mod api;
use api::Opcode;
use utralib::generated::*;
use core::convert::TryFrom;
pub struct XousTickTimer {
csr: xous::MemoryRange,
}
const TICKS_PER_MS: u64 = 1;
impl XousTickTimer {
pub fn new() -> XousTickTimer {
let ctrl = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::ticktimer::HW_TICKTIMER_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map Tick Timer CSR range");
XousTickTimer { csr: ctrl }
#[cfg(target_os = "none")]
mod implementation {
const TICKS_PER_MS: u64 = 1;
use utralib::generated::*;
pub struct XousTickTimer {
csr: xous::MemoryRange,
}
pub fn reset(&self) {
let mut tt = CSR::new(self.csr.as_mut_ptr() as *mut u32);
tt.wfo(utra::ticktimer::CONTROL_RESET, 0b1);
tt.wo(utra::ticktimer::CONTROL, 0); // not paused, not reset -> free-run
}
impl XousTickTimer {
pub fn new() -> XousTickTimer {
let ctrl = xous::syscall::map_memory(
xous::MemoryAddress::new(utra::ticktimer::HW_TICKTIMER_BASE),
None,
4096,
xous::MemoryFlags::R | xous::MemoryFlags::W,
)
.expect("couldn't map Tick Timer CSR range");
pub fn raw_ticktime(&self) -> u64 {
let tt = CSR::new(self.csr.as_mut_ptr() as *mut u32);
let mut time: u64 = tt.r(utra::ticktimer::TIME0) as u64;
time |= (tt.r(utra::ticktimer::TIME1) as u64) << 32;
XousTickTimer { csr: ctrl }
}
time
}
pub fn reset(&mut self) {
let mut tt = CSR::new(self.csr.as_mut_ptr() as *mut u32);
tt.wfo(utra::ticktimer::CONTROL_RESET, 0b1);
tt.wo(utra::ticktimer::CONTROL, 0); // not paused, not reset -> free-run
}
pub fn elapsed_ms(&self) -> u64 {
self.raw_ticktime() / TICKS_PER_MS
pub fn raw_ticktime(&self) -> u64 {
let tt = CSR::new(self.csr.as_mut_ptr() as *mut u32);
let mut time: u64 = tt.r(utra::ticktimer::TIME0) as u64;
time |= (tt.r(utra::ticktimer::TIME1) as u64) << 32;
time
}
pub fn elapsed_ms(&self) -> u64 {
self.raw_ticktime() / TICKS_PER_MS
}
}
}
#[cfg(not(target_os = "none"))]
mod implementation {
use std::convert::TryInto;
pub struct XousTickTimer {
start: std::time::Instant,
}
impl XousTickTimer {
pub fn new() -> XousTickTimer {
XousTickTimer {
start: std::time::Instant::now(),
}
}
pub fn reset(&mut self) {
self.start = std::time::Instant::now();
}
pub fn raw_ticktime(&self) -> u64 {
self.start.elapsed().as_micros().try_into().unwrap()
}
pub fn elapsed_ms(&self) -> u64 {
self.start.elapsed().as_nanos().try_into().unwrap()
}
}
}
use implementation::*;
#[xous::xous_main]
fn xmain() -> ! {
// Create a new ticktimer object
let ticktimer = XousTickTimer::new();
let mut ticktimer = XousTickTimer::new();
let ticktimer_server = xous::create_server(b"ticktimer-server").expect("Couldn't create Ticktimer server");
let ticktimer_server =
xous::create_server(b"ticktimer-server").expect("Couldn't create Ticktimer server");
loop {
println!("TickTimer: waiting for message");
let envelope = xous::receive_message(ticktimer_server).unwrap();
@ -66,14 +99,16 @@ fn xmain() -> ! {
Opcode::Reset => {
println!("TickTimer: reset called");
ticktimer.reset();
},
}
Opcode::ElapsedMs => {
let time = ticktimer.elapsed_ms();
println!("TickTimer: returning time of {:?}", time);
xous::return_scalar2(envelope.sender,
xous::return_scalar2(
envelope.sender,
(time & 0xFFFF_FFFFu64) as usize,
((time >> 32) & 0xFFF_FFFFu64) as usize,
).expect("TickTimer: couldn't return time request");
)
.expect("TickTimer: couldn't return time request");
println!("TickTimer: done returning value");
}
}