diff options
| -rw-r--r-- | embassy-stm32/Cargo.toml | 6 | ||||
| -rw-r--r-- | embassy-stm32/src/low_power.rs | 39 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f247.rs | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/h.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l.rs | 2 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/u5.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/datetime.rs | 4 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/mod.rs | 49 | ||||
| -rw-r--r-- | embassy-stm32/src/rtc/v3.rs | 36 | ||||
| -rw-r--r-- | examples/stm32h5/Cargo.toml | 2 | ||||
| -rw-r--r-- | examples/stm32h5/src/bin/stop.rs | 71 | ||||
| -rw-r--r-- | tests/stm32/Cargo.toml | 4 | ||||
| -rw-r--r-- | tests/stm32/src/bin/stop.rs | 7 |
13 files changed, 154 insertions, 72 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 669e6537a..653a376bd 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -24,7 +24,7 @@ flavors = [ | |||
| 24 | { regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" }, | 24 | { regex_feature = "stm32c0.*", target = "thumbv6m-none-eabi" }, |
| 25 | { regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" }, | 25 | { regex_feature = "stm32g0.*", target = "thumbv6m-none-eabi" }, |
| 26 | { regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi", features = ["low-power"] }, | 26 | { regex_feature = "stm32g4.*", target = "thumbv7em-none-eabi", features = ["low-power"] }, |
| 27 | { regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf" }, | 27 | { regex_feature = "stm32h5.*", target = "thumbv8m.main-none-eabihf", features = ["low-power"] }, |
| 28 | { regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" }, | 28 | { regex_feature = "stm32h7.*", target = "thumbv7em-none-eabi" }, |
| 29 | { regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi", features = ["low-power"] }, | 29 | { regex_feature = "stm32l0.*", target = "thumbv6m-none-eabi", features = ["low-power"] }, |
| 30 | { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" }, | 30 | { regex_feature = "stm32l1.*", target = "thumbv7m-none-eabi" }, |
| @@ -72,7 +72,7 @@ rand_core = "0.6.3" | |||
| 72 | sdio-host = "0.5.0" | 72 | sdio-host = "0.5.0" |
| 73 | critical-section = "1.1" | 73 | critical-section = "1.1" |
| 74 | #stm32-metapac = { version = "15" } | 74 | #stm32-metapac = { version = "15" } |
| 75 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-01ac9bfd035961dc75f32dcd6080501538246d5c" } | 75 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-823168933f3860770111f7bde2a82b912eac58c0" } |
| 76 | 76 | ||
| 77 | vcell = "0.1.3" | 77 | vcell = "0.1.3" |
| 78 | nb = "1.0.0" | 78 | nb = "1.0.0" |
| @@ -98,7 +98,7 @@ proc-macro2 = "1.0.36" | |||
| 98 | quote = "1.0.15" | 98 | quote = "1.0.15" |
| 99 | 99 | ||
| 100 | #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} | 100 | #stm32-metapac = { version = "15", default-features = false, features = ["metadata"]} |
| 101 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-01ac9bfd035961dc75f32dcd6080501538246d5c", default-features = false, features = ["metadata"]} | 101 | stm32-metapac = { git = "https://github.com/embassy-rs/stm32-data-generated", tag = "stm32-data-823168933f3860770111f7bde2a82b912eac58c0", default-features = false, features = ["metadata"]} |
| 102 | 102 | ||
| 103 | [features] | 103 | [features] |
| 104 | default = ["rt"] | 104 | default = ["rt"] |
diff --git a/embassy-stm32/src/low_power.rs b/embassy-stm32/src/low_power.rs index 4c3d288fd..604bdf416 100644 --- a/embassy-stm32/src/low_power.rs +++ b/embassy-stm32/src/low_power.rs | |||
| @@ -10,14 +10,14 @@ | |||
| 10 | //! exceptions to this rule: | 10 | //! exceptions to this rule: |
| 11 | //! | 11 | //! |
| 12 | //! * `GPIO` | 12 | //! * `GPIO` |
| 13 | //! * `RCC` | 13 | //! * `RTC` |
| 14 | //! | 14 | //! |
| 15 | //! Since entering and leaving low-power modes typically incurs a significant latency, the | 15 | //! 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 | 16 | //! 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. | 17 | //! [`time_driver::MIN_STOP_PAUSE`] in the future. |
| 18 | //! | 18 | //! |
| 19 | //! Currently there is no macro analogous to `embassy_executor::main` for this executor; | 19 | //! Currently there is no macro analogous to `embassy_executor::main` for this executor; |
| 20 | //! consequently one must define their entrypoint manually. Moveover, you must relinquish control | 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 | 21 | //! of the `RTC` peripheral to the executor. This will typically look like |
| 22 | //! | 22 | //! |
| 23 | //! ```rust,no_run | 23 | //! ```rust,no_run |
| @@ -99,7 +99,7 @@ pub fn stop_ready(stop_mode: StopMode) -> bool { | |||
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | /// Available stop modes. | 102 | /// Available Stop modes. |
| 103 | #[non_exhaustive] | 103 | #[non_exhaustive] |
| 104 | #[derive(PartialEq)] | 104 | #[derive(PartialEq)] |
| 105 | pub enum StopMode { | 105 | pub enum StopMode { |
| @@ -183,6 +183,12 @@ impl Executor { | |||
| 183 | fn configure_stop(&mut self, stop_mode: StopMode) { | 183 | fn configure_stop(&mut self, stop_mode: StopMode) { |
| 184 | #[cfg(stm32l5)] | 184 | #[cfg(stm32l5)] |
| 185 | crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into())); | 185 | crate::pac::PWR.cr1().modify(|m| m.set_lpms(stop_mode.into())); |
| 186 | #[cfg(stm32h5)] | ||
| 187 | crate::pac::PWR.pmcr().modify(|v| { | ||
| 188 | use crate::pac::pwr::vals; | ||
| 189 | v.set_lpms(vals::Lpms::STOP); | ||
| 190 | v.set_svos(vals::Svos::SCALE3); | ||
| 191 | }); | ||
| 186 | } | 192 | } |
| 187 | 193 | ||
| 188 | fn configure_pwr(&mut self) { | 194 | fn configure_pwr(&mut self) { |
| @@ -191,21 +197,26 @@ impl Executor { | |||
| 191 | compiler_fence(Ordering::SeqCst); | 197 | compiler_fence(Ordering::SeqCst); |
| 192 | 198 | ||
| 193 | let stop_mode = self.stop_mode(); | 199 | let stop_mode = self.stop_mode(); |
| 200 | |||
| 194 | if stop_mode.is_none() { | 201 | if stop_mode.is_none() { |
| 195 | trace!("low power: not ready to stop"); | 202 | trace!("low power: not ready to stop"); |
| 196 | } else if self.time_driver.pause_time().is_err() { | 203 | return; |
| 204 | } | ||
| 205 | |||
| 206 | if self.time_driver.pause_time().is_err() { | ||
| 197 | trace!("low power: failed to pause time"); | 207 | trace!("low power: failed to pause time"); |
| 198 | } else { | 208 | return; |
| 199 | let stop_mode = stop_mode.unwrap(); | ||
| 200 | match stop_mode { | ||
| 201 | StopMode::Stop1 => trace!("low power: stop 1"), | ||
| 202 | StopMode::Stop2 => trace!("low power: stop 2"), | ||
| 203 | } | ||
| 204 | self.configure_stop(stop_mode); | ||
| 205 | |||
| 206 | #[cfg(not(feature = "low-power-debug-with-sleep"))] | ||
| 207 | self.scb.set_sleepdeep(); | ||
| 208 | } | 209 | } |
| 210 | |||
| 211 | let stop_mode = stop_mode.unwrap(); | ||
| 212 | match stop_mode { | ||
| 213 | StopMode::Stop1 => trace!("low power: stop 1"), | ||
| 214 | StopMode::Stop2 => trace!("low power: stop 2"), | ||
| 215 | } | ||
| 216 | self.configure_stop(stop_mode); | ||
| 217 | |||
| 218 | #[cfg(not(feature = "low-power-debug-with-sleep"))] | ||
| 219 | self.scb.set_sleepdeep(); | ||
| 209 | } | 220 | } |
| 210 | 221 | ||
| 211 | /// Run the executor. | 222 | /// Run the executor. |
diff --git a/embassy-stm32/src/rcc/f247.rs b/embassy-stm32/src/rcc/f247.rs index 7b252870c..e3ee9a039 100644 --- a/embassy-stm32/src/rcc/f247.rs +++ b/embassy-stm32/src/rcc/f247.rs | |||
| @@ -277,6 +277,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 277 | pclk2_tim: Some(pclk2_tim), | 277 | pclk2_tim: Some(pclk2_tim), |
| 278 | rtc: rtc, | 278 | rtc: rtc, |
| 279 | pll1_q: pll.q, | 279 | pll1_q: pll.q, |
| 280 | pll1_r: None, // TODO | ||
| 280 | 281 | ||
| 281 | #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))] | 282 | #[cfg(any(stm32f2, all(stm32f4, not(stm32f410)), stm32f7))] |
| 282 | plli2s1_p: plli2s.p, | 283 | plli2s1_p: plli2s.p, |
| @@ -299,6 +300,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 299 | hsi_div488: hsi.map(|hsi| hsi/488u32), | 300 | hsi_div488: hsi.map(|hsi| hsi/488u32), |
| 300 | hsi_hse: None, | 301 | hsi_hse: None, |
| 301 | afif: None, | 302 | afif: None, |
| 303 | #[cfg(any(stm32f4, stm32f7))] | ||
| 304 | dsi_phy: None, // TODO | ||
| 302 | ); | 305 | ); |
| 303 | } | 306 | } |
| 304 | 307 | ||
diff --git a/embassy-stm32/src/rcc/h.rs b/embassy-stm32/src/rcc/h.rs index 1949fc891..aa8c4b1f7 100644 --- a/embassy-stm32/src/rcc/h.rs +++ b/embassy-stm32/src/rcc/h.rs | |||
| @@ -601,6 +601,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 601 | #[cfg(stm32h5)] | 601 | #[cfg(stm32h5)] |
| 602 | audioclk: None, | 602 | audioclk: None, |
| 603 | i2s_ckin: None, | 603 | i2s_ckin: None, |
| 604 | #[cfg(stm32h7)] | ||
| 605 | dsi_phy: None, // TODO | ||
| 604 | ); | 606 | ); |
| 605 | } | 607 | } |
| 606 | 608 | ||
diff --git a/embassy-stm32/src/rcc/l.rs b/embassy-stm32/src/rcc/l.rs index d7235ac7f..c625948fb 100644 --- a/embassy-stm32/src/rcc/l.rs +++ b/embassy-stm32/src/rcc/l.rs | |||
| @@ -420,6 +420,8 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 420 | sai2_extclk: None, | 420 | sai2_extclk: None, |
| 421 | lsi: None, | 421 | lsi: None, |
| 422 | lse: None, | 422 | lse: None, |
| 423 | #[cfg(stm32l4)] | ||
| 424 | dsi_phy: None, | ||
| 423 | ); | 425 | ); |
| 424 | } | 426 | } |
| 425 | 427 | ||
diff --git a/embassy-stm32/src/rcc/u5.rs b/embassy-stm32/src/rcc/u5.rs index 9533e16c4..4013d0a46 100644 --- a/embassy-stm32/src/rcc/u5.rs +++ b/embassy-stm32/src/rcc/u5.rs | |||
| @@ -297,6 +297,7 @@ pub(crate) unsafe fn init(config: Config) { | |||
| 297 | msik: None, | 297 | msik: None, |
| 298 | shsi: None, | 298 | shsi: None, |
| 299 | shsi_div_2: None, | 299 | shsi_div_2: None, |
| 300 | dsi_phy: None, | ||
| 300 | ); | 301 | ); |
| 301 | } | 302 | } |
| 302 | 303 | ||
diff --git a/embassy-stm32/src/rtc/datetime.rs b/embassy-stm32/src/rtc/datetime.rs index bab8cf4a3..77d89293d 100644 --- a/embassy-stm32/src/rtc/datetime.rs +++ b/embassy-stm32/src/rtc/datetime.rs | |||
| @@ -148,9 +148,9 @@ impl DateTime { | |||
| 148 | ) -> Result<Self, Error> { | 148 | ) -> Result<Self, Error> { |
| 149 | if year > 4095 { | 149 | if year > 4095 { |
| 150 | Err(Error::InvalidYear) | 150 | Err(Error::InvalidYear) |
| 151 | } else if month < 1 || month > 12 { | 151 | } else if !(1..=12).contains(&month) { |
| 152 | Err(Error::InvalidMonth) | 152 | Err(Error::InvalidMonth) |
| 153 | } else if day < 1 || day > 31 { | 153 | } else if !(1..=31).contains(&day) { |
| 154 | Err(Error::InvalidDay) | 154 | Err(Error::InvalidDay) |
| 155 | } else if hour > 23 { | 155 | } else if hour > 23 { |
| 156 | Err(Error::InvalidHour) | 156 | Err(Error::InvalidHour) |
diff --git a/embassy-stm32/src/rtc/mod.rs b/embassy-stm32/src/rtc/mod.rs index 00abe9356..b12a0db66 100644 --- a/embassy-stm32/src/rtc/mod.rs +++ b/embassy-stm32/src/rtc/mod.rs | |||
| @@ -42,7 +42,7 @@ pub(crate) enum WakeupPrescaler { | |||
| 42 | Div16 = 16, | 42 | Div16 = 16, |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | #[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4, stm32l5, stm32g0))] | 45 | #[cfg(any(stm32f4, stm32l0, stm32g4, stm32l5, stm32wb, stm32h5, stm32g0))] |
| 46 | impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { | 46 | impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { |
| 47 | fn from(val: WakeupPrescaler) -> Self { | 47 | fn from(val: WakeupPrescaler) -> Self { |
| 48 | use crate::pac::rtc::vals::Wucksel; | 48 | use crate::pac::rtc::vals::Wucksel; |
| @@ -56,7 +56,7 @@ impl From<WakeupPrescaler> for crate::pac::rtc::vals::Wucksel { | |||
| 56 | } | 56 | } |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | #[cfg(any(stm32wb, stm32f4, stm32l0, stm32g4, stm32l5, stm32g0))] | 59 | #[cfg(any(stm32f4, stm32l0, stm32g4, stm32l5, stm32wb, stm32h5, stm32g0))] |
| 60 | impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { | 60 | impl From<crate::pac::rtc::vals::Wucksel> for WakeupPrescaler { |
| 61 | fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { | 61 | fn from(val: crate::pac::rtc::vals::Wucksel) -> Self { |
| 62 | use crate::pac::rtc::vals::Wucksel; | 62 | use crate::pac::rtc::vals::Wucksel; |
| @@ -81,8 +81,7 @@ impl WakeupPrescaler { | |||
| 81 | WakeupPrescaler::Div16, | 81 | WakeupPrescaler::Div16, |
| 82 | ] | 82 | ] |
| 83 | .iter() | 83 | .iter() |
| 84 | .skip_while(|psc| **psc as u32 <= val) | 84 | .find(|psc| **psc as u32 > val) |
| 85 | .next() | ||
| 86 | .unwrap_or(&WakeupPrescaler::Div16) | 85 | .unwrap_or(&WakeupPrescaler::Div16) |
| 87 | } | 86 | } |
| 88 | } | 87 | } |
| @@ -159,7 +158,7 @@ impl RtcTimeProvider { | |||
| 159 | } | 158 | } |
| 160 | } | 159 | } |
| 161 | 160 | ||
| 162 | return Err(RtcError::ReadFailure); | 161 | Err(RtcError::ReadFailure) |
| 163 | } | 162 | } |
| 164 | } | 163 | } |
| 165 | 164 | ||
| @@ -190,7 +189,7 @@ impl Default for RtcConfig { | |||
| 190 | } | 189 | } |
| 191 | 190 | ||
| 192 | /// Calibration cycle period. | 191 | /// Calibration cycle period. |
| 193 | #[derive(Copy, Clone, Debug, PartialEq)] | 192 | #[derive(Default, Copy, Clone, Debug, PartialEq)] |
| 194 | #[repr(u8)] | 193 | #[repr(u8)] |
| 195 | pub enum RtcCalibrationCyclePeriod { | 194 | pub enum RtcCalibrationCyclePeriod { |
| 196 | /// 8-second calibration period | 195 | /// 8-second calibration period |
| @@ -198,15 +197,10 @@ pub enum RtcCalibrationCyclePeriod { | |||
| 198 | /// 16-second calibration period | 197 | /// 16-second calibration period |
| 199 | Seconds16, | 198 | Seconds16, |
| 200 | /// 32-second calibration period | 199 | /// 32-second calibration period |
| 200 | #[default] | ||
| 201 | Seconds32, | 201 | Seconds32, |
| 202 | } | 202 | } |
| 203 | 203 | ||
| 204 | impl Default for RtcCalibrationCyclePeriod { | ||
| 205 | fn default() -> Self { | ||
| 206 | RtcCalibrationCyclePeriod::Seconds32 | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | impl Rtc { | 204 | impl Rtc { |
| 211 | /// Create a new RTC instance. | 205 | /// Create a new RTC instance. |
| 212 | pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { | 206 | pub fn new(_rtc: impl Peripheral<P = RTC>, rtc_config: RtcConfig) -> Self { |
| @@ -254,13 +248,13 @@ impl Rtc { | |||
| 254 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. | 248 | /// Will return `RtcError::InvalidDateTime` if the datetime is not a valid range. |
| 255 | pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> { | 249 | pub fn set_datetime(&mut self, t: DateTime) -> Result<(), RtcError> { |
| 256 | self.write(true, |rtc| { | 250 | self.write(true, |rtc| { |
| 257 | let (ht, hu) = byte_to_bcd2(t.hour() as u8); | 251 | let (ht, hu) = byte_to_bcd2(t.hour()); |
| 258 | let (mnt, mnu) = byte_to_bcd2(t.minute() as u8); | 252 | let (mnt, mnu) = byte_to_bcd2(t.minute()); |
| 259 | let (st, su) = byte_to_bcd2(t.second() as u8); | 253 | let (st, su) = byte_to_bcd2(t.second()); |
| 260 | 254 | ||
| 261 | let (dt, du) = byte_to_bcd2(t.day() as u8); | 255 | let (dt, du) = byte_to_bcd2(t.day()); |
| 262 | let (mt, mu) = byte_to_bcd2(t.month() as u8); | 256 | let (mt, mu) = byte_to_bcd2(t.month()); |
| 263 | let yr = t.year() as u16; | 257 | let yr = t.year(); |
| 264 | let yr_offset = (yr - 2000_u16) as u8; | 258 | let yr_offset = (yr - 2000_u16) as u8; |
| 265 | let (yt, yu) = byte_to_bcd2(yr_offset); | 259 | let (yt, yu) = byte_to_bcd2(yr_offset); |
| 266 | 260 | ||
| @@ -338,7 +332,7 @@ impl Rtc { | |||
| 338 | } | 332 | } |
| 339 | 333 | ||
| 340 | #[cfg(feature = "low-power")] | 334 | #[cfg(feature = "low-power")] |
| 341 | /// start the wakeup alarm and wtih a duration that is as close to but less than | 335 | /// start the wakeup alarm and with a duration that is as close to but less than |
| 342 | /// the requested duration, and record the instant the wakeup alarm was started | 336 | /// the requested duration, and record the instant the wakeup alarm was started |
| 343 | pub(crate) fn start_wakeup_alarm( | 337 | pub(crate) fn start_wakeup_alarm( |
| 344 | &self, | 338 | &self, |
| @@ -422,20 +416,15 @@ impl Rtc { | |||
| 422 | #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] | 416 | #[cfg(any(rtc_v3, rtc_v3u5, rtc_v3l5))] |
| 423 | regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); | 417 | regs.scr().write(|w| w.set_cwutf(Calrf::CLEAR)); |
| 424 | 418 | ||
| 425 | #[cfg(all(stm32g0))] | 419 | // Check RM for EXTI and/or NVIC section, "Event event input mapping" or "EXTI interrupt/event mapping" or something similar, |
| 426 | crate::pac::EXTI | 420 | // there is a table for every "Event input" / "EXTI Line". |
| 427 | .rpr(0) | 421 | // If you find the EXTI line related to "RTC wakeup" marks as "Configurable" (not "Direct"), |
| 428 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | 422 | // then write 1 to related field of Pending Register, to clean it's pending state. |
| 429 | #[cfg(all(not(stm32g0), not(stm32l5)))] | 423 | #[cfg(any(exti_v1, stm32h7, stm32wb))] |
| 430 | crate::pac::EXTI | 424 | crate::pac::EXTI |
| 431 | .pr(0) | 425 | .pr(0) |
| 432 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | 426 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); |
| 433 | 427 | ||
| 434 | #[cfg(stm32l5)] | ||
| 435 | crate::pac::EXTI | ||
| 436 | .fpr(0) | ||
| 437 | .modify(|w| w.set_line(RTC::EXTI_WAKEUP_LINE, true)); | ||
| 438 | |||
| 439 | <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); | 428 | <RTC as crate::rtc::SealedInstance>::WakeupInterrupt::unpend(); |
| 440 | }); | 429 | }); |
| 441 | } | 430 | } |
| @@ -465,7 +454,7 @@ pub(crate) fn byte_to_bcd2(byte: u8) -> (u8, u8) { | |||
| 465 | value -= 10; | 454 | value -= 10; |
| 466 | } | 455 | } |
| 467 | 456 | ||
| 468 | (bcd_high, ((bcd_high << 4) | value) as u8) | 457 | (bcd_high, ((bcd_high << 4) | value)) |
| 469 | } | 458 | } |
| 470 | 459 | ||
| 471 | pub(crate) fn bcd2_to_byte(bcd: (u8, u8)) -> u8 { | 460 | pub(crate) fn bcd2_to_byte(bcd: (u8, u8)) -> u8 { |
diff --git a/embassy-stm32/src/rtc/v3.rs b/embassy-stm32/src/rtc/v3.rs index 8a78d16e1..e51e09e7c 100644 --- a/embassy-stm32/src/rtc/v3.rs +++ b/embassy-stm32/src/rtc/v3.rs | |||
| @@ -50,7 +50,7 @@ impl super::Rtc { | |||
| 50 | clock_drift = Self::RTC_CALR_MAX_PPM; | 50 | clock_drift = Self::RTC_CALR_MAX_PPM; |
| 51 | } | 51 | } |
| 52 | 52 | ||
| 53 | clock_drift = clock_drift / Self::RTC_CALR_RESOLUTION_PPM; | 53 | clock_drift /= Self::RTC_CALR_RESOLUTION_PPM; |
| 54 | 54 | ||
| 55 | self.write(false, |rtc| { | 55 | self.write(false, |rtc| { |
| 56 | rtc.calr().write(|w| { | 56 | rtc.calr().write(|w| { |
| @@ -129,29 +129,25 @@ impl super::Rtc { | |||
| 129 | impl SealedInstance for crate::peripherals::RTC { | 129 | impl SealedInstance for crate::peripherals::RTC { |
| 130 | const BACKUP_REGISTER_COUNT: usize = 32; | 130 | const BACKUP_REGISTER_COUNT: usize = 32; |
| 131 | 131 | ||
| 132 | #[cfg(all(feature = "low-power", stm32g4))] | 132 | #[cfg(feature = "low-power")] |
| 133 | const EXTI_WAKEUP_LINE: usize = 20; | 133 | cfg_if::cfg_if!( |
| 134 | 134 | if #[cfg(stm32g4)] { | |
| 135 | #[cfg(all(feature = "low-power", stm32g0))] | 135 | const EXTI_WAKEUP_LINE: usize = 20; |
| 136 | const EXTI_WAKEUP_LINE: usize = 19; | 136 | type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; |
| 137 | 137 | } else if #[cfg(stm32g0)] { | |
| 138 | #[cfg(all(feature = "low-power", stm32g0))] | 138 | const EXTI_WAKEUP_LINE: usize = 19; |
| 139 | type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP; | 139 | type WakeupInterrupt = crate::interrupt::typelevel::RTC_TAMP; |
| 140 | 140 | } else if #[cfg(any(stm32l5, stm32h5))] { | |
| 141 | #[cfg(all(feature = "low-power", stm32g4))] | 141 | const EXTI_WAKEUP_LINE: usize = 17; |
| 142 | type WakeupInterrupt = crate::interrupt::typelevel::RTC_WKUP; | 142 | type WakeupInterrupt = crate::interrupt::typelevel::RTC; |
| 143 | 143 | } | |
| 144 | #[cfg(all(feature = "low-power", stm32l5))] | 144 | ); |
| 145 | const EXTI_WAKEUP_LINE: usize = 17; | ||
| 146 | |||
| 147 | #[cfg(all(feature = "low-power", stm32l5))] | ||
| 148 | type WakeupInterrupt = crate::interrupt::typelevel::RTC; | ||
| 149 | 145 | ||
| 150 | fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { | 146 | fn read_backup_register(_rtc: &Rtc, register: usize) -> Option<u32> { |
| 151 | #[allow(clippy::if_same_then_else)] | 147 | #[allow(clippy::if_same_then_else)] |
| 152 | if register < Self::BACKUP_REGISTER_COUNT { | 148 | if register < Self::BACKUP_REGISTER_COUNT { |
| 153 | //Some(rtc.bkpr()[register].read().bits()) | 149 | //Some(rtc.bkpr()[register].read().bits()) |
| 154 | None // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC | 150 | None // RTC3 backup registers come from the TAMP peripheral, not RTC. Not() even in the L412 PAC |
| 155 | } else { | 151 | } else { |
| 156 | None | 152 | None |
| 157 | } | 153 | } |
| @@ -159,7 +155,7 @@ impl SealedInstance for crate::peripherals::RTC { | |||
| 159 | 155 | ||
| 160 | fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { | 156 | fn write_backup_register(_rtc: &Rtc, register: usize, _value: u32) { |
| 161 | if register < Self::BACKUP_REGISTER_COUNT { | 157 | if register < Self::BACKUP_REGISTER_COUNT { |
| 162 | // RTC3 backup registers come from the TAMP peripe=heral, not RTC. Not() even in the L412 PAC | 158 | // RTC3 backup registers come from the TAMP peripheral, not RTC. Not() even in the L412 PAC |
| 163 | //self.rtc.bkpr()[register].write(|w| w.bits(value)) | 159 | //self.rtc.bkpr()[register].write(|w| w.bits(value)) |
| 164 | } | 160 | } |
| 165 | } | 161 | } |
diff --git a/examples/stm32h5/Cargo.toml b/examples/stm32h5/Cargo.toml index 4527f4bcb..82760db64 100644 --- a/examples/stm32h5/Cargo.toml +++ b/examples/stm32h5/Cargo.toml | |||
| @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" | |||
| 6 | 6 | ||
| 7 | [dependencies] | 7 | [dependencies] |
| 8 | # Change stm32h563zi to your chip name, if necessary. | 8 | # Change stm32h563zi to your chip name, if necessary. |
| 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac"] } | 9 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "stm32h563zi", "memory-x", "time-driver-any", "exti", "unstable-pac", "low-power"] } |
| 10 | embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } | 10 | embassy-sync = { version = "0.5.0", path = "../../embassy-sync", features = ["defmt"] } |
| 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } | 11 | embassy-executor = { version = "0.5.0", path = "../../embassy-executor", features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "defmt", "integrated-timers"] } |
| 12 | embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } | 12 | embassy-time = { version = "0.3.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime", "tick-hz-32_768"] } |
diff --git a/examples/stm32h5/src/bin/stop.rs b/examples/stm32h5/src/bin/stop.rs new file mode 100644 index 000000000..0d14c0668 --- /dev/null +++ b/examples/stm32h5/src/bin/stop.rs | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // Notice: | ||
| 2 | // the MCU might need an extra reset to make the code actually running | ||
| 3 | |||
| 4 | #![no_std] | ||
| 5 | #![no_main] | ||
| 6 | |||
| 7 | use defmt::*; | ||
| 8 | use embassy_executor::Spawner; | ||
| 9 | use embassy_stm32::gpio::{AnyPin, Level, Output, Speed}; | ||
| 10 | use embassy_stm32::low_power::Executor; | ||
| 11 | use embassy_stm32::rcc::{HSIPrescaler, LsConfig}; | ||
| 12 | use embassy_stm32::rtc::{Rtc, RtcConfig}; | ||
| 13 | use embassy_stm32::Config; | ||
| 14 | use embassy_time::Timer; | ||
| 15 | use static_cell::StaticCell; | ||
| 16 | use {defmt_rtt as _, panic_probe as _}; | ||
| 17 | |||
| 18 | #[cortex_m_rt::entry] | ||
| 19 | fn main() -> ! { | ||
| 20 | Executor::take().run(|spawner| { | ||
| 21 | unwrap!(spawner.spawn(async_main(spawner))); | ||
| 22 | }) | ||
| 23 | } | ||
| 24 | |||
| 25 | #[embassy_executor::task] | ||
| 26 | async fn async_main(spawner: Spawner) { | ||
| 27 | defmt::info!("Program Start"); | ||
| 28 | |||
| 29 | let mut config = Config::default(); | ||
| 30 | |||
| 31 | // System Clock seems need to be equal or lower than 16 MHz | ||
| 32 | config.rcc.hsi = Some(HSIPrescaler::DIV4); | ||
| 33 | |||
| 34 | config.rcc.ls = LsConfig::default_lsi(); | ||
| 35 | // when enabled the power-consumption is much higher during stop, but debugging and RTT is working | ||
| 36 | // if you wan't to measure the power-consumption, or for production: uncomment this line | ||
| 37 | // config.enable_debug_during_sleep = false; | ||
| 38 | let p = embassy_stm32::init(config); | ||
| 39 | |||
| 40 | // give the RTC to the executor... | ||
| 41 | let rtc = Rtc::new(p.RTC, RtcConfig::default()); | ||
| 42 | static RTC: StaticCell<Rtc> = StaticCell::new(); | ||
| 43 | let rtc = RTC.init(rtc); | ||
| 44 | embassy_stm32::low_power::stop_with_rtc(rtc); | ||
| 45 | |||
| 46 | unwrap!(spawner.spawn(blinky(p.PB4.into()))); | ||
| 47 | unwrap!(spawner.spawn(timeout())); | ||
| 48 | } | ||
| 49 | |||
| 50 | #[embassy_executor::task] | ||
| 51 | async fn blinky(led: AnyPin) { | ||
| 52 | let mut led = Output::new(led, Level::Low, Speed::Low); | ||
| 53 | loop { | ||
| 54 | info!("high"); | ||
| 55 | led.set_high(); | ||
| 56 | Timer::after_millis(300).await; | ||
| 57 | |||
| 58 | info!("low"); | ||
| 59 | led.set_low(); | ||
| 60 | Timer::after_millis(300).await; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | // when enable_debug_during_sleep is false, it is more difficult to reprogram the MCU | ||
| 65 | // therefore we block the MCU after 30s to be able to reprogram it easily | ||
| 66 | #[embassy_executor::task] | ||
| 67 | async fn timeout() -> ! { | ||
| 68 | Timer::after_secs(30).await; | ||
| 69 | #[allow(clippy::empty_loop)] | ||
| 70 | loop {} | ||
| 71 | } | ||
diff --git a/tests/stm32/Cargo.toml b/tests/stm32/Cargo.toml index 004846a9b..30669b88c 100644 --- a/tests/stm32/Cargo.toml +++ b/tests/stm32/Cargo.toml | |||
| @@ -15,7 +15,7 @@ stm32f446re = ["embassy-stm32/stm32f446re", "chrono", "stop", "can", "not-gpdma" | |||
| 15 | stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] | 15 | stm32f767zi = ["embassy-stm32/stm32f767zi", "chrono", "not-gpdma", "eth", "rng"] |
| 16 | stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"] | 16 | stm32g071rb = ["embassy-stm32/stm32g071rb", "cm0", "not-gpdma", "dac", "ucpd"] |
| 17 | stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan", "cordic"] | 17 | stm32g491re = ["embassy-stm32/stm32g491re", "chrono", "stop", "not-gpdma", "rng", "fdcan", "cordic"] |
| 18 | stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "fdcan", "hash", "cordic"] | 18 | stm32h563zi = ["embassy-stm32/stm32h563zi", "chrono", "eth", "rng", "fdcan", "hash", "cordic", "stop"] |
| 19 | stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] | 19 | stm32h753zi = ["embassy-stm32/stm32h753zi", "chrono", "not-gpdma", "eth", "rng", "fdcan", "hash", "cryp"] |
| 20 | stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"] | 20 | stm32h755zi = ["embassy-stm32/stm32h755zi-cm7", "chrono", "not-gpdma", "eth", "dac", "rng", "fdcan", "hash", "cryp"] |
| 21 | stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"] | 21 | stm32h7a3zi = ["embassy-stm32/stm32h7a3zi", "not-gpdma", "rng", "fdcan"] |
| @@ -31,7 +31,7 @@ stm32wb55rg = ["embassy-stm32/stm32wb55rg", "chrono", "not-gpdma", "ble", "mac" | |||
| 31 | stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng", "hash"] | 31 | stm32wba52cg = ["embassy-stm32/stm32wba52cg", "chrono", "rng", "hash"] |
| 32 | stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"] | 32 | stm32wl55jc = ["embassy-stm32/stm32wl55jc-cm4", "not-gpdma", "rng", "chrono"] |
| 33 | stm32f091rc = ["embassy-stm32/stm32f091rc", "cm0", "not-gpdma", "chrono"] | 33 | stm32f091rc = ["embassy-stm32/stm32f091rc", "cm0", "not-gpdma", "chrono"] |
| 34 | stm32h503rb = ["embassy-stm32/stm32h503rb", "rng"] | 34 | stm32h503rb = ["embassy-stm32/stm32h503rb", "rng", "stop"] |
| 35 | 35 | ||
| 36 | cryp = [] | 36 | cryp = [] |
| 37 | hash = [] | 37 | hash = [] |
diff --git a/tests/stm32/src/bin/stop.rs b/tests/stm32/src/bin/stop.rs index 000296d46..c1106bb2f 100644 --- a/tests/stm32/src/bin/stop.rs +++ b/tests/stm32/src/bin/stop.rs | |||
| @@ -51,6 +51,13 @@ async fn async_main(spawner: Spawner) { | |||
| 51 | let mut config = Config::default(); | 51 | let mut config = Config::default(); |
| 52 | config.rcc.ls = LsConfig::default_lse(); | 52 | config.rcc.ls = LsConfig::default_lse(); |
| 53 | 53 | ||
| 54 | // System Clock seems cannot be greater than 16 MHz | ||
| 55 | #[cfg(any(feature = "stm32h563zi", feature = "stm32h503rb"))] | ||
| 56 | { | ||
| 57 | use embassy_stm32::rcc::HSIPrescaler; | ||
| 58 | config.rcc.hsi = Some(HSIPrescaler::DIV4); // 64 MHz HSI will need a /4 | ||
| 59 | } | ||
| 60 | |||
| 54 | let p = embassy_stm32::init(config); | 61 | let p = embassy_stm32::init(config); |
| 55 | info!("Hello World!"); | 62 | info!("Hello World!"); |
| 56 | 63 | ||
