aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xci.sh4
-rw-r--r--cyw43/Cargo.toml6
-rw-r--r--cyw43/src/bluetooth.rs8
-rw-r--r--embassy-imxrt/Cargo.toml4
-rw-r--r--embassy-mcxa/Cargo.toml4
-rw-r--r--embassy-mcxa/src/clkout.rs8
-rw-r--r--embassy-mcxa/src/clocks/config.rs136
-rw-r--r--embassy-mcxa/src/clocks/mod.rs567
-rw-r--r--embassy-mcxa/src/dma.rs2
-rw-r--r--embassy-mcxa/src/gpio.rs20
-rw-r--r--embassy-mcxa/src/i2c/mod.rs7
-rw-r--r--embassy-mcxa/src/lib.rs24
-rw-r--r--embassy-mcxa/src/lpuart/mod.rs21
-rw-r--r--embassy-mcxa/src/reset_reason.rs187
-rw-r--r--embassy-mspm0/Cargo.toml4
-rw-r--r--embassy-mspm0/src/uart/buffered.rs4
-rw-r--r--embassy-net-nrf91/Cargo.toml2
-rw-r--r--embassy-net-ppp/Cargo.toml2
-rw-r--r--embassy-net/Cargo.toml4
-rw-r--r--embassy-net/src/tcp.rs16
-rw-r--r--embassy-nrf/CHANGELOG.md2
-rw-r--r--embassy-nrf/Cargo.toml4
-rw-r--r--embassy-nrf/src/buffered_uarte/v1.rs9
-rw-r--r--embassy-nrf/src/buffered_uarte/v2.rs8
-rw-r--r--embassy-nrf/src/time_driver.rs4
-rw-r--r--embassy-nrf/src/uarte.rs20
-rw-r--r--embassy-nxp/Cargo.toml2
-rw-r--r--embassy-nxp/src/usart/lpc55.rs9
-rw-r--r--embassy-rp/Cargo.toml4
-rw-r--r--embassy-rp/src/pio_programs/uart.rs4
-rw-r--r--embassy-rp/src/uart/mod.rs8
-rw-r--r--embassy-stm32-wpan/src/wb55/mod.rs2
-rw-r--r--embassy-stm32-wpan/src/wb55/shci.rs122
-rw-r--r--embassy-stm32-wpan/src/wb55/sub/sys.rs45
-rw-r--r--embassy-stm32/Cargo.toml12
-rw-r--r--embassy-stm32/src/lib.rs3
-rw-r--r--embassy-stm32/src/low_power.rs29
-rw-r--r--embassy-stm32/src/rcc/c0.rs6
-rw-r--r--embassy-stm32/src/rcc/f013.rs6
-rw-r--r--embassy-stm32/src/rcc/g0.rs6
-rw-r--r--embassy-stm32/src/rcc/g4.rs6
-rw-r--r--embassy-stm32/src/rcc/h.rs6
-rw-r--r--embassy-stm32/src/rcc/hsi48.rs21
-rw-r--r--embassy-stm32/src/rcc/l.rs11
-rw-r--r--embassy-stm32/src/rcc/u5.rs11
-rw-r--r--embassy-stm32/src/rcc/wba.rs5
-rw-r--r--embassy-stm32/src/rtc/low_power.rs94
-rw-r--r--embassy-stm32/src/rtc/mod.rs16
-rw-r--r--embassy-stm32/src/time_driver.rs23
-rw-r--r--embassy-sync/Cargo.toml2
-rw-r--r--embassy-usb-driver/Cargo.toml1
-rw-r--r--embassy-usb-driver/src/lib.rs1
-rw-r--r--embassy-usb/Cargo.toml2
-rw-r--r--embassy-usb/src/class/cdc_acm.rs51
-rw-r--r--examples/mcxa/Cargo.toml2
-rw-r--r--examples/mcxa/src/bin/clkout.rs104
-rw-r--r--examples/mcxa/src/bin/reset-reason.rs4
-rw-r--r--examples/mspm0g3507/Cargo.toml2
-rw-r--r--examples/nrf52840/Cargo.toml4
-rw-r--r--examples/nrf5340/Cargo.toml2
-rw-r--r--examples/nrf54l15/Cargo.toml4
-rw-r--r--examples/nrf54lm20/Cargo.toml4
-rw-r--r--examples/nrf9160/Cargo.toml4
-rw-r--r--examples/rp/Cargo.toml4
-rw-r--r--examples/rp235x/Cargo.toml2
-rw-r--r--examples/std/Cargo.toml4
-rw-r--r--examples/stm32f4/Cargo.toml4
-rw-r--r--examples/stm32f7/Cargo.toml2
-rw-r--r--examples/stm32g0/Cargo.toml2
-rw-r--r--examples/stm32h5/Cargo.toml4
-rw-r--r--examples/stm32h7/Cargo.toml4
-rw-r--r--examples/stm32h723/Cargo.toml4
-rw-r--r--examples/stm32h742/Cargo.toml2
-rw-r--r--examples/stm32h755cm4/Cargo.toml4
-rw-r--r--examples/stm32h755cm7/Cargo.toml4
-rw-r--r--examples/stm32h7b0/Cargo.toml4
-rw-r--r--examples/stm32h7rs/Cargo.toml4
-rw-r--r--examples/stm32l0/Cargo.toml4
-rw-r--r--examples/stm32l4/Cargo.toml4
-rw-r--r--examples/stm32l5/Cargo.toml2
-rw-r--r--examples/stm32n6/Cargo.toml2
-rw-r--r--examples/stm32wb/Cargo.toml4
-rw-r--r--examples/stm32wb/src/bin/blinky.rs2
-rw-r--r--examples/stm32wb/src/bin/button_exti.rs2
-rw-r--r--examples/stm32wb/src/bin/eddystone_beacon.rs2
-rw-r--r--examples/stm32wb/src/bin/gatt_server.rs2
-rw-r--r--examples/stm32wb/src/bin/mac_ffd.rs2
-rw-r--r--examples/stm32wb/src/bin/mac_ffd_net.rs2
-rw-r--r--examples/stm32wb/src/bin/mac_rfd.rs2
-rw-r--r--examples/stm32wb/src/bin/tl_mbox.rs2
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_ble.rs2
-rw-r--r--examples/stm32wb/src/bin/tl_mbox_mac.rs2
-rw-r--r--examples/stm32wle5/Cargo.toml2
-rw-r--r--tests/mspm0/Cargo.toml4
-rw-r--r--tests/nrf/Cargo.toml2
-rw-r--r--tests/rp/Cargo.toml2
-rw-r--r--tests/stm32/src/bin/stop.rs2
97 files changed, 1440 insertions, 371 deletions
diff --git a/ci.sh b/ci.sh
index e489982a7..1eecd158f 100755
--- a/ci.sh
+++ b/ci.sh
@@ -35,8 +35,8 @@ rm -rf out/tests/nrf5340-dk
35# disabled because these boards are not on the shelf 35# disabled because these boards are not on the shelf
36rm -rf out/tests/mspm0g3507 36rm -rf out/tests/mspm0g3507
37 37
38# rm out/tests/stm32wb55rg/wpan_mac 38rm out/tests/stm32wb55rg/wpan_mac
39# rm out/tests/stm32wb55rg/wpan_ble 39rm out/tests/stm32wb55rg/wpan_ble
40 40
41# unstable, I think it's running out of RAM? 41# unstable, I think it's running out of RAM?
42rm out/tests/stm32f207zg/eth 42rm out/tests/stm32f207zg/eth
diff --git a/cyw43/Cargo.toml b/cyw43/Cargo.toml
index 6d7647697..c4f5c0ebd 100644
--- a/cyw43/Cargo.toml
+++ b/cyw43/Cargo.toml
@@ -10,7 +10,7 @@ repository = "https://github.com/embassy-rs/embassy"
10documentation = "https://docs.embassy.dev/cyw43" 10documentation = "https://docs.embassy.dev/cyw43"
11 11
12[features] 12[features]
13defmt = ["dep:defmt", "heapless/defmt-03", "embassy-time/defmt", "bt-hci?/defmt", "embedded-io-async?/defmt-03"] 13defmt = ["dep:defmt", "heapless/defmt-03", "embassy-time/defmt", "bt-hci?/defmt", "embedded-io-async?/defmt"]
14log = ["dep:log"] 14log = ["dep:log"]
15bluetooth = ["dep:bt-hci", "dep:embedded-io-async"] 15bluetooth = ["dep:bt-hci", "dep:embedded-io-async"]
16 16
@@ -35,8 +35,8 @@ num_enum = { version = "0.5.7", default-features = false }
35heapless = "0.8.0" 35heapless = "0.8.0"
36 36
37# Bluetooth deps 37# Bluetooth deps
38embedded-io-async = { version = "0.6.0", optional = true } 38embedded-io-async = { version = "0.7.0", optional = true }
39bt-hci = { version = "0.6.0", optional = true } 39bt-hci = { git = "https://github.com/embassy-rs/bt-hci", rev = "51791fd4d422449dd0eca5ddead32886101215f7", optional = true }
40 40
41[package.metadata.embassy] 41[package.metadata.embassy]
42build = [ 42build = [
diff --git a/cyw43/src/bluetooth.rs b/cyw43/src/bluetooth.rs
index 332b7048d..256451fae 100644
--- a/cyw43/src/bluetooth.rs
+++ b/cyw43/src/bluetooth.rs
@@ -490,6 +490,14 @@ impl From<FromHciBytesError> for Error {
490 } 490 }
491} 491}
492 492
493impl core::fmt::Display for Error {
494 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
495 core::fmt::Debug::fmt(self, f)
496 }
497}
498
499impl core::error::Error for Error {}
500
493impl<'d> embedded_io_async::ErrorType for BtDriver<'d> { 501impl<'d> embedded_io_async::ErrorType for BtDriver<'d> {
494 type Error = Error; 502 type Error = Error;
495} 503}
diff --git a/embassy-imxrt/Cargo.toml b/embassy-imxrt/Cargo.toml
index 81377579b..5ffa054f1 100644
--- a/embassy-imxrt/Cargo.toml
+++ b/embassy-imxrt/Cargo.toml
@@ -85,8 +85,8 @@ cfg-if = "1.0.0"
85cortex-m-rt = ">=0.7.3,<0.8" 85cortex-m-rt = ">=0.7.3,<0.8"
86cortex-m = "0.7.6" 86cortex-m = "0.7.6"
87critical-section = "1.1" 87critical-section = "1.1"
88embedded-io = { version = "0.6.1" } 88embedded-io = { version = "0.7.1" }
89embedded-io-async = { version = "0.6.1" } 89embedded-io-async = { version = "0.7.0" }
90fixed = "1.23.1" 90fixed = "1.23.1"
91 91
92rand-core-06 = { package = "rand_core", version = "0.6" } 92rand-core-06 = { package = "rand_core", version = "0.6" }
diff --git a/embassy-mcxa/Cargo.toml b/embassy-mcxa/Cargo.toml
index 76ce59f5a..0d9663879 100644
--- a/embassy-mcxa/Cargo.toml
+++ b/embassy-mcxa/Cargo.toml
@@ -36,8 +36,8 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
36embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 36embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
37embedded-hal-async = { version = "1.0" } 37embedded-hal-async = { version = "1.0" }
38embedded-hal-nb = { version = "1.0" } 38embedded-hal-nb = { version = "1.0" }
39embedded-io = "0.6" 39embedded-io = "0.7"
40embedded-io-async = { version = "0.6.1" } 40embedded-io-async = { version = "0.7.0" }
41heapless = "0.8" 41heapless = "0.8"
42mcxa-pac = { version = "0.1.0", features = ["rt", "critical-section"] } 42mcxa-pac = { version = "0.1.0", features = ["rt", "critical-section"] }
43nb = "1.1.0" 43nb = "1.1.0"
diff --git a/embassy-mcxa/src/clkout.rs b/embassy-mcxa/src/clkout.rs
index 5b21f24b0..3495eb886 100644
--- a/embassy-mcxa/src/clkout.rs
+++ b/embassy-mcxa/src/clkout.rs
@@ -20,6 +20,7 @@ pub struct ClockOut<'a> {
20} 20}
21 21
22/// Selected clock source to output 22/// Selected clock source to output
23#[derive(Copy, Clone)]
23pub enum ClockOutSel { 24pub enum ClockOutSel {
24 /// 12MHz Internal Oscillator 25 /// 12MHz Internal Oscillator
25 Fro12M, 26 Fro12M,
@@ -36,6 +37,7 @@ pub enum ClockOutSel {
36} 37}
37 38
38/// Configuration for the ClockOut 39/// Configuration for the ClockOut
40#[derive(Copy, Clone)]
39pub struct Config { 41pub struct Config {
40 /// Selected Source Clock 42 /// Selected Source Clock
41 pub sel: ClockOutSel, 43 pub sel: ClockOutSel,
@@ -157,6 +159,12 @@ mod sealed {
157 fn mux(&self) { 159 fn mux(&self) {
158 self.set_function(crate::pac::port0::pcr0::Mux::$func); 160 self.set_function(crate::pac::port0::pcr0::Mux::$func);
159 self.set_pull(Pull::Disabled); 161 self.set_pull(Pull::Disabled);
162
163 // TODO: we may want to expose these as options to allow the slew rate
164 // and drive strength for clocks if they are particularly high speed.
165 //
166 // self.set_drive_strength(crate::pac::port0::pcr0::Dse::Dse1);
167 // self.set_slew_rate(crate::pac::port0::pcr0::Sre::Sre0);
160 } 168 }
161 } 169 }
162 }; 170 };
diff --git a/embassy-mcxa/src/clocks/config.rs b/embassy-mcxa/src/clocks/config.rs
index 0563b8917..4beca5f27 100644
--- a/embassy-mcxa/src/clocks/config.rs
+++ b/embassy-mcxa/src/clocks/config.rs
@@ -119,6 +119,140 @@ pub struct ClocksConfig {
119 pub sirc: SircConfig, 119 pub sirc: SircConfig,
120 /// FRO16K clock source 120 /// FRO16K clock source
121 pub fro16k: Option<Fro16KConfig>, 121 pub fro16k: Option<Fro16KConfig>,
122 /// SOSC, clk_in clock source
123 pub sosc: Option<SoscConfig>,
124 /// SPLL
125 pub spll: Option<SpllConfig>,
126}
127
128// SOSC
129
130/// The mode of the external reference clock
131#[derive(Copy, Clone)]
132pub enum SoscMode {
133 /// Passive crystal oscillators
134 CrystalOscillator,
135 /// Active external reference clock
136 ActiveClock,
137}
138
139/// SOSC/clk_in configuration
140#[derive(Copy, Clone)]
141pub struct SoscConfig {
142 /// Mode of the external reference clock
143 pub mode: SoscMode,
144 /// Specific frequency of the external reference clock
145 pub frequency: u32,
146 /// Power state of the external reference clock
147 pub power: PoweredClock,
148}
149
150// SPLL
151
152/// PLL1/SPLL configuration
153pub struct SpllConfig {
154 /// Input clock source for the PLL1/SPLL
155 pub source: SpllSource,
156 /// Mode of operation for the PLL1/SPLL
157 pub mode: SpllMode,
158 /// Power state of the SPLL
159 pub power: PoweredClock,
160 /// Is the "pll1_clk_div" clock enabled?
161 pub pll1_clk_div: Option<Div8>,
162}
163
164/// Input clock source for the PLL1/SPLL
165pub enum SpllSource {
166 /// External Oscillator (8-50MHz)
167 Sosc,
168 /// Fast Internal Oscillator (45MHz)
169 // NOTE: Figure 69 says "firc_45mhz"/"clk_45m", not "fro_hf_gated",
170 // so this is is always 45MHz.
171 Firc,
172 /// S Internal Oscillator (12M)
173 Sirc,
174 // TODO: the reference manual hints that ROSC is possible,
175 // however the minimum input frequency is 32K, but ROSC is 16K.
176 // Some diagrams show this option, and some diagrams omit it.
177 // SVD shows it as "reserved".
178 //
179 // /// Realtime Internal Oscillator (16K Osc)
180 // Rosc,
181}
182
183/// Mode of operation for the SPLL/PLL1
184///
185/// NOTE: Currently, only "Mode 1" normal operational modes are implemented,
186/// as described in the Reference Manual.
187#[non_exhaustive]
188pub enum SpllMode {
189 /// Mode 1a does not use the Pre/Post dividers.
190 ///
191 /// `Fout = m_mult x SpllSource`
192 ///
193 /// Both of the following constraints must be met:
194 ///
195 /// * Fout: 275MHz to 550MHz
196 /// * Fout: 4.3MHz to 2x Max CPU Frequency
197 Mode1a {
198 /// PLL Multiplier. Must be in the range 1..=65535.
199 m_mult: u16,
200 },
201
202 /// Mode 1b does not use the Pre-divider.
203 ///
204 /// * `if !bypass_p2_div: Fout = (M / (2 x P)) x Fin`
205 /// * `if bypass_p2_div: Fout = (M / P ) x Fin`
206 ///
207 /// Both of the following constraints must be met:
208 ///
209 /// * Fcco: 275MHz to 550MHz
210 /// * `Fcco = m_mult x SpllSource`
211 /// * Fout: 4.3MHz to 2x Max CPU Frequency
212 Mode1b {
213 /// PLL Multiplier. `m_mult` must be in the range 1..=65535.
214 m_mult: u16,
215 /// Post Divider. `p_div` must be in the range 1..=31.
216 p_div: u8,
217 /// Bonus post divider
218 bypass_p2_div: bool,
219 },
220
221 /// Mode 1c does use the Pre-divider, but does not use the Post-divider
222 ///
223 /// `Fout = (M / N) x Fin`
224 ///
225 /// Both of the following constraints must be met:
226 ///
227 /// * Fout: 275MHz to 550MHz
228 /// * Fout: 4.3MHz to 2x Max CPU Frequency
229 Mode1c {
230 /// PLL Multiplier. `m_mult` must be in the range 1..=65535.
231 m_mult: u16,
232 /// Pre Divider. `n_div` must be in the range 1..=255.
233 n_div: u8,
234 },
235
236 /// Mode 1b uses both the Pre and Post dividers.
237 ///
238 /// * `if !bypass_p2_div: Fout = (M / (N x 2 x P)) x Fin`
239 /// * `if bypass_p2_div: Fout = (M / ( N x P )) x Fin`
240 ///
241 /// Both of the following constraints must be met:
242 ///
243 /// * Fcco: 275MHz to 550MHz
244 /// * `Fcco = (m_mult x SpllSource) / (n_div x p_div (x 2))`
245 /// * Fout: 4.3MHz to 2x Max CPU Frequency
246 Mode1d {
247 /// PLL Multiplier. `m_mult` must be in the range 1..=65535.
248 m_mult: u16,
249 /// Pre Divider. `n_div` must be in the range 1..=255.
250 n_div: u8,
251 /// Post Divider. `p_div` must be in the range 1..=31.
252 p_div: u8,
253 /// Bonus post divider
254 bypass_p2_div: bool,
255 },
122} 256}
123 257
124// FIRC/FRO180M 258// FIRC/FRO180M
@@ -199,6 +333,8 @@ impl Default for ClocksConfig {
199 vsys_domain_active: true, 333 vsys_domain_active: true,
200 vdd_core_domain_active: true, 334 vdd_core_domain_active: true,
201 }), 335 }),
336 sosc: None,
337 spll: None,
202 } 338 }
203 } 339 }
204} 340}
diff --git a/embassy-mcxa/src/clocks/mod.rs b/embassy-mcxa/src/clocks/mod.rs
index 037f0a656..04559fd04 100644
--- a/embassy-mcxa/src/clocks/mod.rs
+++ b/embassy-mcxa/src/clocks/mod.rs
@@ -87,6 +87,8 @@ pub fn init(settings: ClocksConfig) -> Result<(), ClockError> {
87 operator.configure_firc_clocks()?; 87 operator.configure_firc_clocks()?;
88 operator.configure_sirc_clocks()?; 88 operator.configure_sirc_clocks()?;
89 operator.configure_fro16k_clocks()?; 89 operator.configure_fro16k_clocks()?;
90 operator.configure_sosc()?;
91 operator.configure_spll()?;
90 92
91 // For now, just use FIRC as the main/cpu clock, which should already be 93 // For now, just use FIRC as the main/cpu clock, which should already be
92 // the case on reset 94 // the case on reset
@@ -136,6 +138,7 @@ pub fn with_clocks<R: 'static, F: FnOnce(&Clocks) -> R>(f: F) -> Option<R> {
136#[non_exhaustive] 138#[non_exhaustive]
137pub struct Clocks { 139pub struct Clocks {
138 /// The `clk_in` is a clock provided by an external oscillator 140 /// The `clk_in` is a clock provided by an external oscillator
141 /// AKA SOSC
139 pub clk_in: Option<Clock>, 142 pub clk_in: Option<Clock>,
140 143
141 // FRO180M stuff 144 // FRO180M stuff
@@ -197,6 +200,9 @@ pub struct Clocks {
197 200
198 /// `pll1_clk` is the output of the main system PLL, `pll1`. 201 /// `pll1_clk` is the output of the main system PLL, `pll1`.
199 pub pll1_clk: Option<Clock>, 202 pub pll1_clk: Option<Clock>,
203
204 /// `pll1_clk_div` is a configurable frequency clock, sourced from `pll1_clk`
205 pub pll1_clk_div: Option<Clock>,
200} 206}
201 207
202/// `ClockError` is the main error returned when configuring or checking clock state 208/// `ClockError` is the main error returned when configuring or checking clock state
@@ -433,60 +439,49 @@ pub unsafe fn pulse_reset<G: Gate>() {
433/// selected clocks are active at a suitable level at time of construction. These methods 439/// selected clocks are active at a suitable level at time of construction. These methods
434/// return the frequency of the requested clock, in Hertz, or a [`ClockError`]. 440/// return the frequency of the requested clock, in Hertz, or a [`ClockError`].
435impl Clocks { 441impl Clocks {
436 /// Ensure the `fro_lf_div` clock is active and valid at the given power state. 442 fn ensure_clock_active(
437 pub fn ensure_fro_lf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { 443 &self,
438 let Some(clk) = self.fro_lf_div.as_ref() else { 444 clock: &Option<Clock>,
445 name: &'static str,
446 at_level: &PoweredClock,
447 ) -> Result<u32, ClockError> {
448 let Some(clk) = clock.as_ref() else {
439 return Err(ClockError::BadConfig { 449 return Err(ClockError::BadConfig {
440 clock: "fro_lf_div", 450 clock: name,
441 reason: "required but not active", 451 reason: "required but not active",
442 }); 452 });
443 }; 453 };
444 if !clk.power.meets_requirement_of(at_level) { 454 if !clk.power.meets_requirement_of(at_level) {
445 return Err(ClockError::BadConfig { 455 return Err(ClockError::BadConfig {
446 clock: "fro_lf_div", 456 clock: name,
447 reason: "not low power active", 457 reason: "not low power active",
448 }); 458 });
449 } 459 }
450 Ok(clk.frequency) 460 Ok(clk.frequency)
451 } 461 }
452 462
463 /// Ensure the `fro_lf_div` clock is active and valid at the given power state.
464 #[inline]
465 pub fn ensure_fro_lf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
466 self.ensure_clock_active(&self.fro_lf_div, "fro_lf_div", at_level)
467 }
468
453 /// Ensure the `fro_hf` clock is active and valid at the given power state. 469 /// Ensure the `fro_hf` clock is active and valid at the given power state.
470 #[inline]
454 pub fn ensure_fro_hf_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { 471 pub fn ensure_fro_hf_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
455 let Some(clk) = self.fro_hf.as_ref() else { 472 self.ensure_clock_active(&self.fro_hf, "fro_hf", at_level)
456 return Err(ClockError::BadConfig {
457 clock: "fro_hf",
458 reason: "required but not active",
459 });
460 };
461 if !clk.power.meets_requirement_of(at_level) {
462 return Err(ClockError::BadConfig {
463 clock: "fro_hf",
464 reason: "not low power active",
465 });
466 }
467 Ok(clk.frequency)
468 } 473 }
469 474
470 /// Ensure the `fro_hf_div` clock is active and valid at the given power state. 475 /// Ensure the `fro_hf_div` clock is active and valid at the given power state.
476 #[inline]
471 pub fn ensure_fro_hf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { 477 pub fn ensure_fro_hf_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
472 let Some(clk) = self.fro_hf_div.as_ref() else { 478 self.ensure_clock_active(&self.fro_hf_div, "fro_hf_div", at_level)
473 return Err(ClockError::BadConfig {
474 clock: "fro_hf_div",
475 reason: "required but not active",
476 });
477 };
478 if !clk.power.meets_requirement_of(at_level) {
479 return Err(ClockError::BadConfig {
480 clock: "fro_hf_div",
481 reason: "not low power active",
482 });
483 }
484 Ok(clk.frequency)
485 } 479 }
486 480
487 /// Ensure the `clk_in` clock is active and valid at the given power state. 481 /// Ensure the `clk_in` clock is active and valid at the given power state.
488 pub fn ensure_clk_in_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { 482 #[inline]
489 Err(ClockError::NotImplemented { clock: "clk_in" }) 483 pub fn ensure_clk_in_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
484 self.ensure_clock_active(&self.clk_in, "clk_in", at_level)
490 } 485 }
491 486
492 /// Ensure the `clk_16k_vsys` clock is active and valid at the given power state. 487 /// Ensure the `clk_16k_vsys` clock is active and valid at the given power state.
@@ -516,30 +511,21 @@ impl Clocks {
516 } 511 }
517 512
518 /// Ensure the `clk_1m` clock is active and valid at the given power state. 513 /// Ensure the `clk_1m` clock is active and valid at the given power state.
514 #[inline]
519 pub fn ensure_clk_1m_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> { 515 pub fn ensure_clk_1m_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
520 let Some(clk) = self.clk_1m.as_ref() else { 516 self.ensure_clock_active(&self.clk_1m, "clk_1m", at_level)
521 return Err(ClockError::BadConfig {
522 clock: "clk_1m",
523 reason: "required but not active",
524 });
525 };
526 if !clk.power.meets_requirement_of(at_level) {
527 return Err(ClockError::BadConfig {
528 clock: "clk_1m",
529 reason: "not low power active",
530 });
531 }
532 Ok(clk.frequency)
533 } 517 }
534 518
535 /// Ensure the `pll1_clk` clock is active and valid at the given power state. 519 /// Ensure the `pll1_clk` clock is active and valid at the given power state.
536 pub fn ensure_pll1_clk_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { 520 #[inline]
537 Err(ClockError::NotImplemented { clock: "pll1_clk" }) 521 pub fn ensure_pll1_clk_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
522 self.ensure_clock_active(&self.pll1_clk, "pll1_clk", at_level)
538 } 523 }
539 524
540 /// Ensure the `pll1_clk_div` clock is active and valid at the given power state. 525 /// Ensure the `pll1_clk_div` clock is active and valid at the given power state.
541 pub fn ensure_pll1_clk_div_active(&self, _at_level: &PoweredClock) -> Result<u32, ClockError> { 526 #[inline]
542 Err(ClockError::NotImplemented { clock: "pll1_clk_div" }) 527 pub fn ensure_pll1_clk_div_active(&self, at_level: &PoweredClock) -> Result<u32, ClockError> {
528 self.ensure_clock_active(&self.pll1_clk_div, "pll1_clk_div", at_level)
543 } 529 }
544 530
545 /// Ensure the `CPU_CLK` or `SYSTEM_CLK` is active 531 /// Ensure the `CPU_CLK` or `SYSTEM_CLK` is active
@@ -811,7 +797,7 @@ impl ClockOperator<'_> {
811 Ok(()) 797 Ok(())
812 } 798 }
813 799
814 /// Configure the FRO16K/clk_16k clock family 800 /// Configure the ROSC/FRO16K/clk_16k clock family
815 fn configure_fro16k_clocks(&mut self) -> Result<(), ClockError> { 801 fn configure_fro16k_clocks(&mut self) -> Result<(), ClockError> {
816 let Some(fro16k) = self.config.fro16k.as_ref() else { 802 let Some(fro16k) = self.config.fro16k.as_ref() else {
817 return Ok(()); 803 return Ok(());
@@ -851,6 +837,485 @@ impl ClockOperator<'_> {
851 837
852 Ok(()) 838 Ok(())
853 } 839 }
840
841 fn ensure_ldo_active(&mut self) {
842 // TODO: Config for the LDO? For now, just enable
843 // using the default settings:
844 // LDOBYPASS: 0/not bypassed
845 // VOUT_SEL: 0b100: 1.1v
846 // LDOEN: 0/Disabled
847 let already_enabled = {
848 let ldocsr = self.scg0.ldocsr().read();
849 ldocsr.ldoen().is_enabled() && ldocsr.vout_ok().is_enabled()
850 };
851 if !already_enabled {
852 self.scg0.ldocsr().modify(|_r, w| w.ldoen().enabled());
853 while self.scg0.ldocsr().read().vout_ok().is_disabled() {}
854 }
855 }
856
857 /// Configure the SOSC/clk_in oscillator
858 fn configure_sosc(&mut self) -> Result<(), ClockError> {
859 let Some(parts) = self.config.sosc.as_ref() else {
860 return Ok(());
861 };
862
863 // Enable (and wait for) LDO to be active
864 self.ensure_ldo_active();
865
866 // TODO: something something pins? This seems to work when the pins are
867 // not enabled, even if GPIO hasn't been initialized at all yet.
868 let eref = match parts.mode {
869 config::SoscMode::CrystalOscillator => pac::scg0::sosccfg::Erefs::Internal,
870 config::SoscMode::ActiveClock => pac::scg0::sosccfg::Erefs::External,
871 };
872 let freq = parts.frequency;
873
874 // TODO: Fix PAC names here
875 //
876 // #[doc = "0: Frequency range select of 8-16 MHz."]
877 // Freq16to20mhz = 0,
878 // #[doc = "1: Frequency range select of 16-25 MHz."]
879 // LowFreq = 1,
880 // #[doc = "2: Frequency range select of 25-40 MHz."]
881 // MediumFreq = 2,
882 // #[doc = "3: Frequency range select of 40-50 MHz."]
883 // HighFreq = 3,
884 let range = match freq {
885 0..8_000_000 => {
886 return Err(ClockError::BadConfig {
887 clock: "clk_in",
888 reason: "freq too low",
889 });
890 }
891 8_000_000..16_000_000 => pac::scg0::sosccfg::Range::Freq16to20mhz,
892 16_000_000..25_000_000 => pac::scg0::sosccfg::Range::LowFreq,
893 25_000_000..40_000_000 => pac::scg0::sosccfg::Range::MediumFreq,
894 40_000_000..50_000_001 => pac::scg0::sosccfg::Range::HighFreq,
895 50_000_001.. => {
896 return Err(ClockError::BadConfig {
897 clock: "clk_in",
898 reason: "freq too high",
899 });
900 }
901 };
902
903 // Set source/erefs and range
904 self.scg0.sosccfg().modify(|_r, w| {
905 w.erefs().variant(eref);
906 w.range().variant(range);
907 w
908 });
909
910 // Disable lock
911 self.scg0.sosccsr().modify(|_r, w| w.lk().clear_bit());
912
913 // TODO: We could enable the SOSC clock monitor. There are some things to
914 // figure out first:
915 //
916 // * This requires SIRC to be enabled, not sure which branch. Maybe fro12m_root?
917 // * If SOSC needs to work in deep sleep, AND the monitor is enabled:
918 // * SIRC also need needs to be low power
919 // * We need to decide if we need an interrupt or a reset if the monitor trips
920
921 // Apply remaining config
922 self.scg0.sosccsr().modify(|_r, w| {
923 // For now, just disable the monitor. See above.
924 w.sosccm().disabled();
925
926 // Set deep sleep mode
927 match parts.power {
928 PoweredClock::NormalEnabledDeepSleepDisabled => {
929 w.soscsten().clear_bit();
930 }
931 PoweredClock::AlwaysEnabled => {
932 w.soscsten().set_bit();
933 }
934 }
935
936 // Enable SOSC
937 w.soscen().enabled()
938 });
939
940 // Wait for SOSC to be valid, check for errors
941 while !self.scg0.sosccsr().read().soscvld().bit_is_set() {}
942 if self.scg0.sosccsr().read().soscerr().is_enabled_and_error() {
943 return Err(ClockError::BadConfig {
944 clock: "clk_in",
945 reason: "soscerr is set",
946 });
947 }
948
949 // Re-lock the sosc
950 self.scg0.sosccsr().modify(|_r, w| w.lk().set_bit());
951
952 self.clocks.clk_in = Some(Clock {
953 frequency: freq,
954 power: parts.power,
955 });
956
957 Ok(())
958 }
959
960 fn configure_spll(&mut self) -> Result<(), ClockError> {
961 // # Vocab
962 //
963 // | Name | Meaning |
964 // | :--- | :--- |
965 // | Fin | Frequency of clkin |
966 // | clkout | Output clock of the PLL |
967 // | Fout | Frequency of clkout (depends on mode) |
968 // | clkref | PLL Reference clock, the input clock to the PFD |
969 // | Fref | Frequency of clkref, Fref = Fin / N |
970 // | Fcco | Frequency of the output clock of the CCO, Fcco = M * Fref |
971 // | N | Predivider value |
972 // | M | Feedback divider value |
973 // | P | Postdivider value |
974 // | Tpon | PLL start-up time |
975
976 // No PLL? Nothing to do!
977 let Some(cfg) = self.config.spll.as_ref() else {
978 return Ok(());
979 };
980
981 // Ensure the LDO is active
982 self.ensure_ldo_active();
983
984 // match on the source, ensure it is active already
985 let res = match cfg.source {
986 config::SpllSource::Sosc => self
987 .clocks
988 .clk_in
989 .as_ref()
990 .map(|c| (c, pac::scg0::spllctrl::Source::Sosc))
991 .ok_or("sosc not active"),
992 config::SpllSource::Firc => self
993 .clocks
994 .clk_45m
995 .as_ref()
996 .map(|c| (c, pac::scg0::spllctrl::Source::Firc))
997 .ok_or("firc not active"),
998 config::SpllSource::Sirc => self
999 .clocks
1000 .fro_12m
1001 .as_ref()
1002 .map(|c| (c, pac::scg0::spllctrl::Source::Sirc))
1003 .ok_or("sirc not active"),
1004 };
1005 // This checks if active
1006 let (clk, variant) = res.map_err(|s| ClockError::BadConfig {
1007 clock: "spll",
1008 reason: s,
1009 })?;
1010 // This checks the correct power reqs
1011 if !clk.power.meets_requirement_of(&cfg.power) {
1012 return Err(ClockError::BadConfig {
1013 clock: "spll",
1014 reason: "needs low power source",
1015 });
1016 }
1017
1018 // Bandwidth calc
1019 //
1020 // > In normal applications, you must calculate the bandwidth manually by using the feedback divider M (ranging from 1 to 216-1),
1021 // > Equation 1, and Equation 2. The PLL is automatically stable in such case. In normal applications, SPLLCTRL[BANDDIRECT] must
1022 // > be 0; in this case, the bandwidth changes as a function of M.
1023 if clk.frequency == 0 {
1024 return Err(ClockError::BadConfig {
1025 clock: "spll",
1026 reason: "internal error",
1027 });
1028 }
1029
1030 // These are calculated differently depending on the mode.
1031 let f_in = clk.frequency;
1032 let bp_pre: bool;
1033 let bp_post: bool;
1034 let bp_post2: bool;
1035 let m: u16;
1036 let p: Option<u8>;
1037 let n: Option<u8>;
1038
1039 // Calculate both Fout and Fcco so we can ensure they don't overflow
1040 // and are in range
1041 let fout: Option<u32>;
1042 let fcco: Option<u32>;
1043
1044 let m_check = |m: u16| {
1045 if !(1..=u16::MAX).contains(&m) {
1046 Err(ClockError::BadConfig {
1047 clock: "spll",
1048 reason: "m_mult out of range",
1049 })
1050 } else {
1051 Ok(m)
1052 }
1053 };
1054 let p_check = |p: u8| {
1055 if !(1..=31).contains(&p) {
1056 Err(ClockError::BadConfig {
1057 clock: "spll",
1058 reason: "p_div out of range",
1059 })
1060 } else {
1061 Ok(p)
1062 }
1063 };
1064 let n_check = |n: u8| {
1065 if !(1..=u8::MAX).contains(&n) {
1066 Err(ClockError::BadConfig {
1067 clock: "spll",
1068 reason: "n_div out of range",
1069 })
1070 } else {
1071 Ok(n)
1072 }
1073 };
1074
1075 match cfg.mode {
1076 // Fout = M x Fin
1077 config::SpllMode::Mode1a { m_mult } => {
1078 bp_pre = true;
1079 bp_post = true;
1080 bp_post2 = false;
1081 m = m_check(m_mult)?;
1082 p = None;
1083 n = None;
1084 fcco = f_in.checked_mul(m_mult as u32);
1085 fout = fcco;
1086 }
1087 // if !bypass_p2_div: Fout = (M / (2 x P)) x Fin
1088 // if bypass_p2_div: Fout = (M / P ) x Fin
1089 config::SpllMode::Mode1b {
1090 m_mult,
1091 p_div,
1092 bypass_p2_div,
1093 } => {
1094 bp_pre = true;
1095 bp_post = false;
1096 bp_post2 = bypass_p2_div;
1097 m = m_check(m_mult)?;
1098 p = Some(p_check(p_div)?);
1099 n = None;
1100 let mut div = p_div as u32;
1101 if !bypass_p2_div {
1102 div *= 2;
1103 }
1104 fcco = f_in.checked_mul(m_mult as u32);
1105 fout = (f_in / div).checked_mul(m_mult as u32);
1106 }
1107 // Fout = (M / N) x Fin
1108 config::SpllMode::Mode1c { m_mult, n_div } => {
1109 bp_pre = false;
1110 bp_post = true;
1111 bp_post2 = false;
1112 m = m_check(m_mult)?;
1113 p = None;
1114 n = Some(n_check(n_div)?);
1115 fcco = (f_in / (n_div as u32)).checked_mul(m_mult as u32);
1116 fout = fcco;
1117 }
1118 // if !bypass_p2_div: Fout = (M / (N x 2 x P)) x Fin
1119 // if bypass_p2_div: Fout = (M / ( N x P )) x Fin
1120 config::SpllMode::Mode1d {
1121 m_mult,
1122 n_div,
1123 p_div,
1124 bypass_p2_div,
1125 } => {
1126 bp_pre = false;
1127 bp_post = false;
1128 bp_post2 = bypass_p2_div;
1129 m = m_check(m_mult)?;
1130 p = Some(p_check(p_div)?);
1131 n = Some(n_check(n_div)?);
1132 // This can't overflow: u8 x u8 (x 2) always fits in u32
1133 let mut div = (p_div as u32) * (n_div as u32);
1134 if !bypass_p2_div {
1135 div *= 2;
1136 }
1137 fcco = (f_in / (n_div as u32)).checked_mul(m_mult as u32);
1138 fout = (f_in / div).checked_mul(m_mult as u32);
1139 }
1140 };
1141
1142 // Dump all the PLL calcs if needed for debugging
1143 #[cfg(feature = "defmt")]
1144 {
1145 defmt::debug!("f_in: {:?}", f_in);
1146 defmt::debug!("bp_pre: {:?}", bp_pre);
1147 defmt::debug!("bp_post: {:?}", bp_post);
1148 defmt::debug!("bp_post2: {:?}", bp_post2);
1149 defmt::debug!("m: {:?}", m);
1150 defmt::debug!("p: {:?}", p);
1151 defmt::debug!("n: {:?}", n);
1152 defmt::debug!("fout: {:?}", fout);
1153 defmt::debug!("fcco: {:?}", fcco);
1154 }
1155
1156 // Ensure the Fcco and Fout calcs didn't overflow
1157 let fcco = fcco.ok_or(ClockError::BadConfig {
1158 clock: "spll",
1159 reason: "fcco invalid1",
1160 })?;
1161 let fout = fout.ok_or(ClockError::BadConfig {
1162 clock: "spll",
1163 reason: "fout invalid",
1164 })?;
1165
1166 // Fcco: 275MHz to 550MHz
1167 if !(275_000_000..=550_000_000).contains(&fcco) {
1168 return Err(ClockError::BadConfig {
1169 clock: "spll",
1170 reason: "fcco invalid2",
1171 });
1172 }
1173
1174 // TODO: Different for different CPUs?
1175 const CPU_MAX_FREQ: u32 = 180_000_000;
1176
1177 // Fout: 4.3MHz to 2x Max CPU Frequency
1178 if !(4_300_000..=(2 * CPU_MAX_FREQ)).contains(&fout) {
1179 return Err(ClockError::BadConfig {
1180 clock: "spll",
1181 reason: "fout invalid",
1182 });
1183 }
1184
1185 // A = floor(m / 4) + 1
1186 let selp_a = (m / 4) + 1;
1187 // SELP = A if A < 31
1188 // = 31 if A >= 31
1189 let selp = selp_a.min(31);
1190
1191 // A = 1 if M >= 8000
1192 // = floor(8000 / M) if 8000 > M >= 122
1193 // = 2 x floor(M / 4) / 3 if 122 > M >= 1
1194 let seli_a = if m >= 8000 {
1195 1
1196 } else if m >= 122 {
1197 8000 / m
1198 } else {
1199 (2 * (m / 4)) / 3
1200 };
1201 // SELI = A if A < 63
1202 // = 63 if A >= 63
1203 let seli = seli_a.min(63);
1204 // SELR must be 0.
1205 let selr = 0;
1206
1207 self.scg0.spllctrl().modify(|_r, w| {
1208 w.source().variant(variant);
1209 unsafe {
1210 w.selp().bits(selp as u8);
1211 w.seli().bits(seli as u8);
1212 w.selr().bits(selr);
1213 }
1214 w
1215 });
1216
1217 if let Some(n) = n {
1218 self.scg0.spllndiv().modify(|_r, w| unsafe { w.ndiv().bits(n) });
1219 }
1220 if let Some(p) = p {
1221 self.scg0.spllpdiv().modify(|_r, w| unsafe { w.pdiv().bits(p) });
1222 }
1223 self.scg0.spllmdiv().modify(|_r, w| unsafe { w.mdiv().bits(m) });
1224
1225 self.scg0.spllctrl().modify(|_r, w| {
1226 w.bypassprediv().bit(bp_pre);
1227 w.bypasspostdiv().bit(bp_post);
1228 w.bypasspostdiv2().bit(bp_post2);
1229
1230 // TODO: support FRM?
1231 w.frm().disabled();
1232
1233 w
1234 });
1235
1236 // Unlock
1237 self.scg0.spllcsr().modify(|_r, w| w.lk().write_enabled());
1238
1239 // TODO: Support clock monitors?
1240 // self.scg0.spllcsr().modify(|_r, w| w.spllcm().?);
1241
1242 self.scg0.trim_lock().write(|w| unsafe {
1243 w.trim_lock_key().bits(0x5a5a);
1244 w.trim_unlock().not_locked()
1245 });
1246
1247 // SPLLLOCK_CNFG: The lock time programmed in this register must be
1248 // equal to meet the PLL 500μs lock time plus the 300 refclk count startup.
1249 //
1250 // LOCK_TIME = 500μs/T ref + 300, F ref = F in /N (input frequency divided by pre-divider ratio).
1251 //
1252 // 500us is 1/2000th of a second, therefore Fref / 2000 is the number of cycles in 500us.
1253 let f_ref = if let Some(n) = n { f_in / (n as u32) } else { f_in };
1254 let lock_time = f_ref.div_ceil(2000) + 300;
1255 self.scg0
1256 .splllock_cnfg()
1257 .write(|w| unsafe { w.lock_time().bits(lock_time) });
1258
1259 // TODO: Support Spread spectrum?
1260
1261 self.scg0.spllcsr().modify(|_r, w| {
1262 w.spllclken().enabled();
1263 w.spllpwren().enabled();
1264 w.spllsten().bit(matches!(cfg.power, PoweredClock::AlwaysEnabled));
1265 w
1266 });
1267
1268 // Wait for SPLL to set up
1269 loop {
1270 let csr = self.scg0.spllcsr().read();
1271 if csr.spll_lock().is_enabled_and_valid() {
1272 if csr.spllerr().is_enabled_and_error() {
1273 return Err(ClockError::BadConfig {
1274 clock: "spll",
1275 reason: "spllerr is set",
1276 });
1277 }
1278 break;
1279 }
1280 }
1281
1282 // Re-lock SPLL CSR
1283 self.scg0.spllcsr().modify(|_r, w| w.lk().write_disabled());
1284
1285 // Store clock state
1286 self.clocks.pll1_clk = Some(Clock {
1287 frequency: fout,
1288 power: cfg.power,
1289 });
1290
1291 // Do we enable the `pll1_clk_div` output?
1292 if let Some(d) = cfg.pll1_clk_div.as_ref() {
1293 // Halt and reset the div; then set our desired div.
1294 self.syscon.pll1clkdiv().write(|w| {
1295 w.halt().halt();
1296 w.reset().asserted();
1297 unsafe { w.div().bits(d.into_bits()) };
1298 w
1299 });
1300 // Then unhalt it, and reset it
1301 self.syscon.pll1clkdiv().write(|w| {
1302 w.halt().run();
1303 w.reset().released();
1304 w
1305 });
1306
1307 // Wait for clock to stabilize
1308 while self.syscon.pll1clkdiv().read().unstab().is_ongoing() {}
1309
1310 // Store off the clock info
1311 self.clocks.pll1_clk_div = Some(Clock {
1312 frequency: fout / d.into_divisor(),
1313 power: cfg.power,
1314 });
1315 }
1316
1317 Ok(())
1318 }
854} 1319}
855 1320
856// 1321//
diff --git a/embassy-mcxa/src/dma.rs b/embassy-mcxa/src/dma.rs
index 8d519d99b..b68f55e65 100644
--- a/embassy-mcxa/src/dma.rs
+++ b/embassy-mcxa/src/dma.rs
@@ -1924,7 +1924,7 @@ impl Iterator for TransferErrorRawIter {
1924 1924
1925 for (mask, var) in TransferErrorRaw::MAP { 1925 for (mask, var) in TransferErrorRaw::MAP {
1926 // If the bit is set... 1926 // If the bit is set...
1927 if self.0 | mask != 0 { 1927 if self.0 & mask != 0 {
1928 // clear the bit 1928 // clear the bit
1929 self.0 &= !mask; 1929 self.0 &= !mask;
1930 // and return the answer 1930 // and return the answer
diff --git a/embassy-mcxa/src/gpio.rs b/embassy-mcxa/src/gpio.rs
index 65f8df985..29d66656d 100644
--- a/embassy-mcxa/src/gpio.rs
+++ b/embassy-mcxa/src/gpio.rs
@@ -81,7 +81,7 @@ fn GPIO4() {
81 irq_handler(4, crate::pac::Gpio4::ptr()); 81 irq_handler(4, crate::pac::Gpio4::ptr());
82} 82}
83 83
84pub(crate) unsafe fn init() { 84pub(crate) unsafe fn interrupt_init() {
85 use embassy_hal_internal::interrupt::InterruptExt; 85 use embassy_hal_internal::interrupt::InterruptExt;
86 86
87 crate::pac::interrupt::GPIO0.enable(); 87 crate::pac::interrupt::GPIO0.enable();
@@ -320,8 +320,12 @@ impl GpioPin for AnyPin {}
320 320
321macro_rules! impl_pin { 321macro_rules! impl_pin {
322 ($peri:ident, $port:expr, $pin:expr, $block:ident) => { 322 ($peri:ident, $port:expr, $pin:expr, $block:ident) => {
323 impl_pin!(crate::peripherals, $peri, $port, $pin, $block);
324 };
325
326 ($perip:path, $peri:ident, $port:expr, $pin:expr, $block:ident) => {
323 paste! { 327 paste! {
324 impl SealedPin for crate::peripherals::$peri { 328 impl SealedPin for $perip::$peri {
325 fn pin_port(&self) -> usize { 329 fn pin_port(&self) -> usize {
326 $port * 32 + $pin 330 $port * 32 + $pin
327 } 331 }
@@ -372,15 +376,15 @@ macro_rules! impl_pin {
372 } 376 }
373 } 377 }
374 378
375 impl GpioPin for crate::peripherals::$peri {} 379 impl GpioPin for $perip::$peri {}
376 380
377 impl From<crate::peripherals::$peri> for AnyPin { 381 impl From<$perip::$peri> for AnyPin {
378 fn from(value: crate::peripherals::$peri) -> Self { 382 fn from(value: $perip::$peri) -> Self {
379 value.degrade() 383 value.degrade()
380 } 384 }
381 } 385 }
382 386
383 impl crate::peripherals::$peri { 387 impl $perip::$peri {
384 /// Convenience helper to obtain a type-erased handle to this pin. 388 /// Convenience helper to obtain a type-erased handle to this pin.
385 pub fn degrade(&self) -> AnyPin { 389 pub fn degrade(&self) -> AnyPin {
386 AnyPin::new(self.port(), self.pin(), self.gpio(), self.port_reg(), self.pcr_reg()) 390 AnyPin::new(self.port(), self.pin(), self.gpio(), self.port_reg(), self.pcr_reg())
@@ -453,8 +457,8 @@ impl_pin!(P1_26, 1, 26, Gpio1);
453impl_pin!(P1_27, 1, 27, Gpio1); 457impl_pin!(P1_27, 1, 27, Gpio1);
454impl_pin!(P1_28, 1, 28, Gpio1); 458impl_pin!(P1_28, 1, 28, Gpio1);
455impl_pin!(P1_29, 1, 29, Gpio1); 459impl_pin!(P1_29, 1, 29, Gpio1);
456impl_pin!(P1_30, 1, 30, Gpio1); 460impl_pin!(crate::internal_peripherals, P1_30, 1, 30, Gpio1);
457impl_pin!(P1_31, 1, 31, Gpio1); 461impl_pin!(crate::internal_peripherals, P1_31, 1, 31, Gpio1);
458 462
459impl_pin!(P2_0, 2, 0, Gpio2); 463impl_pin!(P2_0, 2, 0, Gpio2);
460impl_pin!(P2_1, 2, 1, Gpio2); 464impl_pin!(P2_1, 2, 1, Gpio2);
diff --git a/embassy-mcxa/src/i2c/mod.rs b/embassy-mcxa/src/i2c/mod.rs
index 9a014224a..55c933f71 100644
--- a/embassy-mcxa/src/i2c/mod.rs
+++ b/embassy-mcxa/src/i2c/mod.rs
@@ -180,8 +180,11 @@ impl_pin!(P1_12, LPI2C1, Mux2, SdaPin);
180impl_pin!(P1_13, LPI2C1, Mux2, SclPin); 180impl_pin!(P1_13, LPI2C1, Mux2, SclPin);
181impl_pin!(P1_14, LPI2C1, Mux2, SclPin); 181impl_pin!(P1_14, LPI2C1, Mux2, SclPin);
182impl_pin!(P1_15, LPI2C1, Mux2, SdaPin); 182impl_pin!(P1_15, LPI2C1, Mux2, SdaPin);
183impl_pin!(P1_30, LPI2C0, Mux3, SdaPin); 183// NOTE: P1_30 and P1_31 are typically used for the external oscillator
184impl_pin!(P1_31, LPI2C0, Mux3, SclPin); 184// For now, we just don't give users these pins.
185//
186// impl_pin!(P1_30, LPI2C0, Mux3, SdaPin);
187// impl_pin!(P1_31, LPI2C0, Mux3, SclPin);
185impl_pin!(P3_27, LPI2C3, Mux2, SclPin); 188impl_pin!(P3_27, LPI2C3, Mux2, SclPin);
186impl_pin!(P3_28, LPI2C3, Mux2, SdaPin); 189impl_pin!(P3_28, LPI2C3, Mux2, SdaPin);
187// impl_pin!(P3_29, LPI2C3, Mux2, HreqPin); What is this HREQ pin? 190// impl_pin!(P3_29, LPI2C3, Mux2, HreqPin); What is this HREQ pin?
diff --git a/embassy-mcxa/src/lib.rs b/embassy-mcxa/src/lib.rs
index 6383353db..76fd58210 100644
--- a/embassy-mcxa/src/lib.rs
+++ b/embassy-mcxa/src/lib.rs
@@ -175,8 +175,18 @@ embassy_hal_internal::peripherals!(
175 P1_27, 175 P1_27,
176 P1_28, 176 P1_28,
177 P1_29, 177 P1_29,
178 P1_30, 178 // TODO: These pins are optionally used as the clock sources for SOSC.
179 P1_31, 179 // Ideally, we'd want to have a custom version of the `peripheral!` macro
180 // that presented these as `Option<Peri<'_, P1_30>>` instead of `Peri<'_, P1_30>`
181 // when the user DOES enable the external SOSC. For now, I'm guessing MOST designs
182 // will have an external clock sitting on these pins anyway, so we just notch them
183 // out from the `Peripherals` struct given to users.
184 //
185 // If you find this and want your extra two pins to be available: please open an
186 // embassy issue to discuss how we could do this.
187 //
188 // P1_30,
189 // P1_31,
180 190
181 P2_0, 191 P2_0,
182 P2_1, 192 P2_1,
@@ -337,6 +347,14 @@ embassy_hal_internal::peripherals!(
337 WWDT0, 347 WWDT0,
338); 348);
339 349
350// See commented out items above to understand why we create the instances
351// here but don't give them to the user.
352pub(crate) mod internal_peripherals {
353 embassy_hal_internal::peripherals_definition!(P1_30, P1_31,);
354
355 pub(crate) use peripherals::*;
356}
357
340// Use cortex-m-rt's #[interrupt] attribute directly; PAC does not re-export it. 358// Use cortex-m-rt's #[interrupt] attribute directly; PAC does not re-export it.
341 359
342// Re-export interrupt traits and types 360// Re-export interrupt traits and types
@@ -369,7 +387,7 @@ pub fn init(cfg: crate::config::Config) -> Peripherals {
369 crate::clocks::init(cfg.clock_cfg).unwrap(); 387 crate::clocks::init(cfg.clock_cfg).unwrap();
370 388
371 unsafe { 389 unsafe {
372 crate::gpio::init(); 390 crate::gpio::interrupt_init();
373 } 391 }
374 392
375 // Initialize DMA controller (clock, reset, configuration) 393 // Initialize DMA controller (clock, reset, configuration)
diff --git a/embassy-mcxa/src/lpuart/mod.rs b/embassy-mcxa/src/lpuart/mod.rs
index bce3986b5..ae511e8d3 100644
--- a/embassy-mcxa/src/lpuart/mod.rs
+++ b/embassy-mcxa/src/lpuart/mod.rs
@@ -568,6 +568,27 @@ pub enum Error {
568 ClockSetup(ClockError), 568 ClockSetup(ClockError),
569} 569}
570 570
571impl core::fmt::Display for Error {
572 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
573 match self {
574 Error::Read => write!(f, "Read error"),
575 Error::Overrun => write!(f, "Buffer overflow"),
576 Error::Noise => write!(f, "Noise error"),
577 Error::Framing => write!(f, "Framing error"),
578 Error::Parity => write!(f, "Parity error"),
579 Error::Fail => write!(f, "Failure"),
580 Error::InvalidArgument => write!(f, "Invalid argument"),
581 Error::UnsupportedBaudrate => write!(f, "Unsupported baud rate"),
582 Error::RxFifoEmpty => write!(f, "RX FIFO empty"),
583 Error::TxFifoFull => write!(f, "TX FIFO full"),
584 Error::TxBusy => write!(f, "TX busy"),
585 Error::ClockSetup(e) => write!(f, "Clock setup error: {:?}", e),
586 }
587 }
588}
589
590impl core::error::Error for Error {}
591
571/// A specialized Result type for LPUART operations 592/// A specialized Result type for LPUART operations
572pub type Result<T> = core::result::Result<T, Error>; 593pub type Result<T> = core::result::Result<T, Error>;
573 594
diff --git a/embassy-mcxa/src/reset_reason.rs b/embassy-mcxa/src/reset_reason.rs
index f9a9ce096..1787690a7 100644
--- a/embassy-mcxa/src/reset_reason.rs
+++ b/embassy-mcxa/src/reset_reason.rs
@@ -6,45 +6,158 @@
6 6
7/// Reads the most recent reset reason from the Core Mode Controller 7/// Reads the most recent reset reason from the Core Mode Controller
8/// (CMC). 8/// (CMC).
9pub fn reset_reason() -> ResetReason { 9pub fn reset_reason() -> ResetReasonRaw {
10 let regs = unsafe { &*crate::pac::Cmc::steal() }; 10 let regs = unsafe { &*crate::pac::Cmc::steal() };
11 let srs = regs.srs().read().bits();
12 ResetReasonRaw(srs)
13}
14
15/// Raw reset reason bits. Can be queried or all reasons can be iterated over
16#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17#[derive(Copy, Clone, Debug)]
18pub struct ResetReasonRaw(u32);
19
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21#[derive(Copy, Clone, Debug)]
22pub struct ResetReasonRawIter(u32);
23
24impl ResetReasonRaw {
25 const MAP: &[(u32, ResetReason)] = &[
26 (1 << 0, ResetReason::WakeUp),
27 (1 << 1, ResetReason::Por),
28 (1 << 2, ResetReason::VoltageDetect),
29 (1 << 4, ResetReason::Warm),
30 (1 << 5, ResetReason::Fatal),
31 (1 << 8, ResetReason::Pin),
32 (1 << 9, ResetReason::Dap),
33 (1 << 10, ResetReason::ResetAckTimeout),
34 (1 << 11, ResetReason::LowPowerAckTimeout),
35 (1 << 12, ResetReason::SystemClockGeneration),
36 (1 << 13, ResetReason::Wwdt0),
37 (1 << 14, ResetReason::Software),
38 (1 << 15, ResetReason::Lockup),
39 (1 << 26, ResetReason::Cdog0),
40 (1 << 27, ResetReason::Cdog1),
41 (1 << 28, ResetReason::Jtag),
42 ];
43
44 /// Convert to an iterator of contained reset reasons
45 pub fn into_iter(self) -> ResetReasonRawIter {
46 ResetReasonRawIter(self.0)
47 }
48
49 /// Wake up
50 #[inline]
51 pub fn is_wakeup(&self) -> bool {
52 (self.0 & (1 << 0)) != 0
53 }
54
55 /// Power-on Reset
56 #[inline]
57 pub fn is_por(&self) -> bool {
58 (self.0 & (1 << 1)) != 0
59 }
60
61 /// Voltage detect
62 #[inline]
63 pub fn is_voltage_detect(&self) -> bool {
64 (self.0 & (1 << 2)) != 0
65 }
66
67 /// Warm
68 #[inline]
69 pub fn is_warm(&self) -> bool {
70 (self.0 & (1 << 4)) != 0
71 }
72
73 /// Fatal
74 #[inline]
75 pub fn is_fatal(&self) -> bool {
76 (self.0 & (1 << 5)) != 0
77 }
78
79 /// Pin
80 #[inline]
81 pub fn is_pin(&self) -> bool {
82 (self.0 & (1 << 8)) != 0
83 }
84
85 /// DAP
86 #[inline]
87 pub fn is_dap(&self) -> bool {
88 (self.0 & (1 << 9)) != 0
89 }
90
91 /// Reset ack timeout
92 #[inline]
93 pub fn is_reset_ack_timeout(&self) -> bool {
94 (self.0 & (1 << 10)) != 0
95 }
96
97 /// Low power ack timeout
98 #[inline]
99 pub fn is_low_power_ack_timeout(&self) -> bool {
100 (self.0 & (1 << 11)) != 0
101 }
102
103 /// System clock generation
104 #[inline]
105 pub fn is_system_clock_generation(&self) -> bool {
106 (self.0 & (1 << 12)) != 0
107 }
108
109 /// Watchdog 0
110 #[inline]
111 pub fn is_watchdog0(&self) -> bool {
112 (self.0 & (1 << 13)) != 0
113 }
114
115 /// Software
116 pub fn is_software(&self) -> bool {
117 (self.0 & (1 << 14)) != 0
118 }
119
120 /// Lockup
121 pub fn is_lockup(&self) -> bool {
122 (self.0 & (1 << 15)) != 0
123 }
124
125 /// Code watchdog 0
126 pub fn is_code_watchdog0(&self) -> bool {
127 (self.0 & (1 << 26)) != 0
128 }
129
130 /// Code watchdog 1
131 pub fn is_code_watchdog1(&self) -> bool {
132 (self.0 & (1 << 27)) != 0
133 }
134
135 /// JTAG
136 pub fn is_jtag(&self) -> bool {
137 (self.0 & (1 << 28)) != 0
138 }
139}
11 140
12 let srs = regs.srs().read(); 141impl Iterator for ResetReasonRawIter {
13 142 type Item = ResetReason;
14 if srs.wakeup().is_enabled() { 143
15 ResetReason::WakeUp 144 fn next(&mut self) -> Option<Self::Item> {
16 } else if srs.por().bit_is_set() { 145 if self.0 == 0 {
17 ResetReason::Por 146 return None;
18 } else if srs.vd().bit_is_set() { 147 }
19 ResetReason::VoltageDetect 148
20 } else if srs.warm().bit_is_set() { 149 for (mask, var) in ResetReasonRaw::MAP {
21 ResetReason::Warm 150 // If the bit is set...
22 } else if srs.fatal().bit_is_set() { 151 if self.0 & mask != 0 {
23 ResetReason::Fatal 152 // clear the bit
24 } else if srs.pin().bit_is_set() { 153 self.0 &= !mask;
25 ResetReason::Pin 154 // and return the answer
26 } else if srs.dap().bit_is_set() { 155 return Some(*var);
27 ResetReason::Dap 156 }
28 } else if srs.rstack().bit_is_set() { 157 }
29 ResetReason::ResetAckTimeout 158
30 } else if srs.lpack().bit_is_set() { 159 // Shouldn't happen, but oh well.
31 ResetReason::LowPowerAckTimeout 160 None
32 } else if srs.scg().bit_is_set() {
33 ResetReason::SystemClockGeneration
34 } else if srs.wwdt0().bit_is_set() {
35 ResetReason::Wwdt0
36 } else if srs.sw().bit_is_set() {
37 ResetReason::Software
38 } else if srs.lockup().bit_is_set() {
39 ResetReason::Lockup
40 } else if srs.cdog0().bit_is_set() {
41 ResetReason::Cdog0
42 } else if srs.cdog1().bit_is_set() {
43 ResetReason::Cdog1
44 } else if srs.jtag().bit_is_set() {
45 ResetReason::Jtag
46 } else {
47 ResetReason::Tamper
48 } 161 }
49} 162}
50 163
diff --git a/embassy-mspm0/Cargo.toml b/embassy-mspm0/Cargo.toml
index cf2346328..c7f5de6a1 100644
--- a/embassy-mspm0/Cargo.toml
+++ b/embassy-mspm0/Cargo.toml
@@ -61,8 +61,8 @@ embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["un
61embedded-hal = { version = "1.0" } 61embedded-hal = { version = "1.0" }
62embedded-hal-nb = { version = "1.0" } 62embedded-hal-nb = { version = "1.0" }
63embedded-hal-async = { version = "1.0" } 63embedded-hal-async = { version = "1.0" }
64embedded-io = "0.6.1" 64embedded-io = { version = "0.7.1" }
65embedded-io-async = "0.6.1" 65embedded-io-async = { version = "0.7.0" }
66 66
67defmt = { version = "1.0.1", optional = true } 67defmt = { version = "1.0.1", optional = true }
68fixed = "1.29" 68fixed = "1.29"
diff --git a/embassy-mspm0/src/uart/buffered.rs b/embassy-mspm0/src/uart/buffered.rs
index 89e6bcc7b..d1b75b177 100644
--- a/embassy-mspm0/src/uart/buffered.rs
+++ b/embassy-mspm0/src/uart/buffered.rs
@@ -436,6 +436,10 @@ impl embedded_io_async::Write for BufferedUart<'_> {
436 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { 436 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
437 self.tx.write_inner(buf).await 437 self.tx.write_inner(buf).await
438 } 438 }
439
440 async fn flush(&mut self) -> Result<(), Self::Error> {
441 self.tx.flush_inner().await
442 }
439} 443}
440 444
441impl embedded_io_async::Write for BufferedUartTx<'_> { 445impl embedded_io_async::Write for BufferedUartTx<'_> {
diff --git a/embassy-net-nrf91/Cargo.toml b/embassy-net-nrf91/Cargo.toml
index 349ff2880..c5c582fc3 100644
--- a/embassy-net-nrf91/Cargo.toml
+++ b/embassy-net-nrf91/Cargo.toml
@@ -27,7 +27,7 @@ embassy-futures = { version = "0.1.2", path = "../embassy-futures" }
27embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } 27embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" }
28 28
29heapless = "0.8" 29heapless = "0.8"
30embedded-io = "0.6.1" 30embedded-io = { version = "0.7.1" }
31at-commands = "0.5.4" 31at-commands = "0.5.4"
32 32
33[package.metadata.embassy] 33[package.metadata.embassy]
diff --git a/embassy-net-ppp/Cargo.toml b/embassy-net-ppp/Cargo.toml
index 45ee2f6b5..1dda5017f 100644
--- a/embassy-net-ppp/Cargo.toml
+++ b/embassy-net-ppp/Cargo.toml
@@ -17,7 +17,7 @@ log = ["dep:log", "ppproto/log"]
17defmt = { version = "1.0.1", optional = true } 17defmt = { version = "1.0.1", optional = true }
18log = { version = "0.4.14", optional = true } 18log = { version = "0.4.14", optional = true }
19 19
20embedded-io-async = { version = "0.6.1" } 20embedded-io-async = { version = "0.7.0" }
21embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" } 21embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-channel" }
22embassy-futures = { version = "0.1.2", path = "../embassy-futures" } 22embassy-futures = { version = "0.1.2", path = "../embassy-futures" }
23ppproto = { version = "0.2.1"} 23ppproto = { version = "0.2.1"}
diff --git a/embassy-net/Cargo.toml b/embassy-net/Cargo.toml
index 4c8075c43..d66ba1133 100644
--- a/embassy-net/Cargo.toml
+++ b/embassy-net/Cargo.toml
@@ -109,9 +109,9 @@ smoltcp = { version = "0.12.0", default-features = false, features = [
109embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" } 109embassy-net-driver = { version = "0.2.0", path = "../embassy-net-driver" }
110embassy-time = { version = "0.5.0", path = "../embassy-time" } 110embassy-time = { version = "0.5.0", path = "../embassy-time" }
111embassy-sync = { version = "0.7.2", path = "../embassy-sync" } 111embassy-sync = { version = "0.7.2", path = "../embassy-sync" }
112embedded-io-async = { version = "0.6.1" } 112embedded-io-async = { version = "0.7.0" }
113 113
114managed = { version = "0.8.0", default-features = false, features = [ "map" ] } 114managed = { version = "0.8.0", default-features = false, features = [ "map" ] }
115heapless = { version = "0.8", default-features = false } 115heapless = { version = "0.8", default-features = false }
116embedded-nal-async = "0.8.0" 116embedded-nal-async = "0.9.0"
117document-features = "0.2.7" 117document-features = "0.2.7"
diff --git a/embassy-net/src/tcp.rs b/embassy-net/src/tcp.rs
index b4db7b88c..74672df1c 100644
--- a/embassy-net/src/tcp.rs
+++ b/embassy-net/src/tcp.rs
@@ -670,6 +670,13 @@ impl<'d> TcpIo<'d> {
670mod embedded_io_impls { 670mod embedded_io_impls {
671 use super::*; 671 use super::*;
672 672
673 impl core::fmt::Display for ConnectError {
674 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
675 f.write_str("ConnectError")
676 }
677 }
678 impl core::error::Error for ConnectError {}
679
673 impl embedded_io_async::Error for ConnectError { 680 impl embedded_io_async::Error for ConnectError {
674 fn kind(&self) -> embedded_io_async::ErrorKind { 681 fn kind(&self) -> embedded_io_async::ErrorKind {
675 match self { 682 match self {
@@ -681,6 +688,15 @@ mod embedded_io_impls {
681 } 688 }
682 } 689 }
683 690
691 impl core::fmt::Display for Error {
692 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
693 match self {
694 Self::ConnectionReset => f.write_str("ConnectionReset"),
695 }
696 }
697 }
698 impl core::error::Error for Error {}
699
684 impl embedded_io_async::Error for Error { 700 impl embedded_io_async::Error for Error {
685 fn kind(&self) -> embedded_io_async::ErrorKind { 701 fn kind(&self) -> embedded_io_async::ErrorKind {
686 match self { 702 match self {
diff --git a/embassy-nrf/CHANGELOG.md b/embassy-nrf/CHANGELOG.md
index 0d7bfb5f0..921835417 100644
--- a/embassy-nrf/CHANGELOG.md
+++ b/embassy-nrf/CHANGELOG.md
@@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8<!-- next-header --> 8<!-- next-header -->
9## Unreleased - ReleaseDate 9## Unreleased - ReleaseDate
10 10
11- bugfix: avoid hang if calling now() before syscounter is enabled on nrf54
12
11## 0.9.0 - 2025-12-15 13## 0.9.0 - 2025-12-15
12 14
13- changed: apply trimming values from FICR.TRIMCNF on nrf53/54l 15- changed: apply trimming values from FICR.TRIMCNF on nrf53/54l
diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml
index f8a6ef864..a8070aa45 100644
--- a/embassy-nrf/Cargo.toml
+++ b/embassy-nrf/Cargo.toml
@@ -217,8 +217,8 @@ embassy-futures = { version = "0.1.2", path = "../embassy-futures", optional = t
217embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 217embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
218embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 218embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
219embedded-hal-async = { version = "1.0" } 219embedded-hal-async = { version = "1.0" }
220embedded-io = { version = "0.6.0" } 220embedded-io = { version = "0.7.1" }
221embedded-io-async = { version = "0.6.1" } 221embedded-io-async = { version = "0.7.0" }
222 222
223rand-core-06 = { package = "rand_core", version = "0.6" } 223rand-core-06 = { package = "rand_core", version = "0.6" }
224rand-core-09 = { package = "rand_core", version = "0.9" } 224rand-core-09 = { package = "rand_core", version = "0.9" }
diff --git a/embassy-nrf/src/buffered_uarte/v1.rs b/embassy-nrf/src/buffered_uarte/v1.rs
index ec360f7d0..c14cdfadb 100644
--- a/embassy-nrf/src/buffered_uarte/v1.rs
+++ b/embassy-nrf/src/buffered_uarte/v1.rs
@@ -874,6 +874,15 @@ impl<'a> Drop for BufferedUarteRx<'a> {
874 } 874 }
875} 875}
876 876
877impl core::fmt::Display for Error {
878 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
879 match *self {
880 Error::Overrun => write!(f, "Buffer Overrun"),
881 }
882 }
883}
884impl core::error::Error for Error {}
885
877mod _embedded_io { 886mod _embedded_io {
878 use super::*; 887 use super::*;
879 888
diff --git a/embassy-nrf/src/buffered_uarte/v2.rs b/embassy-nrf/src/buffered_uarte/v2.rs
index d0d2d97d1..4a6360b69 100644
--- a/embassy-nrf/src/buffered_uarte/v2.rs
+++ b/embassy-nrf/src/buffered_uarte/v2.rs
@@ -50,6 +50,14 @@ pub enum Error {
50 // No errors for now 50 // No errors for now
51} 51}
52 52
53impl core::fmt::Display for Error {
54 fn fmt(&self, _f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
55 match *self {}
56 }
57}
58
59impl core::error::Error for Error {}
60
53impl State { 61impl State {
54 pub(crate) const fn new() -> Self { 62 pub(crate) const fn new() -> Self {
55 Self { 63 Self {
diff --git a/embassy-nrf/src/time_driver.rs b/embassy-nrf/src/time_driver.rs
index 35f65bd64..21d94cc30 100644
--- a/embassy-nrf/src/time_driver.rs
+++ b/embassy-nrf/src/time_driver.rs
@@ -79,6 +79,10 @@ fn calc_now(period: u32, counter: u32) -> u64 {
79#[cfg(feature = "_grtc")] 79#[cfg(feature = "_grtc")]
80fn syscounter() -> u64 { 80fn syscounter() -> u64 {
81 let r = rtc(); 81 let r = rtc();
82 if !r.mode().read().syscounteren() {
83 return 0;
84 }
85
82 r.syscounter(0).active().write(|w| w.set_active(true)); 86 r.syscounter(0).active().write(|w| w.set_active(true));
83 loop { 87 loop {
84 let countl: u32 = r.syscounter(0).syscounterl().read(); 88 let countl: u32 = r.syscounter(0).syscounterl().read();
diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs
index 049830aed..ef5d6c6d1 100644
--- a/embassy-nrf/src/uarte.rs
+++ b/embassy-nrf/src/uarte.rs
@@ -1092,6 +1092,20 @@ mod eh02 {
1092 } 1092 }
1093} 1093}
1094 1094
1095impl core::fmt::Display for Error {
1096 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1097 match *self {
1098 Self::BufferTooLong => f.write_str("BufferTooLong"),
1099 Self::BufferNotInRAM => f.write_str("BufferNotInRAM"),
1100 Self::Framing => f.write_str("Framing"),
1101 Self::Parity => f.write_str("Parity"),
1102 Self::Overrun => f.write_str("Overrun"),
1103 Self::Break => f.write_str("Break"),
1104 }
1105 }
1106}
1107impl core::error::Error for Error {}
1108
1095mod _embedded_io { 1109mod _embedded_io {
1096 use super::*; 1110 use super::*;
1097 1111
@@ -1121,6 +1135,9 @@ mod _embedded_io {
1121 self.write(buf).await?; 1135 self.write(buf).await?;
1122 Ok(buf.len()) 1136 Ok(buf.len())
1123 } 1137 }
1138 async fn flush(&mut self) -> Result<(), Self::Error> {
1139 Ok(())
1140 }
1124 } 1141 }
1125 1142
1126 impl<'d> embedded_io_async::Write for UarteTx<'d> { 1143 impl<'d> embedded_io_async::Write for UarteTx<'d> {
@@ -1128,5 +1145,8 @@ mod _embedded_io {
1128 self.write(buf).await?; 1145 self.write(buf).await?;
1129 Ok(buf.len()) 1146 Ok(buf.len())
1130 } 1147 }
1148 async fn flush(&mut self) -> Result<(), Self::Error> {
1149 Ok(())
1150 }
1131 } 1151 }
1132} 1152}
diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml
index b78c26c77..d5ef38531 100644
--- a/embassy-nxp/Cargo.toml
+++ b/embassy-nxp/Cargo.toml
@@ -35,7 +35,7 @@ log = { version = "0.4.27", optional = true }
35embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true } 35embassy-time = { version = "0.5.0", path = "../embassy-time", optional = true }
36embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true } 36embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true }
37embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true } 37embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-utils", optional = true }
38embedded-io = "0.6.1" 38embedded-io = { version = "0.7.1" }
39embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 39embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
40## Chip dependencies 40## Chip dependencies
41nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "af5122e1cbe1483833c5d2e5af96b26a34ed5d62"} 41nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "af5122e1cbe1483833c5d2e5af96b26a34ed5d62"}
diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs
index d77f08fd8..319e29054 100644
--- a/embassy-nxp/src/usart/lpc55.rs
+++ b/embassy-nxp/src/usart/lpc55.rs
@@ -51,6 +51,15 @@ impl embedded_io::Error for Error {
51 } 51 }
52 } 52 }
53} 53}
54
55impl core::fmt::Display for Error {
56 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
57 core::fmt::Debug::fmt(self, f)
58 }
59}
60
61impl core::error::Error for Error {}
62
54/// Word length. 63/// Word length.
55#[derive(Clone, Copy, PartialEq, Eq, Debug)] 64#[derive(Clone, Copy, PartialEq, Eq, Debug)]
56pub enum DataBits { 65pub enum DataBits {
diff --git a/embassy-rp/Cargo.toml b/embassy-rp/Cargo.toml
index 8e4bb927f..585acc064 100644
--- a/embassy-rp/Cargo.toml
+++ b/embassy-rp/Cargo.toml
@@ -167,8 +167,8 @@ cortex-m-rt = ">=0.6.15,<0.8"
167cortex-m = "0.7.6" 167cortex-m = "0.7.6"
168critical-section = "1.2.0" 168critical-section = "1.2.0"
169chrono = { version = "0.4", default-features = false, optional = true } 169chrono = { version = "0.4", default-features = false, optional = true }
170embedded-io = { version = "0.6.1" } 170embedded-io = { version = "0.7.1" }
171embedded-io-async = { version = "0.6.1" } 171embedded-io-async = { version = "0.7.0" }
172embedded-storage = { version = "0.3" } 172embedded-storage = { version = "0.3" }
173embedded-storage-async = { version = "0.4.1" } 173embedded-storage-async = { version = "0.4.1" }
174fixed = "1.28.0" 174fixed = "1.28.0"
diff --git a/embassy-rp/src/pio_programs/uart.rs b/embassy-rp/src/pio_programs/uart.rs
index d59596dd1..a16d89a75 100644
--- a/embassy-rp/src/pio_programs/uart.rs
+++ b/embassy-rp/src/pio_programs/uart.rs
@@ -90,6 +90,10 @@ impl<PIO: Instance, const SM: usize> Write for PioUartTx<'_, PIO, SM> {
90 } 90 }
91 Ok(buf.len()) 91 Ok(buf.len())
92 } 92 }
93
94 async fn flush(&mut self) -> Result<(), Infallible> {
95 Ok(())
96 }
93} 97}
94 98
95/// This struct represents a Uart Rx program loaded into pio instruction memory. 99/// This struct represents a Uart Rx program loaded into pio instruction memory.
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index b7b569dd5..f53b2f88e 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -118,6 +118,14 @@ pub enum Error {
118 Framing, 118 Framing,
119} 119}
120 120
121impl core::fmt::Display for Error {
122 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123 core::fmt::Debug::fmt(self, f)
124 }
125}
126
127impl core::error::Error for Error {}
128
121/// Read To Break error 129/// Read To Break error
122#[derive(Debug, Eq, PartialEq, Copy, Clone)] 130#[derive(Debug, Eq, PartialEq, Copy, Clone)]
123#[cfg_attr(feature = "defmt", derive(defmt::Format))] 131#[cfg_attr(feature = "defmt", derive(defmt::Format))]
diff --git a/embassy-stm32-wpan/src/wb55/mod.rs b/embassy-stm32-wpan/src/wb55/mod.rs
index 95cfe09f1..814303a05 100644
--- a/embassy-stm32-wpan/src/wb55/mod.rs
+++ b/embassy-stm32-wpan/src/wb55/mod.rs
@@ -176,7 +176,7 @@ impl<'d> TlMbox<'d> {
176 let mm = sub::mm::MemoryManager::new(ipcc_mm_release_buffer_channel); 176 let mm = sub::mm::MemoryManager::new(ipcc_mm_release_buffer_channel);
177 let mut sys = sub::sys::Sys::new(ipcc_system_cmd_rsp_channel, ipcc_system_event_channel); 177 let mut sys = sub::sys::Sys::new(ipcc_system_cmd_rsp_channel, ipcc_system_event_channel);
178 178
179 debug!("sys event: {}", sys.read().await.payload()); 179 debug!("sys event: {}", sys.read_ready().await);
180 180
181 Self { 181 Self {
182 sys_subsystem: sys, 182 sys_subsystem: sys,
diff --git a/embassy-stm32-wpan/src/wb55/shci.rs b/embassy-stm32-wpan/src/wb55/shci.rs
index 3faa79209..3eb9525d3 100644
--- a/embassy-stm32-wpan/src/wb55/shci.rs
+++ b/embassy-stm32-wpan/src/wb55/shci.rs
@@ -12,6 +12,28 @@ const fn opcode(ogf: u16, ocf: u16) -> isize {
12 ((ogf << 10) + ocf) as isize 12 ((ogf << 10) + ocf) as isize
13} 13}
14 14
15pub(crate) trait SealedSchiFromPacket: Sized {
16 unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()>;
17}
18
19#[allow(private_bounds)]
20pub trait SchiFromPacket: SealedSchiFromPacket {}
21impl<T: SealedSchiFromPacket> SchiFromPacket for T {}
22
23trait ShciFromEventSerial: TryFrom<u8, Error = ()> {}
24
25impl<T: ShciFromEventSerial> SealedSchiFromPacket for T {
26 unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()> {
27 let p_cmd_serial = (cmd_buf as *mut u8).add(size_of::<PacketHeader>());
28 let p_evt_payload = p_cmd_serial.add(size_of::<EvtStub>());
29
30 compiler_fence(Ordering::Acquire);
31 let cc_evt = ptr::read_unaligned(p_evt_payload as *const CcEvt);
32
33 cc_evt.payload[0].try_into()
34 }
35}
36
15#[allow(dead_code)] 37#[allow(dead_code)]
16#[cfg_attr(feature = "defmt", derive(defmt::Format))] 38#[cfg_attr(feature = "defmt", derive(defmt::Format))]
17pub enum SchiCommandStatus { 39pub enum SchiCommandStatus {
@@ -25,37 +47,20 @@ pub enum SchiCommandStatus {
25 ShciFusCmdNotSupported = 0xFF, 47 ShciFusCmdNotSupported = 0xFF,
26} 48}
27 49
28impl SchiCommandStatus { 50impl ShciFromEventSerial for SchiCommandStatus {}
29 pub unsafe fn from_packet(cmd_buf: *const CmdPacket) -> Result<Self, ()> {
30 let p_cmd_serial = (cmd_buf as *mut u8).add(size_of::<PacketHeader>());
31 let p_evt_payload = p_cmd_serial.add(size_of::<EvtStub>());
32
33 compiler_fence(Ordering::Acquire);
34 let cc_evt = ptr::read_unaligned(p_evt_payload as *const CcEvt);
35
36 cc_evt.payload[0].try_into()
37 }
38}
39
40impl TryFrom<u8> for SchiCommandStatus { 51impl TryFrom<u8> for SchiCommandStatus {
41 type Error = (); 52 type Error = ();
42 53
43 fn try_from(v: u8) -> Result<Self, Self::Error> { 54 fn try_from(v: u8) -> Result<Self, Self::Error> {
44 match v { 55 match v {
45 x if x == SchiCommandStatus::ShciSuccess as u8 => Ok(SchiCommandStatus::ShciSuccess), 56 0x00 => Ok(Self::ShciSuccess),
46 x if x == SchiCommandStatus::ShciUnknownCmd as u8 => Ok(SchiCommandStatus::ShciUnknownCmd), 57 0x01 => Ok(Self::ShciUnknownCmd),
47 x if x == SchiCommandStatus::ShciMemoryCapacityExceededErrCode as u8 => { 58 0x07 => Ok(Self::ShciMemoryCapacityExceededErrCode),
48 Ok(SchiCommandStatus::ShciMemoryCapacityExceededErrCode) 59 0x11 => Ok(Self::ShciErrUnsupportedFeature),
49 } 60 0x12 => Ok(Self::ShciErrInvalidHciCmdParams),
50 x if x == SchiCommandStatus::ShciErrUnsupportedFeature as u8 => { 61 0x42 => Ok(Self::ShciErrInvalidParams), /* only used for release < v1.13.0 */
51 Ok(SchiCommandStatus::ShciErrUnsupportedFeature) 62 0x92 => Ok(Self::ShciErrInvalidParamsV2), /* available for release >= v1.13.0 */
52 } 63 0xFF => Ok(Self::ShciFusCmdNotSupported),
53 x if x == SchiCommandStatus::ShciErrInvalidHciCmdParams as u8 => {
54 Ok(SchiCommandStatus::ShciErrInvalidHciCmdParams)
55 }
56 x if x == SchiCommandStatus::ShciErrInvalidParams as u8 => Ok(SchiCommandStatus::ShciErrInvalidParams), /* only used for release < v1.13.0 */
57 x if x == SchiCommandStatus::ShciErrInvalidParamsV2 as u8 => Ok(SchiCommandStatus::ShciErrInvalidParamsV2), /* available for release >= v1.13.0 */
58 x if x == SchiCommandStatus::ShciFusCmdNotSupported as u8 => Ok(SchiCommandStatus::ShciFusCmdNotSupported),
59 _ => Err(()), 64 _ => Err(()),
60 } 65 }
61 } 66 }
@@ -107,6 +112,71 @@ pub enum ShciOpcode {
107 Mac802_15_4DeInit = opcode(SHCI_OGF, 0x78), 112 Mac802_15_4DeInit = opcode(SHCI_OGF, 0x78),
108} 113}
109 114
115#[cfg_attr(feature = "defmt", derive(defmt::Format))]
116pub enum ShciFusGetStateErrorCode {
117 FusStateErrorNoError = 0x00,
118 FusStateErrorImgNotFound = 0x01,
119 FusStateErrorImgCorrupt = 0x02,
120 FusStateErrorImgNotAuthentic = 0x03,
121 FusStateErrorImgNotEnoughSpace = 0x04,
122 FusStateErrorImageUsrAbort = 0x05,
123 FusStateErrorImageErsError = 0x06,
124 FusStateErrorImageWrtError = 0x07,
125 FusStateErrorAuthTagStNotFound = 0x08,
126 FusStateErrorAuthTagCustNotFound = 0x09,
127 FusStateErrorAuthKeyLocked = 0x0A,
128 FusStateErrorFwRollbackError = 0x11,
129 FusStateErrorStateNotRunning = 0xFE,
130 FusStateErrorErrUnknown = 0xFF,
131}
132
133impl ShciFromEventSerial for ShciFusGetStateErrorCode {}
134impl TryFrom<u8> for ShciFusGetStateErrorCode {
135 type Error = ();
136
137 fn try_from(v: u8) -> Result<Self, Self::Error> {
138 match v {
139 0x00 => Ok(Self::FusStateErrorNoError),
140 0x01 => Ok(Self::FusStateErrorImgNotFound),
141 0x02 => Ok(Self::FusStateErrorImgCorrupt),
142 0x03 => Ok(Self::FusStateErrorImgNotAuthentic),
143 0x04 => Ok(Self::FusStateErrorImgNotEnoughSpace),
144 0x05 => Ok(Self::FusStateErrorImageUsrAbort),
145 0x06 => Ok(Self::FusStateErrorImageErsError),
146 0x07 => Ok(Self::FusStateErrorImageWrtError),
147 0x08 => Ok(Self::FusStateErrorAuthTagStNotFound),
148 0x09 => Ok(Self::FusStateErrorAuthTagCustNotFound),
149 0x0A => Ok(Self::FusStateErrorAuthKeyLocked),
150 0x11 => Ok(Self::FusStateErrorFwRollbackError),
151 0xFE => Ok(Self::FusStateErrorStateNotRunning),
152 0xFF => Ok(Self::FusStateErrorErrUnknown),
153 _ => Err(()),
154 }
155 }
156}
157
158#[cfg_attr(feature = "defmt", derive(defmt::Format))]
159pub enum SchiSysEventReady {
160 WirelessFwRunning = 0x00,
161 FusFwRunning = 0x01,
162 NvmBackupRunning = 0x10,
163 NvmRestoreRunning = 0x11,
164}
165
166impl TryFrom<u8> for SchiSysEventReady {
167 type Error = ();
168
169 fn try_from(v: u8) -> Result<Self, Self::Error> {
170 match v {
171 0x00 => Ok(Self::WirelessFwRunning),
172 0x01 => Ok(Self::FusFwRunning),
173 0x10 => Ok(Self::NvmBackupRunning),
174 0x11 => Ok(Self::NvmRestoreRunning),
175 _ => Err(()),
176 }
177 }
178}
179
110pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0; 180pub const SHCI_C2_CONFIG_EVTMASK1_BIT0_ERROR_NOTIF_ENABLE: u8 = 1 << 0;
111pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1; 181pub const SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 1;
112pub const SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 2; 182pub const SHCI_C2_CONFIG_EVTMASK1_BIT2_THREAD_NVM_RAM_UPDATE_ENABLE: u8 = 1 << 2;
diff --git a/embassy-stm32-wpan/src/wb55/sub/sys.rs b/embassy-stm32-wpan/src/wb55/sub/sys.rs
index 2e625a677..3d774eeb7 100644
--- a/embassy-stm32-wpan/src/wb55/sub/sys.rs
+++ b/embassy-stm32-wpan/src/wb55/sub/sys.rs
@@ -1,3 +1,5 @@
1use core::slice;
2
1use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel}; 3use embassy_stm32::ipcc::{IpccRxChannel, IpccTxChannel};
2 4
3use crate::cmd::CmdPacket; 5use crate::cmd::CmdPacket;
@@ -5,12 +7,17 @@ use crate::consts::TlPacketType;
5use crate::evt::EvtBox; 7use crate::evt::EvtBox;
6#[cfg(feature = "wb55_ble")] 8#[cfg(feature = "wb55_ble")]
7use crate::shci::ShciBleInitCmdParam; 9use crate::shci::ShciBleInitCmdParam;
8use crate::shci::{SchiCommandStatus, ShciOpcode}; 10use crate::shci::{SchiCommandStatus, SchiFromPacket, SchiSysEventReady, ShciFusGetStateErrorCode, ShciOpcode};
9use crate::sub::mm; 11use crate::sub::mm;
10use crate::tables::{SysTable, WirelessFwInfoTable}; 12use crate::tables::{SysTable, WirelessFwInfoTable};
11use crate::unsafe_linked_list::LinkedListNode; 13use crate::unsafe_linked_list::LinkedListNode;
12use crate::wb55::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE}; 14use crate::wb55::{SYS_CMD_BUF, SYSTEM_EVT_QUEUE, TL_DEVICE_INFO_TABLE, TL_SYS_TABLE};
13 15
16const fn slice8_ref(x: &[u32]) -> &[u8] {
17 let len = x.len() * 4;
18 unsafe { slice::from_raw_parts(x.as_ptr() as *const u8, len) }
19}
20
14/// A guard that, once constructed, allows for sys commands to be sent to CPU2. 21/// A guard that, once constructed, allows for sys commands to be sent to CPU2.
15pub struct Sys<'a> { 22pub struct Sys<'a> {
16 ipcc_system_cmd_rsp_channel: IpccTxChannel<'a>, 23 ipcc_system_cmd_rsp_channel: IpccTxChannel<'a>,
@@ -55,15 +62,15 @@ impl<'a> Sys<'a> {
55 } 62 }
56 63
57 /// `HW_IPCC_SYS_CmdEvtNot` 64 /// `HW_IPCC_SYS_CmdEvtNot`
58 pub async fn write_and_get_response( 65 pub async fn write_and_get_response<T: SchiFromPacket>(
59 &mut self, 66 &mut self,
60 opcode: ShciOpcode, 67 opcode: ShciOpcode,
61 payload: &[u8], 68 payload: &[u8],
62 ) -> Result<SchiCommandStatus, ()> { 69 ) -> Result<T, ()> {
63 self.write(opcode, payload).await; 70 self.write(opcode, payload).await;
64 self.ipcc_system_cmd_rsp_channel.flush().await; 71 self.ipcc_system_cmd_rsp_channel.flush().await;
65 72
66 unsafe { SchiCommandStatus::from_packet(SYS_CMD_BUF.as_ptr()) } 73 unsafe { T::from_packet(SYS_CMD_BUF.as_ptr()) }
67 } 74 }
68 75
69 #[cfg(feature = "wb55_mac")] 76 #[cfg(feature = "wb55_mac")]
@@ -82,6 +89,36 @@ impl<'a> Sys<'a> {
82 self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await 89 self.write_and_get_response(ShciOpcode::BleInit, param.payload()).await
83 } 90 }
84 91
92 pub async fn shci_c2_fus_getstate(&mut self) -> Result<ShciFusGetStateErrorCode, ()> {
93 self.write_and_get_response(ShciOpcode::FusStartWirelessStack, &[])
94 .await
95 }
96
97 /// Send a request to CPU2 to start the wireless stack
98 pub async fn shci_c2_fus_startws(&mut self) -> Result<SchiCommandStatus, ()> {
99 self.write_and_get_response(ShciOpcode::FusStartWirelessStack, &[])
100 .await
101 }
102
103 /// Send a request to CPU2 to upgrade the firmware
104 pub async fn shci_c2_fus_fwupgrade(&mut self, fw_src_add: u32, fw_dst_add: u32) -> Result<SchiCommandStatus, ()> {
105 let buf = [fw_src_add, fw_dst_add];
106 let len = if fw_dst_add != 0 {
107 2
108 } else if fw_src_add != 0 {
109 1
110 } else {
111 0
112 };
113
114 self.write_and_get_response(ShciOpcode::FusFirmwareUpgrade, slice8_ref(&buf[..len]))
115 .await
116 }
117
118 pub async fn read_ready(&mut self) -> Result<SchiSysEventReady, ()> {
119 self.read().await.payload()[0].try_into()
120 }
121
85 /// `HW_IPCC_SYS_EvtNot` 122 /// `HW_IPCC_SYS_EvtNot`
86 /// 123 ///
87 /// This method takes the place of the `HW_IPCC_SYS_EvtNot`/`SysUserEvtRx`/`APPE_SysUserEvtRx`, 124 /// This method takes the place of the `HW_IPCC_SYS_EvtNot`/`SysUserEvtRx`/`APPE_SysUserEvtRx`,
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index e96933b78..27f26df28 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -184,8 +184,8 @@ vcell = "0.1.3"
184nb = "1.0.0" 184nb = "1.0.0"
185stm32-fmc = "0.4.0" 185stm32-fmc = "0.4.0"
186cfg-if = "1.0.0" 186cfg-if = "1.0.0"
187embedded-io = { version = "0.6.0" } 187embedded-io = { version = "0.7.1" }
188embedded-io-async = { version = "0.6.1" } 188embedded-io-async = { version = "0.7.0" }
189chrono = { version = "^0.4", default-features = false, optional = true } 189chrono = { version = "^0.4", default-features = false, optional = true }
190bit_field = "0.10.2" 190bit_field = "0.10.2"
191trait-set = "0.3.0" 191trait-set = "0.3.0"
@@ -228,7 +228,7 @@ defmt = [
228 "embassy-sync/defmt", 228 "embassy-sync/defmt",
229 "embassy-embedded-hal/defmt", 229 "embassy-embedded-hal/defmt",
230 "embassy-hal-internal/defmt", 230 "embassy-hal-internal/defmt",
231 "embedded-io-async/defmt-03", 231 "embedded-io-async/defmt",
232 "embassy-usb-driver/defmt", 232 "embassy-usb-driver/defmt",
233 "embassy-net-driver/defmt", 233 "embassy-net-driver/defmt",
234 "embassy-time?/defmt", 234 "embassy-time?/defmt",
@@ -241,9 +241,9 @@ log = ["dep:log"]
241chrono = ["dep:chrono"] 241chrono = ["dep:chrono"]
242 242
243exti = [] 243exti = []
244low-power = [ "dep:embassy-executor", "time" ] 244low-power = [ "dep:embassy-executor", "time", "chrono" ]
245low-power-pender = [ ] 245low-power-pender = [ "low-power" ]
246low-power-debug-with-sleep = [] 246low-power-debug-with-sleep = [ "low-power" ]
247 247
248## Automatically generate `memory.x` file based on the memory map from [`stm32-metapac`](https://docs.rs/stm32-metapac/) 248## Automatically generate `memory.x` file based on the memory map from [`stm32-metapac`](https://docs.rs/stm32-metapac/)
249memory-x = [] 249memory-x = []
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 2f783bf64..a0b2f045c 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -138,6 +138,9 @@ pub mod wdg;
138#[cfg(xspi)] 138#[cfg(xspi)]
139pub mod xspi; 139pub mod xspi;
140 140
141#[cfg(feature = "low-power")]
142pub use low_power::Executor;
143
141// This must go last, so that it sees all the impl_foo! macros defined earlier. 144// This must go last, so that it sees all the impl_foo! macros defined earlier.
142pub(crate) mod _generated { 145pub(crate) mod _generated {
143 #![allow(dead_code)] 146 #![allow(dead_code)]
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs
index 5c10c1a5d..02116e08a 100644
--- a/embassy-stm32/src/low_power.rs
+++ b/embassy-stm32/src/low_power.rs
@@ -3,31 +3,31 @@
3//! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating 3//! The STM32 line of microcontrollers support various deep-sleep modes which exploit clock-gating
4//! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which 4//! to reduce power consumption. `embassy-stm32` provides a low-power executor, [`Executor`] which
5//! can use knowledge of which peripherals are currently blocked upon to transparently and safely 5//! can use knowledge of which peripherals are currently blocked upon to transparently and safely
6//! enter such low-power modes (currently, only `STOP2`) when idle. 6//! enter such low-power modes including `STOP1` and `STOP2` when idle.
7//! 7//!
8//! The executor determines which peripherals are active by their RCC state; consequently, 8//! The executor determines which peripherals are active by their RCC state; consequently,
9//! low-power states can only be entered if all peripherals have been `drop`'d. There are a few 9//! low-power states can only be entered if peripherals which block stop have been `drop`'d and if
10//! exceptions to this rule: 10//! peripherals that do not block stop are busy. Peripherals which never block stop include:
11//! 11//!
12//! * `GPIO` 12//! * `GPIO`
13//! * `RTC` 13//! * `RTC`
14//! 14//!
15//! Other peripherals which block stop when busy include (this list may be stale):
16//!
17//! * `I2C`
18//! * `USART`
19//!
15//! Since entering and leaving low-power modes typically incurs a significant latency, the 20//! Since entering and leaving low-power modes typically incurs a significant latency, the
16//! low-power executor will only attempt to enter when the next timer event is at least 21//! low-power executor will only attempt to enter when the next timer event is at least
17//! [`time_driver::min_stop_pause`] in the future. 22//! [`config.min_stop_pause`] in the future.
18//! 23//!
19//! Currently there is no macro analogous to `embassy_executor::main` for this executor;
20//! consequently one must define their entrypoint manually. Moreover, you must relinquish control
21//! of the `RTC` peripheral to the executor. This will typically look like
22//! 24//!
23//! ```rust,no_run 25//! ```rust,no_run
24//! use embassy_executor::Spawner; 26//! use embassy_executor::Spawner;
25//! use embassy_stm32::low_power;
26//! use embassy_stm32::rtc::{Rtc, RtcConfig};
27//! use embassy_time::Duration; 27//! use embassy_time::Duration;
28//! 28//!
29//! #[embassy_executor::main(executor = "low_power::Executor")] 29//! #[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
30//! async fn async_main(spawner: Spawner) { 30//! async fn main(spawner: Spawner) {
31//! // initialize the platform... 31//! // initialize the platform...
32//! let mut config = embassy_stm32::Config::default(); 32//! let mut config = embassy_stm32::Config::default();
33//! // the default value, but can be adjusted 33//! // the default value, but can be adjusted
@@ -210,7 +210,7 @@ impl Executor {
210 w.set_c1cssf(false); 210 w.set_c1cssf(false);
211 }); 211 });
212 212
213 let has_stopped2 = { 213 let _has_stopped2 = {
214 #[cfg(stm32wb)] 214 #[cfg(stm32wb)]
215 { 215 {
216 es.c2stopf() 216 es.c2stopf()
@@ -222,10 +222,11 @@ impl Executor {
222 } 222 }
223 }; 223 };
224 224
225 if es.c1stopf() || has_stopped2 { 225 #[cfg(not(stm32wb))]
226 if es.c1stopf() || _has_stopped2 {
226 // when we wake from any stop mode we need to re-initialize the rcc 227 // when we wake from any stop mode we need to re-initialize the rcc
227 crate::rcc::init(RCC_CONFIG.unwrap()); 228 crate::rcc::init(RCC_CONFIG.unwrap());
228 if has_stopped2 { 229 if _has_stopped2 {
229 // when we wake from STOP2, we need to re-initialize the time driver 230 // when we wake from STOP2, we need to re-initialize the time driver
230 get_driver().init_timer(cs); 231 get_driver().init_timer(cs);
231 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer) 232 // reset the refcounts for STOP2 and STOP1 (initializing the time driver will increment one of them for the timer)
diff --git a/embassy-stm32/src/rcc/c0.rs b/embassy-stm32/src/rcc/c0.rs
index 99f22273d..7801078c3 100644
--- a/embassy-stm32/src/rcc/c0.rs
+++ b/embassy-stm32/src/rcc/c0.rs
@@ -185,6 +185,12 @@ pub(crate) unsafe fn init(config: Config) {
185 RCC.cr().modify(|w| w.set_hsion(false)); 185 RCC.cr().modify(|w| w.set_hsion(false));
186 } 186 }
187 187
188 // Disable the HSI48, if not used
189 #[cfg(crs)]
190 if config.hsi48.is_none() {
191 super::disable_hsi48();
192 }
193
188 config.mux.init(); 194 config.mux.init();
189 195
190 set_clocks!( 196 set_clocks!(
diff --git a/embassy-stm32/src/rcc/f013.rs b/embassy-stm32/src/rcc/f013.rs
index 1155b6acd..92cf9fca7 100644
--- a/embassy-stm32/src/rcc/f013.rs
+++ b/embassy-stm32/src/rcc/f013.rs
@@ -480,6 +480,12 @@ pub(crate) unsafe fn init(config: Config) {
480 }; 480 };
481 */ 481 */
482 482
483 // Disable the HSI48, if not used
484 #[cfg(crs)]
485 if config.hsi48.is_none() {
486 super::disable_hsi48();
487 }
488
483 config.mux.init(); 489 config.mux.init();
484 490
485 set_clocks!( 491 set_clocks!(
diff --git a/embassy-stm32/src/rcc/g0.rs b/embassy-stm32/src/rcc/g0.rs
index ce6398afd..2665c20f9 100644
--- a/embassy-stm32/src/rcc/g0.rs
+++ b/embassy-stm32/src/rcc/g0.rs
@@ -294,6 +294,12 @@ pub(crate) unsafe fn init(config: Config) {
294 RCC.cr().modify(|w| w.set_hsion(false)); 294 RCC.cr().modify(|w| w.set_hsion(false));
295 } 295 }
296 296
297 // Disable the HSI48, if not used
298 #[cfg(crs)]
299 if config.hsi48.is_none() {
300 super::disable_hsi48();
301 }
302
297 if config.low_power_run { 303 if config.low_power_run {
298 assert!(sys <= Hertz(2_000_000)); 304 assert!(sys <= Hertz(2_000_000));
299 PWR.cr1().modify(|w| w.set_lpr(true)); 305 PWR.cr1().modify(|w| w.set_lpr(true));
diff --git a/embassy-stm32/src/rcc/g4.rs b/embassy-stm32/src/rcc/g4.rs
index da13e16aa..0dd3713c8 100644
--- a/embassy-stm32/src/rcc/g4.rs
+++ b/embassy-stm32/src/rcc/g4.rs
@@ -300,6 +300,12 @@ pub(crate) unsafe fn init(config: Config) {
300 RCC.cr().modify(|w| w.set_hsion(false)); 300 RCC.cr().modify(|w| w.set_hsion(false));
301 } 301 }
302 302
303 // Disable the HSI48, if not used
304 #[cfg(crs)]
305 if config.hsi48.is_none() {
306 super::disable_hsi48();
307 }
308
303 if config.low_power_run { 309 if config.low_power_run {
304 assert!(sys <= Hertz(2_000_000)); 310 assert!(sys <= Hertz(2_000_000));
305 PWR.cr1().modify(|w| w.set_lpr(true)); 311 PWR.cr1().modify(|w| w.set_lpr(true));
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs
index 485edd390..2fe2a435c 100644
--- a/embassy-stm32/src/rcc/h.rs
+++ b/embassy-stm32/src/rcc/h.rs
@@ -671,6 +671,12 @@ pub(crate) unsafe fn init(config: Config) {
671 RCC.cr().modify(|w| w.set_hsion(false)); 671 RCC.cr().modify(|w| w.set_hsion(false));
672 } 672 }
673 673
674 // Disable the HSI48, if not used
675 #[cfg(crs)]
676 if config.hsi48.is_none() {
677 super::disable_hsi48();
678 }
679
674 // IO compensation cell - Requires CSI clock and SYSCFG 680 // IO compensation cell - Requires CSI clock and SYSCFG
675 #[cfg(any(stm32h7))] // TODO h5, h7rs 681 #[cfg(any(stm32h7))] // TODO h5, h7rs
676 if csi.is_some() { 682 if csi.is_some() {
diff --git a/embassy-stm32/src/rcc/hsi48.rs b/embassy-stm32/src/rcc/hsi48.rs
index 49be4af5e..50ac162a4 100644
--- a/embassy-stm32/src/rcc/hsi48.rs
+++ b/embassy-stm32/src/rcc/hsi48.rs
@@ -66,3 +66,24 @@ pub(crate) fn init_hsi48(config: Hsi48Config) -> Hertz {
66 66
67 HSI48_FREQ 67 HSI48_FREQ
68} 68}
69
70pub(crate) fn disable_hsi48() {
71 // disable CRS if it is enabled
72 rcc::disable::<crate::peripherals::CRS>();
73
74 // Disable HSI48
75 #[cfg(not(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32f0, stm32c071)))]
76 let r = RCC.crrcr();
77 #[cfg(any(stm32u5, stm32g0, stm32h5, stm32h7, stm32h7rs, stm32u5, stm32wba, stm32c071))]
78 let r = RCC.cr();
79 #[cfg(any(stm32f0))]
80 let r = RCC.cr2();
81
82 r.modify(|w| w.set_hsi48on(false));
83
84 // Disable VREFINT reference for HSI48 oscillator
85 #[cfg(stm32l0)]
86 crate::pac::SYSCFG.cfgr3().modify(|w| {
87 w.set_enref_hsi48(false);
88 });
89}
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs
index 0d668103c..55f383374 100644
--- a/embassy-stm32/src/rcc/l.rs
+++ b/embassy-stm32/src/rcc/l.rs
@@ -385,6 +385,17 @@ pub(crate) unsafe fn init(config: Config) {
385 while !RCC.extcfgr().read().c2hpref() {} 385 while !RCC.extcfgr().read().c2hpref() {}
386 } 386 }
387 387
388 // Disable HSI if not used
389 if !config.hsi {
390 RCC.cr().modify(|w| w.set_hsion(false));
391 }
392
393 // Disable the HSI48, if not used
394 #[cfg(crs)]
395 if config.hsi48.is_none() {
396 super::disable_hsi48();
397 }
398
388 config.mux.init(); 399 config.mux.init();
389 400
390 set_clocks!( 401 set_clocks!(
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs
index 47cc29c6f..9f37107a3 100644
--- a/embassy-stm32/src/rcc/u5.rs
+++ b/embassy-stm32/src/rcc/u5.rs
@@ -467,6 +467,17 @@ pub(crate) unsafe fn init(config: Config) {
467 let lse = config.ls.lse.map(|l| l.frequency); 467 let lse = config.ls.lse.map(|l| l.frequency);
468 let lsi = config.ls.lsi.then_some(LSI_FREQ); 468 let lsi = config.ls.lsi.then_some(LSI_FREQ);
469 469
470 // Disable HSI if not used
471 if !config.hsi {
472 RCC.cr().modify(|w| w.set_hsion(false));
473 }
474
475 // Disable the HSI48, if not used
476 #[cfg(crs)]
477 if config.hsi48.is_none() {
478 super::disable_hsi48();
479 }
480
470 config.mux.init(); 481 config.mux.init();
471 482
472 set_clocks!( 483 set_clocks!(
diff --git a/embassy-stm32/src/rcc/wba.rs b/embassy-stm32/src/rcc/wba.rs
index 2528996d5..4ab3067bc 100644
--- a/embassy-stm32/src/rcc/wba.rs
+++ b/embassy-stm32/src/rcc/wba.rs
@@ -269,6 +269,11 @@ pub(crate) unsafe fn init(config: Config) {
269 269
270 let lsi = config.ls.lsi.then_some(LSI_FREQ); 270 let lsi = config.ls.lsi.then_some(LSI_FREQ);
271 271
272 // Disable HSI if not used
273 if !config.hsi {
274 RCC.cr().modify(|w| w.set_hsion(false));
275 }
276
272 config.mux.init(); 277 config.mux.init();
273 278
274 set_clocks!( 279 set_clocks!(
diff --git a/embassy-stm32/src/rtc/low_power.rs b/embassy-stm32/src/rtc/low_power.rs
index f049d6b12..cd5cea081 100644
--- a/embassy-stm32/src/rtc/low_power.rs
+++ b/embassy-stm32/src/rtc/low_power.rs
@@ -1,64 +1,12 @@
1#[cfg(feature = "time")] 1use chrono::{DateTime, NaiveDateTime, TimeDelta, Utc};
2use embassy_time::{Duration, TICK_HZ}; 2use embassy_time::{Duration, Instant, TICK_HZ};
3 3
4use super::{DateTimeError, Rtc, RtcError, bcd2_to_byte}; 4use super::Rtc;
5use crate::interrupt::typelevel::Interrupt; 5use crate::interrupt::typelevel::Interrupt;
6use crate::pac::rtc::vals::Wucksel; 6use crate::pac::rtc::vals::Wucksel;
7use crate::peripherals::RTC; 7use crate::peripherals::RTC;
8use crate::rtc::{RtcTimeProvider, SealedInstance}; 8use crate::rtc::{RtcTimeProvider, SealedInstance};
9 9
10/// Represents an instant in time that can be substracted to compute a duration
11pub(super) struct RtcInstant {
12 /// 0..59
13 second: u8,
14 /// 0..256
15 subsecond: u16,
16}
17
18impl RtcInstant {
19 #[cfg(not(rtc_v2_f2))]
20 const fn from(second: u8, subsecond: u16) -> Result<Self, DateTimeError> {
21 if second > 59 {
22 Err(DateTimeError::InvalidSecond)
23 } else {
24 Ok(Self { second, subsecond })
25 }
26 }
27}
28
29#[cfg(feature = "defmt")]
30impl defmt::Format for RtcInstant {
31 fn format(&self, fmt: defmt::Formatter) {
32 defmt::write!(
33 fmt,
34 "{}:{}",
35 self.second,
36 RTC::regs().prer().read().prediv_s() - self.subsecond,
37 )
38 }
39}
40
41#[cfg(feature = "time")]
42impl core::ops::Sub for RtcInstant {
43 type Output = embassy_time::Duration;
44
45 fn sub(self, rhs: Self) -> Self::Output {
46 let second = if self.second < rhs.second {
47 self.second + 60
48 } else {
49 self.second
50 };
51
52 let psc = RTC::regs().prer().read().prediv_s() as u32;
53
54 let self_ticks = second as u32 * (psc + 1) + (psc - self.subsecond as u32);
55 let other_ticks = rhs.second as u32 * (psc + 1) + (psc - rhs.subsecond as u32);
56 let rtc_ticks = self_ticks - other_ticks;
57
58 Duration::from_ticks(((rtc_ticks * TICK_HZ as u32) / (psc + 1)) as u64)
59 }
60}
61
62fn wucksel_compute_min(val: u32) -> (Wucksel, u32) { 10fn wucksel_compute_min(val: u32) -> (Wucksel, u32) {
63 *[ 11 *[
64 (Wucksel::DIV2, 2), 12 (Wucksel::DIV2, 2),
@@ -72,22 +20,15 @@ fn wucksel_compute_min(val: u32) -> (Wucksel, u32) {
72} 20}
73 21
74impl Rtc { 22impl Rtc {
75 /// Return the current instant. 23 pub(super) fn calc_epoch(&self) -> DateTime<Utc> {
76 fn instant(&self) -> Result<RtcInstant, RtcError> { 24 let now: NaiveDateTime = RtcTimeProvider::new().now().unwrap().into();
77 RtcTimeProvider::new().read(|_, tr, ss| {
78 let second = bcd2_to_byte((tr.st(), tr.su()));
79 25
80 RtcInstant::from(second, ss).map_err(RtcError::InvalidDateTime) 26 now.and_utc() - TimeDelta::microseconds(Instant::now().as_micros().try_into().unwrap())
81 })
82 } 27 }
83 28
84 /// start the wakeup alarm and with a duration that is as close to but less than 29 /// start the wakeup alarm and with a duration that is as close to but less than
85 /// the requested duration, and record the instant the wakeup alarm was started 30 /// the requested duration, and record the instant the wakeup alarm was started
86 pub(crate) fn start_wakeup_alarm( 31 pub(crate) fn start_wakeup_alarm(&mut self, requested_duration: embassy_time::Duration) {
87 &mut self,
88 requested_duration: embassy_time::Duration,
89 cs: critical_section::CriticalSection,
90 ) {
91 // Panic if the rcc mod knows we're not using low-power rtc 32 // Panic if the rcc mod knows we're not using low-power rtc
92 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))] 33 #[cfg(any(rcc_wb, rcc_f4, rcc_f410))]
93 unsafe { crate::rcc::get_freqs() }.rtc.to_hertz().unwrap(); 34 unsafe { crate::rcc::get_freqs() }.rtc.to_hertz().unwrap();
@@ -122,27 +63,19 @@ impl Rtc {
122 regs.cr().modify(|w| w.set_wutie(true)); 63 regs.cr().modify(|w| w.set_wutie(true));
123 }); 64 });
124 65
125 let instant = self.instant().unwrap();
126 trace!( 66 trace!(
127 "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {}) at {}", 67 "rtc: start wakeup alarm for {} ms (psc: {}, ticks: {})",
128 Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(), 68 Duration::from_ticks(rtc_ticks as u64 * TICK_HZ * prescaler as u64 / rtc_hz).as_millis(),
129 prescaler as u32, 69 prescaler as u32,
130 rtc_ticks, 70 rtc_ticks,
131 instant,
132 ); 71 );
133
134 assert!(self.stop_time.borrow(cs).replace(Some(instant)).is_none())
135 } 72 }
136 73
137 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm` 74 /// stop the wakeup alarm and return the time elapsed since `start_wakeup_alarm`
138 /// was called, otherwise none 75 /// was called, otherwise none
139 pub(crate) fn stop_wakeup_alarm( 76 pub(crate) fn stop_wakeup_alarm(&mut self) -> embassy_time::Instant {
140 &mut self,
141 cs: critical_section::CriticalSection,
142 ) -> Option<embassy_time::Duration> {
143 let instant = self.instant().unwrap();
144 if RTC::regs().cr().read().wute() { 77 if RTC::regs().cr().read().wute() {
145 trace!("rtc: stop wakeup alarm at {}", instant); 78 trace!("rtc: stop wakeup alarm");
146 79
147 self.write(false, |regs| { 80 self.write(false, |regs| {
148 regs.cr().modify(|w| w.set_wutie(false)); 81 regs.cr().modify(|w| w.set_wutie(false));
@@ -166,10 +99,13 @@ impl Rtc {
166 }); 99 });
167 } 100 }
168 101
169 self.stop_time.borrow(cs).take().map(|stop_time| instant - stop_time) 102 let datetime: NaiveDateTime = RtcTimeProvider::new().now().expect("failed to read now").into();
103 let offset = datetime.and_utc() - self.epoch;
104
105 Instant::from_micros(offset.num_microseconds().unwrap().try_into().unwrap())
170 } 106 }
171 107
172 pub(crate) fn enable_wakeup_line(&self) { 108 pub(super) fn enable_wakeup_line(&mut self) {
173 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); 109 <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend();
174 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() }; 110 unsafe { <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::enable() };
175 111
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs
index e88bd7ab2..94ba13ae1 100644
--- a/embassy-stm32/src/rtc/mod.rs
+++ b/embassy-stm32/src/rtc/mod.rs
@@ -5,7 +5,7 @@ mod datetime;
5mod low_power; 5mod low_power;
6 6
7#[cfg(feature = "low-power")] 7#[cfg(feature = "low-power")]
8use core::cell::{Cell, RefCell, RefMut}; 8use core::cell::{RefCell, RefMut};
9#[cfg(feature = "low-power")] 9#[cfg(feature = "low-power")]
10use core::ops; 10use core::ops;
11 11
@@ -163,7 +163,7 @@ impl<'a> ops::DerefMut for RtcBorrow<'a> {
163/// RTC driver. 163/// RTC driver.
164pub struct Rtc { 164pub struct Rtc {
165 #[cfg(feature = "low-power")] 165 #[cfg(feature = "low-power")]
166 stop_time: Mutex<CriticalSectionRawMutex, Cell<Option<low_power::RtcInstant>>>, 166 epoch: chrono::DateTime<chrono::Utc>,
167 _private: (), 167 _private: (),
168} 168}
169 169
@@ -225,7 +225,7 @@ impl Rtc {
225 225
226 let mut this = Self { 226 let mut this = Self {
227 #[cfg(feature = "low-power")] 227 #[cfg(feature = "low-power")]
228 stop_time: Mutex::const_new(CriticalSectionRawMutex::new(), Cell::new(None)), 228 epoch: chrono::DateTime::from_timestamp_secs(0).unwrap(),
229 _private: (), 229 _private: (),
230 }; 230 };
231 231
@@ -243,7 +243,10 @@ impl Rtc {
243 } 243 }
244 244
245 #[cfg(feature = "low-power")] 245 #[cfg(feature = "low-power")]
246 this.enable_wakeup_line(); 246 {
247 this.enable_wakeup_line();
248 this.epoch = this.calc_epoch();
249 }
247 250
248 this 251 this
249 } 252 }
@@ -293,6 +296,11 @@ impl Rtc {
293 }); 296 });
294 }); 297 });
295 298
299 #[cfg(feature = "low-power")]
300 {
301 self.epoch = self.calc_epoch();
302 }
303
296 Ok(()) 304 Ok(())
297 } 305 }
298 306
diff --git a/embassy-stm32/src/time_driver.rs b/embassy-stm32/src/time_driver.rs
index ed5d902bd..59ec58575 100644
--- a/embassy-stm32/src/time_driver.rs
+++ b/embassy-stm32/src/time_driver.rs
@@ -251,8 +251,8 @@ impl RtcDriver {
251 251
252 #[cfg(feature = "low-power")] 252 #[cfg(feature = "low-power")]
253 /// Add the given offset to the current time 253 /// Add the given offset to the current time
254 fn add_time(&self, offset: embassy_time::Duration, cs: CriticalSection) { 254 fn set_time(&self, instant: u64, cs: CriticalSection) {
255 let (period, counter) = calc_period_counter(self.now() + offset.as_ticks()); 255 let (period, counter) = calc_period_counter(core::cmp::max(self.now(), instant));
256 256
257 self.period.store(period, Ordering::SeqCst); 257 self.period.store(period, Ordering::SeqCst);
258 regs_gp16().cnt().write(|w| w.set_cnt(counter)); 258 regs_gp16().cnt().write(|w| w.set_cnt(counter));
@@ -269,10 +269,17 @@ impl RtcDriver {
269 #[cfg(feature = "low-power")] 269 #[cfg(feature = "low-power")]
270 /// Stop the wakeup alarm, if enabled, and add the appropriate offset 270 /// Stop the wakeup alarm, if enabled, and add the appropriate offset
271 fn stop_wakeup_alarm(&self, cs: CriticalSection) { 271 fn stop_wakeup_alarm(&self, cs: CriticalSection) {
272 if !regs_gp16().cr1().read().cen() 272 if !regs_gp16().cr1().read().cen() {
273 && let Some(offset) = self.rtc.borrow(cs).borrow_mut().as_mut().unwrap().stop_wakeup_alarm(cs) 273 self.set_time(
274 { 274 self.rtc
275 self.add_time(offset, cs); 275 .borrow(cs)
276 .borrow_mut()
277 .as_mut()
278 .unwrap()
279 .stop_wakeup_alarm()
280 .as_ticks(),
281 cs,
282 );
276 } 283 }
277 } 284 }
278 285
@@ -287,7 +294,7 @@ impl RtcDriver {
287 #[cfg(feature = "low-power")] 294 #[cfg(feature = "low-power")]
288 /// Set the rtc but panic if it's already been set 295 /// Set the rtc but panic if it's already been set
289 pub(crate) fn set_rtc(&self, cs: CriticalSection, mut rtc: Rtc) { 296 pub(crate) fn set_rtc(&self, cs: CriticalSection, mut rtc: Rtc) {
290 rtc.stop_wakeup_alarm(cs); 297 rtc.stop_wakeup_alarm();
291 298
292 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none()); 299 assert!(self.rtc.borrow(cs).replace(Some(rtc)).is_none());
293 } 300 }
@@ -310,7 +317,7 @@ impl RtcDriver {
310 .borrow_mut() 317 .borrow_mut()
311 .as_mut() 318 .as_mut()
312 .unwrap() 319 .unwrap()
313 .start_wakeup_alarm(time_until_next_alarm, cs); 320 .start_wakeup_alarm(time_until_next_alarm);
314 321
315 regs_gp16().cr1().modify(|w| w.set_cen(false)); 322 regs_gp16().cr1().modify(|w| w.set_cen(false));
316 // save the count for the timer as its lost in STOP2 for stm32wlex 323 // save the count for the timer as its lost in STOP2 for stm32wlex
diff --git a/embassy-sync/Cargo.toml b/embassy-sync/Cargo.toml
index 0c28cec7d..86c87b7b1 100644
--- a/embassy-sync/Cargo.toml
+++ b/embassy-sync/Cargo.toml
@@ -41,7 +41,7 @@ futures-core = { version = "0.3.31", default-features = false }
41critical-section = "1.1" 41critical-section = "1.1"
42heapless = "0.8" 42heapless = "0.8"
43cfg-if = "1.0.0" 43cfg-if = "1.0.0"
44embedded-io-async = { version = "0.6.1" } 44embedded-io-async = { version = "0.7.0" }
45 45
46[dev-dependencies] 46[dev-dependencies]
47futures-executor = { version = "0.3.17", features = [ "thread-pool" ] } 47futures-executor = { version = "0.3.17", features = [ "thread-pool" ] }
diff --git a/embassy-usb-driver/Cargo.toml b/embassy-usb-driver/Cargo.toml
index 3f43f60a3..a11658213 100644
--- a/embassy-usb-driver/Cargo.toml
+++ b/embassy-usb-driver/Cargo.toml
@@ -19,6 +19,7 @@ target = "thumbv7em-none-eabi"
19features = ["defmt"] 19features = ["defmt"]
20 20
21[dependencies] 21[dependencies]
22# TODO: remove before releasing embassy-usb-driver v0.3
22embedded-io-async = "0.6.1" 23embedded-io-async = "0.6.1"
23defmt = { version = "1", optional = true } 24defmt = { version = "1", optional = true }
24 25
diff --git a/embassy-usb-driver/src/lib.rs b/embassy-usb-driver/src/lib.rs
index f19e0a401..782f130f6 100644
--- a/embassy-usb-driver/src/lib.rs
+++ b/embassy-usb-driver/src/lib.rs
@@ -429,6 +429,7 @@ pub enum EndpointError {
429 Disabled, 429 Disabled,
430} 430}
431 431
432// TODO: remove before releasing embassy-usb-driver v0.3
432impl embedded_io_async::Error for EndpointError { 433impl embedded_io_async::Error for EndpointError {
433 fn kind(&self) -> embedded_io_async::ErrorKind { 434 fn kind(&self) -> embedded_io_async::ErrorKind {
434 match self { 435 match self {
diff --git a/embassy-usb/Cargo.toml b/embassy-usb/Cargo.toml
index 3d1e005e4..6c3ddc1db 100644
--- a/embassy-usb/Cargo.toml
+++ b/embassy-usb/Cargo.toml
@@ -66,7 +66,7 @@ embassy-net-driver-channel = { version = "0.3.2", path = "../embassy-net-driver-
66defmt = { version = "1", optional = true } 66defmt = { version = "1", optional = true }
67log = { version = "0.4.14", optional = true } 67log = { version = "0.4.14", optional = true }
68heapless = "0.8" 68heapless = "0.8"
69embedded-io-async = "0.6.1" 69embedded-io-async = { version = "0.7.0" }
70 70
71# for HID 71# for HID
72usbd-hid = { version = "0.9.0", optional = true } 72usbd-hid = { version = "0.9.0", optional = true }
diff --git a/embassy-usb/src/class/cdc_acm.rs b/embassy-usb/src/class/cdc_acm.rs
index ab2311f4e..56acdb2a6 100644
--- a/embassy-usb/src/class/cdc_acm.rs
+++ b/embassy-usb/src/class/cdc_acm.rs
@@ -33,6 +33,30 @@ const REQ_SET_LINE_CODING: u8 = 0x20;
33const REQ_GET_LINE_CODING: u8 = 0x21; 33const REQ_GET_LINE_CODING: u8 = 0x21;
34const REQ_SET_CONTROL_LINE_STATE: u8 = 0x22; 34const REQ_SET_CONTROL_LINE_STATE: u8 = 0x22;
35 35
36/// CDC ACM error.
37#[derive(Clone, Debug)]
38pub enum CdcAcmError {
39 /// USB is not connected.
40 NotConnected,
41}
42
43impl core::fmt::Display for CdcAcmError {
44 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
45 match *self {
46 Self::NotConnected => f.write_str("NotConnected"),
47 }
48 }
49}
50
51impl core::error::Error for CdcAcmError {}
52impl embedded_io_async::Error for CdcAcmError {
53 fn kind(&self) -> embedded_io_async::ErrorKind {
54 match *self {
55 Self::NotConnected => embedded_io_async::ErrorKind::NotConnected,
56 }
57 }
58}
59
36/// Internal state for CDC-ACM 60/// Internal state for CDC-ACM
37pub struct State<'a> { 61pub struct State<'a> {
38 control: MaybeUninit<Control<'a>>, 62 control: MaybeUninit<Control<'a>>,
@@ -421,14 +445,21 @@ impl<'d, D: Driver<'d>> Sender<'d, D> {
421} 445}
422 446
423impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for Sender<'d, D> { 447impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for Sender<'d, D> {
424 type Error = EndpointError; 448 type Error = CdcAcmError;
425} 449}
426 450
427impl<'d, D: Driver<'d>> embedded_io_async::Write for Sender<'d, D> { 451impl<'d, D: Driver<'d>> embedded_io_async::Write for Sender<'d, D> {
428 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { 452 async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
429 let len = core::cmp::min(buf.len(), self.max_packet_size() as usize); 453 let len = core::cmp::min(buf.len(), self.max_packet_size() as usize);
430 self.write_packet(&buf[..len]).await?; 454 match self.write_packet(&buf[..len]).await {
431 Ok(len) 455 Ok(()) => Ok(len),
456 Err(EndpointError::BufferOverflow) => unreachable!(),
457 Err(EndpointError::Disabled) => Err(CdcAcmError::NotConnected),
458 }
459 }
460
461 async fn flush(&mut self) -> Result<(), Self::Error> {
462 Ok(())
432 } 463 }
433} 464}
434 465
@@ -539,7 +570,7 @@ impl<'d, D: Driver<'d>> BufferedReceiver<'d, D> {
539} 570}
540 571
541impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for BufferedReceiver<'d, D> { 572impl<'d, D: Driver<'d>> embedded_io_async::ErrorType for BufferedReceiver<'d, D> {
542 type Error = EndpointError; 573 type Error = CdcAcmError;
543} 574}
544 575
545impl<'d, D: Driver<'d>> embedded_io_async::Read for BufferedReceiver<'d, D> { 576impl<'d, D: Driver<'d>> embedded_io_async::Read for BufferedReceiver<'d, D> {
@@ -552,14 +583,22 @@ impl<'d, D: Driver<'d>> embedded_io_async::Read for BufferedReceiver<'d, D> {
552 // If the caller's buffer is large enough to contain an entire packet, read directly into 583 // If the caller's buffer is large enough to contain an entire packet, read directly into
553 // that instead of buffering the packet internally. 584 // that instead of buffering the packet internally.
554 if buf.len() > self.receiver.max_packet_size() as usize { 585 if buf.len() > self.receiver.max_packet_size() as usize {
555 return self.receiver.read_packet(buf).await; 586 return match self.receiver.read_packet(buf).await {
587 Ok(n) => Ok(n),
588 Err(EndpointError::BufferOverflow) => unreachable!(),
589 Err(EndpointError::Disabled) => Err(CdcAcmError::NotConnected),
590 };
556 } 591 }
557 592
558 // Otherwise read a packet into the internal buffer, and return some of it to the caller. 593 // Otherwise read a packet into the internal buffer, and return some of it to the caller.
559 // 594 //
560 // It's important that `start` and `end` be updated in this order so they're left in a 595 // It's important that `start` and `end` be updated in this order so they're left in a
561 // consistent state if the `read` future is dropped mid-execution, e.g. from a timeout. 596 // consistent state if the `read` future is dropped mid-execution, e.g. from a timeout.
562 self.end = self.receiver.read_packet(&mut self.buffer).await?; 597 match self.receiver.read_packet(&mut self.buffer).await {
598 Ok(n) => self.end = n,
599 Err(EndpointError::BufferOverflow) => unreachable!(),
600 Err(EndpointError::Disabled) => return Err(CdcAcmError::NotConnected),
601 }
563 self.start = 0; 602 self.start = 0;
564 return Ok(self.read_from_buffer(buf)); 603 return Ok(self.read_from_buffer(buf));
565 } 604 }
diff --git a/examples/mcxa/Cargo.toml b/examples/mcxa/Cargo.toml
index 347659f5b..29d319375 100644
--- a/examples/mcxa/Cargo.toml
+++ b/examples/mcxa/Cargo.toml
@@ -18,7 +18,7 @@ embassy-mcxa = { path = "../../embassy-mcxa", features = ["defmt", "unstable-pac
18embassy-sync = "0.7.2" 18embassy-sync = "0.7.2"
19embassy-time = "0.5.0" 19embassy-time = "0.5.0"
20embassy-time-driver = "0.2.1" 20embassy-time-driver = "0.2.1"
21embedded-io-async = "0.6.1" 21embedded-io-async = "0.7.0"
22heapless = "0.9.2" 22heapless = "0.9.2"
23panic-probe = { version = "1.0", features = ["print-defmt"] } 23panic-probe = { version = "1.0", features = ["print-defmt"] }
24rand_core = "0.9" 24rand_core = "0.9"
diff --git a/examples/mcxa/src/bin/clkout.rs b/examples/mcxa/src/bin/clkout.rs
index 1e52912d3..c0e8c330d 100644
--- a/examples/mcxa/src/bin/clkout.rs
+++ b/examples/mcxa/src/bin/clkout.rs
@@ -4,6 +4,7 @@
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; 5use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4};
6use embassy_mcxa::clocks::PoweredClock; 6use embassy_mcxa::clocks::PoweredClock;
7use embassy_mcxa::clocks::config::{SoscConfig, SoscMode, SpllConfig, SpllMode, SpllSource};
7use embassy_mcxa::gpio::{DriveStrength, Level, Output, SlewRate}; 8use embassy_mcxa::gpio::{DriveStrength, Level, Output, SlewRate};
8use embassy_time::Timer; 9use embassy_time::Timer;
9use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; 10use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
@@ -11,58 +12,81 @@ use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
11/// Demonstrate CLKOUT, using Pin P4.2 12/// Demonstrate CLKOUT, using Pin P4.2
12#[embassy_executor::main] 13#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 14async fn main(_spawner: Spawner) {
14 let p = hal::init(hal::config::Config::default()); 15 let mut cfg = hal::config::Config::default();
16 cfg.clock_cfg.sosc = Some(SoscConfig {
17 mode: SoscMode::CrystalOscillator,
18 frequency: 8_000_000,
19 power: PoweredClock::NormalEnabledDeepSleepDisabled,
20 });
21 cfg.clock_cfg.spll = Some(SpllConfig {
22 source: SpllSource::Sirc,
23 // 12MHz
24 // 12 x 32 => 384MHz
25 // 384 / (16 x 2) => 12.0MHz
26 mode: SpllMode::Mode1b {
27 m_mult: 32,
28 p_div: 16,
29 bypass_p2_div: false,
30 },
31 power: PoweredClock::NormalEnabledDeepSleepDisabled,
32 pll1_clk_div: None,
33 });
34
35 let p = hal::init(cfg);
36
15 let mut pin = p.P4_2; 37 let mut pin = p.P4_2;
16 let mut clkout = p.CLKOUT; 38 let mut clkout = p.CLKOUT;
17 39
18 loop { 40 const K16_CONFIG: Config = Config {
19 defmt::info!("Set Low..."); 41 sel: ClockOutSel::Clk16K,
20 let mut output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); 42 div: Div4::no_div(),
21 Timer::after_millis(500).await; 43 level: PoweredClock::NormalEnabledDeepSleepDisabled,
44 };
45 const M4_CONFIG: Config = Config {
46 sel: ClockOutSel::Fro12M,
47 div: const { Div4::from_divisor(3).unwrap() },
48 level: PoweredClock::NormalEnabledDeepSleepDisabled,
49 };
50 const K512_CONFIG: Config = Config {
51 sel: ClockOutSel::ClkIn,
52 div: const { Div4::from_divisor(16).unwrap() },
53 level: PoweredClock::NormalEnabledDeepSleepDisabled,
54 };
55 const M1_CONFIG: Config = Config {
56 sel: ClockOutSel::Pll1Clk,
57 div: const { Div4::from_divisor(12).unwrap() },
58 level: PoweredClock::NormalEnabledDeepSleepDisabled,
59 };
22 60
61 #[rustfmt::skip]
62 let configs = [
63 ("16K -> /1 = 16K", K16_CONFIG),
64 ("12M -> /3 = 4M", M4_CONFIG),
65 ("8M -> /16 = 512K", K512_CONFIG),
66 ("12M-> /12 = 1M", M1_CONFIG),
67 ];
68
69 loop {
23 defmt::info!("Set High..."); 70 defmt::info!("Set High...");
24 output.set_high(); 71 let mut output = Output::new(pin.reborrow(), Level::High, DriveStrength::Normal, SlewRate::Slow);
25 Timer::after_millis(400).await; 72 Timer::after_millis(250).await;
26 73
27 defmt::info!("Set Low..."); 74 defmt::info!("Set Low...");
28 output.set_low(); 75 output.set_low();
29 Timer::after_millis(500).await; 76 Timer::after_millis(750).await;
30 77
31 defmt::info!("16k..."); 78 for (name, conf) in configs.iter() {
32 // Run Clock Out with the 16K clock 79 defmt::info!("Running {=str}", name);
33 let _clock_out = ClockOut::new(
34 clkout.reborrow(),
35 pin.reborrow(),
36 Config {
37 sel: ClockOutSel::Clk16K,
38 div: Div4::no_div(),
39 level: PoweredClock::NormalEnabledDeepSleepDisabled,
40 },
41 )
42 .unwrap();
43 80
44 Timer::after_millis(3000).await; 81 let _clock_out = ClockOut::new(clkout.reborrow(), pin.reborrow(), *conf).unwrap();
45
46 defmt::info!("Set Low...");
47 drop(_clock_out);
48 82
49 let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); 83 Timer::after_millis(3000).await;
50 Timer::after_millis(500).await;
51 84
52 // Run Clock Out with the 12M clock, divided by 3 85 defmt::info!("Set Low...");
53 defmt::info!("4M..."); 86 drop(_clock_out);
54 let _clock_out = ClockOut::new(
55 clkout.reborrow(),
56 pin.reborrow(),
57 Config {
58 sel: ClockOutSel::Fro12M,
59 div: const { Div4::from_divisor(3).unwrap() },
60 level: PoweredClock::NormalEnabledDeepSleepDisabled,
61 },
62 )
63 .unwrap();
64 87
65 // Let it run for 3 seconds... 88 let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow);
66 Timer::after_millis(3000).await; 89 Timer::after_millis(500).await;
90 }
67 } 91 }
68} 92}
diff --git a/examples/mcxa/src/bin/reset-reason.rs b/examples/mcxa/src/bin/reset-reason.rs
index c244fbe04..2d48a92b1 100644
--- a/examples/mcxa/src/bin/reset-reason.rs
+++ b/examples/mcxa/src/bin/reset-reason.rs
@@ -11,5 +11,7 @@ async fn main(_spawner: Spawner) {
11 let config = Config::default(); 11 let config = Config::default();
12 let _p = hal::init(config); 12 let _p = hal::init(config);
13 13
14 defmt::info!("Reset Reason: '{}'", reset_reason()); 14 for reason in reset_reason().into_iter() {
15 defmt::info!("Reset Reason: '{}'", reason);
16 }
15} 17}
diff --git a/examples/mspm0g3507/Cargo.toml b/examples/mspm0g3507/Cargo.toml
index 8c230f038..f4fc7e09f 100644
--- a/examples/mspm0g3507/Cargo.toml
+++ b/examples/mspm0g3507/Cargo.toml
@@ -18,7 +18,7 @@ defmt-rtt = "1.0.0"
18panic-probe = { version = "1.0.0", features = ["print-defmt"] } 18panic-probe = { version = "1.0.0", features = ["print-defmt"] }
19panic-semihosting = "0.6.0" 19panic-semihosting = "0.6.0"
20 20
21embedded-io-async = "0.6.1" 21embedded-io-async = { version = "0.7.0" }
22 22
23[profile.release] 23[profile.release]
24debug = 2 24debug = 2
diff --git a/examples/nrf52840/Cargo.toml b/examples/nrf52840/Cargo.toml
index a57bd7b24..15c187328 100644
--- a/examples/nrf52840/Cargo.toml
+++ b/examples/nrf52840/Cargo.toml
@@ -13,8 +13,8 @@ embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["de
13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time", "net-driver"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet","udp", "medium-ieee802154", "proto-ipv6"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embedded-io = { version = "0.6.0", features = ["defmt-03"] } 16embedded-io = { version = "0.7.1", features = ["defmt"] }
17embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 17embedded-io-async = { version = "0.7.0", features = ["defmt"] }
18embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] } 18embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] }
19embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] } 19embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] }
20 20
diff --git a/examples/nrf5340/Cargo.toml b/examples/nrf5340/Cargo.toml
index b8d5dbfb1..c54a84d22 100644
--- a/examples/nrf5340/Cargo.toml
+++ b/examples/nrf5340/Cargo.toml
@@ -13,7 +13,7 @@ embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["de
13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf5340-app-s", "time-driver-rtc1", "gpiote", "unstable-pac"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] } 15embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = ["defmt"] }
16embedded-io-async = { version = "0.6.1" } 16embedded-io-async = { version = "0.7.0" }
17 17
18defmt = "1.0.1" 18defmt = "1.0.1"
19defmt-rtt = "1.0.0" 19defmt-rtt = "1.0.0"
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
index 353d1b46e..9940443ff 100644
--- a/examples/nrf54l15/Cargo.toml
+++ b/examples/nrf54l15/Cargo.toml
@@ -11,8 +11,8 @@ embassy-executor = { version = "0.9.0", path = "../../embassy-executor", feature
11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54l15-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] } 14embedded-io = { version = "0.7.0", features = ["defmt"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 15embedded-io-async = { version = "0.7.0", features = ["defmt"] }
16 16
17rand = { version = "0.9.0", default-features = false } 17rand = { version = "0.9.0", default-features = false }
18 18
diff --git a/examples/nrf54lm20/Cargo.toml b/examples/nrf54lm20/Cargo.toml
index e3bf22b25..78ce60596 100644
--- a/examples/nrf54lm20/Cargo.toml
+++ b/examples/nrf54lm20/Cargo.toml
@@ -11,8 +11,8 @@ embassy-executor = { version = "0.9.0", path = "../../embassy-executor", feature
11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 11embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54lm20-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] } 13embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "nrf54lm20-app-s", "time-driver-grtc", "gpiote", "unstable-pac", "time"] }
14embedded-io = { version = "0.6.0", features = ["defmt-03"] } 14embedded-io = { version = "0.7.0", features = ["defmt"] }
15embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 15embedded-io-async = { version = "0.7.0", features = ["defmt"] }
16 16
17rand = { version = "0.9.0", default-features = false } 17rand = { version = "0.9.0", default-features = false }
18 18
diff --git a/examples/nrf9160/Cargo.toml b/examples/nrf9160/Cargo.toml
index 907b06e6d..bad7fdc79 100644
--- a/examples/nrf9160/Cargo.toml
+++ b/examples/nrf9160/Cargo.toml
@@ -20,8 +20,8 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
20cortex-m-rt = "0.7.0" 20cortex-m-rt = "0.7.0"
21panic-probe = { version = "1.0.0", features = ["print-defmt"] } 21panic-probe = { version = "1.0.0", features = ["print-defmt"] }
22static_cell = { version = "2" } 22static_cell = { version = "2" }
23embedded-io = "0.6.1" 23embedded-io = { version = "0.7.1" }
24embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 24embedded-io-async = { version = "0.7.0", features = ["defmt"] }
25 25
26[profile.release] 26[profile.release]
27debug = 2 27debug = 2
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index e247f6f7a..1a5712dd3 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -26,7 +26,7 @@ fixed = "1.23.1"
26fixed-macro = "1.2" 26fixed-macro = "1.2"
27 27
28# for web request example 28# for web request example
29reqwless = { version = "0.13.0", features = ["defmt"] } 29reqwless = { git = "https://github.com/drogue-iot/reqwless", rev = "68f703dfc16e6f7f964b7238c922c0d433118872", features = ["defmt"] }
30serde = { version = "1.0.203", default-features = false, features = ["derive"] } 30serde = { version = "1.0.203", default-features = false, features = ["derive"] }
31serde-json-core = "0.5.1" 31serde-json-core = "0.5.1"
32 32
@@ -50,7 +50,7 @@ usbd-hid = "0.9.0"
50embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 50embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
51embedded-hal-async = "1.0" 51embedded-hal-async = "1.0"
52embedded-hal-bus = { version = "0.1", features = ["async"] } 52embedded-hal-bus = { version = "0.1", features = ["async"] }
53embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 53embedded-io-async = { version = "0.7.0", features = ["defmt"] }
54embedded-storage = { version = "0.3" } 54embedded-storage = { version = "0.3" }
55static_cell = "2.1" 55static_cell = "2.1"
56portable-atomic = { version = "1.5", features = ["critical-section"] } 56portable-atomic = { version = "1.5", features = ["critical-section"] }
diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml
index 16dfb5b77..bc2bcf5b6 100644
--- a/examples/rp235x/Cargo.toml
+++ b/examples/rp235x/Cargo.toml
@@ -51,7 +51,7 @@ usbd-hid = "0.9.0"
51embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 51embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
52embedded-hal-async = "1.0" 52embedded-hal-async = "1.0"
53embedded-hal-bus = { version = "0.1", features = ["async"] } 53embedded-hal-bus = { version = "0.1", features = ["async"] }
54embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 54embedded-io-async = { version = "0.7.0", features = ["defmt"] }
55embedded-storage = { version = "0.3" } 55embedded-storage = { version = "0.3" }
56static_cell = "2.1" 56static_cell = "2.1"
57portable-atomic = { version = "1.5", features = ["critical-section"] } 57portable-atomic = { version = "1.5", features = ["critical-section"] }
diff --git a/examples/std/Cargo.toml b/examples/std/Cargo.toml
index 0e3b3c6d5..06f1ba67e 100644
--- a/examples/std/Cargo.toml
+++ b/examples/std/Cargo.toml
@@ -12,8 +12,8 @@ embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["lo
12embassy-net = { version = "0.7.1", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] } 12embassy-net = { version = "0.7.1", path = "../../embassy-net", features=[ "log", "medium-ethernet", "medium-ip", "tcp", "udp", "dns", "dhcpv4", "proto-ipv6"] }
13embassy-net-tuntap = { version = "0.1.1", path = "../../embassy-net-tuntap" } 13embassy-net-tuntap = { version = "0.1.1", path = "../../embassy-net-tuntap" }
14embassy-net-ppp = { version = "0.2.1", path = "../../embassy-net-ppp", features = ["log"]} 14embassy-net-ppp = { version = "0.2.1", path = "../../embassy-net-ppp", features = ["log"]}
15embedded-io-async = { version = "0.6.1" } 15embedded-io-async = { version = "0.7.0" }
16embedded-io-adapters = { version = "0.6.1", features = ["futures-03"] } 16embedded-io-adapters = { version = "0.7.0", features = ["futures-03"] }
17critical-section = { version = "1.1", features = ["std"] } 17critical-section = { version = "1.1", features = ["std"] }
18 18
19async-io = "1.6.0" 19async-io = "1.6.0"
diff --git a/examples/stm32f4/Cargo.toml b/examples/stm32f4/Cargo.toml
index b4555045a..5bcf66ade 100644
--- a/examples/stm32f4/Cargo.toml
+++ b/examples/stm32f4/Cargo.toml
@@ -23,8 +23,8 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
23cortex-m-rt = "0.7.0" 23cortex-m-rt = "0.7.0"
24embedded-hal = "0.2.6" 24embedded-hal = "0.2.6"
25embedded-hal-bus = { version = "0.2", features = ["async"] } 25embedded-hal-bus = { version = "0.2", features = ["async"] }
26embedded-io = { version = "0.6.0" } 26embedded-io = { version = "0.7.1" }
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.7.0" }
28panic-probe = { version = "1.0.0", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29futures-util = { version = "0.3.30", default-features = false } 29futures-util = { version = "0.3.30", default-features = false }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
diff --git a/examples/stm32f7/Cargo.toml b/examples/stm32f7/Cargo.toml
index 565277394..a952b770b 100644
--- a/examples/stm32f7/Cargo.toml
+++ b/examples/stm32f7/Cargo.toml
@@ -12,7 +12,7 @@ embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["de
12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 12embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 13embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] } 14embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet"] }
15embedded-io-async = { version = "0.6.1" } 15embedded-io-async = { version = "0.7.0" }
16embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } 16embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
18 18
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
index 16f28500d..a25a01e59 100644
--- a/examples/stm32g0/Cargo.toml
+++ b/examples/stm32g0/Cargo.toml
@@ -24,7 +24,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
24heapless = { version = "0.8", default-features = false } 24heapless = { version = "0.8", default-features = false }
25portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] } 25portable-atomic = { version = "1.5", features = ["unsafe-assume-single-core"] }
26 26
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.7.0" }
28 28
29[profile.release] 29[profile.release]
30debug = 2 30debug = 2
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml
index 512186c3d..f674a2936 100644
--- a/examples/stm32h5/Cargo.toml
+++ b/examples/stm32h5/Cargo.toml
@@ -23,8 +23,8 @@ cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6" 23embedded-hal = "0.2.6"
24embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 24embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
26embedded-io-async = { version = "0.6.1" } 26embedded-io-async = { version = "0.7.0" }
27embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.9.0"
28panic-probe = { version = "1.0.0", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
diff --git a/examples/stm32h7/Cargo.toml b/examples/stm32h7/Cargo.toml
index 09b734054..8f4b2bf4f 100644
--- a/examples/stm32h7/Cargo.toml
+++ b/examples/stm32h7/Cargo.toml
@@ -24,8 +24,8 @@ cortex-m-rt = "0.7.0"
24embedded-hal = "0.2.6" 24embedded-hal = "0.2.6"
25embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 25embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
26embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
27embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.9.0"
28embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.7.0" }
29panic-probe = { version = "1.0.0", features = ["print-defmt"] } 29panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
diff --git a/examples/stm32h723/Cargo.toml b/examples/stm32h723/Cargo.toml
index 93a5109e2..8b3f8dc55 100644
--- a/examples/stm32h723/Cargo.toml
+++ b/examples/stm32h723/Cargo.toml
@@ -21,8 +21,8 @@ cortex-m-rt = "0.7.0"
21embedded-hal = "0.2.6" 21embedded-hal = "0.2.6"
22embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 22embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
23embedded-hal-async = { version = "1.0" } 23embedded-hal-async = { version = "1.0" }
24embedded-nal-async = "0.8.0" 24embedded-nal-async = "0.9.0"
25embedded-io-async = { version = "0.6.1" } 25embedded-io-async = { version = "0.7.0" }
26panic-probe = { version = "1.0.0", features = ["print-defmt"] } 26panic-probe = { version = "1.0.0", features = ["print-defmt"] }
27heapless = { version = "0.8", default-features = false } 27heapless = { version = "0.8", default-features = false }
28critical-section = "1.1" 28critical-section = "1.1"
diff --git a/examples/stm32h742/Cargo.toml b/examples/stm32h742/Cargo.toml
index 9b5e5d93d..7ff4dfbe4 100644
--- a/examples/stm32h742/Cargo.toml
+++ b/examples/stm32h742/Cargo.toml
@@ -33,7 +33,7 @@ embassy-net = { version = "0.7.1", path = "../../embassy-net", features = [
33 "dhcpv4", 33 "dhcpv4",
34 "medium-ethernet", 34 "medium-ethernet",
35] } 35] }
36embedded-io-async = { version = "0.6.1" } 36embedded-io-async = { version = "0.7.0" }
37embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = [ 37embassy-usb = { version = "0.5.1", path = "../../embassy-usb", features = [
38 "defmt", 38 "defmt",
39] } 39] }
diff --git a/examples/stm32h755cm4/Cargo.toml b/examples/stm32h755cm4/Cargo.toml
index d69f0228e..e5be0056f 100644
--- a/examples/stm32h755cm4/Cargo.toml
+++ b/examples/stm32h755cm4/Cargo.toml
@@ -24,8 +24,8 @@ cortex-m-rt = "0.7.0"
24embedded-hal = "0.2.6" 24embedded-hal = "0.2.6"
25embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 25embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
26embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
27embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.9.0"
28embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.7.0" }
29panic-probe = { version = "1.0.0", features = ["print-defmt"] } 29panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
diff --git a/examples/stm32h755cm7/Cargo.toml b/examples/stm32h755cm7/Cargo.toml
index f4e1e53b7..42c05549b 100644
--- a/examples/stm32h755cm7/Cargo.toml
+++ b/examples/stm32h755cm7/Cargo.toml
@@ -24,8 +24,8 @@ cortex-m-rt = "0.7.0"
24embedded-hal = "0.2.6" 24embedded-hal = "0.2.6"
25embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 25embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
26embedded-hal-async = { version = "1.0" } 26embedded-hal-async = { version = "1.0" }
27embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.9.0"
28embedded-io-async = { version = "0.6.1" } 28embedded-io-async = { version = "0.7.0" }
29panic-probe = { version = "1.0.0", features = ["print-defmt"] } 29panic-probe = { version = "1.0.0", features = ["print-defmt"] }
30heapless = { version = "0.8", default-features = false } 30heapless = { version = "0.8", default-features = false }
31critical-section = "1.1" 31critical-section = "1.1"
diff --git a/examples/stm32h7b0/Cargo.toml b/examples/stm32h7b0/Cargo.toml
index 0509d394d..434bfebce 100644
--- a/examples/stm32h7b0/Cargo.toml
+++ b/examples/stm32h7b0/Cargo.toml
@@ -23,8 +23,8 @@ cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6" 23embedded-hal = "0.2.6"
24embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 24embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
26embedded-nal-async = "0.8.0" 26embedded-nal-async = "0.9.0"
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.7.0" }
28panic-probe = { version = "1.0.0", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
diff --git a/examples/stm32h7rs/Cargo.toml b/examples/stm32h7rs/Cargo.toml
index ab525ad91..74664432f 100644
--- a/examples/stm32h7rs/Cargo.toml
+++ b/examples/stm32h7rs/Cargo.toml
@@ -23,8 +23,8 @@ cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6" 23embedded-hal = "0.2.6"
24embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 24embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
26embedded-nal-async = "0.8.0" 26embedded-nal-async = "0.9.0"
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.7.0" }
28panic-probe = { version = "1.0.0", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
30critical-section = "1.1" 30critical-section = "1.1"
diff --git a/examples/stm32l0/Cargo.toml b/examples/stm32l0/Cargo.toml
index a9c71d655..c06c761c9 100644
--- a/examples/stm32l0/Cargo.toml
+++ b/examples/stm32l0/Cargo.toml
@@ -18,8 +18,8 @@ defmt = "1.0.1"
18defmt-rtt = "1.0.0" 18defmt-rtt = "1.0.0"
19 19
20embedded-storage = "0.3.1" 20embedded-storage = "0.3.1"
21embedded-io = { version = "0.6.0" } 21embedded-io = { version = "0.7.1" }
22embedded-io-async = { version = "0.6.1" } 22embedded-io-async = { version = "0.7.0" }
23 23
24cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 24cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
25cortex-m-rt = "0.7.0" 25cortex-m-rt = "0.7.0"
diff --git a/examples/stm32l4/Cargo.toml b/examples/stm32l4/Cargo.toml
index 936472199..995c8c694 100644
--- a/examples/stm32l4/Cargo.toml
+++ b/examples/stm32l4/Cargo.toml
@@ -16,8 +16,8 @@ embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defm
16embassy-net-adin1110 = { version = "0.3.1", path = "../../embassy-net-adin1110" } 16embassy-net-adin1110 = { version = "0.3.1", path = "../../embassy-net-adin1110" }
17embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] } 17embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "tcp", "dhcpv4", "medium-ethernet"] }
18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" } 18embassy-futures = { version = "0.1.2", path = "../../embassy-futures" }
19embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 19embedded-io-async = { version = "0.7.0", features = ["defmt"] }
20embedded-io = { version = "0.6.0", features = ["defmt-03"] } 20embedded-io = { version = "0.7.1", features = ["defmt"] }
21 21
22defmt = "1.0.1" 22defmt = "1.0.1"
23defmt-rtt = "1.0.0" 23defmt-rtt = "1.0.0"
diff --git a/examples/stm32l5/Cargo.toml b/examples/stm32l5/Cargo.toml
index 586b00836..b6d14ce25 100644
--- a/examples/stm32l5/Cargo.toml
+++ b/examples/stm32l5/Cargo.toml
@@ -24,7 +24,7 @@ cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-sing
24cortex-m-rt = "0.7.0" 24cortex-m-rt = "0.7.0"
25embedded-hal = "0.2.6" 25embedded-hal = "0.2.6"
26heapless = { version = "0.8", default-features = false } 26heapless = { version = "0.8", default-features = false }
27embedded-io-async = { version = "0.6.1" } 27embedded-io-async = { version = "0.7.0" }
28static_cell = "2" 28static_cell = "2"
29 29
30[profile.release] 30[profile.release]
diff --git a/examples/stm32n6/Cargo.toml b/examples/stm32n6/Cargo.toml
index 5ad5b97ce..fdfaed531 100644
--- a/examples/stm32n6/Cargo.toml
+++ b/examples/stm32n6/Cargo.toml
@@ -23,7 +23,7 @@ cortex-m-rt = "0.7.0"
23embedded-hal = "0.2.6" 23embedded-hal = "0.2.6"
24embedded-hal-1 = { package = "embedded-hal", version = "1.0" } 24embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
25embedded-hal-async = { version = "1.0" } 25embedded-hal-async = { version = "1.0" }
26embedded-io-async = { version = "0.6.1" } 26embedded-io-async = { version = "0.7.0" }
27embedded-nal-async = "0.8.0" 27embedded-nal-async = "0.8.0"
28panic-probe = { version = "1.0.0", features = ["print-defmt"] } 28panic-probe = { version = "1.0.0", features = ["print-defmt"] }
29heapless = { version = "0.8", default-features = false } 29heapless = { version = "0.8", default-features = false }
diff --git a/examples/stm32wb/Cargo.toml b/examples/stm32wb/Cargo.toml
index 83f7cb56b..496500f75 100644
--- a/examples/stm32wb/Cargo.toml
+++ b/examples/stm32wb/Cargo.toml
@@ -7,10 +7,10 @@ publish = false
7 7
8[dependencies] 8[dependencies]
9# Change stm32wb55rg to your chip name in both dependencies, if necessary. 9# Change stm32wb55rg to your chip name in both dependencies, if necessary.
10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti", "low-power"] } 10embassy-stm32 = { version = "0.4.0", path = "../../embassy-stm32", features = [ "defmt", "stm32wb55rg", "time-driver-any", "memory-x", "exti", "low-power-pender"] }
11embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] } 11embassy-stm32-wpan = { version = "0.1.0", path = "../../embassy-stm32-wpan", features = ["defmt", "stm32wb55rg"] }
12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } 12embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] }
13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["defmt"] }
14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] }
15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true } 15embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "udp", "proto-ipv6", "medium-ieee802154", ], optional = true }
16 16
diff --git a/examples/stm32wb/src/bin/blinky.rs b/examples/stm32wb/src/bin/blinky.rs
index f37e8b1d8..e2737fcd5 100644
--- a/examples/stm32wb/src/bin/blinky.rs
+++ b/examples/stm32wb/src/bin/blinky.rs
@@ -7,7 +7,7 @@ use embassy_stm32::gpio::{Level, Output, Speed};
7use embassy_time::Timer; 7use embassy_time::Timer;
8use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
11async fn main(_spawner: Spawner) { 11async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 12 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 13 info!("Hello World!");
diff --git a/examples/stm32wb/src/bin/button_exti.rs b/examples/stm32wb/src/bin/button_exti.rs
index 3c58eb556..37a207519 100644
--- a/examples/stm32wb/src/bin/button_exti.rs
+++ b/examples/stm32wb/src/bin/button_exti.rs
@@ -13,7 +13,7 @@ bind_interrupts!(
13 EXTI4 => exti::InterruptHandler<interrupt::typelevel::EXTI4>; 13 EXTI4 => exti::InterruptHandler<interrupt::typelevel::EXTI4>;
14}); 14});
15 15
16#[embassy_executor::main] 16#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
17async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
19 info!("Hello World!"); 19 info!("Hello World!");
diff --git a/examples/stm32wb/src/bin/eddystone_beacon.rs b/examples/stm32wb/src/bin/eddystone_beacon.rs
index 413b1ac8f..a679e6fb1 100644
--- a/examples/stm32wb/src/bin/eddystone_beacon.rs
+++ b/examples/stm32wb/src/bin/eddystone_beacon.rs
@@ -26,7 +26,7 @@ bind_interrupts!(struct Irqs{
26 26
27const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; 27const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7;
28 28
29#[embassy_executor::main] 29#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
30async fn main(_spawner: Spawner) { 30async fn main(_spawner: Spawner) {
31 /* 31 /*
32 How to make this work: 32 How to make this work:
diff --git a/examples/stm32wb/src/bin/gatt_server.rs b/examples/stm32wb/src/bin/gatt_server.rs
index 3484f1844..10c7fd0ba 100644
--- a/examples/stm32wb/src/bin/gatt_server.rs
+++ b/examples/stm32wb/src/bin/gatt_server.rs
@@ -38,7 +38,7 @@ bind_interrupts!(struct Irqs{
38 38
39const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7; 39const BLE_GAP_DEVICE_NAME_LENGTH: u8 = 7;
40 40
41#[embassy_executor::main] 41#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
42async fn main(spawner: Spawner) { 42async fn main(spawner: Spawner) {
43 /* 43 /*
44 How to make this work: 44 How to make this work:
diff --git a/examples/stm32wb/src/bin/mac_ffd.rs b/examples/stm32wb/src/bin/mac_ffd.rs
index 4bab6ea9f..cd15968d2 100644
--- a/examples/stm32wb/src/bin/mac_ffd.rs
+++ b/examples/stm32wb/src/bin/mac_ffd.rs
@@ -23,7 +23,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
23 memory_manager.run_queue().await; 23 memory_manager.run_queue().await;
24} 24}
25 25
26#[embassy_executor::main] 26#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
27async fn main(spawner: Spawner) { 27async fn main(spawner: Spawner) {
28 /* 28 /*
29 How to make this work: 29 How to make this work:
diff --git a/examples/stm32wb/src/bin/mac_ffd_net.rs b/examples/stm32wb/src/bin/mac_ffd_net.rs
index b4789e3ee..244b35243 100644
--- a/examples/stm32wb/src/bin/mac_ffd_net.rs
+++ b/examples/stm32wb/src/bin/mac_ffd_net.rs
@@ -41,7 +41,7 @@ async fn run_net(mut runner: embassy_net::Runner<'static, Driver<'static>>) -> !
41 runner.run().await 41 runner.run().await
42} 42}
43 43
44#[embassy_executor::main] 44#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
45async fn main(spawner: Spawner) { 45async fn main(spawner: Spawner) {
46 /* 46 /*
47 How to make this work: 47 How to make this work:
diff --git a/examples/stm32wb/src/bin/mac_rfd.rs b/examples/stm32wb/src/bin/mac_rfd.rs
index dae3c5200..f3e65c66b 100644
--- a/examples/stm32wb/src/bin/mac_rfd.rs
+++ b/examples/stm32wb/src/bin/mac_rfd.rs
@@ -25,7 +25,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
25 memory_manager.run_queue().await; 25 memory_manager.run_queue().await;
26} 26}
27 27
28#[embassy_executor::main] 28#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
29async fn main(spawner: Spawner) { 29async fn main(spawner: Spawner) {
30 /* 30 /*
31 How to make this work: 31 How to make this work:
diff --git a/examples/stm32wb/src/bin/tl_mbox.rs b/examples/stm32wb/src/bin/tl_mbox.rs
index 0902e28e8..adb6eff7b 100644
--- a/examples/stm32wb/src/bin/tl_mbox.rs
+++ b/examples/stm32wb/src/bin/tl_mbox.rs
@@ -15,7 +15,7 @@ bind_interrupts!(struct Irqs{
15 IPCC_C1_TX => TransmitInterruptHandler; 15 IPCC_C1_TX => TransmitInterruptHandler;
16}); 16});
17 17
18#[embassy_executor::main] 18#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
19async fn main(_spawner: Spawner) { 19async fn main(_spawner: Spawner) {
20 /* 20 /*
21 How to make this work: 21 How to make this work:
diff --git a/examples/stm32wb/src/bin/tl_mbox_ble.rs b/examples/stm32wb/src/bin/tl_mbox_ble.rs
index 763dc32cd..376b808de 100644
--- a/examples/stm32wb/src/bin/tl_mbox_ble.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_ble.rs
@@ -20,7 +20,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
20 memory_manager.run_queue().await; 20 memory_manager.run_queue().await;
21} 21}
22 22
23#[embassy_executor::main] 23#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
24async fn main(spawner: Spawner) { 24async fn main(spawner: Spawner) {
25 /* 25 /*
26 How to make this work: 26 How to make this work:
diff --git a/examples/stm32wb/src/bin/tl_mbox_mac.rs b/examples/stm32wb/src/bin/tl_mbox_mac.rs
index 235a48241..697e061c1 100644
--- a/examples/stm32wb/src/bin/tl_mbox_mac.rs
+++ b/examples/stm32wb/src/bin/tl_mbox_mac.rs
@@ -20,7 +20,7 @@ async fn run_mm_queue(mut memory_manager: mm::MemoryManager<'static>) {
20 memory_manager.run_queue().await; 20 memory_manager.run_queue().await;
21} 21}
22 22
23#[embassy_executor::main] 23#[embassy_executor::main(executor = "embassy_stm32::Executor", entry = "cortex_m_rt::entry")]
24async fn main(spawner: Spawner) { 24async fn main(spawner: Spawner) {
25 /* 25 /*
26 How to make this work: 26 How to make this work:
diff --git a/examples/stm32wle5/Cargo.toml b/examples/stm32wle5/Cargo.toml
index f2fc4dd3d..64c81c761 100644
--- a/examples/stm32wle5/Cargo.toml
+++ b/examples/stm32wle5/Cargo.toml
@@ -15,7 +15,7 @@ embassy-embedded-hal = { version = "0.5.0", path = "../../embassy-embedded-hal"
15 15
16defmt = "1.0.1" 16defmt = "1.0.1"
17defmt-rtt = { version = "1.1.0", optional = true } 17defmt-rtt = { version = "1.1.0", optional = true }
18defmt-serial = { version = "0.10.0", optional = true } 18defmt-serial = { git = "https://github.com/gauteh/defmt-serial", rev = "411ae7fa909b4fd2667885aff687e009b9108190", optional = true }
19 19
20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 20cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
21cortex-m-rt = "0.7.0" 21cortex-m-rt = "0.7.0"
diff --git a/tests/mspm0/Cargo.toml b/tests/mspm0/Cargo.toml
index df52b538d..56b027feb 100644
--- a/tests/mspm0/Cargo.toml
+++ b/tests/mspm0/Cargo.toml
@@ -26,8 +26,8 @@ cortex-m = { version = "0.7.6", features = [ "inline-asm", "critical-section-sin
26cortex-m-rt = "0.7.0" 26cortex-m-rt = "0.7.0"
27embedded-hal = { package = "embedded-hal", version = "1.0" } 27embedded-hal = { package = "embedded-hal", version = "1.0" }
28embedded-hal-async = { version = "1.0" } 28embedded-hal-async = { version = "1.0" }
29embedded-io = { version = "0.6.1", features = ["defmt-03"] } 29embedded-io = { version = "0.7.1", features = ["defmt"] }
30embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 30embedded-io-async = { version = "0.7.0", features = ["defmt"] }
31panic-probe = { version = "1.0.0", features = ["print-defmt"] } 31panic-probe = { version = "1.0.0", features = ["print-defmt"] }
32static_cell = "2" 32static_cell = "2"
33portable-atomic = { version = "1.5", features = ["critical-section"] } 33portable-atomic = { version = "1.5", features = ["critical-section"] }
diff --git a/tests/nrf/Cargo.toml b/tests/nrf/Cargo.toml
index 50f059b34..b1e0a68c2 100644
--- a/tests/nrf/Cargo.toml
+++ b/tests/nrf/Cargo.toml
@@ -13,7 +13,7 @@ embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["de
13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] } 13embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "defmt"] }
14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 14embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
15embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] } 15embassy-nrf = { version = "0.9.0", path = "../../embassy-nrf", features = ["defmt", "time-driver-rtc1", "gpiote", "unstable-pac"] }
16embedded-io-async = { version = "0.6.1", features = ["defmt-03"] } 16embedded-io-async = { version = "0.7.0", features = ["defmt"] }
17embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] } 17embassy-net = { version = "0.7.1", path = "../../embassy-net", features = ["defmt", "tcp", "dhcpv4", "medium-ethernet", ] }
18embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] } 18embassy-net-esp-hosted = { version = "0.2.1", path = "../../embassy-net-esp-hosted", features = ["defmt"] }
19embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] } 19embassy-net-enc28j60 = { version = "0.2.1", path = "../../embassy-net-enc28j60", features = ["defmt"] }
diff --git a/tests/rp/Cargo.toml b/tests/rp/Cargo.toml
index 4dfe6904e..375a613d2 100644
--- a/tests/rp/Cargo.toml
+++ b/tests/rp/Cargo.toml
@@ -35,7 +35,7 @@ embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
35embedded-hal-async = { version = "1.0" } 35embedded-hal-async = { version = "1.0" }
36embedded-hal-bus = { version = "0.1", features = ["async"] } 36embedded-hal-bus = { version = "0.1", features = ["async"] }
37panic-probe = { version = "1.0.0", features = ["print-defmt"] } 37panic-probe = { version = "1.0.0", features = ["print-defmt"] }
38embedded-io-async = { version = "0.6.1" } 38embedded-io-async = { version = "0.7.0" }
39embedded-storage = { version = "0.3" } 39embedded-storage = { version = "0.3" }
40static_cell = "2" 40static_cell = "2"
41portable-atomic = { version = "1.5", features = ["critical-section"] } 41portable-atomic = { version = "1.5", features = ["critical-section"] }
diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs
index 83c375bc5..75dacbe7e 100644
--- a/tests/stm32/src/bin/stop.rs
+++ b/tests/stm32/src/bin/stop.rs
@@ -60,10 +60,12 @@ async fn async_main(spawner: Spawner) {
60 60
61 let (rtc, _time_provider) = Rtc::new(p.RTC); 61 let (rtc, _time_provider) = Rtc::new(p.RTC);
62 62
63 info!("set datetime");
63 critical_section::with(|cs| { 64 critical_section::with(|cs| {
64 rtc.borrow_mut(cs).set_datetime(now.into()).expect("datetime not set"); 65 rtc.borrow_mut(cs).set_datetime(now.into()).expect("datetime not set");
65 }); 66 });
66 67
68 info!("spawn");
67 spawner.spawn(task_1().unwrap()); 69 spawner.spawn(task_1().unwrap());
68 spawner.spawn(task_2().unwrap()); 70 spawner.spawn(task_2().unwrap());
69} 71}