fw: refactor timer stuff into its own module

This commit is contained in:
David Lenfesty 2023-06-17 16:32:22 +00:00
parent a132f2e1f1
commit 034160b301
2 changed files with 84 additions and 46 deletions

View File

@ -7,7 +7,6 @@ extern crate panic_halt;
use core::fmt::Write;
use core::{
arch::asm,
ptr::{read_volatile, write_volatile},
};
@ -33,11 +32,12 @@ mod mcp4726;
mod proto;
mod uart;
mod sampler;
mod timer;
use timer::millis;
const MAC: [u8; 6] = [0xA0, 0xBB, 0xCC, 0xDD, 0xEE, 0xF0];
static mut SECONDS: u32 = 0;
// use `main` as the entry point of this application
// `main` is not allowed to return
#[entry]
@ -111,13 +111,7 @@ fn main() -> ! {
//defmt::info!("Done setup");
// Set up timer for polling events
unsafe {
// Timer stuff
write_reg(0xf000_3808, 0u32); // Disable timer
write_reg(0xf000_3800, 0u32); // Set LOAD value
write_reg(0xf000_3804, 60_000_000u32); // Set RELOAD value
write_reg(0xf000_3808, 1u32); // Enable timer
}
timer::init();
let mut cmd = command_interface::CommandInterface::new();
@ -156,33 +150,11 @@ fn main() -> ! {
// TODO I think the timer might actually stop until the event is cleared? this may pose
// problems, might explain why moving this above the smoltcp stuff "broke" things
handle_timer_event();
timer::poll();
}
}
fn handle_timer_event() {
unsafe {
if read_reg::<u32>(0xf000_3818) == 0 {
// No event yet, continue
return;
}
// Clear TIMER0 event status, and update time
write_reg(0xf000_3818, 1u32);
SECONDS += 1;
}
}
fn busy_wait(ms: u32) {
let start = millis();
while millis() - start < ms {
unsafe {
asm!("nop");
}
}
}
fn write_led(val: u32) {
unsafe {
write_reg(0xf000_2000, val);
@ -196,16 +168,3 @@ unsafe fn write_reg<T>(addr: u32, value: T) {
unsafe fn read_reg<T>(addr: u32) -> T {
return read_volatile(addr as *mut T);
}
fn millis() -> u32 {
riscv::interrupt::free(|| {
unsafe {
// Latch timer value
write_reg(0xf000_380c, 1u32);
// Read timer value
let val: u32 = read_reg(0xf000_3810);
let val = 60_000_000 - val;
(SECONDS * 1000) + val / 60_000
}
})
}

79
firmware/src/timer.rs Normal file
View File

@ -0,0 +1,79 @@
//! Simple module to use LiteX TIMER0 for simple timekeeping
use crate::{read_reg, write_reg};
use core::arch::asm;
/// Initializes the timer to use for polling events as a wall clock.
///
/// Timer is running at system frequency (60MHz)
pub fn init() {
unsafe {
write_reg(0xf000_3808, 0u32); // Disable timer
write_reg(0xf000_3800, 0u32); // Set LOAD value
write_reg(0xf000_3804, 60_000_000u32); // Set RELOAD value
write_reg(0xf000_3808, 1u32); // Enable timer
}
}
// Storage for overflow time
static mut SECONDS: u32 = 0;
/// Processes potential timer events. Must be polled regularly
pub fn poll() {
unsafe {
if read_reg::<u32>(0xf000_3818) == 0 {
// No event yet, continue
return;
}
// Clear TIMER0 event status, and update time
write_reg(0xf000_3818, 1u32);
SECONDS += 1;
}
}
/// Gets system time in milliseconds
pub fn millis() -> u32 {
riscv::interrupt::free(|| {
unsafe {
// Latch timer value
write_reg(0xf000_380c, 1u32);
// Read timer value
let val: u32 = read_reg(0xf000_3810);
let val = 60_000_000 - val;
(SECONDS * 1000) + val / 60_000
}
})
}
/// Gets system time in microseconds
pub fn micros() -> u64 {
riscv::interrupt::free(|| {
unsafe {
// Latch timer value
write_reg(0xf000_380c, 1u32);
// Read timer value
let val: u32 = read_reg(0xf000_3810);
let val = 60_000_000 - val;
(SECONDS as u64 * 1_000_000) + (val as u64 / 60)
}
})
}
pub fn busy_wait_ms(ms: u32) {
let start = millis();
while millis() - start < ms {
unsafe {
asm!("nop");
}
}
}
pub fn busy_wait_us(us: u64) {
let start = micros();
while micros() - start < us {
unsafe {
asm!("nop");
}
}
}