fw: refactor timer stuff into its own module
This commit is contained in:
parent
a132f2e1f1
commit
034160b301
@ -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
79
firmware/src/timer.rs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user