alt_stm32f30x_hal/
exti.rs1use crate::gpio;
4use crate::syscfg::Syscfg;
5
6use crate::pac::{self, EXTI};
7
8pub trait ExtiExt {
10 fn constrain(self) -> ExternalInterrupts;
13}
14
15pub struct Exti<E: ExternalInterrupt> {
17 ei: E,
18}
19
20pub struct BoundInterrupt<GP, E> {
22 pin: GP,
23 ei: E,
24}
25
26impl<GP, E> BoundInterrupt<GP, E>
27 where GP: gpio::GPIOPin,
28 E: ExternalInterrupt
29{
30 pub fn unpend(&mut self) {
32 let mask: bool = true;
33 let exti = unsafe { &(*EXTI::ptr()) };
34 let offset: u8 = self.ei.index();
35
36 exti.pr1.modify(|r, w| unsafe {
37 w.bits((r.bits() & !((mask as u32) << offset))
38 | (((true & mask) as u32) << offset))
39 });
40 }
41
42 pub fn free(self, syscfg: &mut Syscfg) -> (GP, E) {
44 let exti = unsafe { &(*EXTI::ptr()) };
45
46 let offset = self.pin.index() as u32;
48 exti.imr1
49 .modify(|r, w| unsafe { w.bits(r.bits() & !(0b1 << offset)) });
50 exti.emr1
51 .modify(|r, w| unsafe { w.bits(r.bits() & !(0b1 << offset)) });
52 exti.rtsr1
53 .modify(|r, w| unsafe { w.bits(r.bits() & !(0b1 << offset)) });
54
55 let group_bits_to_clear = !bits_of_gpio_group(&self.pin.group());
57 match self.ei.enumeration() {
58 ExtIn::EXTI0 => {
59 syscfg.exticr1().modify(|_, w| unsafe {
60 w.exti0().bits(group_bits_to_clear)
61 });
62 }
63 ExtIn::EXTI1 => {
64 syscfg.exticr1().modify(|_, w| unsafe {
65 w.exti1().bits(group_bits_to_clear)
66 });
67 }
68 ExtIn::EXTI2 => {
69 syscfg.exticr1().modify(|_, w| unsafe {
70 w.exti2().bits(group_bits_to_clear)
71 });
72 }
73 ExtIn::EXTI3 => {
74 syscfg.exticr1().modify(|_, w| unsafe {
75 w.exti3().bits(group_bits_to_clear)
76 });
77 }
78 ExtIn::EXTI4 => {
79 syscfg.exticr2().modify(|_, w| unsafe {
80 w.exti4().bits(group_bits_to_clear)
81 });
82 }
83 ExtIn::EXTI13 => {
84 syscfg.exticr4().modify(|_, w| unsafe {
85 w.exti13().bits(group_bits_to_clear)
86 });
87 }
88 }
89
90 (self.pin, self.ei)
91 }
92}
93
94impl<E: ExternalInterrupt> Exti<E> {
95 pub fn bind<GP>(self, pin: GP, syscfg: &mut Syscfg) -> BoundInterrupt<GP, E>
98 where GP: gpio::GPIOPin + hal::digital::v2::InputPin
99 {
100 let exti = unsafe { &(*EXTI::ptr()) };
101
102 let group_bits = bits_of_gpio_group(&pin.group());
103
104 match self.ei.enumeration() {
106 ExtIn::EXTI0 => {
107 syscfg.exticr1()
108 .modify(|_, w| unsafe { w.exti0().bits(group_bits) });
109 }
110 ExtIn::EXTI1 => {
111 syscfg.exticr1()
112 .modify(|_, w| unsafe { w.exti1().bits(group_bits) });
113 }
114 ExtIn::EXTI2 => {
115 syscfg.exticr1()
116 .modify(|_, w| unsafe { w.exti2().bits(group_bits) });
117 }
118 ExtIn::EXTI3 => {
119 syscfg.exticr1()
120 .modify(|_, w| unsafe { w.exti3().bits(group_bits) });
121 }
122 ExtIn::EXTI4 => {
123 syscfg.exticr2()
124 .modify(|_, w| unsafe { w.exti4().bits(group_bits) });
125 }
126 ExtIn::EXTI13 => {
127 syscfg.exticr4()
128 .modify(|_, w| unsafe { w.exti13().bits(group_bits) });
129 }
130 }
131
132 let offset = pin.index() as u32;
133 exti.imr1.modify(|r, w| unsafe {
135 w.bits((r.bits() & !(0b1 << offset)) | (1 << offset))
136 });
137 exti.emr1.modify(|r, w| unsafe {
138 w.bits((r.bits() & !(0b1 << offset)) | (1 << offset))
139 });
140 exti.rtsr1.modify(|r, w| unsafe {
141 w.bits((r.bits() & !(0b1 << offset)) | (1 << offset))
142 });
143
144 BoundInterrupt { pin: pin,
145 ei: self.ei }
146 }
147}
148
149#[doc(hidden)]
150pub trait ExternalInterrupt: private::Sealed {
151 #[doc(hidden)]
152 fn interrupt(&self) -> pac::Interrupt;
153 #[doc(hidden)]
154 fn enumeration(&self) -> ExtIn;
155 #[doc(hidden)]
156 fn index(&self) -> u8;
157}
158
159#[doc(hidden)]
161pub enum ExtIn {
162 EXTI0,
164 EXTI1,
166 EXTI2,
168 EXTI3,
170 EXTI4,
172 EXTI13,
174}
175
176macro_rules! gen_exti {
177 ([$(($name:ident, $exti:ident, $i: expr),)+]) => {
178 #[doc(hidden)]
179 mod private {
180 #[doc(hidden)]
181 pub trait Sealed {}
182 $(
183 impl Sealed for super::$name {}
184 )+
185 }
186
187
188 $(
189 pub struct $name {
191 _0: (),
192 }
193 impl ExternalInterrupt for $name {
194 fn interrupt(&self) -> pac::Interrupt {
195 pac::Interrupt::$exti
196 }
197
198 fn enumeration(&self) -> ExtIn {
199 ExtIn::$name
200 }
201
202 fn index(&self) -> u8 {
203 $i
204 }
205 }
206 )+
207
208 #[allow(non_snake_case)]
210 pub struct ExternalInterrupts {
211 $(
212 pub $name: Exti<$name>,
214 )+
215 }
216
217 impl ExtiExt for EXTI {
218 fn constrain(self) -> ExternalInterrupts {
219 (
220 ExternalInterrupts {
221 $(
222 $name: Exti { ei: $name { _0: () }} ,
223 )+
224 }
225 )
226 }
227 }
228 }
229}
230
231gen_exti!([(EXTI0, EXTI0, 0),
233 (EXTI1, EXTI1, 1),
234 (EXTI2, EXTI2_TSC, 2),
235 (EXTI3, EXTI3, 2),
236 (EXTI4, EXTI4, 4),
237 (EXTI13, EXTI15_10, 13),]);
238
239fn bits_of_gpio_group(group: &gpio::Group) -> u8 {
240 match group {
241 gpio::Group::A => 0b0000,
242 gpio::Group::B => 0b0001,
243 gpio::Group::C => 0b0010,
244 gpio::Group::D => 0b0011,
245 gpio::Group::E => 0b0100,
246 gpio::Group::F => 0b0101,
247 gpio::Group::G => 0b0110,
248 }
249}