Skip to content

Commit 7db793f

Browse files
Merge #174
174: Implement ExtiPin for pins in output mode r=therealprof a=mvirkkunen Since `InputPin` is implemented for pins in output mode, it also makes sense to implement `ExtiPin`. Especially useful in open drain mode. Co-authored-by: Matti Virkkunen <[email protected]>
2 parents 76a26de + 9e57fdb commit 7db793f

File tree

2 files changed

+137
-104
lines changed

2 files changed

+137
-104
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1010
### Added
1111

1212
- Reexport PAC as `pac` for consistency with other crates, consider `stm32` virtually deprecated
13+
- Added external interrupt (EXTI) support for output pins
1314

1415
## [v0.8.3] - 2020-06-12
1516

src/gpio.rs

Lines changed: 136 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,138 @@ pub trait ExtiPin {
9292
fn clear_interrupt_pending_bit(&mut self);
9393
}
9494

95+
macro_rules! exti_erased {
96+
($PIN:ty, $extigpionr:expr) => {
97+
impl<MODE> ExtiPin for $PIN {
98+
/// Make corresponding EXTI line sensitive to this pin
99+
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
100+
let offset = 4 * (self.i % 4);
101+
match self.i {
102+
0..=3 => {
103+
syscfg.exticr1.modify(|r, w| unsafe {
104+
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
105+
});
106+
}
107+
4..=7 => {
108+
syscfg.exticr2.modify(|r, w| unsafe {
109+
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
110+
});
111+
}
112+
8..=11 => {
113+
syscfg.exticr3.modify(|r, w| unsafe {
114+
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
115+
});
116+
}
117+
12..=15 => {
118+
syscfg.exticr4.modify(|r, w| unsafe {
119+
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
120+
});
121+
}
122+
_ => {}
123+
}
124+
}
125+
126+
/// Generate interrupt on rising edge, falling edge or both
127+
fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
128+
match edge {
129+
Edge::RISING => {
130+
exti.rtsr
131+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
132+
exti.ftsr
133+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
134+
}
135+
Edge::FALLING => {
136+
exti.ftsr
137+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
138+
exti.rtsr
139+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
140+
}
141+
Edge::RISING_FALLING => {
142+
exti.rtsr
143+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
144+
exti.ftsr
145+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
146+
}
147+
}
148+
}
149+
150+
/// Enable external interrupts from this pin.
151+
fn enable_interrupt(&mut self, exti: &mut EXTI) {
152+
exti.imr
153+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
154+
}
155+
156+
/// Disable external interrupts from this pin
157+
fn disable_interrupt(&mut self, exti: &mut EXTI) {
158+
exti.imr
159+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
160+
}
161+
162+
/// Clear the interrupt pending bit for this pin
163+
fn clear_interrupt_pending_bit(&mut self) {
164+
unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << self.i)) };
165+
}
166+
}
167+
};
168+
}
169+
170+
macro_rules! exti {
171+
($PIN:ty, $extigpionr:expr, $i:expr, $exticri:ident) => {
172+
impl<MODE> ExtiPin for $PIN {
173+
/// Configure EXTI Line $i to trigger from this pin.
174+
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
175+
let offset = 4 * ($i % 4);
176+
syscfg.$exticri.modify(|r, w| unsafe {
177+
let mut exticr = r.bits();
178+
exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset);
179+
w.bits(exticr)
180+
});
181+
}
182+
183+
/// Generate interrupt on rising edge, falling edge or both
184+
fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
185+
match edge {
186+
Edge::RISING => {
187+
exti.rtsr
188+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
189+
exti.ftsr
190+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
191+
}
192+
Edge::FALLING => {
193+
exti.ftsr
194+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
195+
exti.rtsr
196+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
197+
}
198+
Edge::RISING_FALLING => {
199+
exti.rtsr
200+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
201+
exti.ftsr
202+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
203+
}
204+
}
205+
}
206+
207+
/// Enable external interrupts from this pin.
208+
fn enable_interrupt(&mut self, exti: &mut EXTI) {
209+
exti.imr
210+
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
211+
}
212+
213+
/// Disable external interrupts from this pin
214+
fn disable_interrupt(&mut self, exti: &mut EXTI) {
215+
exti.imr
216+
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
217+
}
218+
219+
/// Clear the interrupt pending bit for this pin
220+
fn clear_interrupt_pending_bit(&mut self) {
221+
unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << $i)) };
222+
}
223+
}
224+
};
225+
}
226+
95227
macro_rules! gpio {
96228
($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, $extigpionr:expr, [
97229
$($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty, $exticri:ident),)+
@@ -202,68 +334,9 @@ macro_rules! gpio {
202334
}
203335
}
204336

205-
impl<MODE> ExtiPin for $PXx<Input<MODE>> {
206-
/// Make corresponding EXTI line sensitive to this pin
207-
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
208-
let offset = 4 * (self.i % 4);
209-
match self.i {
210-
0..=3 => {
211-
syscfg.exticr1.modify(|r, w| unsafe {
212-
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
213-
});
214-
},
215-
4..=7 => {
216-
syscfg.exticr2.modify(|r, w| unsafe {
217-
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
218-
});
219-
},
220-
8..=11 => {
221-
syscfg.exticr3.modify(|r, w| unsafe {
222-
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
223-
});
224-
},
225-
12..=15 => {
226-
syscfg.exticr4.modify(|r, w| unsafe {
227-
w.bits((r.bits() & !(0xf << offset)) | ($extigpionr << offset))
228-
});
229-
},
230-
_ => {}
231-
}
232-
}
233-
234-
/// Generate interrupt on rising edge, falling edge or both
235-
fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
236-
match edge {
237-
Edge::RISING => {
238-
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
239-
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
240-
},
241-
Edge::FALLING => {
242-
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
243-
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
244-
},
245-
Edge::RISING_FALLING => {
246-
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
247-
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
248-
}
249-
}
250-
}
251-
252-
/// Enable external interrupts from this pin.
253-
fn enable_interrupt(&mut self, exti: &mut EXTI) {
254-
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.i)) });
255-
}
256-
257-
/// Disable external interrupts from this pin
258-
fn disable_interrupt(&mut self, exti: &mut EXTI) {
259-
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.i)) });
260-
}
337+
exti_erased!($PXx<Output<MODE>>, $extigpionr);
261338

262-
/// Clear the interrupt pending bit for this pin
263-
fn clear_interrupt_pending_bit(&mut self) {
264-
unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << self.i) ) };
265-
}
266-
}
339+
exti_erased!($PXx<Input<MODE>>, $extigpionr);
267340

268341
fn _set_alternate_mode (index: usize, mode: u32)
269342
{
@@ -722,50 +795,9 @@ macro_rules! gpio {
722795
}
723796
}
724797

725-
impl<MODE> ExtiPin for $PXi<Input<MODE>> {
726-
/// Configure EXTI Line $i to trigger from this pin.
727-
fn make_interrupt_source(&mut self, syscfg: &mut SYSCFG) {
728-
let offset = 4 * ($i % 4);
729-
syscfg.$exticri.modify(|r, w| unsafe {
730-
let mut exticr = r.bits();
731-
exticr = (exticr & !(0xf << offset)) | ($extigpionr << offset);
732-
w.bits(exticr)
733-
});
734-
}
798+
exti!($PXi<Output<MODE>>, $extigpionr, $i, $exticri);
735799

736-
/// Generate interrupt on rising edge, falling edge or both
737-
fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
738-
match edge {
739-
Edge::RISING => {
740-
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
741-
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
742-
},
743-
Edge::FALLING => {
744-
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
745-
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
746-
},
747-
Edge::RISING_FALLING => {
748-
exti.rtsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
749-
exti.ftsr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
750-
}
751-
}
752-
}
753-
754-
/// Enable external interrupts from this pin.
755-
fn enable_interrupt(&mut self, exti: &mut EXTI) {
756-
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() | (1 << $i)) });
757-
}
758-
759-
/// Disable external interrupts from this pin
760-
fn disable_interrupt(&mut self, exti: &mut EXTI) {
761-
exti.imr.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << $i)) });
762-
}
763-
764-
/// Clear the interrupt pending bit for this pin
765-
fn clear_interrupt_pending_bit(&mut self) {
766-
unsafe { (*EXTI::ptr()).pr.write(|w| w.bits(1 << $i) ) };
767-
}
768-
}
800+
exti!($PXi<Input<MODE>>, $extigpionr, $i, $exticri);
769801

770802
)+
771803
}

0 commit comments

Comments
 (0)