diff --git a/rp2040-hal/examples/adc_fifo_dma.rs b/rp2040-hal/examples/adc_fifo_dma.rs index ad237df80..be3b287ee 100644 --- a/rp2040-hal/examples/adc_fifo_dma.rs +++ b/rp2040-hal/examples/adc_fifo_dma.rs @@ -146,7 +146,12 @@ fn main() -> ! { adc_fifo.resume(); // initialize a timer, to measure the total sampling time (printed below) - let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); + let timer = hal::Timer::new( + pac.TIMER, + &mut pac.RESETS, + &watchdog, + &clocks.reference_clock, + ); // NOTE: in a real-world program, instead of calling `wait` now, you would probably: // 1. Enable one of the DMA interrupts for the channel (e.g. `dma.ch0.enable_irq0()`) diff --git a/rp2040-hal/examples/adc_fifo_poll.rs b/rp2040-hal/examples/adc_fifo_poll.rs index 3f5a6fe2e..c2c011873 100644 --- a/rp2040-hal/examples/adc_fifo_poll.rs +++ b/rp2040-hal/examples/adc_fifo_poll.rs @@ -133,7 +133,12 @@ fn main() -> ! { let mut i = 0; // initialize a timer, to measure the total sampling time (printed below) - let timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); + let timer = hal::Timer::new( + pac.TIMER, + &mut pac.RESETS, + &watchdog, + &clocks.reference_clock, + ); loop { // busy-wait until the FIFO contains at least two samples: diff --git a/rp2040-hal/examples/blinky.rs b/rp2040-hal/examples/blinky.rs index ac55a6f8d..732a1af73 100644 --- a/rp2040-hal/examples/blinky.rs +++ b/rp2040-hal/examples/blinky.rs @@ -64,7 +64,12 @@ fn main() -> ! { .ok() .unwrap(); - let mut timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); + let mut timer = rp2040_hal::Timer::new( + pac.TIMER, + &mut pac.RESETS, + &watchdog, + &clocks.reference_clock, + ); // The single-cycle I/O block controls our GPIO pins let sio = hal::Sio::new(pac.SIO); diff --git a/rp2040-hal/examples/vector_table.rs b/rp2040-hal/examples/vector_table.rs index b1c083069..8ed12fa1f 100644 --- a/rp2040-hal/examples/vector_table.rs +++ b/rp2040-hal/examples/vector_table.rs @@ -110,7 +110,12 @@ fn main() -> ! { // Configure GPIO25 as an output let led_pin = pins.gpio25.into_push_pull_output(); - let mut timer = hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); + let mut timer = hal::Timer::new( + pac.TIMER, + &mut pac.RESETS, + &watchdog, + &clocks.reference_clock, + ); critical_section::with(|cs| { let mut alarm = timer.alarm_0().unwrap(); // Schedule an alarm in 1 second diff --git a/rp2040-hal/src/clocks/mod.rs b/rp2040-hal/src/clocks/mod.rs index 5f280a5c5..3a757fbbc 100644 --- a/rp2040-hal/src/clocks/mod.rs +++ b/rp2040-hal/src/clocks/mod.rs @@ -26,7 +26,7 @@ //! let xosc = setup_xosc_blocking(peripherals.XOSC, XOSC_CRYSTAL_FREQ.Hz()).map_err(InitError::XoscErr)?; //! //! // Start tick in watchdog -//! watchdog.enable_tick_generation((XOSC_CRYSTAL_FREQ / 1_000_000) as u8); +//! watchdog.enable_tick_generation((XOSC_CRYSTAL_FREQ / 1_000_000) as u16); //! //! let mut clocks = ClocksManager::new(peripherals.CLOCKS); //! @@ -330,7 +330,7 @@ pub fn init_clocks_and_plls( let xosc = setup_xosc_blocking(xosc_dev, xosc_crystal_freq.Hz()).map_err(InitError::XoscErr)?; // Configure watchdog tick generation to tick over every microsecond - watchdog.enable_tick_generation((xosc_crystal_freq / 1_000_000) as u8); + watchdog.enable_tick_generation((xosc_crystal_freq / 1_000_000) as u16); let mut clocks = ClocksManager::new(clocks_dev); diff --git a/rp2040-hal/src/timer.rs b/rp2040-hal/src/timer.rs index ca6832a3c..a4601ff29 100644 --- a/rp2040-hal/src/timer.rs +++ b/rp2040-hal/src/timer.rs @@ -13,10 +13,11 @@ use fugit::{MicrosDurationU32, MicrosDurationU64, TimerInstantU64}; use crate::{ atomic_register_access::{write_bitmask_clear, write_bitmask_set}, - clocks::ClocksManager, + clocks::ReferenceClock, pac::{self, RESETS, TIMER}, resets::SubsystemReset, typelevel::Sealed, + Clock, Watchdog, }; /// Instant type used by the Timer & Alarm methods. @@ -59,7 +60,16 @@ impl Timer { /// Make sure that clocks and watchdog are configured, so /// that timer ticks happen at a frequency of 1MHz. /// Otherwise, `Timer` won't work as expected. - pub fn new(timer: TIMER, resets: &mut RESETS, _clocks: &ClocksManager) -> Self { + pub fn new( + timer: TIMER, + resets: &mut RESETS, + watchdog: &Watchdog, + clocks: &ReferenceClock, + ) -> Self { + assert_eq!( + clocks.freq().to_Hz(), + 1_000_000 * u32::from(watchdog.cycles_per_ticks()) + ); timer.reset_bring_down(resets); timer.reset_bring_up(resets); Self { _private: () } @@ -184,8 +194,9 @@ impl eh1_0_alpha::delay::DelayUs for Timer { /// // Make sure to initialize clocks, otherwise the timer wouldn't work /// // properly. Omitted here for terseness. /// let clocks: rp2040_hal::clocks::ClocksManager = todo!(); +/// let watchdog: rp2040_hal::Watchdog = todo!(); /// // Configure the Timer peripheral in count-down mode -/// let timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &clocks); +/// let timer = rp2040_hal::Timer::new(pac.TIMER, &mut pac.RESETS, &watchdog, &clocks.reference_clock); /// let mut count_down = timer.count_down(); /// // Create a count_down timer for 500 milliseconds /// count_down.start(500.millis()); diff --git a/rp2040-hal/src/watchdog.rs b/rp2040-hal/src/watchdog.rs index bef51cc35..d2da7d7aa 100644 --- a/rp2040-hal/src/watchdog.rs +++ b/rp2040-hal/src/watchdog.rs @@ -60,14 +60,21 @@ impl Watchdog { /// /// * `cycles` - Total number of tick cycles before the next tick is generated. /// It is expected to be the frequency in MHz of clk_ref. - pub fn enable_tick_generation(&mut self, cycles: u8) { + pub fn enable_tick_generation(&mut self, cycles: u16) { const WATCHDOG_TICK_ENABLE_BITS: u32 = 0x200; + assert_eq!(cycles & !0x1FF, 0); + self.watchdog .tick .write(|w| unsafe { w.bits(WATCHDOG_TICK_ENABLE_BITS | cycles as u32) }) } + /// Returns the number of `clk_ref` cycles between each watchdog (and Timer) ticks. + pub fn cycles_per_ticks(&self) -> u16 { + self.watchdog.tick.read().cycles().bits() + } + /// Defines whether or not the watchdog timer should be paused when processor(s) are in debug mode /// or when JTAG is accessing bus fabric ///