Skip to content

Commit ef54d03

Browse files
committed
Add example that cycles through all power modes
1 parent 9828f3c commit ef54d03

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed

examples/pwr.rs

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
5+
extern crate panic_halt;
6+
7+
8+
use cortex_m::asm;
9+
use cortex_m_rt::entry;
10+
use stm32l0xx_hal::{
11+
prelude::*,
12+
exti,
13+
gpio::{
14+
self,
15+
Output,
16+
PushPull,
17+
gpiob::PB,
18+
},
19+
pac,
20+
pwr::{
21+
self,
22+
PWR,
23+
},
24+
rcc,
25+
rtc::{
26+
self,
27+
Instant,
28+
RTC,
29+
},
30+
syscfg::SYSCFG,
31+
};
32+
33+
34+
#[entry]
35+
fn main() -> ! {
36+
let cp = pac::CorePeripherals::take().unwrap();
37+
let dp = pac::Peripherals::take().unwrap();
38+
39+
let mut scb = cp.SCB;
40+
let mut rcc = dp.RCC.freeze(rcc::Config::msi(rcc::MSIRange::Range0));
41+
let mut exti = dp.EXTI;
42+
let mut pwr = PWR::new(dp.PWR, &mut rcc);
43+
let gpiob = dp.GPIOB.split(&mut rcc);
44+
45+
let mut led = gpiob.pb2.into_push_pull_output().downgrade();
46+
47+
#[cfg(feature = "stm32l0x1")]
48+
let mut syscfg = SYSCFG::new(dp.SYSCFG, &mut rcc);
49+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
50+
let mut syscfg = SYSCFG::new(dp.SYSCFG_COMP, &mut rcc);
51+
52+
let instant = Instant::new()
53+
.set_year(19)
54+
.set_month(9)
55+
.set_day(26)
56+
.set_hour(11)
57+
.set_minute(57)
58+
.set_second(0);
59+
60+
let mut rtc = RTC::new(dp.RTC, &mut rcc, &mut pwr, instant);
61+
62+
let exti_line = 20; // RTC wakeup timer
63+
64+
rtc.enable_interrupts(rtc::Interrupts {
65+
wakeup_timer: true,
66+
..rtc::Interrupts::default()
67+
});
68+
exti.listen(
69+
&mut syscfg,
70+
gpio::Port::PA, // argument ignored; next argument is not a GPIO line
71+
exti_line,
72+
exti::TriggerEdge::Rising,
73+
);
74+
75+
let mut timer = rtc.wakeup_timer();
76+
77+
// Blink twice to signal the start of the program
78+
blink(&mut led);
79+
blink(&mut led);
80+
81+
// 5 seconds of regular run mode
82+
timer.start(5u32);
83+
while let Err(nb::Error::WouldBlock) = timer.wait() {}
84+
exti.clear_irq(exti_line);
85+
cortex_m::peripheral::NVIC::unpend(pac::Interrupt::RTC);
86+
87+
blink(&mut led);
88+
89+
// 5 seconds of low-power run mode
90+
pwr.enter_low_power_run_mode(rcc.clocks);
91+
while let Err(nb::Error::WouldBlock) = timer.wait() {}
92+
pwr.exit_low_power_run_mode();
93+
exti.clear_irq(exti_line);
94+
cortex_m::peripheral::NVIC::unpend(pac::Interrupt::RTC);
95+
96+
blink(&mut led);
97+
98+
// 5 seconds of sleep mode
99+
exti.wait_for_irq(
100+
exti_line,
101+
pwr.sleep_mode(&mut scb),
102+
);
103+
timer.wait().unwrap(); // returns immediately; we just got the interrupt
104+
105+
blink(&mut led);
106+
107+
// 5 seconds of low-power sleep mode
108+
exti.wait_for_irq(
109+
exti_line,
110+
pwr.low_power_sleep_mode(&mut scb, &mut rcc),
111+
);
112+
timer.wait().unwrap(); // returns immediately; we just got the interrupt
113+
114+
blink(&mut led);
115+
116+
// 5 seconds of stop mode
117+
exti.wait_for_irq(
118+
exti_line,
119+
pwr.stop_mode(
120+
&mut scb,
121+
&mut rcc,
122+
pwr::StopModeConfig {
123+
ultra_low_power: true,
124+
},
125+
),
126+
);
127+
timer.wait().unwrap(); // returns immediately; we just got the interrupt
128+
129+
blink(&mut led);
130+
131+
// 5 seconds of standby mode
132+
cortex_m::peripheral::NVIC::unpend(pac::Interrupt::RTC);
133+
exti.wait_for_irq(
134+
exti_line,
135+
pwr.standby_mode(&mut scb),
136+
);
137+
138+
// The microcontroller resets after leaving standby mode. We should never
139+
// reach this point.
140+
loop {
141+
blink(&mut led);
142+
}
143+
}
144+
145+
146+
fn blink(led: &mut PB<Output<PushPull>>) {
147+
led.set_high().unwrap();
148+
delay();
149+
led.set_low().unwrap();
150+
delay();
151+
}
152+
153+
fn delay() {
154+
// We can't use `Delay`, as that requires a frequency of at least one MHz.
155+
// Given our clock selection, the following loop should give us a nice delay
156+
// when compiled in release mode.
157+
for _ in 0 .. 1_000 { asm::nop() }
158+
}

0 commit comments

Comments
 (0)