diff --git a/src/mailbox.rs b/src/mailbox.rs index 5cfe8ad..35cce2f 100644 --- a/src/mailbox.rs +++ b/src/mailbox.rs @@ -51,7 +51,7 @@ macro_rules! mailbox_command { return Err(NovaError::Mailbox); } - let mut out = [0u32; $response_len / 4]; // TODO: Can this be improved? + let mut out = [0u32; $response_len / 4]; out.copy_from_slice(&mailbox[5..(5 + $response_len / 4)]); Ok(out) } diff --git a/src/peripherals/gpio.rs b/src/peripherals/gpio.rs index bf03ffa..a6e8bb0 100644 --- a/src/peripherals/gpio.rs +++ b/src/peripherals/gpio.rs @@ -170,7 +170,7 @@ pub fn set_rising_edge_detect(gpio: u8, enable: bool) { mmio_write(register_addr, new_val); } -pub fn blink_gpio(gpio: u8, duration_ms: u32) { +pub fn blink_gpio(gpio: u8, duration_ms: u64) { let _ = gpio_high(gpio); sleep_ms(duration_ms); diff --git a/src/timer.rs b/src/timer.rs index af623dc..72ef2b6 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,32 +1,61 @@ -use crate::mmio_read; +use core::{hint::spin_loop, ptr::read_volatile}; -const TIMER_CLO: u32 = 0x3F00_3004; +const TIMER_CLOCK_LO: u32 = 0x3F00_3004; +const TIMER_CLOCK_HI: u32 = 0x3F00_3008; -fn read_clo() -> u32 { - mmio_read(TIMER_CLO) +fn read_timer_32() -> u32 { + unsafe { read_volatile(TIMER_CLOCK_LO as *const u32) } +} + +fn read_timer_64() -> u64 { + loop { + let clock_hi1 = unsafe { read_volatile(TIMER_CLOCK_HI as *const u32) }; + let clock_lo = unsafe { read_volatile(TIMER_CLOCK_LO as *const u32) }; + let clock_hi2 = unsafe { read_volatile(TIMER_CLOCK_HI as *const u32) }; + + // account for roll over during read + if clock_hi1 == clock_hi2 { + return ((clock_hi1 as u64) << 32) | clock_lo as u64; + } + } } /// Sleep for `us` microseconds -pub fn sleep_us(us: u32) { - let start = read_clo(); - while read_clo() - start < us { - unsafe { core::arch::asm!("nop") } +pub fn sleep_us(us: u64) { + if us < u32::MAX as u64 { + sleep_us_u32(us as u32); + } else { + sleep_us_u64(us); + } +} + +fn sleep_us_u32(us: u32) { + let start = read_timer_32(); + while read_timer_32().wrapping_sub(start) < us { + spin_loop(); + } +} + +fn sleep_us_u64(us: u64) { + let start = read_timer_64(); + while read_timer_64().wrapping_sub(start) < us { + spin_loop(); } } /// Sleep for `ms` milliseconds -pub fn sleep_ms(ms: u32) { - sleep_us(ms * 1000); +pub fn sleep_ms(ms: u64) { + sleep_us(ms * 1_000); } /// Sleep for `s` seconds -pub fn sleep_s(s: u32) { - sleep_us(s * 1000); +pub fn sleep_s(s: u64) { + sleep_ms(s * 1_000); } /// Wait for `count` operations to pass pub fn delay_nops(count: u32) { for _ in 0..count { - unsafe { core::arch::asm!("nop") } + spin_loop() } }