aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2021-04-10 01:48:12 +0200
committerDario Nieuwenhuis <[email protected]>2021-04-20 02:44:54 +0200
commit170536b0730d8ab7c2bdce4d3167aca7b70d2cd2 (patch)
treef4d6a040b4fa0d4fe2b4ccd4b01a7ce47bb06815
parent258ba533bdf8dc353513bbd5d409e8b12d307d5f (diff)
stm32: add exti
-rw-r--r--embassy-stm32-examples/Cargo.toml4
-rw-r--r--embassy-stm32-examples/src/bin/button_exti.rs129
-rw-r--r--embassy-stm32/src/chip/f429.rs5
-rw-r--r--embassy-stm32/src/exti.rs886
-rw-r--r--embassy-stm32/src/gpio.rs159
-rw-r--r--embassy-stm32/src/lib.rs3
6 files changed, 365 insertions, 821 deletions
diff --git a/embassy-stm32-examples/Cargo.toml b/embassy-stm32-examples/Cargo.toml
index af809b838..14ffcc083 100644
--- a/embassy-stm32-examples/Cargo.toml
+++ b/embassy-stm32-examples/Cargo.toml
@@ -38,9 +38,9 @@ f479 = ["embassy-stm32/f469"]
38[dependencies] 38[dependencies]
39embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } 39embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] }
40embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } 40embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] }
41embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } 41embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32", features = ["defmt", "defmt-trace"] }
42embassy-extras = {version = "0.1.0", path = "../embassy-extras" } 42embassy-extras = {version = "0.1.0", path = "../embassy-extras" }
43stm32f4 = { version = "0.13", features = ["stm32f429"] } 43stm32f4 = { version = "0.13", features = ["stm32f429", "rt"] }
44 44
45defmt = "0.2.0" 45defmt = "0.2.0"
46defmt-rtt = "0.2.0" 46defmt-rtt = "0.2.0"
diff --git a/embassy-stm32-examples/src/bin/button_exti.rs b/embassy-stm32-examples/src/bin/button_exti.rs
new file mode 100644
index 000000000..8f6799604
--- /dev/null
+++ b/embassy-stm32-examples/src/bin/button_exti.rs
@@ -0,0 +1,129 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(min_type_alias_impl_trait)]
5#![feature(impl_trait_in_bindings)]
6#![feature(type_alias_impl_trait)]
7
8#[path = "../example_common.rs"]
9mod example_common;
10use embassy::executor::Executor;
11use embassy::time::Clock;
12use embassy::util::Forever;
13use embassy_stm32::exti::{self, ExtiInput};
14use embassy_stm32::gpio::{Input, Pull};
15use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge};
16use example_common::*;
17
18use cortex_m_rt::entry;
19use pac::{interrupt, NVIC};
20use stm32f4::stm32f429 as pac;
21
22#[embassy::task]
23async fn main_task() {
24 let p = embassy_stm32::Peripherals::take().unwrap();
25 let button = Input::new(p.PC13, Pull::Down);
26 let mut button = ExtiInput::new(button, p.EXTI13);
27
28 info!("Press the USER button...");
29
30 loop {
31 button.wait_for_rising_edge().await;
32 info!("Pressed!");
33 button.wait_for_falling_edge().await;
34 info!("Released!");
35 }
36}
37
38struct ZeroClock;
39
40impl Clock for ZeroClock {
41 fn now(&self) -> u64 {
42 0
43 }
44}
45
46static EXECUTOR: Forever<Executor> = Forever::new();
47
48#[entry]
49fn main() -> ! {
50 info!("Hello World!");
51
52 let pp = pac::Peripherals::take().unwrap();
53
54 pp.DBGMCU.cr.modify(|_, w| {
55 w.dbg_sleep().set_bit();
56 w.dbg_standby().set_bit();
57 w.dbg_stop().set_bit()
58 });
59 pp.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled());
60
61 pp.RCC.ahb1enr.modify(|_, w| {
62 w.gpioaen().enabled();
63 w.gpioben().enabled();
64 w.gpiocen().enabled();
65 w.gpioden().enabled();
66 w.gpioeen().enabled();
67 w.gpiofen().enabled();
68 w
69 });
70 pp.RCC.apb2enr.modify(|_, w| {
71 w.syscfgen().enabled();
72 w
73 });
74
75 unsafe { embassy::time::set_clock(&ZeroClock) };
76
77 unsafe {
78 NVIC::unmask(interrupt::EXTI0);
79 NVIC::unmask(interrupt::EXTI1);
80 NVIC::unmask(interrupt::EXTI2);
81 NVIC::unmask(interrupt::EXTI3);
82 NVIC::unmask(interrupt::EXTI4);
83 NVIC::unmask(interrupt::EXTI9_5);
84 NVIC::unmask(interrupt::EXTI15_10);
85 }
86
87 let executor = EXECUTOR.put(Executor::new());
88
89 executor.run(|spawner| {
90 unwrap!(spawner.spawn(main_task()));
91 })
92}
93
94// TODO for now irq handling is done by user code using the old pac, until we figure out how interrupts work in the metapac
95
96#[interrupt]
97unsafe fn EXTI0() {
98 exti::on_irq()
99}
100
101#[interrupt]
102unsafe fn EXTI1() {
103 exti::on_irq()
104}
105
106#[interrupt]
107unsafe fn EXTI2() {
108 exti::on_irq()
109}
110
111#[interrupt]
112unsafe fn EXTI3() {
113 exti::on_irq()
114}
115
116#[interrupt]
117unsafe fn EXTI4() {
118 exti::on_irq()
119}
120
121#[interrupt]
122unsafe fn EXTI9_5() {
123 exti::on_irq()
124}
125
126#[interrupt]
127unsafe fn EXTI15_10() {
128 exti::on_irq()
129}
diff --git a/embassy-stm32/src/chip/f429.rs b/embassy-stm32/src/chip/f429.rs
index 26956e01f..db68faa5a 100644
--- a/embassy-stm32/src/chip/f429.rs
+++ b/embassy-stm32/src/chip/f429.rs
@@ -7,4 +7,9 @@ peripherals!(
7 PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15, 7 PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15,
8 // GPIO Port C 8 // GPIO Port C
9 PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15, 9 PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15,
10 // todo more ports
11
12 // EXTI
13 EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5, EXTI6, EXTI7, EXTI8, EXTI9, EXTI10, EXTI11, EXTI12,
14 EXTI13, EXTI14, EXTI15,
10); 15);
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 9a12f8115..d1b5eabbf 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -1,89 +1,75 @@
1use core::convert::Infallible;
1use core::future::Future; 2use core::future::Future;
2use core::mem; 3use core::marker::PhantomData;
3use cortex_m; 4use core::pin::Pin;
4 5use core::task::{Context, Poll};
5use crate::hal::gpio; 6use embassy::traits::gpio::{WaitForAnyEdge, WaitForFallingEdge, WaitForRisingEdge};
6 7use embassy::util::{AtomicWaker, Unborrow};
7#[cfg(any( 8use embassy_extras::impl_unborrow;
8 feature = "stm32f401", 9use embedded_hal::digital::v2::InputPin;
9 feature = "stm32f405", 10use futures::future::Select;
10 feature = "stm32f407", 11use pac::exti::{regs, vals};
11 feature = "stm32f410", 12
12 feature = "stm32f411", 13use crate::fmt::*;
13 feature = "stm32f412", 14use crate::gpio::{AnyPin, Input, Pin as GpioPin};
14 feature = "stm32f413", 15use crate::pac;
15 feature = "stm32f415", 16use crate::peripherals;
16 feature = "stm32f417", 17
17 feature = "stm32f423", 18// TODO hardcoding peripheral addrs until we figure out how these are handled in the metapac
18 feature = "stm32f427", 19const SYSCFG: pac::syscfg_f4::Syscfg = pac::syscfg_f4::Syscfg(0x40013800 as *mut _);
19 feature = "stm32f429", 20const EXTI: pac::exti::Exti = pac::exti::Exti(0x40013c00 as *mut _);
20 feature = "stm32f437", 21
21 feature = "stm32f439", 22const EXTI_COUNT: usize = 16;
22 feature = "stm32f446", 23const NEW_AW: AtomicWaker = AtomicWaker::new();
23 feature = "stm32f469", 24static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [NEW_AW; EXTI_COUNT];
24 feature = "stm32f479", 25
25))] 26// TODO for now delegate irq handling to user code until we figure out how interrupts work in the metapac
26use crate::hal::syscfg::SysCfg; 27pub unsafe fn on_irq() {
27 28 let bits = EXTI.pr().read().0;
28#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] 29
29use crate::hal::syscfg::SYSCFG as SysCfg; 30 // Mask all the channels that fired.
30 31 EXTI.imr().modify(|w| w.0 &= !bits);
31use embassy::traits::gpio::{ 32
32 WaitForAnyEdge, WaitForFallingEdge, WaitForHigh, WaitForLow, WaitForRisingEdge, 33 // Wake the tasks
33}; 34 for pin in BitIter(bits) {
34use embassy::util::InterruptFuture; 35 EXTI_WAKERS[pin as usize].wake();
35
36use embedded_hal::digital::v2 as digital;
37
38use crate::interrupt;
39
40pub struct ExtiPin<T: Instance> {
41 pin: T,
42 interrupt: T::Interrupt,
43}
44
45impl<T: Instance> ExtiPin<T> {
46 pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self {
47 cortex_m::interrupt::free(|_| {
48 pin.make_source(syscfg);
49 });
50
51 Self { pin, interrupt }
52 } 36 }
37
38 // Clear pending
39 EXTI.pr().write_value(regs::Pr(bits));
53} 40}
54 41
55impl<T: Instance + digital::OutputPin> digital::OutputPin for ExtiPin<T> { 42struct BitIter(u32);
56 type Error = T::Error;
57 43
58 fn set_low(&mut self) -> Result<(), Self::Error> { 44impl Iterator for BitIter {
59 self.pin.set_low() 45 type Item = u32;
60 }
61 46
62 fn set_high(&mut self) -> Result<(), Self::Error> { 47 fn next(&mut self) -> Option<Self::Item> {
63 self.pin.set_high() 48 match self.0.trailing_zeros() {
49 32 => None,
50 b => {
51 self.0 &= !(1 << b);
52 Some(b)
53 }
54 }
64 } 55 }
65} 56}
66 57
67impl<T: Instance + digital::StatefulOutputPin> digital::StatefulOutputPin for ExtiPin<T> { 58/// EXTI input driver
68 fn is_set_low(&self) -> Result<bool, Self::Error> { 59pub struct ExtiInput<'d, T: GpioPin> {
69 self.pin.is_set_low() 60 pin: Input<'d, T>,
70 }
71
72 fn is_set_high(&self) -> Result<bool, Self::Error> {
73 self.pin.is_set_high()
74 }
75} 61}
76 62
77impl<T: Instance + digital::ToggleableOutputPin> digital::ToggleableOutputPin for ExtiPin<T> { 63impl<'d, T: GpioPin> Unpin for ExtiInput<'d, T> {}
78 type Error = T::Error;
79 64
80 fn toggle(&mut self) -> Result<(), Self::Error> { 65impl<'d, T: GpioPin> ExtiInput<'d, T> {
81 self.pin.toggle() 66 pub fn new(pin: Input<'d, T>, _ch: impl Unborrow<Target = T::ExtiChannel> + 'd) -> Self {
67 Self { pin }
82 } 68 }
83} 69}
84 70
85impl<T: Instance + digital::InputPin> digital::InputPin for ExtiPin<T> { 71impl<'d, T: GpioPin> InputPin for ExtiInput<'d, T> {
86 type Error = T::Error; 72 type Error = Infallible;
87 73
88 fn is_high(&self) -> Result<bool, Self::Error> { 74 fn is_high(&self) -> Result<bool, Self::Error> {
89 self.pin.is_high() 75 self.pin.is_high()
@@ -94,697 +80,139 @@ impl<T: Instance + digital::InputPin> digital::InputPin for ExtiPin<T> {
94 } 80 }
95} 81}
96 82
97impl<T: Instance + digital::InputPin + 'static> ExtiPin<T> { 83impl<'d, T: GpioPin> WaitForRisingEdge for ExtiInput<'d, T> {
98 fn wait_for_state<'a>(&'a mut self, state: bool) -> impl Future<Output = ()> + 'a { 84 type Future<'a> = ExtiInputFuture<'a>;
99 async move {
100 let fut = InterruptFuture::new(&mut self.interrupt);
101 let pin = &mut self.pin;
102 cortex_m::interrupt::free(|_| {
103 pin.trigger_edge(if state {
104 EdgeOption::Rising
105 } else {
106 EdgeOption::Falling
107 });
108 });
109
110 if (state && self.pin.is_high().unwrap_or(false))
111 || (!state && self.pin.is_low().unwrap_or(false))
112 {
113 return;
114 }
115
116 fut.await;
117 85
118 self.pin.clear_pending_bit(); 86 fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> {
119 } 87 ExtiInputFuture::new(
88 self.pin.pin.pin(),
89 self.pin.pin.port(),
90 vals::Tr::ENABLED,
91 vals::Tr::DISABLED,
92 )
120 } 93 }
121} 94}
122 95
123impl<T: Instance + 'static> ExtiPin<T> { 96impl<'d, T: GpioPin> WaitForFallingEdge for ExtiInput<'d, T> {
124 fn wait_for_edge<'a>(&'a mut self, state: EdgeOption) -> impl Future<Output = ()> + 'a { 97 type Future<'a> = ExtiInputFuture<'a>;
125 self.pin.clear_pending_bit();
126 async move {
127 let fut = InterruptFuture::new(&mut self.interrupt);
128 let pin = &mut self.pin;
129 cortex_m::interrupt::free(|_| {
130 pin.trigger_edge(state);
131 });
132 98
133 fut.await; 99 fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> {
134 100 ExtiInputFuture::new(
135 self.pin.clear_pending_bit(); 101 self.pin.pin.pin(),
136 } 102 self.pin.pin.port(),
103 vals::Tr::DISABLED,
104 vals::Tr::ENABLED,
105 )
137 } 106 }
138} 107}
139 108
140impl<T: Instance + digital::InputPin + 'static> WaitForHigh for ExtiPin<T> { 109impl<'d, T: GpioPin> WaitForAnyEdge for ExtiInput<'d, T> {
141 type Future<'a> = impl Future<Output = ()> + 'a; 110 type Future<'a> = ExtiInputFuture<'a>;
142 111
143 fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { 112 fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> {
144 self.wait_for_state(true) 113 ExtiInputFuture::new(
114 self.pin.pin.pin(),
115 self.pin.pin.port(),
116 vals::Tr::ENABLED,
117 vals::Tr::ENABLED,
118 )
145 } 119 }
146} 120}
147 121
148impl<T: Instance + digital::InputPin + 'static> WaitForLow for ExtiPin<T> { 122pub struct ExtiInputFuture<'a> {
149 type Future<'a> = impl Future<Output = ()> + 'a; 123 pin: u8,
150 124 phantom: PhantomData<&'a mut AnyPin>,
151 fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> {
152 self.wait_for_state(false)
153 }
154} 125}
155 126
156/* 127impl<'a> ExtiInputFuture<'a> {
157 Irq Handler Description 128 fn new(pin: u8, port: u8, rising: vals::Tr, falling: vals::Tr) -> Self {
158 EXTI0_IRQn EXTI0_IRQHandler Handler for pins connected to line 0 129 cortex_m::interrupt::free(|_| unsafe {
159 EXTI1_IRQn EXTI1_IRQHandler Handler for pins connected to line 1 130 let pin = pin as usize;
160 EXTI2_IRQn EXTI2_IRQHandler Handler for pins connected to line 2 131 SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port));
161 EXTI3_IRQn EXTI3_IRQHandler Handler for pins connected to line 3 132 EXTI.rtsr().modify(|w| w.set_tr(pin, rising));
162 EXTI4_IRQn EXTI4_IRQHandler Handler for pins connected to line 4 133 EXTI.ftsr().modify(|w| w.set_tr(pin, falling));
163 EXTI9_5_IRQn EXTI9_5_IRQHandler Handler for pins connected to line 5 to 9 134 EXTI.pr().write(|w| w.set_pr(pin, true)); // clear pending bit
164 EXTI15_10_IRQn EXTI15_10_IRQHandler Handler for pins connected to line 10 to 15 135 EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::UNMASKED));
165*/ 136 });
166
167impl<T: Instance + 'static> WaitForRisingEdge for ExtiPin<T> {
168 type Future<'a> = impl Future<Output = ()> + 'a;
169 137
170 fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { 138 Self {
171 self.wait_for_edge(EdgeOption::Rising) 139 pin,
140 phantom: PhantomData,
141 }
172 } 142 }
173} 143}
174 144
175impl<T: Instance + 'static> WaitForFallingEdge for ExtiPin<T> { 145impl<'a> Drop for ExtiInputFuture<'a> {
176 type Future<'a> = impl Future<Output = ()> + 'a; 146 fn drop(&mut self) {
177 147 cortex_m::interrupt::free(|_| unsafe {
178 fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { 148 let pin = self.pin as _;
179 self.wait_for_edge(EdgeOption::Falling) 149 EXTI.imr().modify(|w| w.set_mr(pin, vals::Mr::MASKED));
150 });
180 } 151 }
181} 152}
182 153
183impl<T: Instance + 'static> WaitForAnyEdge for ExtiPin<T> { 154impl<'a> Future for ExtiInputFuture<'a> {
184 type Future<'a> = impl Future<Output = ()> + 'a; 155 type Output = ();
185 156
186 fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { 157 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
187 self.wait_for_edge(EdgeOption::RisingFalling) 158 EXTI_WAKERS[self.pin as usize].register(cx.waker());
159
160 if unsafe { EXTI.imr().read().mr(self.pin as _) == vals::Mr::MASKED } {
161 Poll::Ready(())
162 } else {
163 Poll::Pending
164 }
188 } 165 }
189} 166}
190 167
191mod private { 168pub(crate) mod sealed {
192 pub trait Sealed {} 169 pub trait Channel {}
193} 170}
194 171
195#[derive(Copy, Clone)] 172pub trait Channel: sealed::Channel + Sized {
196pub enum EdgeOption { 173 fn number(&self) -> usize;
197 Rising, 174 fn degrade(self) -> AnyChannel {
198 Falling, 175 AnyChannel {
199 RisingFalling, 176 number: self.number() as u8,
177 }
178 }
200} 179}
201 180
202pub trait WithInterrupt: private::Sealed { 181pub struct AnyChannel {
203 type Interrupt: interrupt::Interrupt; 182 number: u8,
204} 183}
205 184impl_unborrow!(AnyChannel);
206pub trait Instance: WithInterrupt { 185impl sealed::Channel for AnyChannel {}
207 fn make_source(&mut self, syscfg: &mut SysCfg); 186impl Channel for AnyChannel {
208 fn clear_pending_bit(&mut self); 187 fn number(&self) -> usize {
209 fn trigger_edge(&mut self, edge: EdgeOption); 188 self.number as usize
189 }
210} 190}
211 191
212macro_rules! exti { 192macro_rules! impl_exti {
213 ($set:ident, [ 193 ($type:ident, $number:expr) => {
214 $($INT:ident => $pin:ident,)+ 194 impl sealed::Channel for peripherals::$type {}
215 ]) => { 195 impl Channel for peripherals::$type {
216 $( 196 fn number(&self) -> usize {
217 impl<T> private::Sealed for gpio::$set::$pin<T> {} 197 $number as usize
218 impl<T> WithInterrupt for gpio::$set::$pin<T> {
219 type Interrupt = interrupt::$INT;
220 } 198 }
221 199 }
222 #[cfg(any(
223 feature = "stm32f401",
224 feature = "stm32f405",
225 feature = "stm32f407",
226 feature = "stm32f410",
227 feature = "stm32f411",
228 feature = "stm32f412",
229 feature = "stm32f413",
230 feature = "stm32f415",
231 feature = "stm32f417",
232 feature = "stm32f423",
233 feature = "stm32f427",
234 feature = "stm32f429",
235 feature = "stm32f437",
236 feature = "stm32f439",
237 feature = "stm32f446",
238 feature = "stm32f469",
239 feature = "stm32f479",
240 ))]
241 impl<T> Instance for gpio::$set::$pin<gpio::Input<T>> {
242 fn make_source(&mut self, syscfg: &mut SysCfg) {
243 use crate::hal::gpio::ExtiPin;
244 self.make_interrupt_source(syscfg);
245 }
246
247 fn clear_pending_bit(&mut self) {
248 use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg};
249
250 self.clear_interrupt_pending_bit();
251 }
252
253 fn trigger_edge(&mut self, edge: EdgeOption) {
254 use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg};
255 use crate::pac::EXTI;
256 let mut exti: EXTI = unsafe { mem::transmute(()) };
257 let edge = match edge {
258 EdgeOption::Falling => Edge::FALLING,
259 EdgeOption::Rising => Edge::RISING,
260 EdgeOption::RisingFalling => Edge::RISING_FALLING,
261 };
262 self.trigger_on_edge(&mut exti, edge);
263 self.enable_interrupt(&mut exti);
264 }
265 }
266
267 #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
268 impl<T> Instance for gpio::$set::$pin<T> {
269 fn make_source(&mut self, syscfg: &mut SysCfg) {}
270
271 fn clear_pending_bit(&mut self) {
272 use crate::hal::{
273 exti::{Exti, ExtiLine, GpioLine, TriggerEdge},
274 syscfg::SYSCFG,
275 };
276
277 Exti::unpend(GpioLine::from_raw_line(self.pin_number()).unwrap());
278 }
279
280 fn trigger_edge(&mut self, edge: EdgeOption) {
281 use crate::hal::{
282 exti::{Exti, ExtiLine, GpioLine, TriggerEdge},
283 syscfg::SYSCFG,
284 };
285
286 use crate::pac::EXTI;
287
288 let edge = match edge {
289 EdgeOption::Falling => TriggerEdge::Falling,
290 EdgeOption::Rising => TriggerEdge::Rising,
291 EdgeOption::RisingFalling => TriggerEdge::Both,
292 };
293
294 let exti: EXTI = unsafe { mem::transmute(()) };
295 let mut exti = Exti::new(exti);
296 let port = self.port();
297 let mut syscfg: SYSCFG = unsafe { mem::transmute(()) };
298 let line = GpioLine::from_raw_line(self.pin_number()).unwrap();
299 exti.listen_gpio(&mut syscfg, port, line, edge);
300 }
301 }
302 )+
303 }; 200 };
304} 201}
305 202
306#[cfg(any( 203impl_exti!(EXTI0, 0);
307 feature = "stm32f401", 204impl_exti!(EXTI1, 1);
308 feature = "stm32f405", 205impl_exti!(EXTI2, 2);
309 feature = "stm32f407", 206impl_exti!(EXTI3, 3);
310 feature = "stm32f410", 207impl_exti!(EXTI4, 4);
311 feature = "stm32f411", 208impl_exti!(EXTI5, 5);
312 feature = "stm32f412", 209impl_exti!(EXTI6, 6);
313 feature = "stm32f413", 210impl_exti!(EXTI7, 7);
314 feature = "stm32f415", 211impl_exti!(EXTI8, 8);
315 feature = "stm32f417", 212impl_exti!(EXTI9, 9);
316 feature = "stm32f423", 213impl_exti!(EXTI10, 10);
317 feature = "stm32f427", 214impl_exti!(EXTI11, 11);
318 feature = "stm32f429", 215impl_exti!(EXTI12, 12);
319 feature = "stm32f437", 216impl_exti!(EXTI13, 13);
320 feature = "stm32f439", 217impl_exti!(EXTI14, 14);
321 feature = "stm32f446", 218impl_exti!(EXTI15, 15);
322 feature = "stm32f469",
323 feature = "stm32f479"
324))]
325exti!(gpioa, [
326 EXTI0 => PA0,
327 EXTI1 => PA1,
328 EXTI2 => PA2,
329 EXTI3 => PA3,
330 EXTI4 => PA4,
331 EXTI9_5 => PA5,
332 EXTI9_5 => PA6,
333 EXTI9_5 => PA7,
334 EXTI9_5 => PA8,
335 EXTI9_5 => PA9,
336 EXTI15_10 => PA10,
337 EXTI15_10 => PA11,
338 EXTI15_10 => PA12,
339 EXTI15_10 => PA13,
340 EXTI15_10 => PA14,
341 EXTI15_10 => PA15,
342]);
343
344#[cfg(any(
345 feature = "stm32f401",
346 feature = "stm32f405",
347 feature = "stm32f407",
348 feature = "stm32f410",
349 feature = "stm32f411",
350 feature = "stm32f412",
351 feature = "stm32f413",
352 feature = "stm32f415",
353 feature = "stm32f417",
354 feature = "stm32f423",
355 feature = "stm32f427",
356 feature = "stm32f429",
357 feature = "stm32f437",
358 feature = "stm32f439",
359 feature = "stm32f446",
360 feature = "stm32f469",
361 feature = "stm32f479"
362))]
363exti!(gpiob, [
364 EXTI0 => PB0,
365 EXTI1 => PB1,
366 EXTI2 => PB2,
367 EXTI3 => PB3,
368 EXTI4 => PB4,
369 EXTI9_5 => PB5,
370 EXTI9_5 => PB6,
371 EXTI9_5 => PB7,
372 EXTI9_5 => PB8,
373 EXTI9_5 => PB9,
374 EXTI15_10 => PB10,
375 EXTI15_10 => PB11,
376 EXTI15_10 => PB12,
377 EXTI15_10 => PB13,
378 EXTI15_10 => PB14,
379 EXTI15_10 => PB15,
380]);
381
382#[cfg(any(
383 feature = "stm32f401",
384 feature = "stm32f405",
385 feature = "stm32f407",
386 feature = "stm32f410",
387 feature = "stm32f411",
388 feature = "stm32f412",
389 feature = "stm32f413",
390 feature = "stm32f415",
391 feature = "stm32f417",
392 feature = "stm32f423",
393 feature = "stm32f427",
394 feature = "stm32f429",
395 feature = "stm32f437",
396 feature = "stm32f439",
397 feature = "stm32f446",
398 feature = "stm32f469",
399 feature = "stm32f479"
400))]
401exti!(gpioc, [
402 EXTI0 => PC0,
403 EXTI1 => PC1,
404 EXTI2 => PC2,
405 EXTI3 => PC3,
406 EXTI4 => PC4,
407 EXTI9_5 => PC5,
408 EXTI9_5 => PC6,
409 EXTI9_5 => PC7,
410 EXTI9_5 => PC8,
411 EXTI9_5 => PC9,
412 EXTI15_10 => PC10,
413 EXTI15_10 => PC11,
414 EXTI15_10 => PC12,
415 EXTI15_10 => PC13,
416 EXTI15_10 => PC14,
417 EXTI15_10 => PC15,
418]);
419
420#[cfg(any(
421 feature = "stm32f401",
422 feature = "stm32f405",
423 feature = "stm32f407",
424 feature = "stm32f411",
425 feature = "stm32f412",
426 feature = "stm32f413",
427 feature = "stm32f415",
428 feature = "stm32f417",
429 feature = "stm32f423",
430 feature = "stm32f427",
431 feature = "stm32f429",
432 feature = "stm32f437",
433 feature = "stm32f439",
434 feature = "stm32f446",
435 feature = "stm32f469",
436 feature = "stm32f479"
437))]
438exti!(gpiod, [
439 EXTI0 => PD0,
440 EXTI1 => PD1,
441 EXTI2 => PD2,
442 EXTI3 => PD3,
443 EXTI4 => PD4,
444 EXTI9_5 => PD5,
445 EXTI9_5 => PD6,
446 EXTI9_5 => PD7,
447 EXTI9_5 => PD8,
448 EXTI9_5 => PD9,
449 EXTI15_10 => PD10,
450 EXTI15_10 => PD11,
451 EXTI15_10 => PD12,
452 EXTI15_10 => PD13,
453 EXTI15_10 => PD14,
454 EXTI15_10 => PD15,
455]);
456
457#[cfg(any(
458 feature = "stm32f401",
459 feature = "stm32f405",
460 feature = "stm32f407",
461 feature = "stm32f411",
462 feature = "stm32f412",
463 feature = "stm32f413",
464 feature = "stm32f415",
465 feature = "stm32f417",
466 feature = "stm32f423",
467 feature = "stm32f427",
468 feature = "stm32f429",
469 feature = "stm32f437",
470 feature = "stm32f439",
471 feature = "stm32f446",
472 feature = "stm32f469",
473 feature = "stm32f479"
474))]
475exti!(gpioe, [
476 EXTI0 => PE0,
477 EXTI1 => PE1,
478 EXTI2 => PE2,
479 EXTI3 => PE3,
480 EXTI4 => PE4,
481 EXTI9_5 => PE5,
482 EXTI9_5 => PE6,
483 EXTI9_5 => PE7,
484 EXTI9_5 => PE8,
485 EXTI9_5 => PE9,
486 EXTI15_10 => PE10,
487 EXTI15_10 => PE11,
488 EXTI15_10 => PE12,
489 EXTI15_10 => PE13,
490 EXTI15_10 => PE14,
491 EXTI15_10 => PE15,
492]);
493
494#[cfg(any(
495 feature = "stm32f405",
496 feature = "stm32f407",
497 feature = "stm32f412",
498 feature = "stm32f413",
499 feature = "stm32f415",
500 feature = "stm32f417",
501 feature = "stm32f423",
502 feature = "stm32f427",
503 feature = "stm32f429",
504 feature = "stm32f437",
505 feature = "stm32f439",
506 feature = "stm32f446",
507 feature = "stm32f469",
508 feature = "stm32f479"
509))]
510exti!(gpiof, [
511 EXTI0 => PF0,
512 EXTI1 => PF1,
513 EXTI2 => PF2,
514 EXTI3 => PF3,
515 EXTI4 => PF4,
516 EXTI9_5 => PF5,
517 EXTI9_5 => PF6,
518 EXTI9_5 => PF7,
519 EXTI9_5 => PF8,
520 EXTI9_5 => PF9,
521 EXTI15_10 => PF10,
522 EXTI15_10 => PF11,
523 EXTI15_10 => PF12,
524 EXTI15_10 => PF13,
525 EXTI15_10 => PF14,
526 EXTI15_10 => PF15,
527]);
528
529#[cfg(any(
530 feature = "stm32f405",
531 feature = "stm32f407",
532 feature = "stm32f412",
533 feature = "stm32f413",
534 feature = "stm32f415",
535 feature = "stm32f417",
536 feature = "stm32f423",
537 feature = "stm32f427",
538 feature = "stm32f429",
539 feature = "stm32f437",
540 feature = "stm32f439",
541 feature = "stm32f446",
542 feature = "stm32f469",
543 feature = "stm32f479"
544))]
545exti!(gpiog, [
546 EXTI0 => PG0,
547 EXTI1 => PG1,
548 EXTI2 => PG2,
549 EXTI3 => PG3,
550 EXTI4 => PG4,
551 EXTI9_5 => PG5,
552 EXTI9_5 => PG6,
553 EXTI9_5 => PG7,
554 EXTI9_5 => PG8,
555 EXTI9_5 => PG9,
556 EXTI15_10 => PG10,
557 EXTI15_10 => PG11,
558 EXTI15_10 => PG12,
559 EXTI15_10 => PG13,
560 EXTI15_10 => PG14,
561 EXTI15_10 => PG15,
562]);
563
564#[cfg(any(
565 feature = "stm32f405",
566 feature = "stm32f407",
567 feature = "stm32f410",
568 feature = "stm32f411",
569 feature = "stm32f412",
570 feature = "stm32f413",
571 feature = "stm32f415",
572 feature = "stm32f417",
573 feature = "stm32f423",
574 feature = "stm32f427",
575 feature = "stm32f429",
576 feature = "stm32f437",
577 feature = "stm32f439",
578 feature = "stm32f446",
579 feature = "stm32f469",
580 feature = "stm32f479"
581))]
582exti!(gpioh, [
583 EXTI0 => PH0,
584 EXTI1 => PH1,
585 EXTI2 => PH2,
586 EXTI3 => PH3,
587 EXTI4 => PH4,
588 EXTI9_5 => PH5,
589 EXTI9_5 => PH6,
590 EXTI9_5 => PH7,
591 EXTI9_5 => PH8,
592 EXTI9_5 => PH9,
593 EXTI15_10 => PH10,
594 EXTI15_10 => PH11,
595 EXTI15_10 => PH12,
596 EXTI15_10 => PH13,
597 EXTI15_10 => PH14,
598 EXTI15_10 => PH15,
599]);
600
601#[cfg(any(feature = "stm32f401"))]
602exti!(gpioh, [
603 EXTI0 => PH0,
604 EXTI1 => PH1,
605]);
606
607#[cfg(any(
608 feature = "stm32f405",
609 feature = "stm32f407",
610 feature = "stm32f415",
611 feature = "stm32f417",
612 feature = "stm32f427",
613 feature = "stm32f429",
614 feature = "stm32f437",
615 feature = "stm32f439",
616 feature = "stm32f469",
617 feature = "stm32f479"
618))]
619exti!(gpioi, [
620 EXTI0 => PI0,
621 EXTI1 => PI1,
622 EXTI2 => PI2,
623 EXTI3 => PI3,
624 EXTI4 => PI4,
625 EXTI9_5 => PI5,
626 EXTI9_5 => PI6,
627 EXTI9_5 => PI7,
628 EXTI9_5 => PI8,
629 EXTI9_5 => PI9,
630 EXTI15_10 => PI10,
631 EXTI15_10 => PI11,
632 EXTI15_10 => PI12,
633 EXTI15_10 => PI13,
634 EXTI15_10 => PI14,
635 EXTI15_10 => PI15,
636]);
637
638#[cfg(any(
639 feature = "stm32f427",
640 feature = "stm32f429",
641 feature = "stm32f437",
642 feature = "stm32f439",
643 feature = "stm32f469",
644 feature = "stm32f479"
645))]
646exti!(gpioj, [
647 EXTI0 => PJ0,
648 EXTI1 => PJ1,
649 EXTI2 => PJ2,
650 EXTI3 => PJ3,
651 EXTI4 => PJ4,
652 EXTI9_5 => PJ5,
653 EXTI9_5 => PJ6,
654 EXTI9_5 => PJ7,
655 EXTI9_5 => PJ8,
656 EXTI9_5 => PJ9,
657 EXTI15_10 => PJ10,
658 EXTI15_10 => PJ11,
659 EXTI15_10 => PJ12,
660 EXTI15_10 => PJ13,
661 EXTI15_10 => PJ14,
662 EXTI15_10 => PJ15,
663]);
664
665#[cfg(any(
666 feature = "stm32f427",
667 feature = "stm32f429",
668 feature = "stm32f437",
669 feature = "stm32f439",
670 feature = "stm32f469",
671 feature = "stm32f479"
672))]
673exti!(gpiok, [
674 EXTI0 => PK0,
675 EXTI1 => PK1,
676 EXTI2 => PK2,
677 EXTI3 => PK3,
678 EXTI4 => PK4,
679 EXTI9_5 => PK5,
680 EXTI9_5 => PK6,
681 EXTI9_5 => PK7,
682]);
683
684#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
685exti!(gpioa, [
686 EXTI0_1 => PA0,
687 EXTI0_1 => PA1,
688 EXTI2_3 => PA2,
689 EXTI2_3 => PA3,
690 EXTI4_15 => PA4,
691 EXTI4_15 => PA5,
692 EXTI4_15 => PA6,
693 EXTI4_15 => PA7,
694 EXTI4_15 => PA8,
695 EXTI4_15 => PA9,
696 EXTI4_15 => PA10,
697 EXTI4_15 => PA11,
698 EXTI4_15 => PA12,
699 EXTI4_15 => PA13,
700 EXTI4_15 => PA14,
701 EXTI4_15 => PA15,
702]);
703
704#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
705exti!(gpiob, [
706 EXTI0_1 => PB0,
707 EXTI0_1 => PB1,
708 EXTI2_3 => PB2,
709 EXTI2_3 => PB3,
710 EXTI4_15 => PB4,
711 EXTI4_15 => PB5,
712 EXTI4_15 => PB6,
713 EXTI4_15 => PB7,
714 EXTI4_15 => PB8,
715 EXTI4_15 => PB9,
716 EXTI4_15 => PB10,
717 EXTI4_15 => PB11,
718 EXTI4_15 => PB12,
719 EXTI4_15 => PB13,
720 EXTI4_15 => PB14,
721 EXTI4_15 => PB15,
722]);
723
724#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
725exti!(gpioc, [
726 EXTI0_1 => PC0,
727 EXTI0_1 => PC1,
728 EXTI2_3 => PC2,
729 EXTI2_3 => PC3,
730 EXTI4_15 => PC4,
731 EXTI4_15 => PC5,
732 EXTI4_15 => PC6,
733 EXTI4_15 => PC7,
734 EXTI4_15 => PC8,
735 EXTI4_15 => PC9,
736 EXTI4_15 => PC10,
737 EXTI4_15 => PC11,
738 EXTI4_15 => PC12,
739 EXTI4_15 => PC13,
740 EXTI4_15 => PC14,
741 EXTI4_15 => PC15,
742]);
743
744#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
745exti!(gpiod, [
746 EXTI0_1 => PD0,
747 EXTI0_1 => PD1,
748 EXTI2_3 => PD2,
749 EXTI2_3 => PD3,
750 EXTI4_15 => PD4,
751 EXTI4_15 => PD5,
752 EXTI4_15 => PD6,
753 EXTI4_15 => PD7,
754 EXTI4_15 => PD8,
755 EXTI4_15 => PD9,
756 EXTI4_15 => PD10,
757 EXTI4_15 => PD11,
758 EXTI4_15 => PD12,
759 EXTI4_15 => PD13,
760 EXTI4_15 => PD14,
761 EXTI4_15 => PD15,
762]);
763
764#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
765exti!(gpioe, [
766 EXTI0_1 => PE0,
767 EXTI0_1 => PE1,
768 EXTI2_3 => PE2,
769 EXTI2_3 => PE3,
770 EXTI4_15 => PE4,
771 EXTI4_15 => PE5,
772 EXTI4_15 => PE6,
773 EXTI4_15 => PE7,
774 EXTI4_15 => PE8,
775 EXTI4_15 => PE9,
776 EXTI4_15 => PE10,
777 EXTI4_15 => PE11,
778 EXTI4_15 => PE12,
779 EXTI4_15 => PE13,
780 EXTI4_15 => PE14,
781 EXTI4_15 => PE15,
782]);
783
784#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))]
785exti!(gpioh, [
786 EXTI0_1 => PH0,
787 EXTI0_1 => PH1,
788 EXTI4_15 => PH9,
789 EXTI4_15 => PH10,
790]);
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index f963400a7..e0e6cc477 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -1,8 +1,6 @@
1use core::convert::Infallible; 1use core::convert::Infallible;
2use core::hint::unreachable_unchecked;
3use core::marker::PhantomData; 2use core::marker::PhantomData;
4 3use embassy::util::Unborrow;
5use embassy::util::PeripheralBorrow;
6use embassy_extras::{impl_unborrow, unborrow}; 4use embassy_extras::{impl_unborrow, unborrow};
7use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin}; 5use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin};
8use gpio::vals; 6use gpio::vals;
@@ -10,13 +8,6 @@ use gpio::vals;
10use crate::pac::gpio_v2 as gpio; 8use crate::pac::gpio_v2 as gpio;
11use crate::peripherals; 9use crate::peripherals;
12 10
13/// A GPIO port with up to 16 pins.
14#[derive(Debug, Eq, PartialEq)]
15pub enum Port {
16 PortA,
17 PortB,
18}
19
20/// Pull setting for an input. 11/// Pull setting for an input.
21#[derive(Debug, Eq, PartialEq)] 12#[derive(Debug, Eq, PartialEq)]
22#[cfg_attr(feature = "defmt", derive(defmt::Format))] 13#[cfg_attr(feature = "defmt", derive(defmt::Format))]
@@ -33,7 +24,7 @@ pub struct Input<'d, T: Pin> {
33} 24}
34 25
35impl<'d, T: Pin> Input<'d, T> { 26impl<'d, T: Pin> Input<'d, T> {
36 pub fn new(pin: impl PeripheralBorrow<Target = T> + 'd, pull: Pull) -> Self { 27 pub fn new(pin: impl Unborrow<Target = T> + 'd, pull: Pull) -> Self {
37 unborrow!(pin); 28 unborrow!(pin);
38 29
39 cortex_m::interrupt::free(|_| unsafe { 30 cortex_m::interrupt::free(|_| unsafe {
@@ -94,7 +85,7 @@ pub struct Output<'d, T: Pin> {
94} 85}
95 86
96impl<'d, T: Pin> Output<'d, T> { 87impl<'d, T: Pin> Output<'d, T> {
97 pub fn new(pin: impl PeripheralBorrow<Target = T> + 'd, initial_output: Level) -> Self { 88 pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level) -> Self {
98 unborrow!(pin); 89 unborrow!(pin);
99 90
100 match initial_output { 91 match initial_output {
@@ -173,6 +164,7 @@ pub(crate) mod sealed {
173 164
174 #[inline] 165 #[inline]
175 fn block(&self) -> gpio::Gpio { 166 fn block(&self) -> gpio::Gpio {
167 // TODO hardcoding peripheral addrs until we figure out how these are handled in the metapac
176 let p = 0x4002_0000 + (self._port() as u32) * 0x400; 168 let p = 0x4002_0000 + (self._port() as u32) * 0x400;
177 gpio::Gpio(p as *mut u8) 169 gpio::Gpio(p as *mut u8)
178 } 170 }
@@ -181,9 +173,8 @@ pub(crate) mod sealed {
181 #[inline] 173 #[inline]
182 fn set_high(&self) { 174 fn set_high(&self) {
183 unsafe { 175 unsafe {
184 self.block() 176 let n = self._pin() as _;
185 .bsrr() 177 self.block().bsrr().write(|w| w.set_bs(n, true));
186 .write(|w| w.set_bs(self._pin() as _, true));
187 } 178 }
188 } 179 }
189 180
@@ -191,9 +182,8 @@ pub(crate) mod sealed {
191 #[inline] 182 #[inline]
192 fn set_low(&self) { 183 fn set_low(&self) {
193 unsafe { 184 unsafe {
194 self.block() 185 let n = self._pin() as _;
195 .bsrr() 186 self.block().bsrr().write(|w| w.set_br(n, true));
196 .write(|w| w.set_br(self._pin() as _, true));
197 } 187 }
198 } 188 }
199 } 189 }
@@ -202,6 +192,8 @@ pub(crate) mod sealed {
202} 192}
203 193
204pub trait Pin: sealed::Pin + Sized { 194pub trait Pin: sealed::Pin + Sized {
195 type ExtiChannel: crate::exti::Channel;
196
205 /// Number of the pin within the port (0..31) 197 /// Number of the pin within the port (0..31)
206 #[inline] 198 #[inline]
207 fn pin(&self) -> u8 { 199 fn pin(&self) -> u8 {
@@ -210,12 +202,8 @@ pub trait Pin: sealed::Pin + Sized {
210 202
211 /// Port of the pin 203 /// Port of the pin
212 #[inline] 204 #[inline]
213 fn port(&self) -> Port { 205 fn port(&self) -> u8 {
214 match self.pin_port() / 16 { 206 self._port()
215 0 => Port::PortA,
216 1 => Port::PortB,
217 _ => unsafe { unreachable_unchecked() },
218 }
219 } 207 }
220 208
221 #[inline] 209 #[inline]
@@ -245,7 +233,9 @@ impl AnyPin {
245} 233}
246 234
247impl_unborrow!(AnyPin); 235impl_unborrow!(AnyPin);
248impl Pin for AnyPin {} 236impl Pin for AnyPin {
237 type ExtiChannel = crate::exti::AnyChannel;
238}
249impl sealed::Pin for AnyPin { 239impl sealed::Pin for AnyPin {
250 #[inline] 240 #[inline]
251 fn pin_port(&self) -> u8 { 241 fn pin_port(&self) -> u8 {
@@ -288,31 +278,20 @@ impl<T: Pin> OptionalPin for T {
288 } 278 }
289} 279}
290 280
291// Uninhabited enum, so it's actually impossible to create a DummyPin value.
292#[doc(hidden)]
293pub enum DummyPin {}
294impl Pin for DummyPin {}
295impl sealed::Pin for DummyPin {
296 #[inline]
297 fn pin_port(&self) -> u8 {
298 unreachable!()
299 }
300}
301
302#[derive(Clone, Copy, Debug)] 281#[derive(Clone, Copy, Debug)]
303pub struct NoPin; 282pub struct NoPin;
304impl_unborrow!(NoPin); 283impl_unborrow!(NoPin);
305impl sealed::OptionalPin for NoPin {} 284impl sealed::OptionalPin for NoPin {}
306impl OptionalPin for NoPin { 285impl OptionalPin for NoPin {
307 type Pin = DummyPin; 286 type Pin = AnyPin;
308 287
309 #[inline] 288 #[inline]
310 fn pin(&self) -> Option<&DummyPin> { 289 fn pin(&self) -> Option<&AnyPin> {
311 None 290 None
312 } 291 }
313 292
314 #[inline] 293 #[inline]
315 fn pin_mut(&mut self) -> Option<&mut DummyPin> { 294 fn pin_mut(&mut self) -> Option<&mut AnyPin> {
316 None 295 None
317 } 296 }
318} 297}
@@ -320,8 +299,10 @@ impl OptionalPin for NoPin {
320// ==================== 299// ====================
321 300
322macro_rules! impl_pin { 301macro_rules! impl_pin {
323 ($type:ident, $port_num:expr, $pin_num:expr) => { 302 ($type:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
324 impl Pin for peripherals::$type {} 303 impl Pin for peripherals::$type {
304 type ExtiChannel = peripherals::$exti_ch;
305 }
325 impl sealed::Pin for peripherals::$type { 306 impl sealed::Pin for peripherals::$type {
326 #[inline] 307 #[inline]
327 fn pin_port(&self) -> u8 { 308 fn pin_port(&self) -> u8 {
@@ -331,51 +312,51 @@ macro_rules! impl_pin {
331 }; 312 };
332} 313}
333 314
334impl_pin!(PA0, 0, 0); 315impl_pin!(PA0, 0, 0, EXTI0);
335impl_pin!(PA1, 0, 1); 316impl_pin!(PA1, 0, 1, EXTI1);
336impl_pin!(PA2, 0, 2); 317impl_pin!(PA2, 0, 2, EXTI2);
337impl_pin!(PA3, 0, 3); 318impl_pin!(PA3, 0, 3, EXTI3);
338impl_pin!(PA4, 0, 4); 319impl_pin!(PA4, 0, 4, EXTI4);
339impl_pin!(PA5, 0, 5); 320impl_pin!(PA5, 0, 5, EXTI5);
340impl_pin!(PA6, 0, 6); 321impl_pin!(PA6, 0, 6, EXTI6);
341impl_pin!(PA7, 0, 7); 322impl_pin!(PA7, 0, 7, EXTI7);
342impl_pin!(PA8, 0, 8); 323impl_pin!(PA8, 0, 8, EXTI8);
343impl_pin!(PA9, 0, 9); 324impl_pin!(PA9, 0, 9, EXTI9);
344impl_pin!(PA10, 0, 10); 325impl_pin!(PA10, 0, 10, EXTI10);
345impl_pin!(PA11, 0, 11); 326impl_pin!(PA11, 0, 11, EXTI11);
346impl_pin!(PA12, 0, 12); 327impl_pin!(PA12, 0, 12, EXTI12);
347impl_pin!(PA13, 0, 13); 328impl_pin!(PA13, 0, 13, EXTI13);
348impl_pin!(PA14, 0, 14); 329impl_pin!(PA14, 0, 14, EXTI14);
349impl_pin!(PA15, 0, 15); 330impl_pin!(PA15, 0, 15, EXTI15);
350impl_pin!(PB0, 1, 0); 331impl_pin!(PB0, 1, 0, EXTI0);
351impl_pin!(PB1, 1, 1); 332impl_pin!(PB1, 1, 1, EXTI1);
352impl_pin!(PB2, 1, 2); 333impl_pin!(PB2, 1, 2, EXTI2);
353impl_pin!(PB3, 1, 3); 334impl_pin!(PB3, 1, 3, EXTI3);
354impl_pin!(PB4, 1, 4); 335impl_pin!(PB4, 1, 4, EXTI4);
355impl_pin!(PB5, 1, 5); 336impl_pin!(PB5, 1, 5, EXTI5);
356impl_pin!(PB6, 1, 6); 337impl_pin!(PB6, 1, 6, EXTI6);
357impl_pin!(PB7, 1, 7); 338impl_pin!(PB7, 1, 7, EXTI7);
358impl_pin!(PB8, 1, 8); 339impl_pin!(PB8, 1, 8, EXTI8);
359impl_pin!(PB9, 1, 9); 340impl_pin!(PB9, 1, 9, EXTI9);
360impl_pin!(PB10, 1, 10); 341impl_pin!(PB10, 1, 10, EXTI10);
361impl_pin!(PB11, 1, 11); 342impl_pin!(PB11, 1, 11, EXTI11);
362impl_pin!(PB12, 1, 12); 343impl_pin!(PB12, 1, 12, EXTI12);
363impl_pin!(PB13, 1, 13); 344impl_pin!(PB13, 1, 13, EXTI13);
364impl_pin!(PB14, 1, 14); 345impl_pin!(PB14, 1, 14, EXTI14);
365impl_pin!(PB15, 1, 15); 346impl_pin!(PB15, 1, 15, EXTI15);
366impl_pin!(PC0, 2, 0); 347impl_pin!(PC0, 2, 0, EXTI0);
367impl_pin!(PC1, 2, 1); 348impl_pin!(PC1, 2, 1, EXTI1);
368impl_pin!(PC2, 2, 2); 349impl_pin!(PC2, 2, 2, EXTI2);
369impl_pin!(PC3, 2, 3); 350impl_pin!(PC3, 2, 3, EXTI3);
370impl_pin!(PC4, 2, 4); 351impl_pin!(PC4, 2, 4, EXTI4);
371impl_pin!(PC5, 2, 5); 352impl_pin!(PC5, 2, 5, EXTI5);
372impl_pin!(PC6, 2, 6); 353impl_pin!(PC6, 2, 6, EXTI6);
373impl_pin!(PC7, 2, 7); 354impl_pin!(PC7, 2, 7, EXTI7);
374impl_pin!(PC8, 2, 8); 355impl_pin!(PC8, 2, 8, EXTI8);
375impl_pin!(PC9, 2, 9); 356impl_pin!(PC9, 2, 9, EXTI9);
376impl_pin!(PC10, 2, 10); 357impl_pin!(PC10, 2, 10, EXTI10);
377impl_pin!(PC11, 2, 11); 358impl_pin!(PC11, 2, 11, EXTI11);
378impl_pin!(PC12, 2, 12); 359impl_pin!(PC12, 2, 12, EXTI12);
379impl_pin!(PC13, 2, 13); 360impl_pin!(PC13, 2, 13, EXTI13);
380impl_pin!(PC14, 2, 14); 361impl_pin!(PC14, 2, 14, EXTI14);
381impl_pin!(PC15, 2, 15); 362impl_pin!(PC15, 2, 15, EXTI15);
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 58a846229..da266f75d 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -28,8 +28,9 @@ pub mod fmt;
28mod chip; 28mod chip;
29pub use chip::{peripherals, Peripherals}; 29pub use chip::{peripherals, Peripherals};
30 30
31pub mod exti;
31pub mod gpio; 32pub mod gpio;
32//pub mod exti; 33//pub mod rtc;
33//pub mod interrupt; 34//pub mod interrupt;
34 35
35pub(crate) use stm32_metapac as pac; 36pub(crate) use stm32_metapac as pac;