stm32g0xx_hal/
power.rs

1//! Power control
2
3use crate::{
4    gpio::*,
5    rcc::{Enable, Rcc},
6    stm32::PWR,
7};
8
9pub enum LowPowerMode {
10    StopMode1 = 0b000,
11    StopMode2 = 0b001,
12    Standby = 0b011,
13    Shutdown = 0b111,
14}
15
16pub enum PowerMode {
17    Run,
18    LowPower(LowPowerMode),
19    UltraLowPower(LowPowerMode),
20}
21
22pub enum WakeUp {
23    InternalLine,
24    Line1,
25    Line2,
26    // TODO: Line3 missing in SVD file
27    Line4,
28    Line5,
29    Line6,
30}
31
32pub struct Power {
33    rb: PWR,
34}
35
36impl Power {
37    pub fn new(pwr: PWR, rcc: &mut Rcc) -> Self {
38        PWR::enable(rcc);
39        Self { rb: pwr }
40    }
41
42    pub fn get_standby_flag(&mut self) -> bool {
43        self.rb.sr1.read().sbf().bit_is_set()
44    }
45
46    pub fn get_wakeup_flag<L: Into<WakeUp>>(&self, lane: L) -> bool {
47        match lane.into() {
48            WakeUp::Line1 => self.rb.sr1.read().wuf1().bit_is_set(),
49            WakeUp::Line2 => self.rb.sr1.read().wuf2().bit_is_set(),
50            WakeUp::Line4 => self.rb.sr1.read().wuf4().bit_is_set(),
51            WakeUp::Line5 => self.rb.sr1.read().wuf5().bit_is_set(),
52            WakeUp::Line6 => self.rb.sr1.read().wuf6().bit_is_set(),
53            _ => false,
54        }
55    }
56
57    pub fn clear_wakeup_flag<L: Into<WakeUp>>(&mut self, lane: L) {
58        match lane.into() {
59            WakeUp::Line1 => self.rb.scr.write(|w| w.cwuf1().set_bit()),
60            WakeUp::Line2 => self.rb.scr.write(|w| w.cwuf2().set_bit()),
61            WakeUp::Line4 => self.rb.scr.write(|w| w.cwuf4().set_bit()),
62            WakeUp::Line5 => self.rb.scr.write(|w| w.cwuf5().set_bit()),
63            WakeUp::Line6 => self.rb.scr.write(|w| w.cwuf6().set_bit()),
64            _ => {}
65        }
66    }
67
68    pub fn clear_standby_flag(&mut self) {
69        if self.rb.sr1.read().sbf().bit_is_set() {
70            self.rb.scr.write(|w| w.csbf().set_bit());
71        }
72    }
73
74    pub fn enable_wakeup_lane<L: Into<WakeUp>>(&mut self, lane: L, edge: SignalEdge) {
75        assert!(edge != SignalEdge::All);
76
77        let edge = edge == SignalEdge::Falling;
78        match lane.into() {
79            WakeUp::Line1 => {
80                self.rb.cr3.modify(|_, w| w.ewup1().set_bit());
81                self.rb.cr4.modify(|_, w| w.wp1().bit(edge));
82            }
83            WakeUp::Line2 => {
84                self.rb.cr3.modify(|_, w| w.ewup2().set_bit());
85                self.rb.cr4.modify(|_, w| w.wp2().bit(edge));
86            }
87            WakeUp::Line4 => {
88                self.rb.cr3.modify(|_, w| w.ewup4().set_bit());
89                self.rb.cr4.modify(|_, w| w.wp4().bit(edge));
90            }
91            WakeUp::Line5 => {
92                self.rb.cr3.modify(|_, w| w.ewup5().set_bit());
93                self.rb.cr4.modify(|_, w| w.wp5().bit(edge));
94            }
95            WakeUp::Line6 => {
96                self.rb.cr3.modify(|_, w| w.ewup6().set_bit());
97                self.rb.cr4.modify(|_, w| w.wp6().bit(edge));
98            }
99            WakeUp::InternalLine => self.rb.cr3.modify(|_, w| w.eiwul().set_bit()),
100        }
101    }
102
103    pub fn disable_wakeup_lane<L: Into<WakeUp>>(&mut self, lane: L) {
104        match lane.into() {
105            WakeUp::Line1 => self.rb.cr3.modify(|_, w| w.ewup1().clear_bit()),
106            WakeUp::Line2 => self.rb.cr3.modify(|_, w| w.ewup2().clear_bit()),
107            WakeUp::Line4 => self.rb.cr3.modify(|_, w| w.ewup4().clear_bit()),
108            WakeUp::Line5 => self.rb.cr3.modify(|_, w| w.ewup5().clear_bit()),
109            WakeUp::Line6 => self.rb.cr3.modify(|_, w| w.ewup6().clear_bit()),
110            WakeUp::InternalLine => self.rb.cr3.modify(|_, w| w.eiwul().clear_bit()),
111        }
112    }
113
114    pub fn set_mode(&mut self, mode: PowerMode) {
115        match mode {
116            PowerMode::Run => {
117                self.rb.cr1.modify(|_, w| w.lpr().clear_bit());
118                while !self.rb.sr2.read().reglpf().bit_is_clear() {}
119            }
120            PowerMode::LowPower(sm) => {
121                self.rb.cr3.modify(|_, w| w.ulpen().clear_bit());
122                self.rb
123                    .cr1
124                    .modify(|_, w| unsafe { w.lpr().set_bit().lpms().bits(sm as u8) });
125                while !self.rb.sr2.read().reglps().bit_is_set()
126                    || !self.rb.sr2.read().reglpf().bit_is_set()
127                {}
128            }
129            PowerMode::UltraLowPower(sm) => {
130                self.rb.cr3.modify(|_, w| w.ulpen().set_bit());
131                self.rb
132                    .cr1
133                    .modify(|_, w| unsafe { w.lpr().set_bit().lpms().bits(sm as u8) });
134                while !self.rb.sr2.read().reglps().bit_is_set()
135                    || !self.rb.sr2.read().reglpf().bit_is_set()
136                {}
137            }
138        }
139    }
140}
141
142macro_rules! wakeup_pins {
143    ($($PIN:path: $line:expr,)+) => {
144        $(
145            impl<M> From<&$PIN> for WakeUp {
146                fn from(_: &$PIN) -> Self {
147                    $line
148                 }
149            }
150        )+
151    }
152}
153
154wakeup_pins! {
155    PA0<M>: WakeUp::Line1,
156    PA4<M>: WakeUp::Line2,
157    PC13<M>: WakeUp::Line2,
158    PA2<M>: WakeUp::Line4,
159    PC5<M>: WakeUp::Line5,
160    PB5<M>: WakeUp::Line6,
161}
162
163pub trait PowerExt {
164    fn constrain(self, rcc: &mut Rcc) -> Power;
165}
166
167impl PowerExt for PWR {
168    fn constrain(self, rcc: &mut Rcc) -> Power {
169        Power::new(self, rcc)
170    }
171}