aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2023-11-04 13:51:11 -0500
committerxoviat <[email protected]>2023-11-04 13:51:11 -0500
commit3f2abd4fd5da51d7b8a7711d0eac02c7f7b9deed (patch)
tree3375dd57e07879f2d709f7547d95b2a7f757ae14
parentdc467e89a0f093c1656eaf63955c28dd3b08be6c (diff)
parent655ed3aa887fe2d9e424f239cc07db055d8f8d61 (diff)
Merge branch 'main' of github.com:embassy-rs/embassy into low-power
-rw-r--r--embassy-executor/Cargo.toml1
-rw-r--r--embassy-executor/src/lib.rs1
-rw-r--r--embassy-macros/src/macros/main.rs3
-rw-r--r--embassy-net-adin1110/Cargo.toml4
-rw-r--r--embassy-rp/Cargo.toml2
-rw-r--r--embassy-stm32/src/low_power.rs51
-rw-r--r--embassy-stm32/src/rcc/f4f7.rs23
-rw-r--r--embassy-stm32/src/rtc/datetime.rs32
-rw-r--r--embassy-stm32/src/rtc/mod.rs101
-rw-r--r--embassy-stm32/src/rtc/v2.rs4
-rw-r--r--embassy-stm32/src/rtc/v3.rs1
-rw-r--r--embassy-stm32/src/time_driver.rs6
-rw-r--r--embassy-sync/Cargo.toml2
-rw-r--r--embassy-usb-logger/Cargo.toml2
-rw-r--r--examples/nrf52840/Cargo.toml2
-rw-r--r--examples/nrf5340/Cargo.toml2
-rw-r--r--examples/rp/Cargo.toml3
-rw-r--r--examples/rp/src/bin/pio_rotary_encoder.rs81
-rw-r--r--examples/rp/src/bin/pwm_input.rs26
-rw-r--r--examples/std/Cargo.toml2
-rw-r--r--examples/stm32f0/Cargo.toml3
-rw-r--r--examples/stm32f3/Cargo.toml2
-rw-r--r--examples/stm32f334/Cargo.toml2
-rw-r--r--examples/stm32f4/Cargo.toml2
-rw-r--r--examples/stm32f7/Cargo.toml2
-rw-r--r--examples/stm32g0/Cargo.toml1
-rw-r--r--examples/stm32h5/Cargo.toml2
-rw-r--r--examples/stm32h7/Cargo.toml2
-rw-r--r--examples/stm32l0/Cargo.toml3
-rw-r--r--examples/stm32l4/Cargo.toml2
-rw-r--r--examples/stm32l5/Cargo.toml2
-rw-r--r--examples/stm32wb/Cargo.toml2
-rw-r--r--examples/stm32wba/Cargo.toml2
-rw-r--r--tests/nrf/Cargo.toml2
-rw-r--r--tests/rp/Cargo.toml3
-rw-r--r--tests/rp/src/bin/gpio_multicore.rs2
-rw-r--r--tests/rp/src/bin/i2c.rs2
-rw-r--r--tests/rp/src/bin/multicore.rs2
-rw-r--r--tests/stm32/Cargo.toml11
39 files changed, 272 insertions, 126 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml
index d8cc3e8a7..8e36637a3 100644
--- a/embassy-executor/Cargo.toml
+++ b/embassy-executor/Cargo.toml
@@ -62,7 +62,6 @@ embassy-macros = { version = "0.2.1", path = "../embassy-macros" }
62embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true} 62embassy-time = { version = "0.1.5", path = "../embassy-time", optional = true}
63atomic-polyfill = "1.0.1" 63atomic-polyfill = "1.0.1"
64critical-section = "1.1" 64critical-section = "1.1"
65static_cell = "1.1"
66 65
67# arch-cortex-m dependencies 66# arch-cortex-m dependencies
68cortex-m = { version = "0.7.6", optional = true } 67cortex-m = { version = "0.7.6", optional = true }
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs
index 020f9095c..f2c86d8e6 100644
--- a/embassy-executor/src/lib.rs
+++ b/embassy-executor/src/lib.rs
@@ -47,7 +47,6 @@ pub use spawner::*;
47pub mod _export { 47pub mod _export {
48 #[cfg(feature = "rtos-trace")] 48 #[cfg(feature = "rtos-trace")]
49 pub use rtos_trace::trace; 49 pub use rtos_trace::trace;
50 pub use static_cell::StaticCell;
51 50
52 /// Expands the given block of code when `embassy-executor` is compiled with 51 /// Expands the given block of code when `embassy-executor` is compiled with
53 /// the `rtos-trace-interrupt` feature. 52 /// the `rtos-trace-interrupt` feature.
diff --git a/embassy-macros/src/macros/main.rs b/embassy-macros/src/macros/main.rs
index 7c4d55163..3c0d58567 100644
--- a/embassy-macros/src/macros/main.rs
+++ b/embassy-macros/src/macros/main.rs
@@ -53,8 +53,7 @@ pub fn wasm() -> TokenStream {
53 quote! { 53 quote! {
54 #[wasm_bindgen::prelude::wasm_bindgen(start)] 54 #[wasm_bindgen::prelude::wasm_bindgen(start)]
55 pub fn main() -> Result<(), wasm_bindgen::JsValue> { 55 pub fn main() -> Result<(), wasm_bindgen::JsValue> {
56 static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new(); 56 let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(::embassy_executor::Executor::new()));
57 let executor = EXECUTOR.init(::embassy_executor::Executor::new());
58 57
59 executor.start(|spawner| { 58 executor.start(|spawner| {
60 spawner.spawn(__embassy_main(spawner)).unwrap(); 59 spawner.spawn(__embassy_main(spawner)).unwrap();
diff --git a/embassy-net-adin1110/Cargo.toml b/embassy-net-adin1110/Cargo.toml
index a781f3bd0..08c6aabd3 100644
--- a/embassy-net-adin1110/Cargo.toml
+++ b/embassy-net-adin1110/Cargo.toml
@@ -22,9 +22,7 @@ embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
22bitfield = "0.14.0" 22bitfield = "0.14.0"
23 23
24[dev-dependencies] 24[dev-dependencies]
25# reenable when https://github.com/dbrgn/embedded-hal-mock/pull/86 is merged. 25embedded-hal-mock = { version = "=0.10.0-rc.1", features = ["embedded-hal-async", "eh1"] }
26#embedded-hal-mock = { git = "https://github.com/dbrgn/embedded-hal-mock", branch = "1-alpha", features = ["embedded-hal-async", "eh1"] }] }
27embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", features = ["embedded-hal-async", "eh1"] }
28crc = "3.0.1" 26crc = "3.0.1"
29env_logger = "0.10" 27env_logger = "0.10"
30critical-section = { version = "1.1.2", features = ["std"] } 28critical-section = { version = "1.1.2", features = ["std"] }
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 5dc15c732..6be9f4bb0 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -95,4 +95,4 @@ rp2040-boot2 = "0.3"
95 95
96[dev-dependencies] 96[dev-dependencies]
97embassy-executor = { version = "0.3.1", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] } 97embassy-executor = { version = "0.3.1", path = "../embassy-executor", features = ["nightly", "arch-std", "executor-thread"] }
98static_cell = "1.1" 98static_cell = { version = "2" }
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 8e75f641a..20d8f9045 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -1,3 +1,50 @@
1/// The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
2/// to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
3/// can use knowledge of which peripherals are currently blocked upon to transparently and safely
4/// enter such low-power modes (currently, only `STOP2`) when idle.
5///
6/// The executor determines which peripherals are active by their RCC state; consequently,
7/// low-power states can only be entered if all peripherals have been `drop`'d. There are a few
8/// exceptions to this rule:
9///
10/// * `GPIO`
11/// * `RCC`
12///
13/// Since entering and leaving low-power modes typically incurs a significant latency, the
14/// low-power executor will only attempt to enter when the next timer event is at least
15/// [`time_driver::MIN_STOP_PAUSE`] in the future.
16///
17/// Currently there is no macro analogous to `embassy_executor::main` for this executor;
18/// consequently one must define their entrypoint manually. Moveover, you must relinquish control
19/// of the `RTC` peripheral to the executor. This will typically look like
20///
21/// ```rust,no_run
22/// use embassy_executor::Spawner;
23/// use embassy_stm32::low_power::Executor;
24/// use embassy_stm32::rtc::{Rtc, RtcConfig};
25/// use static_cell::make_static;
26///
27/// #[cortex_m_rt::entry]
28/// fn main() -> ! {
29/// Executor::take().run(|spawner| {
30/// unwrap!(spawner.spawn(async_main(spawner)));
31/// });
32/// }
33///
34/// #[embassy_executor::task]
35/// async fn async_main(spawner: Spawner) {
36/// // initialize the platform...
37/// let mut config = embassy_stm32::Config::default();
38/// let p = embassy_stm32::init(config);
39///
40/// // give the RTC to the executor...
41/// let mut rtc = Rtc::new(p.RTC, RtcConfig::default());
42/// let rtc = make_static!(rtc);
43/// embassy_stm32::low_power::stop_with_rtc(rtc);
44///
45/// // your application here...
46/// }
47/// ```
1use core::arch::asm; 48use core::arch::asm;
2use core::marker::PhantomData; 49use core::marker::PhantomData;
3use core::sync::atomic::{compiler_fence, Ordering}; 50use core::sync::atomic::{compiler_fence, Ordering};
@@ -67,7 +114,7 @@ pub struct Executor {
67impl Executor { 114impl Executor {
68 /// Create a new Executor. 115 /// Create a new Executor.
69 pub fn take() -> &'static mut Self { 116 pub fn take() -> &'static mut Self {
70 unsafe { 117 critical_section::with(|_| unsafe {
71 assert!(EXECUTOR.is_none()); 118 assert!(EXECUTOR.is_none());
72 119
73 EXECUTOR = Some(Self { 120 EXECUTOR = Some(Self {
@@ -78,7 +125,7 @@ impl Executor {
78 }); 125 });
79 126
80 EXECUTOR.as_mut().unwrap() 127 EXECUTOR.as_mut().unwrap()
81 } 128 })
82 } 129 }
83 130
84 unsafe fn on_wakeup_irq(&mut self) { 131 unsafe fn on_wakeup_irq(&mut self) {
diff --git a/embassy-stm32/src/rcc/f4f7.rs b/embassy-stm32/src/rcc/f4f7.rs
index 3102600a1..2e4f95722 100644
--- a/embassy-stm32/src/rcc/f4f7.rs
+++ b/embassy-stm32/src/rcc/f4f7.rs
@@ -152,9 +152,9 @@ pub(crate) unsafe fn init(config: Config) {
152 source: config.pll_src, 152 source: config.pll_src,
153 }; 153 };
154 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input); 154 let pll = init_pll(PllInstance::Pll, config.pll, &pll_input);
155 #[cfg(any(all(stm32f4, not(any(stm32f410, stm32f429))), stm32f7))] 155 #[cfg(any(all(stm32f4, not(stm32f410)), stm32f7))]
156 let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input); 156 let _plli2s = init_pll(PllInstance::Plli2s, config.plli2s, &pll_input);
157 #[cfg(all(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7), not(stm32f429)))] 157 #[cfg(any(stm32f446, stm32f427, stm32f437, stm32f4x9, stm32f7))]
158 let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input); 158 let _pllsai = init_pll(PllInstance::Pllsai, config.pllsai, &pll_input);
159 159
160 // Configure sysclk 160 // Configure sysclk
@@ -197,25 +197,15 @@ pub(crate) unsafe fn init(config: Config) {
197 pclk2_tim, 197 pclk2_tim,
198 rtc, 198 rtc,
199 pll1_q: pll.q, 199 pll1_q: pll.q,
200 #[cfg(all(rcc_f4, not(any(stm32f410, stm32f429))))] 200 #[cfg(all(rcc_f4, not(stm32f410)))]
201 plli2s1_q: _plli2s.q, 201 plli2s1_q: _plli2s.q,
202 #[cfg(all(rcc_f4, not(any(stm32f410, stm32f429))))] 202 #[cfg(all(rcc_f4, not(stm32f410)))]
203 plli2s1_r: _plli2s.r, 203 plli2s1_r: _plli2s.r,
204 204
205 #[cfg(stm32f429)] 205 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
206 plli2s1_q: None,
207 #[cfg(stm32f429)]
208 plli2s1_r: None,
209
210 #[cfg(any(stm32f427, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
211 pllsai1_q: _pllsai.q, 206 pllsai1_q: _pllsai.q,
212 #[cfg(any(stm32f427, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))] 207 #[cfg(any(stm32f427, stm32f429, stm32f437, stm32f439, stm32f446, stm32f469, stm32f479))]
213 pllsai1_r: _pllsai.r, 208 pllsai1_r: _pllsai.r,
214
215 #[cfg(stm32f429)]
216 pllsai1_q: None,
217 #[cfg(stm32f429)]
218 pllsai1_r: None,
219 }); 209 });
220} 210}
221 211
@@ -233,7 +223,6 @@ struct PllOutput {
233 r: Option<Hertz>, 223 r: Option<Hertz>,
234} 224}
235 225
236#[allow(dead_code)]
237#[derive(PartialEq, Eq, Clone, Copy)] 226#[derive(PartialEq, Eq, Clone, Copy)]
238enum PllInstance { 227enum PllInstance {
239 Pll, 228 Pll,
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs
index d897843dc..f3428108c 100644
--- a/embassy-stm32/src/rtc/datetime.rs
+++ b/embassy-stm32/src/rtc/datetime.rs
@@ -18,9 +18,13 @@ pub struct RtcInstant {
18} 18}
19 19
20impl RtcInstant { 20impl RtcInstant {
21 #[allow(dead_code)] 21 #[cfg(not(rtc_v2f2))]
22 pub(super) fn from(second: u8, subsecond: u16) -> Result<Self, super::RtcError> { 22 pub(super) const fn from(second: u8, subsecond: u16) -> Result<Self, Error> {
23 Ok(Self { second, subsecond }) 23 if second > 59 {
24 Err(Error::InvalidSecond)
25 } else {
26 Ok(Self { second, subsecond })
27 }
24 } 28 }
25} 29}
26 30
@@ -226,7 +230,7 @@ impl From<DayOfWeek> for chrono::Weekday {
226 } 230 }
227} 231}
228 232
229fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> { 233pub(super) const fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> {
230 Ok(match v { 234 Ok(match v {
231 1 => DayOfWeek::Monday, 235 1 => DayOfWeek::Monday,
232 2 => DayOfWeek::Tuesday, 236 2 => DayOfWeek::Tuesday,
@@ -239,24 +243,6 @@ fn day_of_week_from_u8(v: u8) -> Result<DayOfWeek, Error> {
239 }) 243 })
240} 244}
241 245
242pub(super) fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 { 246pub(super) const fn day_of_week_to_u8(dotw: DayOfWeek) -> u8 {
243 dotw as u8 247 dotw as u8
244} 248}
245
246pub(super) fn validate_datetime(dt: &DateTime) -> Result<(), Error> {
247 if dt.year > 4095 {
248 Err(Error::InvalidYear)
249 } else if dt.month < 1 || dt.month > 12 {
250 Err(Error::InvalidMonth)
251 } else if dt.day < 1 || dt.day > 31 {
252 Err(Error::InvalidDay)
253 } else if dt.hour > 23 {
254 Err(Error::InvalidHour)
255 } else if dt.minute > 59 {
256 Err(Error::InvalidMinute)
257 } else if dt.second > 59 {
258 Err(Error::InvalidSecond)
259 } else {
260 Ok(())
261 }
262}
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index 68836be07..e94a58575 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -9,8 +9,11 @@ use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
9#[cfg(feature = "low-power")] 9#[cfg(feature = "low-power")]
10use embassy_sync::blocking_mutex::Mutex; 10use embassy_sync::blocking_mutex::Mutex;
11 11
12pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError, RtcInstant}; 12use self::datetime::day_of_week_to_u8;
13use crate::rtc::datetime::day_of_week_to_u8; 13#[cfg(not(rtc_v2f2))]
14use self::datetime::RtcInstant;
15pub use self::datetime::{DateTime, DayOfWeek, Error as DateTimeError};
16use crate::pac::rtc::regs::{Dr, Tr};
14use crate::time::Hertz; 17use crate::time::Hertz;
15 18
16/// refer to AN4759 to compare features of RTC2 and RTC3 19/// refer to AN4759 to compare features of RTC2 and RTC3
@@ -31,11 +34,15 @@ use crate::peripherals::RTC;
31use crate::rtc::sealed::Instance; 34use crate::rtc::sealed::Instance;
32 35
33/// Errors that can occur on methods on [RtcClock] 36/// Errors that can occur on methods on [RtcClock]
37#[non_exhaustive]
34#[derive(Clone, Debug, PartialEq, Eq)] 38#[derive(Clone, Debug, PartialEq, Eq)]
35pub enum RtcError { 39pub enum RtcError {
36 /// An invalid DateTime was given or stored on the hardware. 40 /// An invalid DateTime was given or stored on the hardware.
37 InvalidDateTime(DateTimeError), 41 InvalidDateTime(DateTimeError),
38 42
43 /// The current time could not be read
44 ReadFailure,
45
39 /// The RTC clock is not running 46 /// The RTC clock is not running
40 NotRunning, 47 NotRunning,
41} 48}
@@ -45,48 +52,25 @@ pub struct RtcTimeProvider {
45} 52}
46 53
47impl RtcTimeProvider { 54impl RtcTimeProvider {
55 #[cfg(not(rtc_v2f2))]
56 pub(crate) fn instant(&self) -> Result<RtcInstant, RtcError> {
57 self.read(|_, tr, ss| {
58 let second = bcd2_to_byte((tr.st(), tr.su()));
59
60 RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime)
61 })
62 }
63
48 /// Return the current datetime. 64 /// Return the current datetime.
49 /// 65 ///
50 /// # Errors 66 /// # Errors
51 /// 67 ///
52 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`]. 68 /// Will return an `RtcError::InvalidDateTime` if the stored value in the system is not a valid [`DayOfWeek`].
53 pub fn now(&self) -> Result<DateTime, RtcError> { 69 pub fn now(&self) -> Result<DateTime, RtcError> {
54 // For RM0433 we use BYPSHAD=1 to work around errata ES0392 2.19.1 70 self.read(|dr, tr, _| {
55 #[cfg(rcc_h7rm0433)]
56 loop {
57 let r = RTC::regs();
58 let ss = r.ssr().read().ss();
59 let dr = r.dr().read();
60 let tr = r.tr().read();
61
62 // If an RTCCLK edge occurs during read we may see inconsistent values
63 // so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9)
64 let ss_after = r.ssr().read().ss();
65 if ss == ss_after {
66 let second = bcd2_to_byte((tr.st(), tr.su()));
67 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
68 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
69
70 let weekday = dr.wdu();
71 let day = bcd2_to_byte((dr.dt(), dr.du()));
72 let month = bcd2_to_byte((dr.mt() as u8, dr.mu()));
73 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
74
75 return DateTime::from(year, month, day, weekday, hour, minute, second)
76 .map_err(RtcError::InvalidDateTime);
77 }
78 }
79
80 #[cfg(not(rcc_h7rm0433))]
81 {
82 let r = RTC::regs();
83 let tr = r.tr().read();
84 let second = bcd2_to_byte((tr.st(), tr.su())); 71 let second = bcd2_to_byte((tr.st(), tr.su()));
85 let minute = bcd2_to_byte((tr.mnt(), tr.mnu())); 72 let minute = bcd2_to_byte((tr.mnt(), tr.mnu()));
86 let hour = bcd2_to_byte((tr.ht(), tr.hu())); 73 let hour = bcd2_to_byte((tr.ht(), tr.hu()));
87 // Reading either RTC_SSR or RTC_TR locks the values in the higher-order
88 // calendar shadow registers until RTC_DR is read.
89 let dr = r.dr().read();
90 74
91 let weekday = dr.wdu(); 75 let weekday = dr.wdu();
92 let day = bcd2_to_byte((dr.dt(), dr.du())); 76 let day = bcd2_to_byte((dr.dt(), dr.du()));
@@ -94,7 +78,33 @@ impl RtcTimeProvider {
94 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16; 78 let year = bcd2_to_byte((dr.yt(), dr.yu())) as u16 + 1970_u16;
95 79
96 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime) 80 DateTime::from(year, month, day, weekday, hour, minute, second).map_err(RtcError::InvalidDateTime)
81 })
82 }
83
84 fn read<R>(&self, mut f: impl FnMut(Dr, Tr, u16) -> Result<R, RtcError>) -> Result<R, RtcError> {
85 let r = RTC::regs();
86
87 #[cfg(not(rtc_v2f2))]
88 let read_ss = || r.ssr().read().ss();
89 #[cfg(rtc_v2f2)]
90 let read_ss = || 0;
91
92 let mut ss = read_ss();
93 for _ in 0..5 {
94 let tr = r.tr().read();
95 let dr = r.dr().read();
96 let ss_after = read_ss();
97
98 // If an RTCCLK edge occurs during read we may see inconsistent values
99 // so read ssr again and see if it has changed. (see RM0433 Rev 7 46.3.9)
100 if ss == ss_after {
101 return f(dr, tr, ss.try_into().unwrap());
102 } else {
103 ss = ss_after
104 }
97 } 105 }
106
107 return Err(RtcError::ReadFailure);
98 } 108 }
99} 109}
100 110
@@ -158,6 +168,14 @@ impl Rtc {
158 168
159 this.configure(async_psc, sync_psc); 169 this.configure(async_psc, sync_psc);
160 170
171 // Wait for the clock to update after initialization
172 #[cfg(not(rtc_v2f2))]
173 {
174 let now = this.instant().unwrap();
175
176 while this.instant().unwrap().subsecond == now.subsecond {}
177 }
178
161 this 179 this
162 } 180 }
163 181
@@ -177,7 +195,6 @@ impl Rtc {
177 /// 195 ///
178 /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. 196 /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range.
179 pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> { 197 pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> {
180 self::datetime::validate_datetime(&t).map_err(RtcError::InvalidDateTime)?;
181 self.write(true, |rtc| { 198 self.write(true, |rtc| {
182 let (ht, hu) = byte_to_bcd2(t.hour() as u8); 199 let (ht, hu) = byte_to_bcd2(t.hour() as u8);
183 let (mnt, mnu) = byte_to_bcd2(t.minute() as u8); 200 let (mnt, mnu) = byte_to_bcd2(t.minute() as u8);
@@ -217,16 +234,8 @@ impl Rtc {
217 234
218 #[cfg(not(rtc_v2f2))] 235 #[cfg(not(rtc_v2f2))]
219 /// Return the current instant. 236 /// Return the current instant.
220 pub fn instant(&self) -> Result<RtcInstant, RtcError> { 237 fn instant(&self) -> Result<RtcInstant, RtcError> {
221 let r = RTC::regs(); 238 self.time_provider().instant()
222 let tr = r.tr().read();
223 let subsecond = r.ssr().read().ss();
224 let second = bcd2_to_byte((tr.st(), tr.su()));
225
226 // Unlock the registers
227 r.dr().read();
228
229 RtcInstant::from(second, subsecond.try_into().unwrap())
230 } 239 }
231 240
232 /// Return the current datetime. 241 /// Return the current datetime.
diff --git a/embassy-stm32/src/rtc/v2.rs b/embassy-stm32/src/rtc/v2.rs
index b6ab9b209..006fd63f4 100644
--- a/embassy-stm32/src/rtc/v2.rs
+++ b/embassy-stm32/src/rtc/v2.rs
@@ -150,14 +150,14 @@ impl super::Rtc {
150 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { 150 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
151 self.write(true, |rtc| { 151 self.write(true, |rtc| {
152 rtc.cr().modify(|w| { 152 rtc.cr().modify(|w| {
153 #[cfg(not(rtc_v2f2))]
154 w.set_bypshad(true);
153 #[cfg(rtc_v2f2)] 155 #[cfg(rtc_v2f2)]
154 w.set_fmt(false); 156 w.set_fmt(false);
155 #[cfg(not(rtc_v2f2))] 157 #[cfg(not(rtc_v2f2))]
156 w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR); 158 w.set_fmt(stm32_metapac::rtc::vals::Fmt::TWENTY_FOUR_HOUR);
157 w.set_osel(Osel::DISABLED); 159 w.set_osel(Osel::DISABLED);
158 w.set_pol(Pol::HIGH); 160 w.set_pol(Pol::HIGH);
159 #[cfg(rcc_h7rm0433)]
160 w.set_bypshad(true);
161 }); 161 });
162 162
163 rtc.prer().modify(|w| { 163 rtc.prer().modify(|w| {
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs
index a6b2655d8..7bf757e7d 100644
--- a/embassy-stm32/src/rtc/v3.rs
+++ b/embassy-stm32/src/rtc/v3.rs
@@ -11,6 +11,7 @@ impl super::Rtc {
11 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) { 11 pub(super) fn configure(&mut self, async_psc: u8, sync_psc: u16) {
12 self.write(true, |rtc| { 12 self.write(true, |rtc| {
13 rtc.cr().modify(|w| { 13 rtc.cr().modify(|w| {
14 w.set_bypshad(true);
14 w.set_fmt(Fmt::TWENTYFOURHOUR); 15 w.set_fmt(Fmt::TWENTYFOURHOUR);
15 w.set_osel(Osel::DISABLED); 16 w.set_osel(Osel::DISABLED);
16 w.set_pol(Pol::HIGH); 17 w.set_pol(Pol::HIGH);
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index add8be831..564c9d086 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -346,6 +346,10 @@ impl RtcDriver {
346 } 346 }
347 347
348 #[cfg(feature = "low-power")] 348 #[cfg(feature = "low-power")]
349 /// The minimum pause time beyond which the executor will enter a low-power state.
350 pub(crate) const MIN_STOP_PAUSE: embassy_time::Duration = embassy_time::Duration::from_millis(250);
351
352 #[cfg(feature = "low-power")]
349 /// Pause the timer if ready; return err if not 353 /// Pause the timer if ready; return err if not
350 pub(crate) fn pause_time(&self) -> Result<(), ()> { 354 pub(crate) fn pause_time(&self) -> Result<(), ()> {
351 critical_section::with(|cs| { 355 critical_section::with(|cs| {
@@ -357,7 +361,7 @@ impl RtcDriver {
357 self.stop_wakeup_alarm(cs); 361 self.stop_wakeup_alarm(cs);
358 362
359 let time_until_next_alarm = self.time_until_next_alarm(cs); 363 let time_until_next_alarm = self.time_until_next_alarm(cs);
360 if time_until_next_alarm < embassy_time::Duration::from_millis(250) { 364 if time_until_next_alarm < Self::MIN_STOP_PAUSE {
361 Err(()) 365 Err(())
362 } else { 366 } else {
363 self.rtc 367 self.rtc
diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml
index 81aeafae2..9a47fa212 100644
--- a/embassy-sync/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -45,4 +45,4 @@ futures-util = { version = "0.3.17", features = [ "channel" ] }
45 45
46# Enable critical-section implementation for std, for tests 46# Enable critical-section implementation for std, for tests
47critical-section = { version = "1.1", features = ["std"] } 47critical-section = { version = "1.1", features = ["std"] }
48static_cell = "1.1" 48static_cell = { version = "2" }
diff --git a/embassy-usb-logger/Cargo.toml b/embassy-usb-logger/Cargo.toml
index 29a8e421a..48b8bbcc6 100644
--- a/embassy-usb-logger/Cargo.toml
+++ b/embassy-usb-logger/Cargo.toml
@@ -13,6 +13,6 @@ embassy-usb = { version = "0.1.0", path = "../embassy-usb" }
13embassy-sync = { version = "0.4.0", path = "../embassy-sync" } 13embassy-sync = { version = "0.4.0", path = "../embassy-sync" }
14embassy-futures = { version = "0.1.0", path = "../embassy-futures" } 14embassy-futures = { version = "0.1.0", path = "../embassy-futures" }
15futures = { version = "0.3", default-features = false } 15futures = { version = "0.3", default-features = false }
16static_cell = "1" 16static_cell = { version = "2" }
17usbd-hid = "0.6.0" 17usbd-hid = "0.6.0"
18log = "0.4" 18log = "0.4"
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index 0554b7e06..f803adb03 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -48,7 +48,7 @@ defmt = "0.3"
48defmt-rtt = "0.4" 48defmt-rtt = "0.4"
49 49
50fixed = "1.10.0" 50fixed = "1.10.0"
51static_cell = "1.1" 51static_cell = { version = "2" }
52cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 52cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
53cortex-m-rt = "0.7.0" 53cortex-m-rt = "0.7.0"
54panic-probe = { version = "0.3", features = ["print-defmt"] } 54panic-probe = { version = "0.3", features = ["print-defmt"] }
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index 9c62508cd..4196d61ab 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -42,7 +42,7 @@ embedded-io-async = { version = "0.6.0" }
42defmt = "0.3" 42defmt = "0.3"
43defmt-rtt = "0.4" 43defmt-rtt = "0.4"
44 44
45static_cell = { version = "1.1", features = ["nightly"]} 45static_cell = { version = "2", features = ["nightly"]}
46cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 46cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
47cortex-m-rt = "0.7.0" 47cortex-m-rt = "0.7.0"
48panic-probe = { version = "0.3", features = ["print-defmt"] } 48panic-probe = { version = "0.3", features = ["print-defmt"] }
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index d020a0f5d..fbe7acae1 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -47,7 +47,8 @@ embedded-hal-async = "1.0.0-rc.1"
47embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] } 47embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] }
48embedded-io-async = { version = "0.6.0", features = ["defmt-03"] } 48embedded-io-async = { version = "0.6.0", features = ["defmt-03"] }
49embedded-storage = { version = "0.3" } 49embedded-storage = { version = "0.3" }
50static_cell = { version = "1.1", features = ["nightly"]} 50static_cell = { version = "2", features = ["nightly"]}
51portable-atomic = { version = "1.5", features = ["critical-section"] }
51log = "0.4" 52log = "0.4"
52pio-proc = "0.2" 53pio-proc = "0.2"
53pio = "0.2.1" 54pio = "0.2.1"
diff --git a/examples/rp/src/bin/pio_rotary_encoder.rs b/examples/rp/src/bin/pio_rotary_encoder.rs
new file mode 100644
index 000000000..6d9d59df6
--- /dev/null
+++ b/examples/rp/src/bin/pio_rotary_encoder.rs
@@ -0,0 +1,81 @@
1//! This example shows how to use the PIO module in the RP2040 to read a quadrature rotary encoder.
2
3#![no_std]
4#![no_main]
5#![feature(type_alias_impl_trait)]
6
7use defmt::info;
8use embassy_executor::Spawner;
9use embassy_rp::gpio::Pull;
10use embassy_rp::peripherals::PIO0;
11use embassy_rp::{bind_interrupts, pio};
12use fixed::traits::ToFixed;
13use pio::{Common, Config, FifoJoin, Instance, InterruptHandler, Pio, PioPin, ShiftDirection, StateMachine};
14use {defmt_rtt as _, panic_probe as _};
15
16bind_interrupts!(struct Irqs {
17 PIO0_IRQ_0 => InterruptHandler<PIO0>;
18});
19
20pub struct PioEncoder<'d, T: Instance, const SM: usize> {
21 sm: StateMachine<'d, T, SM>,
22}
23
24impl<'d, T: Instance, const SM: usize> PioEncoder<'d, T, SM> {
25 pub fn new(
26 pio: &mut Common<'d, T>,
27 mut sm: StateMachine<'d, T, SM>,
28 pin_a: impl PioPin,
29 pin_b: impl PioPin,
30 ) -> Self {
31 let mut pin_a = pio.make_pio_pin(pin_a);
32 let mut pin_b = pio.make_pio_pin(pin_b);
33 pin_a.set_pull(Pull::Up);
34 pin_b.set_pull(Pull::Up);
35 sm.set_pin_dirs(pio::Direction::In, &[&pin_a, &pin_b]);
36
37 let prg = pio_proc::pio_asm!("wait 1 pin 1", "wait 0 pin 1", "in pins, 2", "push",);
38
39 let mut cfg = Config::default();
40 cfg.set_in_pins(&[&pin_a, &pin_b]);
41 cfg.fifo_join = FifoJoin::RxOnly;
42 cfg.shift_in.direction = ShiftDirection::Left;
43 cfg.clock_divider = 10_000.to_fixed();
44 cfg.use_program(&pio.load_program(&prg.program), &[]);
45 sm.set_config(&cfg);
46 sm.set_enable(true);
47 Self { sm }
48 }
49
50 pub async fn read(&mut self) -> Direction {
51 loop {
52 match self.sm.rx().wait_pull().await {
53 0 => return Direction::CounterClockwise,
54 1 => return Direction::Clockwise,
55 _ => {}
56 }
57 }
58 }
59}
60
61pub enum Direction {
62 Clockwise,
63 CounterClockwise,
64}
65
66#[embassy_executor::main]
67async fn main(_spawner: Spawner) {
68 let p = embassy_rp::init(Default::default());
69 let Pio { mut common, sm0, .. } = Pio::new(p.PIO0, Irqs);
70
71 let mut encoder = PioEncoder::new(&mut common, sm0, p.PIN_4, p.PIN_5);
72
73 let mut count = 0;
74 loop {
75 info!("Count: {}", count);
76 count += match encoder.read().await {
77 Direction::Clockwise => 1,
78 Direction::CounterClockwise => -1,
79 };
80 }
81}
diff --git a/examples/rp/src/bin/pwm_input.rs b/examples/rp/src/bin/pwm_input.rs
new file mode 100644
index 000000000..0fc2e40c3
--- /dev/null
+++ b/examples/rp/src/bin/pwm_input.rs
@@ -0,0 +1,26 @@
1//! This example shows how to use the PWM module to measure the frequency of an input signal.
2
3#![no_std]
4#![no_main]
5#![feature(type_alias_impl_trait)]
6
7use defmt::*;
8use embassy_executor::Spawner;
9use embassy_rp::pwm::{Config, InputMode, Pwm};
10use embassy_time::{Duration, Ticker};
11use {defmt_rtt as _, panic_probe as _};
12
13#[embassy_executor::main]
14async fn main(_spawner: Spawner) {
15 let p = embassy_rp::init(Default::default());
16
17 let cfg: Config = Default::default();
18 let pwm = Pwm::new_input(p.PWM_CH2, p.PIN_5, InputMode::RisingEdge, cfg);
19
20 let mut ticker = Ticker::every(Duration::from_secs(1));
21 loop {
22 info!("Input frequency: {} Hz", pwm.counter());
23 pwm.set_counter(0);
24 ticker.next().await;
25 }
26}
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index 12ec40fad..99511292f 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -24,7 +24,7 @@ nix = "0.26.2"
24clap = { version = "3.0.0-beta.5", features = ["derive"] } 24clap = { version = "3.0.0-beta.5", features = ["derive"] }
25rand_core = { version = "0.6.3", features = ["std"] } 25rand_core = { version = "0.6.3", features = ["std"] }
26heapless = { version = "0.7.5", default-features = false } 26heapless = { version = "0.7.5", default-features = false }
27static_cell = { version = "1.1", features = ["nightly"]} 27static_cell = { version = "2", features = ["nightly"]}
28 28
29[profile.release] 29[profile.release]
30debug = 2 30debug = 2
diff --git a/examples/stm32f0/Cargo.toml b/examples/stm32f0/Cargo.toml
index 953fa5845..3f781d762 100644
--- a/examples/stm32f0/Cargo.toml
+++ b/examples/stm32f0/Cargo.toml
@@ -17,7 +17,8 @@ panic-probe = "0.3"
17embassy-sync = { version = "0.4.0", path = "../../embassy-sync", features = ["defmt"] } 17embassy-sync = { version = "0.4.0", path = "../../embassy-sync", features = ["defmt"] }
18embassy-executor = { version = "0.3.1", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] } 18embassy-executor = { version = "0.3.1", path = "../../embassy-executor", features = ["nightly", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] }
19embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 19embassy-time = { version = "0.1.5", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
20static_cell = { version = "1.1", features = ["nightly"]} 20static_cell = { version = "2", features = ["nightly"]}
21portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
21 22
22[profile.release] 23[profile.release]
23debug = 2 24debug = 2
diff --git a/examples/stm32f3/Cargo.toml b/examples/stm32f3/Cargo.toml
index 548191ca6..0ab25c4c2 100644
--- a/examples/stm32f3/Cargo.toml
+++ b/examples/stm32f3/Cargo.toml
@@ -24,7 +24,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
24heapless = { version = "0.7.5", default-features = false } 24heapless = { version = "0.7.5", default-features = false }
25nb = "1.0.0" 25nb = "1.0.0"
26embedded-storage = "0.3.0" 26embedded-storage = "0.3.0"
27static_cell = { version = "1.1", features = ["nightly"]} 27static_cell = { version = "2", features = ["nightly"]}
28 28
29[profile.release] 29[profile.release]
30debug = 2 30debug = 2
diff --git a/examples/stm32f334/Cargo.toml b/examples/stm32f334/Cargo.toml
index b42cc9961..b3bfde441 100644
--- a/examples/stm32f334/Cargo.toml
+++ b/examples/stm32f334/Cargo.toml
@@ -23,4 +23,4 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
23heapless = { version = "0.7.5", default-features = false } 23heapless = { version = "0.7.5", default-features = false }
24nb = "1.0.0" 24nb = "1.0.0"
25embedded-storage = "0.3.0" 25embedded-storage = "0.3.0"
26static_cell = { version = "1.1", features = ["nightly"]} 26static_cell = { version = "2", features = ["nightly"]}
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index 916d0490b..fca182036 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -27,7 +27,7 @@ heapless = { version = "0.7.5", default-features = false }
27nb = "1.0.0" 27nb = "1.0.0"
28embedded-storage = "0.3.0" 28embedded-storage = "0.3.0"
29micromath = "2.0.0" 29micromath = "2.0.0"
30static_cell = { version = "1.1", features = ["nightly"]} 30static_cell = { version = "2", features = ["nightly"]}
31chrono = { version = "^0.4", default-features = false} 31chrono = { version = "^0.4", default-features = false}
32 32
33[profile.release] 33[profile.release]
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 35757e623..0a567d046 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -27,7 +27,7 @@ nb = "1.0.0"
27rand_core = "0.6.3" 27rand_core = "0.6.3"
28critical-section = "1.1" 28critical-section = "1.1"
29embedded-storage = "0.3.0" 29embedded-storage = "0.3.0"
30static_cell = { version = "1.1", features = ["nightly"]} 30static_cell = { version = "2", features = ["nightly"]}
31 31
32[profile.release] 32[profile.release]
33debug = 2 33debug = 2
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index fb7f780f9..42d7d328f 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -20,6 +20,7 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
23 24
24[profile.release] 25[profile.release]
25debug = 2 26debug = 2
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index c4f41d1cf..db56b685a 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -31,7 +31,7 @@ critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.0" 33embedded-storage = "0.3.0"
34static_cell = { version = "1.1", features = ["nightly"]} 34static_cell = { version = "2", features = ["nightly"]}
35 35
36# cargo build/run 36# cargo build/run
37[profile.dev] 37[profile.dev]
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index d6b14a602..c300c8644 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -31,7 +31,7 @@ critical-section = "1.1"
31micromath = "2.0.0" 31micromath = "2.0.0"
32stm32-fmc = "0.3.0" 32stm32-fmc = "0.3.0"
33embedded-storage = "0.3.0" 33embedded-storage = "0.3.0"
34static_cell = { version = "1.1", features = ["nightly"]} 34static_cell = { version = "2", features = ["nightly"]}
35chrono = { version = "^0.4", default-features = false } 35chrono = { version = "^0.4", default-features = false }
36 36
37# cargo build/run 37# cargo build/run
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index edd1d0261..e294d0422 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -33,7 +33,8 @@ panic-probe = { version = "0.3", features = ["print-defmt"] }
33futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 33futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
34heapless = { version = "0.7.5", default-features = false } 34heapless = { version = "0.7.5", default-features = false }
35embedded-hal = "0.2.6" 35embedded-hal = "0.2.6"
36static_cell = "1.1" 36static_cell = { version = "2" }
37portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
37 38
38[profile.release] 39[profile.release]
39debug = 2 40debug = 2
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 2fbba4634..5d79cf1ed 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -32,7 +32,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
32heapless = { version = "0.7.5", default-features = false } 32heapless = { version = "0.7.5", default-features = false }
33chrono = { version = "^0.4", default-features = false } 33chrono = { version = "^0.4", default-features = false }
34rand = { version = "0.8.5", default-features = false } 34rand = { version = "0.8.5", default-features = false }
35static_cell = {version = "1.1", features = ["nightly"]} 35static_cell = { version = "2", features = ["nightly"]}
36 36
37micromath = "2.0.0" 37micromath = "2.0.0"
38 38
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 2457b40d7..1cd32892d 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -26,7 +26,7 @@ futures = { version = "0.3.17", default-features = false, features = ["async-awa
26heapless = { version = "0.7.5", default-features = false } 26heapless = { version = "0.7.5", default-features = false }
27rand_core = { version = "0.6.3", default-features = false } 27rand_core = { version = "0.6.3", default-features = false }
28embedded-io-async = { version = "0.6.0" } 28embedded-io-async = { version = "0.6.0" }
29static_cell = { version = "1.1", features = ["nightly"]} 29static_cell = { version = "2", features = ["nightly"]}
30 30
31[profile.release] 31[profile.release]
32debug = 2 32debug = 2
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 5864906d0..daacc11c4 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -22,7 +22,7 @@ embedded-hal = "0.2.6"
22panic-probe = { version = "0.3", features = ["print-defmt"] } 22panic-probe = { version = "0.3", features = ["print-defmt"] }
23futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 23futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
24heapless = { version = "0.7.5", default-features = false } 24heapless = { version = "0.7.5", default-features = false }
25static_cell = { version = "1.1", features = ["nightly"]} 25static_cell = { version = "2", features = ["nightly"]}
26 26
27[features] 27[features]
28default = ["ble", "mac"] 28default = ["ble", "mac"]
diff --git a/examples/stm32wba/Cargo.toml b/examples/stm32wba/Cargo.toml
index 12e0e5ab0..c52848500 100644
--- a/examples/stm32wba/Cargo.toml
+++ b/examples/stm32wba/Cargo.toml
@@ -20,7 +20,7 @@ embedded-hal = "0.2.6"
20panic-probe = { version = "0.3", features = ["print-defmt"] } 20panic-probe = { version = "0.3", features = ["print-defmt"] }
21futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 21futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
22heapless = { version = "0.7.5", default-features = false } 22heapless = { version = "0.7.5", default-features = false }
23static_cell = { version = "1.1", features = ["nightly"]} 23static_cell = { version = "2", features = ["nightly"]}
24 24
25[profile.release] 25[profile.release]
26debug = 2 26debug = 2
diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml
index 6441d5c30..f7a104090 100644
--- a/tests/nrf/Cargo.toml
+++ b/tests/nrf/Cargo.toml
@@ -18,7 +18,7 @@ embassy-net-esp-hosted = { version = "0.1.0", path = "../../embassy-net-esp-host
18embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] } 18embassy-net-enc28j60 = { version = "0.1.0", path = "../../embassy-net-enc28j60", features = ["defmt"] }
19embedded-hal-async = { version = "1.0.0-rc.1" } 19embedded-hal-async = { version = "1.0.0-rc.1" }
20embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] } 20embedded-hal-bus = { version = "0.1.0-rc.1", features = ["async"] }
21static_cell = { version = "1.1", features = [ "nightly" ] } 21static_cell = { version = "2", features = [ "nightly" ] }
22perf-client = { path = "../perf-client" } 22perf-client = { path = "../perf-client" }
23 23
24defmt = "0.3" 24defmt = "0.3"
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index d947568ba..1bf149c90 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -31,7 +31,8 @@ panic-probe = { version = "0.3.0", features = ["print-defmt"] }
31futures = { version = "0.3.17", default-features = false, features = ["async-await"] } 31futures = { version = "0.3.17", default-features = false, features = ["async-await"] }
32embedded-io-async = { version = "0.6.0" } 32embedded-io-async = { version = "0.6.0" }
33embedded-storage = { version = "0.3" } 33embedded-storage = { version = "0.3" }
34static_cell = { version = "1.1", features = ["nightly"]} 34static_cell = { version = "2", features = ["nightly"]}
35portable-atomic = { version = "1.5", features = ["critical-section"] }
35pio = "0.2" 36pio = "0.2"
36pio-proc = "0.2" 37pio-proc = "0.2"
37rand = { version = "0.8.5", default-features = false } 38rand = { version = "0.8.5", default-features = false }
diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs
index 6ab7f6717..a4923b6ba 100644
--- a/tests/rp/src/bin/gpio_multicore.rs
+++ b/tests/rp/src/bin/gpio_multicore.rs
@@ -5,12 +5,12 @@ teleprobe_meta::target!(b"rpi-pico");
5 5
6use defmt::{info, unwrap}; 6use defmt::{info, unwrap};
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_executor::_export::StaticCell;
9use embassy_rp::gpio::{Input, Level, Output, Pull}; 8use embassy_rp::gpio::{Input, Level, Output, Pull};
10use embassy_rp::multicore::{spawn_core1, Stack}; 9use embassy_rp::multicore::{spawn_core1, Stack};
11use embassy_rp::peripherals::{PIN_0, PIN_1}; 10use embassy_rp::peripherals::{PIN_0, PIN_1};
12use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 11use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
13use embassy_sync::channel::Channel; 12use embassy_sync::channel::Channel;
13use static_cell::StaticCell;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16static mut CORE1_STACK: Stack<1024> = Stack::new(); 16static mut CORE1_STACK: Stack<1024> = Stack::new();
diff --git a/tests/rp/src/bin/i2c.rs b/tests/rp/src/bin/i2c.rs
index 425f2d086..7ddb71c7d 100644
--- a/tests/rp/src/bin/i2c.rs
+++ b/tests/rp/src/bin/i2c.rs
@@ -5,12 +5,12 @@ teleprobe_meta::target!(b"rpi-pico");
5 5
6use defmt::{assert_eq, info, panic, unwrap}; 6use defmt::{assert_eq, info, panic, unwrap};
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_executor::_export::StaticCell;
9use embassy_rp::multicore::{spawn_core1, Stack}; 8use embassy_rp::multicore::{spawn_core1, Stack};
10use embassy_rp::peripherals::{I2C0, I2C1}; 9use embassy_rp::peripherals::{I2C0, I2C1};
11use embassy_rp::{bind_interrupts, i2c, i2c_slave}; 10use embassy_rp::{bind_interrupts, i2c, i2c_slave};
12use embedded_hal_1::i2c::Operation; 11use embedded_hal_1::i2c::Operation;
13use embedded_hal_async::i2c::I2c; 12use embedded_hal_async::i2c::I2c;
13use static_cell::StaticCell;
14use {defmt_rtt as _, panic_probe as _, panic_probe as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _, panic_probe as _, panic_probe as _};
15 15
16static mut CORE1_STACK: Stack<1024> = Stack::new(); 16static mut CORE1_STACK: Stack<1024> = Stack::new();
diff --git a/tests/rp/src/bin/multicore.rs b/tests/rp/src/bin/multicore.rs
index f4188135e..6560b6c8d 100644
--- a/tests/rp/src/bin/multicore.rs
+++ b/tests/rp/src/bin/multicore.rs
@@ -5,10 +5,10 @@ teleprobe_meta::target!(b"rpi-pico");
5 5
6use defmt::{info, unwrap}; 6use defmt::{info, unwrap};
7use embassy_executor::Executor; 7use embassy_executor::Executor;
8use embassy_executor::_export::StaticCell;
9use embassy_rp::multicore::{spawn_core1, Stack}; 8use embassy_rp::multicore::{spawn_core1, Stack};
10use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; 9use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
11use embassy_sync::channel::Channel; 10use embassy_sync::channel::Channel;
11use static_cell::StaticCell;
12use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
13 13
14static mut CORE1_STACK: Stack<1024> = Stack::new(); 14static mut CORE1_STACK: Stack<1024> = Stack::new();
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml
index db265daae..4b769b1cb 100644
--- a/tests/stm32/Cargo.toml
+++ b/tests/stm32/Cargo.toml
@@ -8,8 +8,8 @@ autobins = false
8[features] 8[features]
9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"] 9stm32f103c8 = ["embassy-stm32/stm32f103c8", "not-gpdma"]
10stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin", "rng"] 10stm32f429zi = ["embassy-stm32/stm32f429zi", "chrono", "eth", "stop", "can", "not-gpdma", "dac-adc-pin", "rng"]
11stm32g071rb = ["embassy-stm32/stm32g071rb", "not-gpdma", "dac-adc-pin"] 11stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac-adc-pin"]
12stm32c031c6 = ["embassy-stm32/stm32c031c6", "not-gpdma"] 12stm32c031c6 = ["embassy-stm32/stm32c031c6", "cm0", "not-gpdma"]
13stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "not-gpdma", "rng"] 13stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "not-gpdma", "rng"]
14stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin", "rng"] 14stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac-adc-pin", "rng"]
15stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"] 15stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng"]
@@ -19,7 +19,7 @@ stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng"]
19stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono", "rng"] 19stm32u585ai = ["embassy-stm32/stm32u585ai", "chrono", "rng"]
20stm32u5a5zj = ["embassy-stm32/stm32u5a5zj", "chrono", "rng"] 20stm32u5a5zj = ["embassy-stm32/stm32u5a5zj", "chrono", "rng"]
21stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng"] 21stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng"]
22stm32l073rz = ["embassy-stm32/stm32l073rz", "not-gpdma", "rng"] 22stm32l073rz = ["embassy-stm32/stm32l073rz", "cm0", "not-gpdma", "rng"]
23stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"] 23stm32l152re = ["embassy-stm32/stm32l152re", "chrono", "not-gpdma"]
24stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng"] 24stm32l4a6zg = ["embassy-stm32/stm32l4a6zg", "chrono", "not-gpdma", "rng"]
25stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"] 25stm32l4r5zi = ["embassy-stm32/stm32l4r5zi", "chrono", "not-gpdma", "rng"]
@@ -42,6 +42,8 @@ embassy-stm32-wpan = []
42not-gpdma = [] 42not-gpdma = []
43dac-adc-pin = [] 43dac-adc-pin = []
44 44
45cm0 = ["portable-atomic/unsafe-assume-single-core"]
46
45[dependencies] 47[dependencies]
46teleprobe-meta = "1" 48teleprobe-meta = "1"
47 49
@@ -66,7 +68,8 @@ micromath = "2.0.0"
66panic-probe = { version = "0.3.0", features = ["print-defmt"] } 68panic-probe = { version = "0.3.0", features = ["print-defmt"] }
67rand_core = { version = "0.6", default-features = false } 69rand_core = { version = "0.6", default-features = false }
68rand_chacha = { version = "0.3", default-features = false } 70rand_chacha = { version = "0.3", default-features = false }
69static_cell = {version = "1.1", features = ["nightly"] } 71static_cell = { version = "2", features = ["nightly"] }
72portable-atomic = { version = "1.5", features = [] }
70 73
71chrono = { version = "^0.4", default-features = false, optional = true} 74chrono = { version = "^0.4", default-features = false, optional = true}
72 75