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 {