Skip to content

Commit c42cd08

Browse files
committed
Add support for low-power sleep mode
1 parent 946f28c commit c42cd08

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/pwr.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,31 @@ impl PWR {
7070
/// Returns a struct that can be used to enter Sleep mode
7171
pub fn sleep_mode<'r>(&'r mut self, scb: &'r mut SCB) -> SleepMode<'r> {
7272
SleepMode {
73+
pwr: &mut self.0,
74+
scb,
75+
}
76+
}
77+
78+
/// Returns a struct that can be used to enter low-power sleep mode
79+
///
80+
/// # Panics
81+
///
82+
/// To enter low-power sleep mode, the system clock frequency should not
83+
/// exceed the MSI frequency range 1 (131.072 kHz). This method will panic,
84+
/// if that is the case.
85+
pub fn low_power_sleep_mode<'r>(&'r mut self,
86+
scb: &'r mut SCB,
87+
rcc: &mut Rcc,
88+
)
89+
-> LowPowerSleepMode<'r>
90+
{
91+
// Panic, if system clock frequency is outside of allowed range. See
92+
// STM32L0x1/STM32L0x2/STM32L0x3 reference manuals, sections 6.3.8 and
93+
// 7.2.3.
94+
assert!(rcc.clocks.sys_clk().0 <= 131_072);
95+
96+
LowPowerSleepMode {
97+
pwr: self,
7398
scb,
7499
}
75100
}
@@ -150,18 +175,64 @@ pub trait PowerMode {
150175
///
151176
/// Please note that entering Sleep mode may change the SCB configuration.
152177
pub struct SleepMode<'r> {
178+
pwr: &'r mut pac::PWR,
153179
scb: &'r mut SCB,
154180
}
155181

156182
impl PowerMode for SleepMode<'_> {
157183
fn enter(&mut self) {
184+
#[cfg(feature = "stm32l0x1")]
185+
self.pwr.cr.modify(|_, w| w.lpsdsr().main_mode());
186+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
187+
self.pwr.cr.modify(|_, w| w.lpds().clear_bit());
188+
158189
self.scb.clear_sleepdeep();
190+
159191
asm::dsb();
160192
asm::wfi();
161193
}
162194
}
163195

164196

197+
/// Low-power sleep mode
198+
///
199+
/// You can get an instance of this struct by calling
200+
/// [`PWR::low_power_sleep_mode`].
201+
///
202+
/// The `PowerMode` implementation of this type will block until something wakes
203+
/// the microcontroller up again. Please make sure to configure an interrupt, or
204+
/// it could block forever.
205+
///
206+
/// Please note that entering low-power sleep mode may change the SCB
207+
/// configuration.
208+
pub struct LowPowerSleepMode<'r> {
209+
pwr: &'r mut PWR,
210+
scb: &'r mut SCB,
211+
}
212+
213+
impl PowerMode for LowPowerSleepMode<'_> {
214+
fn enter(&mut self) {
215+
// Switch Vcore to range 2. This is required to enter low-power sleep
216+
// mode, according to the reference manual, section 6.3.8.
217+
let old_vcore = self.pwr.get_vcore_range();
218+
self.pwr.switch_vcore_range(VcoreRange::Range2);
219+
220+
#[cfg(feature = "stm32l0x1")]
221+
self.pwr.0.cr.modify(|_, w| w.lpsdsr().low_power_mode());
222+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
223+
self.pwr.0.cr.modify(|_, w| w.lpds().set_bit());
224+
225+
self.scb.clear_sleepdeep();
226+
227+
asm::dsb();
228+
asm::wfi();
229+
230+
// Switch back to previous voltage range.
231+
self.pwr.switch_vcore_range(old_vcore);
232+
}
233+
}
234+
235+
165236
/// Stop mode
166237
///
167238
/// You can get an instance of this struct by calling [`PWR::stop_mode`].

0 commit comments

Comments
 (0)