diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml index b440591cf7..34708e325a 100644 --- a/embassy-rp/Cargo.toml +++ b/embassy-rp/Cargo.toml @@ -42,7 +42,8 @@ critical-section-impl = ["critical-section/restore-state-u8"] unstable-pac = [] ## Enable the timer for use with `embassy-time` with a 1MHz tick rate. -time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-1_000_000", "dep:embassy-time-queue-utils"] +#time-driver = ["dep:embassy-time-driver", "embassy-time-driver?/tick-hz-1_000_000", "dep:embassy-time-queue-utils"] +time-driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] ## Enable ROM function cache. This will store the address of a ROM function when first used, improving performance of subsequent calls. rom-func-cache = [] @@ -122,7 +123,15 @@ _rp235x = ["rp-pac/rp235x"] rp235xa = ["_rp235x"] ## Configure the hal for use with the rp235xB rp235xb = ["_rp235x"] - +## Add a feature which configures `embassy-time-driver` with 150MHz `tick`s. This is an indication +## by the upstream crate that the RP2350's `TIMER`s are configured with the system clock as their +## source (typically 150MHz), instead of the usual 1MHz. +## Compilation flag checks in `lib.rs` ensure this feature is only used together with `_rp235x` +timer-src-clk-sys = [ + "dep:embassy-time-driver", + "embassy-time-driver?/tick-hz-150_000_000", + "dep:embassy-time-queue-utils", +] # hack around cortex-m peripherals being wrong when running tests. _test = [] diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f549446bc6..e895d61969 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -6,6 +6,19 @@ //! ## Feature flags #![doc = document_features::document_features!(feature_label = r#"{feature}"#)] +//! ## Compatible feature flags +// `timer-src-clk-sys` only makes sense on RP235x silicon. +#[cfg(all(feature = "timer-src-clk-sys", not(feature = "_rp235x"),))] +compile_error!( + "`embassy-rp` feature `timer-src-clk-sys` requires an `rp235x` feature (either `rp235xa` or \ + `rp235xb`) to be enabled." +); + +// // Prevent users from selecting both timer drivers (although this condition causes a redefinition +// // error in our deps before this code can halt the compilation with an explanation...) +// #[cfg(all(feature = "timer-src-clk-sys", feature = "time-driver"))] +// compile_error!("Enable only one of `time-driver` or `timer-src-clk-sys`."); + // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; diff --git a/embassy-rp/src/time_driver.rs b/embassy-rp/src/time_driver.rs index d598287a91..89b16d6076 100644 --- a/embassy-rp/src/time_driver.rs +++ b/embassy-rp/src/time_driver.rs @@ -10,6 +10,8 @@ use embassy_time_queue_utils::Queue; use pac::TIMER; #[cfg(feature = "_rp235x")] use pac::TIMER0 as TIMER; +#[cfg(all(feature = "_rp235x", feature = "timer-src-clk-sys"))] +use rp_pac::timer::vals::ClkSys; use crate::interrupt::InterruptExt; use crate::{interrupt, pac}; @@ -129,6 +131,16 @@ pub unsafe fn init() { { interrupt::TIMER0_IRQ_0.enable(); } + #[cfg(all(feature = "_rp235x", feature = "timer-src-clk-sys"))] + { + // The PAC currently only defines `TIMER0` as `TIMER` even though the RP2350 also has + // `TIMER1`. + let timer_0 = TIMER; + // Switch `SOURCE` to `CLK_SYS` (instead of 1 µs tick) + timer_0.source().write(|w| w.set_clk_sys(ClkSys::CLK_SYS)); + // Lock configuration--`TIMER0` now read-only (until reset) + timer_0.locked().write(|w| w.set_locked(true)); + } } #[cfg(all(feature = "rt", feature = "rp2040"))] diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs index 96541ade67..9623cd50d8 100644 --- a/embassy-rp/src/usb.rs +++ b/embassy-rp/src/usb.rs @@ -655,35 +655,33 @@ impl<'d, T: Instance> driver::ControlPipe for ControlPipe<'d, T> { } async fn setup(&mut self) -> [u8; 8] { - loop { - trace!("SETUP read waiting"); - let regs = T::regs(); - regs.inte().write_set(|w| w.set_setup_req(true)); + trace!("SETUP read waiting"); + let regs = T::regs(); + regs.inte().write_set(|w| w.set_setup_req(true)); - poll_fn(|cx| { - EP_OUT_WAKERS[0].register(cx.waker()); - let regs = T::regs(); - if regs.sie_status().read().setup_rec() { - Poll::Ready(()) - } else { - Poll::Pending - } - }) - .await; + poll_fn(|cx| { + EP_OUT_WAKERS[0].register(cx.waker()); + let regs = T::regs(); + if regs.sie_status().read().setup_rec() { + Poll::Ready(()) + } else { + Poll::Pending + } + }) + .await; - let mut buf = [0; 8]; - EndpointBuffer::::new(0, 8).read(&mut buf); + let mut buf = [0; 8]; + EndpointBuffer::::new(0, 8).read(&mut buf); - let regs = T::regs(); - regs.sie_status().write(|w| w.set_setup_rec(true)); + let regs = T::regs(); + regs.sie_status().write(|w| w.set_setup_rec(true)); - // set PID to 0, so (after toggling) first DATA is PID 1 - T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); - T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); + // set PID to 0, so (after toggling) first DATA is PID 1 + T::dpram().ep_in_buffer_control(0).write(|w| w.set_pid(0, false)); + T::dpram().ep_out_buffer_control(0).write(|w| w.set_pid(0, false)); - trace!("SETUP read ok"); - return buf; - } + trace!("SETUP read ok"); + return buf; } async fn data_out(&mut self, buf: &mut [u8], first: bool, last: bool) -> Result {