1use crate::gpio::SignalEdge;
3use crate::stm32::EXTI;
4
5#[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}