stm32f4xx_hal/gpio/
exti.rs1use super::{marker, Edge, Pin, PinExt};
2use crate::{
3 pac::{Interrupt, EXTI},
4 syscfg::SysCfg,
5};
6
7impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
8 pub const fn interrupt(&self) -> Interrupt {
13 match N {
14 0 => Interrupt::EXTI0,
15 1 => Interrupt::EXTI1,
16 2 => Interrupt::EXTI2,
17 3 => Interrupt::EXTI3,
18 4 => Interrupt::EXTI4,
19 5..=9 => Interrupt::EXTI9_5,
20 10..=15 => Interrupt::EXTI15_10,
21 _ => panic!("Unsupported pin number"),
22 }
23 }
24}
25
26pub trait ExtiPin {
28 fn make_interrupt_source(&mut self, syscfg: &mut SysCfg);
30
31 fn trigger_on_edge(&mut self, exti: &mut EXTI, level: Edge);
33
34 fn enable_interrupt(&mut self, exti: &mut EXTI);
36
37 fn disable_interrupt(&mut self, exti: &mut EXTI);
39
40 fn clear_interrupt_pending_bit(&mut self);
42
43 fn check_interrupt(&self) -> bool;
45}
46
47impl<PIN> ExtiPin for PIN
48where
49 PIN: PinExt,
50 PIN::Mode: marker::Interruptible,
51{
52 #[inline(always)]
53 fn make_interrupt_source(&mut self, syscfg: &mut SysCfg) {
54 let i = self.pin_id();
55 let port = self.port_id() as u32;
56 let offset = 4 * (i % 4);
57 match i {
58 0..=3 => {
59 syscfg.exticr1().modify(|r, w| unsafe {
60 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
61 });
62 }
63 4..=7 => {
64 syscfg.exticr2().modify(|r, w| unsafe {
65 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
66 });
67 }
68 8..=11 => {
69 syscfg.exticr3().modify(|r, w| unsafe {
70 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
71 });
72 }
73 12..=15 => {
74 syscfg.exticr4().modify(|r, w| unsafe {
75 w.bits((r.bits() & !(0xf << offset)) | (port << offset))
76 });
77 }
78 _ => unreachable!(),
79 }
80 }
81
82 #[inline(always)]
83 fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
84 let i = self.pin_id();
85 match edge {
86 Edge::Rising => {
87 exti.rtsr()
88 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) });
89 exti.ftsr()
90 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << i)) });
91 }
92 Edge::Falling => {
93 exti.ftsr()
94 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) });
95 exti.rtsr()
96 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << i)) });
97 }
98 Edge::RisingFalling => {
99 exti.rtsr()
100 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) });
101 exti.ftsr()
102 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << i)) });
103 }
104 }
105 }
106
107 #[inline(always)]
108 fn enable_interrupt(&mut self, exti: &mut EXTI) {
109 exti.imr()
110 .modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
111 }
112
113 #[inline(always)]
114 fn disable_interrupt(&mut self, exti: &mut EXTI) {
115 exti.imr()
116 .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
117 }
118
119 #[inline(always)]
120 fn clear_interrupt_pending_bit(&mut self) {
121 unsafe { (*EXTI::ptr()).pr().write(|w| w.bits(1 << self.pin_id())) };
122 }
123
124 #[inline(always)]
125 fn check_interrupt(&self) -> bool {
126 unsafe { ((*EXTI::ptr()).pr().read().bits() & (1 << self.pin_id())) != 0 }
127 }
128}