stm32g0xx_hal/
exti.rs

1//! External interrupt controller
2use crate::gpio::SignalEdge;
3use crate::stm32::EXTI;
4
5/// EXTI trigger event
6#[derive(Eq, PartialEq, PartialOrd, Clone, Copy)]
7pub enum Event {
8    GPIO0 = 0,
9    GPIO1 = 1,
10    GPIO2 = 2,
11    GPIO3 = 3,
12    GPIO4 = 4,
13    GPIO5 = 5,
14    GPIO6 = 6,
15    GPIO7 = 7,
16    GPIO8 = 8,
17    GPIO9 = 9,
18    GPIO10 = 10,
19    GPIO11 = 11,
20    GPIO12 = 12,
21    GPIO13 = 13,
22    GPIO14 = 14,
23    GPIO15 = 15,
24    PVD = 16,
25    #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
26    COMP1 = 17,
27    #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
28    COMP2 = 18,
29    RTC = 19,
30    TAMP = 21,
31    I2C1 = 23,
32    USART1 = 25,
33    USART2 = 26,
34    #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
35    CEC = 27,
36    LPUART1 = 28,
37    LPTIM1 = 29,
38    LPTIM2 = 30,
39    LSE_CSS = 31,
40    #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
41    UCPD1 = 32,
42    #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
43    UCPD2 = 33,
44}
45
46impl Event {
47    pub(crate) fn from_code(n: u8) -> Event {
48        match n {
49            0 => Event::GPIO0,
50            1 => Event::GPIO1,
51            2 => Event::GPIO2,
52            3 => Event::GPIO3,
53            4 => Event::GPIO4,
54            5 => Event::GPIO5,
55            6 => Event::GPIO6,
56            7 => Event::GPIO7,
57            8 => Event::GPIO8,
58            9 => Event::GPIO9,
59            10 => Event::GPIO10,
60            11 => Event::GPIO11,
61            12 => Event::GPIO12,
62            13 => Event::GPIO13,
63            14 => Event::GPIO14,
64            15 => Event::GPIO15,
65            _ => unreachable!(),
66        }
67    }
68}
69
70#[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
71const TRIGGER_MAX: u8 = 18;
72#[cfg(any(feature = "stm32g031", feature = "stm32g041"))]
73const TRIGGER_MAX: u8 = 16;
74#[cfg(any(feature = "stm32g030", feature = "stm32g070"))]
75const TRIGGER_MAX: u8 = 15;
76
77pub trait ExtiExt {
78    fn wakeup(&self, ev: Event);
79    fn listen(&self, ev: Event, edge: SignalEdge);
80    fn unlisten(&self, ev: Event);
81    fn is_pending(&self, ev: Event, edge: SignalEdge) -> bool;
82    fn unpend(&self, ev: Event);
83}
84
85impl ExtiExt for EXTI {
86    fn listen(&self, ev: Event, edge: SignalEdge) {
87        let line = ev as u8;
88        assert!(line <= TRIGGER_MAX);
89        let mask = 1 << line;
90        match edge {
91            SignalEdge::Rising => {
92                self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) });
93            }
94            SignalEdge::Falling => {
95                self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) });
96            }
97            SignalEdge::All => {
98                self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) });
99                self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() | mask) });
100            }
101        }
102        self.wakeup(ev);
103    }
104
105    fn wakeup(&self, ev: Event) {
106        #[cfg(any(
107            feature = "stm32g030",
108            feature = "stm32g070",
109            feature = "stm32g031",
110            feature = "stm32g041"
111        ))]
112        self.imr1
113            .modify(|r, w| unsafe { w.bits(r.bits() | 1 << ev as u8) });
114
115        #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
116        match ev as u8 {
117            line if line < 32 => self
118                .imr1
119                .modify(|r, w| unsafe { w.bits(r.bits() | 1 << line) }),
120            line => self
121                .imr2
122                .modify(|r, w| unsafe { w.bits(r.bits() | 1 << (line - 32)) }),
123        }
124    }
125
126    fn unlisten(&self, ev: Event) {
127        self.unpend(ev);
128
129        #[cfg(any(
130            feature = "stm32g030",
131            feature = "stm32g070",
132            feature = "stm32g031",
133            feature = "stm32g041"
134        ))]
135        {
136            let line = ev as u8;
137            let mask = !(1 << line);
138            self.imr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) });
139            if line <= TRIGGER_MAX {
140                self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) });
141                self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) });
142            }
143        }
144
145        #[cfg(any(feature = "stm32g071", feature = "stm32g081"))]
146        match ev as u8 {
147            line if line < 32 => {
148                let mask = !(1 << line);
149                self.imr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) });
150                if line <= TRIGGER_MAX {
151                    self.rtsr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) });
152                    self.ftsr1.modify(|r, w| unsafe { w.bits(r.bits() & mask) });
153                }
154            }
155            line => {
156                let mask = !(1 << (line - 32));
157                self.imr2.modify(|r, w| unsafe { w.bits(r.bits() & mask) })
158            }
159        }
160    }
161
162    fn is_pending(&self, ev: Event, edge: SignalEdge) -> bool {
163        let line = ev as u8;
164        if line > TRIGGER_MAX {
165            return false;
166        }
167        let mask = 1 << line;
168        match edge {
169            SignalEdge::Rising => self.rpr1.read().bits() & mask != 0,
170            SignalEdge::Falling => self.fpr1.read().bits() & mask != 0,
171            SignalEdge::All => {
172                (self.rpr1.read().bits() & mask != 0) && (self.fpr1.read().bits() & mask != 0)
173            }
174        }
175    }
176
177    fn unpend(&self, ev: Event) {
178        let line = ev as u8;
179        if line <= TRIGGER_MAX {
180            self.rpr1.modify(|_, w| unsafe { w.bits(1 << line) });
181            self.fpr1.modify(|_, w| unsafe { w.bits(1 << line) });
182        }
183    }
184}