aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxoviat <[email protected]>2025-11-23 00:30:52 +0000
committerGitHub <[email protected]>2025-11-23 00:30:52 +0000
commit54a153a9a24a58a7cfa1210f78f61beb913baf2d (patch)
tree6bc432aa7081bf6d2df36e322d5c742eaa449977
parenteb4e4100acbe03ee1d3726c948f91b6927a18125 (diff)
parentb877b0dc6b5fe4541a45e6b43ed9d82131608aee (diff)
Merge pull request #4922 from WillaWillNot/anybinding_and_bindable_exti
Bindable EXTI interrupts, and removal of AnyChannel support for ExtiInput
-rw-r--r--.vscode/settings.json6
-rw-r--r--docs/examples/layer-by-layer/blinky-async/src/main.rs10
-rw-r--r--docs/pages/faq.adoc6
-rw-r--r--docs/pages/layer_by_layer.adoc2
-rw-r--r--embassy-stm32/CHANGELOG.md3
-rw-r--r--embassy-stm32/build.rs17
-rw-r--r--embassy-stm32/src/exti.rs91
-rw-r--r--embassy-stm32/src/gpio.rs21
-rw-r--r--embassy-stm32/src/lib.rs6
-rw-r--r--examples/boot/application/stm32f3/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32f7/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32h7/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32l0/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32l1/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32l4/src/bin/a.rs10
-rw-r--r--examples/boot/application/stm32wl/src/bin/a.rs11
-rw-r--r--examples/stm32c0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f0/src/bin/button_controlled_blink.rs11
-rw-r--r--examples/stm32f0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f3/src/bin/button_events.rs10
-rw-r--r--examples/stm32f3/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f4/src/bin/button_exti.rs10
-rw-r--r--examples/stm32f4/src/bin/eth_w5500.rs7
-rw-r--r--examples/stm32f4/src/bin/usb_hid_keyboard.rs7
-rw-r--r--examples/stm32f7/src/bin/button_exti.rs10
-rw-r--r--examples/stm32g0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32g4/src/bin/button_exti.rs10
-rw-r--r--examples/stm32h5/src/bin/button_exti.rs10
-rw-r--r--examples/stm32h7/src/bin/button_exti.rs10
-rw-r--r--examples/stm32h7rs/src/bin/button_exti.rs10
-rw-r--r--examples/stm32l0/src/bin/button_exti.rs11
-rw-r--r--examples/stm32l4/src/bin/button_exti.rs10
-rw-r--r--examples/stm32l4/src/bin/spe_adin1110_http_server.rs6
-rw-r--r--examples/stm32l4/src/bin/spi_dma.rs4
-rw-r--r--examples/stm32l5/src/bin/button_exti.rs10
-rw-r--r--examples/stm32n6/src/bin/blinky.rs10
-rw-r--r--examples/stm32u0/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wb/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wba/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wba6/src/bin/button_exti.rs10
-rw-r--r--examples/stm32wl/src/bin/button_exti.rs11
-rw-r--r--examples/stm32wle5/src/bin/button_exti.rs11
42 files changed, 357 insertions, 124 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
index c504f3ccd..3c9cce18b 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -61,4 +61,8 @@
61 // "examples/stm32wl/Cargo.toml", 61 // "examples/stm32wl/Cargo.toml",
62 // "examples/wasm/Cargo.toml", 62 // "examples/wasm/Cargo.toml",
63 ], 63 ],
64} 64 "rust-analyzer.rustfmt.extraArgs": [
65 //Uncomment to run rustfmt with nightly-only settings that match the CI
66 // "+nightly"
67 ],
68} \ No newline at end of file
diff --git a/docs/examples/layer-by-layer/blinky-async/src/main.rs b/docs/examples/layer-by-layer/blinky-async/src/main.rs
index 004602816..007f7da46 100644
--- a/docs/examples/layer-by-layer/blinky-async/src/main.rs
+++ b/docs/examples/layer-by-layer/blinky-async/src/main.rs
@@ -2,15 +2,21 @@
2#![no_main] 2#![no_main]
3 3
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_stm32::exti::ExtiInput; 5use embassy_stm32::exti::{self, ExtiInput};
6use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 6use embassy_stm32::gpio::{Level, Output, Pull, Speed};
7use embassy_stm32::{bind_interrupts, interrupt};
7use {defmt_rtt as _, panic_probe as _}; 8use {defmt_rtt as _, panic_probe as _};
8 9
10bind_interrupts!(
11 pub struct Irqs{
12 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10 >;
13});
14
9#[embassy_executor::main] 15#[embassy_executor::main]
10async fn main(_spawner: Spawner) { 16async fn main(_spawner: Spawner) {
11 let p = embassy_stm32::init(Default::default()); 17 let p = embassy_stm32::init(Default::default());
12 let mut led = Output::new(p.PB14, Level::Low, Speed::VeryHigh); 18 let mut led = Output::new(p.PB14, Level::Low, Speed::VeryHigh);
13 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 19 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
14 20
15 loop { 21 loop {
16 button.wait_for_any_edge().await; 22 button.wait_for_any_edge().await;
diff --git a/docs/pages/faq.adoc b/docs/pages/faq.adoc
index 8098e12ac..e59ef7b46 100644
--- a/docs/pages/faq.adoc
+++ b/docs/pages/faq.adoc
@@ -171,7 +171,11 @@ Note that the git revision should match any other embassy patches or git depende
171 171
172== Can I use manual ISRs alongside Embassy? 172== Can I use manual ISRs alongside Embassy?
173 173
174Yes! This can be useful if you need to respond to an event as fast as possible, and the latency caused by the usual “ISR, wake, return from ISR, context switch to woken task” flow is too much for your application. Simply define a `#[interrupt] fn INTERRUPT_NAME() {}` handler as you would link:https://docs.rust-embedded.org/book/start/interrupts.html[in any other embedded rust project]. 174Yes! This can be useful if you need to respond to an event as fast as possible, and the latency caused by the usual “ISR, wake, return from ISR, context switch to woken task” flow is too much for your application.
175
176You may simply define a `#[interrupt] fn INTERRUPT_NAME() {}` handler as you would link:https://docs.rust-embedded.org/book/start/interrupts.html[in any other embedded rust project].
177
178Or you may define a struct implementing the `embassy-[family]::interrupt::typelevel::Handler` trait with an on_interrupt() method, and bind it to the interrupt vector via the `bind_interrupts!` macro, which introduces only a single indirection. This allows the mixing of manual ISRs with Embassy driver-defined ISRs; handlers will be called directly in the order they appear in the macro.
175 179
176== How can I measure resource usage (CPU, RAM, etc.)? 180== How can I measure resource usage (CPU, RAM, etc.)?
177 181
diff --git a/docs/pages/layer_by_layer.adoc b/docs/pages/layer_by_layer.adoc
index 0692ee4fa..f554e642a 100644
--- a/docs/pages/layer_by_layer.adoc
+++ b/docs/pages/layer_by_layer.adoc
@@ -76,7 +76,7 @@ The async version looks very similar to the HAL version, apart from a few minor
76* The peripheral initialization is done by the main macro, and is handed to the main task. 76* The peripheral initialization is done by the main macro, and is handed to the main task.
77* Before checking the button state, the application is awaiting a transition in the pin state (low -> high or high -> low). 77* Before checking the button state, the application is awaiting a transition in the pin state (low -> high or high -> low).
78 78
79When `button.wait_for_any_edge().await` is called, the executor will pause the main task and put the microcontroller in sleep mode, unless there are other tasks that can run. Internally, the Embassy HAL has configured the interrupt handler for the button (in `ExtiInput`), so that whenever an interrupt is raised, the task awaiting the button will be woken up. 79When `button.wait_for_any_edge().await` is called, the executor will pause the main task and put the microcontroller in sleep mode, unless there are other tasks that can run. On this chip, interrupt signals on EXTI lines 10-15 (including the button on EXTI line 13) raise the hardware interrupt EXTI15_10. This interrupt handler has been bound (using `bind_interrupts!`) to call the `InterruptHandler` provided by the exti module, so that whenever an interrupt is raised, the task awaiting the button via `wait_for_any_edge()` will be woken up.
80 80
81The minimal overhead of the executor and the ability to run multiple tasks "concurrently" combined with the enormous simplification of the application, makes `async` a great fit for embedded. 81The minimal overhead of the executor and the ability to run multiple tasks "concurrently" combined with the enormous simplification of the application, makes `async` a great fit for embedded.
82 82
diff --git a/embassy-stm32/CHANGELOG.md b/embassy-stm32/CHANGELOG.md
index da2ea5c79..a66b2d437 100644
--- a/embassy-stm32/CHANGELOG.md
+++ b/embassy-stm32/CHANGELOG.md
@@ -75,6 +75,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
75- fix: fixing channel numbers on vbat and vddcore for adc on adc 75- fix: fixing channel numbers on vbat and vddcore for adc on adc
76- adc: adding disable to vbat 76- adc: adding disable to vbat
77- feat: stm32/flash: add async support for h7 family 77- feat: stm32/flash: add async support for h7 family
78- feat: exti brought in line with other drivers' interrupt rebinding system ([#4922](https://github.com/embassy-rs/embassy/pull/4922))
79- removal: ExtiInput no longer accepts AnyPin/AnyChannel; AnyChannel removed entirely
80- fix: build script ensures EXTI2_TSC is listed as the IRQ of EXTI2 even if the PAC doesn't
78- feat: stm32/lcd: added implementation 81- feat: stm32/lcd: added implementation
79 82
80## 0.4.0 - 2025-08-26 83## 0.4.0 - 2025-08-26
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs
index e218e2492..109571e8f 100644
--- a/embassy-stm32/build.rs
+++ b/embassy-stm32/build.rs
@@ -353,8 +353,13 @@ fn main() {
353 // ======== 353 // ========
354 // Generate interrupt declarations 354 // Generate interrupt declarations
355 355
356 let mut exti2_tsc_shared_int_present: Option<stm32_metapac::metadata::Interrupt> = None;
356 let mut irqs = Vec::new(); 357 let mut irqs = Vec::new();
357 for irq in METADATA.interrupts { 358 for irq in METADATA.interrupts {
359 // The PAC doesn't ensure this is listed as the IRQ of EXTI2, so we must do so
360 if irq.name == "EXTI2_TSC" {
361 exti2_tsc_shared_int_present = Some(irq.clone())
362 }
358 irqs.push(format_ident!("{}", irq.name)); 363 irqs.push(format_ident!("{}", irq.name));
359 } 364 }
360 365
@@ -1812,7 +1817,19 @@ fn main() {
1812 for p in METADATA.peripherals { 1817 for p in METADATA.peripherals {
1813 let mut pt = TokenStream::new(); 1818 let mut pt = TokenStream::new();
1814 1819
1820 let mut exti2_tsc_injected = false;
1821 if let Some(ref irq) = exti2_tsc_shared_int_present
1822 && p.name == "EXTI"
1823 {
1824 exti2_tsc_injected = true;
1825 let iname = format_ident!("{}", irq.name);
1826 let sname = format_ident!("{}", "EXTI2");
1827 pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;));
1828 }
1815 for irq in p.interrupts { 1829 for irq in p.interrupts {
1830 if exti2_tsc_injected && irq.signal == "EXTI2" {
1831 continue;
1832 }
1816 let iname = format_ident!("{}", irq.interrupt); 1833 let iname = format_ident!("{}", irq.interrupt);
1817 let sname = format_ident!("{}", irq.signal); 1834 let sname = format_ident!("{}", irq.signal);
1818 pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;)); 1835 pt.extend(quote!(pub type #sname = crate::interrupt::typelevel::#iname;));
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 899d5e677..7b7896d46 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -5,14 +5,16 @@ use core::marker::PhantomData;
5use core::pin::Pin; 5use core::pin::Pin;
6use core::task::{Context, Poll}; 6use core::task::{Context, Poll};
7 7
8use embassy_hal_internal::{PeripheralType, impl_peripheral}; 8use embassy_hal_internal::PeripheralType;
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
10use futures_util::FutureExt; 10use futures_util::FutureExt;
11 11
12use crate::gpio::{AnyPin, Input, Level, Pin as GpioPin, PinNumber, Pull}; 12use crate::gpio::{AnyPin, ExtiPin, Input, Level, Pin as GpioPin, PinNumber, Pull};
13use crate::interrupt::Interrupt as InterruptEnum;
14use crate::interrupt::typelevel::{Binding, Handler, Interrupt as InterruptType};
13use crate::pac::EXTI; 15use crate::pac::EXTI;
14use crate::pac::exti::regs::Lines; 16use crate::pac::exti::regs::Lines;
15use crate::{Peri, interrupt, pac, peripherals}; 17use crate::{Peri, pac};
16 18
17const EXTI_COUNT: usize = 16; 19const EXTI_COUNT: usize = 16;
18static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [const { AtomicWaker::new() }; EXTI_COUNT]; 20static EXTI_WAKERS: [AtomicWaker; EXTI_COUNT] = [const { AtomicWaker::new() }; EXTI_COUNT];
@@ -106,10 +108,17 @@ impl<'d> Unpin for ExtiInput<'d> {}
106 108
107impl<'d> ExtiInput<'d> { 109impl<'d> ExtiInput<'d> {
108 /// Create an EXTI input. 110 /// Create an EXTI input.
109 pub fn new<T: GpioPin>(pin: Peri<'d, T>, ch: Peri<'d, T::ExtiChannel>, pull: Pull) -> Self { 111 ///
110 // Needed if using AnyPin+AnyChannel. 112 /// The Binding must bind the Channel's IRQ to [InterruptHandler].
111 assert_eq!(pin.pin(), ch.number()); 113 pub fn new<T: ExtiPin + GpioPin>(
112 114 pin: Peri<'d, T>,
115 _ch: Peri<'d, T::ExtiChannel>,
116 pull: Pull,
117 _irq: impl Binding<
118 <<T as ExtiPin>::ExtiChannel as Channel>::IRQ,
119 InterruptHandler<<<T as ExtiPin>::ExtiChannel as Channel>::IRQ>,
120 >,
121 ) -> Self {
113 Self { 122 Self {
114 pin: Input::new(pin, pull), 123 pin: Input::new(pin, pull),
115 } 124 }
@@ -328,7 +337,7 @@ macro_rules! foreach_exti_irq {
328 (EXTI15) => { $action!(EXTI15); }; 337 (EXTI15) => { $action!(EXTI15); };
329 338
330 // plus the weird ones 339 // plus the weird ones
331 (EXTI0_1) => { $action!( EXTI0_1 ); }; 340 (EXTI0_1) => { $action!(EXTI0_1); };
332 (EXTI15_10) => { $action!(EXTI15_10); }; 341 (EXTI15_10) => { $action!(EXTI15_10); };
333 (EXTI15_4) => { $action!(EXTI15_4); }; 342 (EXTI15_4) => { $action!(EXTI15_4); };
334 (EXTI1_0) => { $action!(EXTI1_0); }; 343 (EXTI1_0) => { $action!(EXTI1_0); };
@@ -341,57 +350,67 @@ macro_rules! foreach_exti_irq {
341 }; 350 };
342} 351}
343 352
344macro_rules! impl_irq { 353///EXTI interrupt handler. All EXTI interrupt vectors should be bound to this handler.
345 ($e:ident) => { 354///
346 #[allow(non_snake_case)] 355/// It is generic over the [Interrupt](InterruptType) rather
347 #[cfg(feature = "rt")] 356/// than the [Channel] because it should not be bound multiple
348 #[interrupt] 357/// times to the same vector on chips which multiplex multiple EXTI interrupts into one vector.
349 unsafe fn $e() { 358//
350 on_irq() 359// It technically doesn't need to be generic at all, except to satisfy the generic argument
351 } 360// of [Handler]. All EXTI interrupts eventually land in the same on_irq() function.
352 }; 361pub struct InterruptHandler<T: crate::interrupt::typelevel::Interrupt> {
362 _phantom: PhantomData<T>,
353} 363}
354 364
355foreach_exti_irq!(impl_irq); 365impl<T: InterruptType> Handler<T> for InterruptHandler<T> {
366 unsafe fn on_interrupt() {
367 on_irq()
368 }
369}
356 370
357trait SealedChannel {} 371trait SealedChannel {}
358 372
359/// EXTI channel trait. 373/// EXTI channel trait.
360#[allow(private_bounds)] 374#[allow(private_bounds)]
361pub trait Channel: PeripheralType + SealedChannel + Sized { 375pub trait Channel: PeripheralType + SealedChannel + Sized {
362 /// Get the EXTI channel number. 376 /// EXTI channel number.
363 fn number(&self) -> PinNumber; 377 fn number(&self) -> PinNumber;
378 /// [Enum-level Interrupt](InterruptEnum), which may be the same for multiple channels.
379 fn irq(&self) -> InterruptEnum;
380 /// [Type-level Interrupt](InterruptType), which may be the same for multiple channels.
381 type IRQ: InterruptType;
364} 382}
365 383
366/// Type-erased EXTI channel. 384//Doc isn't hidden in order to surface the explanation to users, even though it's completely inoperable, not just deprecated.
385//Entire type along with doc can probably be removed after deprecation has appeared in a release once.
386/// Deprecated type-erased EXTI channel.
367/// 387///
368/// This represents ownership over any EXTI channel, known at runtime. 388/// Support for AnyChannel was removed in order to support manually bindable EXTI interrupts via bind_interrupts; [ExtiInput::new()]
389/// must know the required IRQ at compile time, and therefore cannot support type-erased channels.
390#[deprecated = "type-erased EXTI channels are no longer supported, in order to support manually bindable EXTI interrupts (more info: https://github.com/embassy-rs/embassy/pull/4922)"]
369pub struct AnyChannel { 391pub struct AnyChannel {
392 #[allow(unused)]
370 number: PinNumber, 393 number: PinNumber,
371} 394}
372 395
373impl_peripheral!(AnyChannel);
374impl SealedChannel for AnyChannel {}
375impl Channel for AnyChannel {
376 fn number(&self) -> PinNumber {
377 self.number
378 }
379}
380
381macro_rules! impl_exti { 396macro_rules! impl_exti {
382 ($type:ident, $number:expr) => { 397 ($type:ident, $number:expr) => {
383 impl SealedChannel for peripherals::$type {} 398 impl SealedChannel for crate::peripherals::$type {}
384 impl Channel for peripherals::$type { 399 impl Channel for crate::peripherals::$type {
385 fn number(&self) -> PinNumber { 400 fn number(&self) -> PinNumber {
386 $number 401 $number
387 } 402 }
403 fn irq(&self) -> InterruptEnum {
404 crate::_generated::peripheral_interrupts::EXTI::$type::IRQ
405 }
406 type IRQ = crate::_generated::peripheral_interrupts::EXTI::$type;
388 } 407 }
389 408
390 impl From<peripherals::$type> for AnyChannel { 409 //Still here to surface deprecation messages to the user - remove when removing AnyChannel
391 fn from(val: peripherals::$type) -> Self { 410 #[allow(deprecated)]
392 Self { 411 impl From<crate::peripherals::$type> for AnyChannel {
393 number: val.number() as PinNumber, 412 fn from(_val: crate::peripherals::$type) -> Self {
394 } 413 Self { number: $number }
395 } 414 }
396 } 415 }
397 }; 416 };
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs
index 17c5a9962..e7d4e9ad3 100644
--- a/embassy-stm32/src/gpio.rs
+++ b/embassy-stm32/src/gpio.rs
@@ -812,15 +812,19 @@ pub type PinNumber = u8;
812#[cfg(stm32n6)] 812#[cfg(stm32n6)]
813pub type PinNumber = u16; 813pub type PinNumber = u16;
814 814
815/// GPIO pin trait. 815/// Pin that can be used to configure an [ExtiInput](crate::exti::ExtiInput). This trait is lost when converting to [AnyPin].
816#[cfg(feature = "exti")]
816#[allow(private_bounds)] 817#[allow(private_bounds)]
817pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static { 818pub trait ExtiPin: PeripheralType + SealedPin {
818 /// EXTI channel assigned to this pin. 819 /// EXTI channel assigned to this pin.
819 /// 820 ///
820 /// For example, PC4 uses EXTI4. 821 /// For example, PC4 uses EXTI4.
821 #[cfg(feature = "exti")]
822 type ExtiChannel: crate::exti::Channel; 822 type ExtiChannel: crate::exti::Channel;
823}
823 824
825/// GPIO pin trait.
826#[allow(private_bounds)]
827pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
824 /// Number of the pin within the port (0..31) 828 /// Number of the pin within the port (0..31)
825 #[inline] 829 #[inline]
826 fn pin(&self) -> PinNumber { 830 fn pin(&self) -> PinNumber {
@@ -834,7 +838,7 @@ pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
834 } 838 }
835} 839}
836 840
837/// Type-erased GPIO pin 841/// Type-erased GPIO pin.
838pub struct AnyPin { 842pub struct AnyPin {
839 pin_port: PinNumber, 843 pin_port: PinNumber,
840} 844}
@@ -862,10 +866,7 @@ impl AnyPin {
862} 866}
863 867
864impl_peripheral!(AnyPin); 868impl_peripheral!(AnyPin);
865impl Pin for AnyPin { 869impl Pin for AnyPin {}
866 #[cfg(feature = "exti")]
867 type ExtiChannel = crate::exti::AnyChannel;
868}
869impl SealedPin for AnyPin { 870impl SealedPin for AnyPin {
870 #[inline] 871 #[inline]
871 fn pin_port(&self) -> PinNumber { 872 fn pin_port(&self) -> PinNumber {
@@ -878,7 +879,9 @@ impl SealedPin for AnyPin {
878foreach_pin!( 879foreach_pin!(
879 ($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => { 880 ($pin_name:ident, $port_name:ident, $port_num:expr, $pin_num:expr, $exti_ch:ident) => {
880 impl Pin for peripherals::$pin_name { 881 impl Pin for peripherals::$pin_name {
881 #[cfg(feature = "exti")] 882 }
883 #[cfg(feature = "exti")]
884 impl ExtiPin for peripherals::$pin_name {
882 type ExtiChannel = peripherals::$exti_ch; 885 type ExtiChannel = peripherals::$exti_ch;
883 } 886 }
884 impl SealedPin for peripherals::$pin_name { 887 impl SealedPin for peripherals::$pin_name {
diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs
index 9e6ba1f34..2f783bf64 100644
--- a/embassy-stm32/src/lib.rs
+++ b/embassy-stm32/src/lib.rs
@@ -153,7 +153,7 @@ pub use crate::_generated::interrupt;
153/// Macro to bind interrupts to handlers. 153/// Macro to bind interrupts to handlers.
154/// 154///
155/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`) 155/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
156/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to 156/// and implements the right [`Binding`](crate::interrupt::typelevel::Binding)s for it. You can pass this struct to drivers to
157/// prove at compile-time that the right interrupts have been bound. 157/// prove at compile-time that the right interrupts have been bound.
158/// 158///
159/// Example of how to bind one interrupt: 159/// Example of how to bind one interrupt:
@@ -180,6 +180,10 @@ pub use crate::_generated::interrupt;
180/// } 180/// }
181/// ); 181/// );
182/// ``` 182/// ```
183///
184/// Some chips collate multiple interrupt signals into a single interrupt vector. In the above example, I2C2_3 is a
185/// single vector which is activated by events and errors on both peripherals I2C2 and I2C3. Check your chip's list
186/// of interrupt vectors if you get an unexpected compile error trying to bind the standard name.
183// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`. 187// developer note: this macro can't be in `embassy-hal-internal` due to the use of `$crate`.
184#[macro_export] 188#[macro_export]
185macro_rules! bind_interrupts { 189macro_rules! bind_interrupts {
diff --git a/examples/boot/application/stm32f3/src/bin/a.rs b/examples/boot/application/stm32f3/src/bin/a.rs
index b608b2e01..da3cbf1e6 100644
--- a/examples/boot/application/stm32f3/src/bin/a.rs
+++ b/examples/boot/application/stm32f3/src/bin/a.rs
@@ -6,12 +6,18 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use panic_reset as _; 14use panic_reset as _;
14 15
16bind_interrupts!(
17 pub struct Irqs{
18 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
19});
20
15#[cfg(feature = "skip-include")] 21#[cfg(feature = "skip-include")]
16static APP_B: &[u8] = &[0, 1, 2, 3]; 22static APP_B: &[u8] = &[0, 1, 2, 3];
17#[cfg(not(feature = "skip-include"))] 23#[cfg(not(feature = "skip-include"))]
@@ -23,7 +29,7 @@ async fn main(_spawner: Spawner) {
23 let flash = Flash::new_blocking(p.FLASH); 29 let flash = Flash::new_blocking(p.FLASH);
24 let flash = Mutex::new(BlockingAsync::new(flash)); 30 let flash = Mutex::new(BlockingAsync::new(flash));
25 31
26 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 32 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
27 33
28 let mut led = Output::new(p.PA5, Level::Low, Speed::Low); 34 let mut led = Output::new(p.PA5, Level::Low, Speed::Low);
29 led.set_high(); 35 led.set_high();
diff --git a/examples/boot/application/stm32f7/src/bin/a.rs b/examples/boot/application/stm32f7/src/bin/a.rs
index 172b4c235..62f1da269 100644
--- a/examples/boot/application/stm32f7/src/bin/a.rs
+++ b/examples/boot/application/stm32f7/src/bin/a.rs
@@ -7,9 +7,10 @@ use core::cell::RefCell;
7use defmt_rtt::*; 7use defmt_rtt::*;
8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::flash::{Flash, WRITE_SIZE}; 11use embassy_stm32::flash::{Flash, WRITE_SIZE};
12use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pull, Speed};
13use embassy_stm32::{bind_interrupts, interrupt};
13use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
14use embedded_storage::nor_flash::NorFlash; 15use embedded_storage::nor_flash::NorFlash;
15use panic_reset as _; 16use panic_reset as _;
@@ -19,13 +20,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
19#[cfg(not(feature = "skip-include"))] 20#[cfg(not(feature = "skip-include"))]
20static APP_B: &[u8] = include_bytes!("../../b.bin"); 21static APP_B: &[u8] = include_bytes!("../../b.bin");
21 22
23bind_interrupts!(
24 pub struct Irqs{
25 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
26});
27
22#[embassy_executor::main] 28#[embassy_executor::main]
23async fn main(_spawner: Spawner) { 29async fn main(_spawner: Spawner) {
24 let p = embassy_stm32::init(Default::default()); 30 let p = embassy_stm32::init(Default::default());
25 let flash = Flash::new_blocking(p.FLASH); 31 let flash = Flash::new_blocking(p.FLASH);
26 let flash = Mutex::new(RefCell::new(flash)); 32 let flash = Mutex::new(RefCell::new(flash));
27 33
28 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 34 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
29 35
30 let mut led = Output::new(p.PB7, Level::Low, Speed::Low); 36 let mut led = Output::new(p.PB7, Level::Low, Speed::Low);
31 led.set_high(); 37 led.set_high();
diff --git a/examples/boot/application/stm32h7/src/bin/a.rs b/examples/boot/application/stm32h7/src/bin/a.rs
index c1b1a267a..226971e02 100644
--- a/examples/boot/application/stm32h7/src/bin/a.rs
+++ b/examples/boot/application/stm32h7/src/bin/a.rs
@@ -7,13 +7,19 @@ use core::cell::RefCell;
7use defmt_rtt::*; 7use defmt_rtt::*;
8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_stm32::{AlignedBuffer, BlockingFirmwareUpdater, FirmwareUpdaterConfig};
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::flash::{Flash, WRITE_SIZE}; 11use embassy_stm32::flash::{Flash, WRITE_SIZE};
12use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 12use embassy_stm32::gpio::{Level, Output, Pull, Speed};
13use embassy_stm32::{bind_interrupts, interrupt};
13use embassy_sync::blocking_mutex::Mutex; 14use embassy_sync::blocking_mutex::Mutex;
14use embedded_storage::nor_flash::NorFlash; 15use embedded_storage::nor_flash::NorFlash;
15use panic_reset as _; 16use panic_reset as _;
16 17
18bind_interrupts!(
19 pub struct Irqs{
20 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
21});
22
17#[cfg(feature = "skip-include")] 23#[cfg(feature = "skip-include")]
18static APP_B: &[u8] = &[0, 1, 2, 3]; 24static APP_B: &[u8] = &[0, 1, 2, 3];
19#[cfg(not(feature = "skip-include"))] 25#[cfg(not(feature = "skip-include"))]
@@ -25,7 +31,7 @@ async fn main(_spawner: Spawner) {
25 let flash = Flash::new_blocking(p.FLASH); 31 let flash = Flash::new_blocking(p.FLASH);
26 let flash = Mutex::new(RefCell::new(flash)); 32 let flash = Mutex::new(RefCell::new(flash));
27 33
28 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 34 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
29 35
30 let mut led = Output::new(p.PB14, Level::Low, Speed::Low); 36 let mut led = Output::new(p.PB14, Level::Low, Speed::Low);
31 led.set_high(); 37 led.set_high();
diff --git a/examples/boot/application/stm32l0/src/bin/a.rs b/examples/boot/application/stm32l0/src/bin/a.rs
index dcc10e5c6..0aa723eaa 100644
--- a/examples/boot/application/stm32l0/src/bin/a.rs
+++ b/examples/boot/application/stm32l0/src/bin/a.rs
@@ -6,13 +6,19 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use embassy_time::Timer; 14use embassy_time::Timer;
14use panic_reset as _; 15use panic_reset as _;
15 16
17bind_interrupts!(
18 pub struct Irqs{
19 EXTI2_3 => exti::InterruptHandler<interrupt::typelevel::EXTI2_3>;
20});
21
16#[cfg(feature = "skip-include")] 22#[cfg(feature = "skip-include")]
17static APP_B: &[u8] = &[0, 1, 2, 3]; 23static APP_B: &[u8] = &[0, 1, 2, 3];
18#[cfg(not(feature = "skip-include"))] 24#[cfg(not(feature = "skip-include"))]
@@ -24,7 +30,7 @@ async fn main(_spawner: Spawner) {
24 let flash = Flash::new_blocking(p.FLASH); 30 let flash = Flash::new_blocking(p.FLASH);
25 let flash = Mutex::new(BlockingAsync::new(flash)); 31 let flash = Mutex::new(BlockingAsync::new(flash));
26 32
27 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); 33 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs);
28 34
29 let mut led = Output::new(p.PB5, Level::Low, Speed::Low); 35 let mut led = Output::new(p.PB5, Level::Low, Speed::Low);
30 36
diff --git a/examples/boot/application/stm32l1/src/bin/a.rs b/examples/boot/application/stm32l1/src/bin/a.rs
index dcc10e5c6..7ad7046fb 100644
--- a/examples/boot/application/stm32l1/src/bin/a.rs
+++ b/examples/boot/application/stm32l1/src/bin/a.rs
@@ -6,9 +6,10 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use embassy_time::Timer; 14use embassy_time::Timer;
14use panic_reset as _; 15use panic_reset as _;
@@ -18,13 +19,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
18#[cfg(not(feature = "skip-include"))] 19#[cfg(not(feature = "skip-include"))]
19static APP_B: &[u8] = include_bytes!("../../b.bin"); 20static APP_B: &[u8] = include_bytes!("../../b.bin");
20 21
22bind_interrupts!(
23 pub struct Irqs{
24 EXTI2 => exti::InterruptHandler<interrupt::typelevel::EXTI2>;
25});
26
21#[embassy_executor::main] 27#[embassy_executor::main]
22async fn main(_spawner: Spawner) { 28async fn main(_spawner: Spawner) {
23 let p = embassy_stm32::init(Default::default()); 29 let p = embassy_stm32::init(Default::default());
24 let flash = Flash::new_blocking(p.FLASH); 30 let flash = Flash::new_blocking(p.FLASH);
25 let flash = Mutex::new(BlockingAsync::new(flash)); 31 let flash = Mutex::new(BlockingAsync::new(flash));
26 32
27 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); 33 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs);
28 34
29 let mut led = Output::new(p.PB5, Level::Low, Speed::Low); 35 let mut led = Output::new(p.PB5, Level::Low, Speed::Low);
30 36
diff --git a/examples/boot/application/stm32l4/src/bin/a.rs b/examples/boot/application/stm32l4/src/bin/a.rs
index 7f8015c04..4edd338c5 100644
--- a/examples/boot/application/stm32l4/src/bin/a.rs
+++ b/examples/boot/application/stm32l4/src/bin/a.rs
@@ -6,9 +6,10 @@ use defmt_rtt::*;
6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 6use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
7use embassy_embedded_hal::adapter::BlockingAsync; 7use embassy_embedded_hal::adapter::BlockingAsync;
8use embassy_executor::Spawner; 8use embassy_executor::Spawner;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::flash::{Flash, WRITE_SIZE}; 10use embassy_stm32::flash::{Flash, WRITE_SIZE};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::{bind_interrupts, interrupt};
12use embassy_sync::mutex::Mutex; 13use embassy_sync::mutex::Mutex;
13use panic_reset as _; 14use panic_reset as _;
14 15
@@ -17,13 +18,18 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
17#[cfg(not(feature = "skip-include"))] 18#[cfg(not(feature = "skip-include"))]
18static APP_B: &[u8] = include_bytes!("../../b.bin"); 19static APP_B: &[u8] = include_bytes!("../../b.bin");
19 20
21bind_interrupts!(
22 pub struct Irqs{
23 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
24});
25
20#[embassy_executor::main] 26#[embassy_executor::main]
21async fn main(_spawner: Spawner) { 27async fn main(_spawner: Spawner) {
22 let p = embassy_stm32::init(Default::default()); 28 let p = embassy_stm32::init(Default::default());
23 let flash = Flash::new_blocking(p.FLASH); 29 let flash = Flash::new_blocking(p.FLASH);
24 let flash = Mutex::new(BlockingAsync::new(flash)); 30 let flash = Mutex::new(BlockingAsync::new(flash));
25 31
26 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 32 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
27 33
28 let mut led = Output::new(p.PB14, Level::Low, Speed::Low); 34 let mut led = Output::new(p.PB14, Level::Low, Speed::Low);
29 led.set_high(); 35 led.set_high();
diff --git a/examples/boot/application/stm32wl/src/bin/a.rs b/examples/boot/application/stm32wl/src/bin/a.rs
index 3f381fd80..58063eb50 100644
--- a/examples/boot/application/stm32wl/src/bin/a.rs
+++ b/examples/boot/application/stm32wl/src/bin/a.rs
@@ -8,10 +8,10 @@ use defmt_rtt::*;
8use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig}; 8use embassy_boot_stm32::{AlignedBuffer, FirmwareUpdater, FirmwareUpdaterConfig};
9use embassy_embedded_hal::adapter::BlockingAsync; 9use embassy_embedded_hal::adapter::BlockingAsync;
10use embassy_executor::Spawner; 10use embassy_executor::Spawner;
11use embassy_stm32::SharedData; 11use embassy_stm32::exti::{self, ExtiInput};
12use embassy_stm32::exti::ExtiInput;
13use embassy_stm32::flash::{Flash, WRITE_SIZE}; 12use embassy_stm32::flash::{Flash, WRITE_SIZE};
14use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 13use embassy_stm32::gpio::{Level, Output, Pull, Speed};
14use embassy_stm32::{SharedData, bind_interrupts, interrupt};
15use embassy_sync::mutex::Mutex; 15use embassy_sync::mutex::Mutex;
16use panic_reset as _; 16use panic_reset as _;
17 17
@@ -20,6 +20,11 @@ static APP_B: &[u8] = &[0, 1, 2, 3];
20#[cfg(not(feature = "skip-include"))] 20#[cfg(not(feature = "skip-include"))]
21static APP_B: &[u8] = include_bytes!("../../b.bin"); 21static APP_B: &[u8] = include_bytes!("../../b.bin");
22 22
23bind_interrupts!(
24 pub struct Irqs{
25 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
26});
27
23#[unsafe(link_section = ".shared_data")] 28#[unsafe(link_section = ".shared_data")]
24static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 29static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
25 30
@@ -29,7 +34,7 @@ async fn main(_spawner: Spawner) {
29 let flash = Flash::new_blocking(p.FLASH); 34 let flash = Flash::new_blocking(p.FLASH);
30 let flash = Mutex::new(BlockingAsync::new(flash)); 35 let flash = Mutex::new(BlockingAsync::new(flash));
31 36
32 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); 37 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
33 38
34 let mut led = Output::new(p.PB9, Level::Low, Speed::Low); 39 let mut led = Output::new(p.PB9, Level::Low, Speed::Low);
35 led.set_high(); 40 led.set_high();
diff --git a/examples/stm32c0/src/bin/button_exti.rs b/examples/stm32c0/src/bin/button_exti.rs
index 34a08bbc6..9d54479da 100644
--- a/examples/stm32c0/src/bin/button_exti.rs
+++ b/examples/stm32c0/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32f0/src/bin/button_controlled_blink.rs b/examples/stm32f0/src/bin/button_controlled_blink.rs
index 0b678af01..9c7bf8a95 100644
--- a/examples/stm32f0/src/bin/button_controlled_blink.rs
+++ b/examples/stm32f0/src/bin/button_controlled_blink.rs
@@ -7,14 +7,19 @@ use core::sync::atomic::{AtomicU32, Ordering};
7 7
8use defmt::info; 8use defmt::info;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_stm32::Peri; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::exti::ExtiInput;
12use embassy_stm32::gpio::{AnyPin, Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{AnyPin, Level, Output, Pull, Speed};
12use embassy_stm32::{Peri, bind_interrupts, interrupt};
13use embassy_time::Timer; 13use embassy_time::Timer;
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16static BLINK_MS: AtomicU32 = AtomicU32::new(0); 16static BLINK_MS: AtomicU32 = AtomicU32::new(0);
17 17
18bind_interrupts!(
19 pub struct Irqs{
20 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
21});
22
18#[embassy_executor::task] 23#[embassy_executor::task]
19async fn led_task(led: Peri<'static, AnyPin>) { 24async fn led_task(led: Peri<'static, AnyPin>) {
20 // Configure the LED pin as a push pull output and obtain handler. 25 // Configure the LED pin as a push pull output and obtain handler.
@@ -37,7 +42,7 @@ async fn main(spawner: Spawner) {
37 42
38 // Configure the button pin and obtain handler. 43 // Configure the button pin and obtain handler.
39 // On the Nucleo F091RC there is a button connected to pin PC13. 44 // On the Nucleo F091RC there is a button connected to pin PC13.
40 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::None); 45 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::None, Irqs);
41 46
42 // Create and initialize a delay variable to manage delay loop 47 // Create and initialize a delay variable to manage delay loop
43 let mut del_var = 2000; 48 let mut del_var = 2000;
diff --git a/examples/stm32f0/src/bin/button_exti.rs b/examples/stm32f0/src/bin/button_exti.rs
index fd615a215..d1312e1be 100644
--- a/examples/stm32f0/src/bin/button_exti.rs
+++ b/examples/stm32f0/src/bin/button_exti.rs
@@ -3,17 +3,23 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 // Initialize and create handle for devicer peripherals 18 // Initialize and create handle for devicer peripherals
13 let p = embassy_stm32::init(Default::default()); 19 let p = embassy_stm32::init(Default::default());
14 // Configure the button pin and obtain handler. 20 // Configure the button pin and obtain handler.
15 // On the Nucleo F091RC there is a button connected to pin PC13. 21 // On the Nucleo F091RC there is a button connected to pin PC13.
16 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 22 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
17 23
18 info!("Press the USER button..."); 24 info!("Press the USER button...");
19 loop { 25 loop {
diff --git a/examples/stm32f3/src/bin/button_events.rs b/examples/stm32f3/src/bin/button_events.rs
index 99957a641..643f499ed 100644
--- a/examples/stm32f3/src/bin/button_events.rs
+++ b/examples/stm32f3/src/bin/button_events.rs
@@ -11,13 +11,19 @@
11 11
12use defmt::*; 12use defmt::*;
13use embassy_executor::Spawner; 13use embassy_executor::Spawner;
14use embassy_stm32::exti::ExtiInput; 14use embassy_stm32::exti::{self, ExtiInput};
15use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 15use embassy_stm32::gpio::{Level, Output, Pull, Speed};
16use embassy_stm32::{bind_interrupts, interrupt};
16use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; 17use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
17use embassy_sync::channel::Channel; 18use embassy_sync::channel::Channel;
18use embassy_time::{Duration, Timer, with_timeout}; 19use embassy_time::{Duration, Timer, with_timeout};
19use {defmt_rtt as _, panic_probe as _}; 20use {defmt_rtt as _, panic_probe as _};
20 21
22bind_interrupts!(
23 pub struct Irqs{
24 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
25});
26
21struct Leds<'a> { 27struct Leds<'a> {
22 leds: [Output<'a>; 8], 28 leds: [Output<'a>; 8],
23 direction: i8, 29 direction: i8,
@@ -99,7 +105,7 @@ static CHANNEL: Channel<ThreadModeRawMutex, ButtonEvent, 4> = Channel::new();
99#[embassy_executor::main] 105#[embassy_executor::main]
100async fn main(spawner: Spawner) { 106async fn main(spawner: Spawner) {
101 let p = embassy_stm32::init(Default::default()); 107 let p = embassy_stm32::init(Default::default());
102 let button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down); 108 let button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down, Irqs);
103 info!("Press the USER button..."); 109 info!("Press the USER button...");
104 let leds = [ 110 let leds = [
105 Output::new(p.PE9, Level::Low, Speed::Low), 111 Output::new(p.PE9, Level::Low, Speed::Low),
diff --git a/examples/stm32f3/src/bin/button_exti.rs b/examples/stm32f3/src/bin/button_exti.rs
index a55530e0e..1df4735ca 100644
--- a/examples/stm32f3/src/bin/button_exti.rs
+++ b/examples/stm32f3/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down); 21 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32f4/src/bin/button_exti.rs b/examples/stm32f4/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32f4/src/bin/button_exti.rs
+++ b/examples/stm32f4/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32f4/src/bin/eth_w5500.rs b/examples/stm32f4/src/bin/eth_w5500.rs
index 0adcda614..e274d2a66 100644
--- a/examples/stm32f4/src/bin/eth_w5500.rs
+++ b/examples/stm32f4/src/bin/eth_w5500.rs
@@ -7,14 +7,14 @@ use embassy_net::tcp::TcpSocket;
7use embassy_net::{Ipv4Address, StackResources}; 7use embassy_net::{Ipv4Address, StackResources};
8use embassy_net_wiznet::chip::W5500; 8use embassy_net_wiznet::chip::W5500;
9use embassy_net_wiznet::{Device, Runner, State}; 9use embassy_net_wiznet::{Device, Runner, State};
10use embassy_stm32::exti::ExtiInput; 10use embassy_stm32::exti::{self, ExtiInput};
11use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 11use embassy_stm32::gpio::{Level, Output, Pull, Speed};
12use embassy_stm32::mode::Async; 12use embassy_stm32::mode::Async;
13use embassy_stm32::rng::Rng; 13use embassy_stm32::rng::Rng;
14use embassy_stm32::spi::Spi; 14use embassy_stm32::spi::Spi;
15use embassy_stm32::spi::mode::Master; 15use embassy_stm32::spi::mode::Master;
16use embassy_stm32::time::Hertz; 16use embassy_stm32::time::Hertz;
17use embassy_stm32::{Config, bind_interrupts, peripherals, rng, spi}; 17use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, rng, spi};
18use embassy_time::{Delay, Timer}; 18use embassy_time::{Delay, Timer};
19use embedded_hal_bus::spi::ExclusiveDevice; 19use embedded_hal_bus::spi::ExclusiveDevice;
20use embedded_io_async::Write; 20use embedded_io_async::Write;
@@ -23,6 +23,7 @@ use {defmt_rtt as _, panic_probe as _};
23 23
24bind_interrupts!(struct Irqs { 24bind_interrupts!(struct Irqs {
25 HASH_RNG => rng::InterruptHandler<peripherals::RNG>; 25 HASH_RNG => rng::InterruptHandler<peripherals::RNG>;
26 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
26}); 27});
27 28
28type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>; 29type EthernetSPI = ExclusiveDevice<Spi<'static, Async, Master>, Output<'static>, Delay>;
@@ -75,7 +76,7 @@ async fn main(spawner: Spawner) -> ! {
75 let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); 76 let cs = Output::new(p.PA4, Level::High, Speed::VeryHigh);
76 let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay)); 77 let spi = unwrap!(ExclusiveDevice::new(spi, cs, Delay));
77 78
78 let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up); 79 let w5500_int = ExtiInput::new(p.PB0, p.EXTI0, Pull::Up, Irqs);
79 let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh); 80 let w5500_reset = Output::new(p.PB1, Level::High, Speed::VeryHigh);
80 81
81 let mac_addr = [0x02, 234, 3, 4, 82, 231]; 82 let mac_addr = [0x02, 234, 3, 4, 82, 231];
diff --git a/examples/stm32f4/src/bin/usb_hid_keyboard.rs b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
index 9971e43f5..2d834dcf7 100644
--- a/examples/stm32f4/src/bin/usb_hid_keyboard.rs
+++ b/examples/stm32f4/src/bin/usb_hid_keyboard.rs
@@ -6,11 +6,11 @@ use core::sync::atomic::{AtomicBool, AtomicU8, Ordering};
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_futures::join::join; 8use embassy_futures::join::join;
9use embassy_stm32::exti::ExtiInput; 9use embassy_stm32::exti::{self, ExtiInput};
10use embassy_stm32::gpio::Pull; 10use embassy_stm32::gpio::Pull;
11use embassy_stm32::time::Hertz; 11use embassy_stm32::time::Hertz;
12use embassy_stm32::usb::Driver; 12use embassy_stm32::usb::Driver;
13use embassy_stm32::{Config, bind_interrupts, peripherals, usb}; 13use embassy_stm32::{Config, bind_interrupts, interrupt, peripherals, usb};
14use embassy_usb::class::hid::{ 14use embassy_usb::class::hid::{
15 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State, 15 HidBootProtocol, HidProtocolMode, HidReaderWriter, HidSubclass, ReportId, RequestHandler, State,
16}; 16};
@@ -21,6 +21,7 @@ use {defmt_rtt as _, panic_probe as _};
21 21
22bind_interrupts!(struct Irqs { 22bind_interrupts!(struct Irqs {
23 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>; 23 OTG_FS => usb::InterruptHandler<peripherals::USB_OTG_FS>;
24 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
24}); 25});
25 26
26static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8); 27static HID_PROTOCOL_MODE: AtomicU8 = AtomicU8::new(HidProtocolMode::Boot as u8);
@@ -123,7 +124,7 @@ async fn main(_spawner: Spawner) {
123 124
124 let (reader, mut writer) = hid.split(); 125 let (reader, mut writer) = hid.split();
125 126
126 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 127 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
127 128
128 // Do stuff with the class! 129 // Do stuff with the class!
129 let in_fut = async { 130 let in_fut = async {
diff --git a/examples/stm32f7/src/bin/button_exti.rs b/examples/stm32f7/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32f7/src/bin/button_exti.rs
+++ b/examples/stm32f7/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32g0/src/bin/button_exti.rs b/examples/stm32g0/src/bin/button_exti.rs
index 34a08bbc6..9d54479da 100644
--- a/examples/stm32g0/src/bin/button_exti.rs
+++ b/examples/stm32g0/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32g4/src/bin/button_exti.rs b/examples/stm32g4/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32g4/src/bin/button_exti.rs
+++ b/examples/stm32g4/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32h5/src/bin/button_exti.rs b/examples/stm32h5/src/bin/button_exti.rs
index 2a546dac5..220f89228 100644
--- a/examples/stm32h5/src/bin/button_exti.rs
+++ b/examples/stm32h5/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32h7/src/bin/button_exti.rs b/examples/stm32h7/src/bin/button_exti.rs
index 2a546dac5..e7e1549a8 100644
--- a/examples/stm32h7/src/bin/button_exti.rs
+++ b/examples/stm32h7/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32h7rs/src/bin/button_exti.rs b/examples/stm32h7rs/src/bin/button_exti.rs
index 34a08bbc6..d63290d42 100644
--- a/examples/stm32h7rs/src/bin/button_exti.rs
+++ b/examples/stm32h7rs/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32l0/src/bin/button_exti.rs b/examples/stm32l0/src/bin/button_exti.rs
index 7ff4a7d52..a118c7a5a 100644
--- a/examples/stm32l0/src/bin/button_exti.rs
+++ b/examples/stm32l0/src/bin/button_exti.rs
@@ -3,17 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::Config; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::exti::ExtiInput;
8use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{Config, bind_interrupts, interrupt};
9use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
10 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI2_3 => exti::InterruptHandler<interrupt::typelevel::EXTI2_3>;
14});
15
11#[embassy_executor::main] 16#[embassy_executor::main]
12async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
13 let config = Config::default(); 18 let config = Config::default();
14 let p = embassy_stm32::init(config); 19 let p = embassy_stm32::init(config);
15 20
16 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up); 21 let mut button = ExtiInput::new(p.PB2, p.EXTI2, Pull::Up, Irqs);
17 22
18 info!("Press the USER button..."); 23 info!("Press the USER button...");
19 24
diff --git a/examples/stm32l4/src/bin/button_exti.rs b/examples/stm32l4/src/bin/button_exti.rs
index 34a08bbc6..c84b11dab 100644
--- a/examples/stm32l4/src/bin/button_exti.rs
+++ b/examples/stm32l4/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
index 0dbf515cf..8f2510cdc 100644
--- a/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
+++ b/examples/stm32l4/src/bin/spe_adin1110_http_server.rs
@@ -24,6 +24,7 @@ use embassy_futures::yield_now;
24use embassy_net::tcp::TcpSocket; 24use embassy_net::tcp::TcpSocket;
25use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4}; 25use embassy_net::{Ipv4Address, Ipv4Cidr, Stack, StackResources, StaticConfigV4};
26use embassy_net_adin1110::{ADIN1110, Device, Runner}; 26use embassy_net_adin1110::{ADIN1110, Device, Runner};
27use embassy_stm32::exti::ExtiInput;
27use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed}; 28use embassy_stm32::gpio::{Input, Level, Output, Pull, Speed};
28use embassy_stm32::i2c::{self, Config as I2C_Config, I2c}; 29use embassy_stm32::i2c::{self, Config as I2C_Config, I2c};
29use embassy_stm32::mode::Async; 30use embassy_stm32::mode::Async;
@@ -31,7 +32,7 @@ use embassy_stm32::rng::{self, Rng};
31use embassy_stm32::spi::mode::Master; 32use embassy_stm32::spi::mode::Master;
32use embassy_stm32::spi::{Config as SPI_Config, Spi}; 33use embassy_stm32::spi::{Config as SPI_Config, Spi};
33use embassy_stm32::time::Hertz; 34use embassy_stm32::time::Hertz;
34use embassy_stm32::{bind_interrupts, exti, pac, peripherals}; 35use embassy_stm32::{bind_interrupts, exti, interrupt, pac, peripherals};
35use embassy_time::{Delay, Duration, Ticker, Timer}; 36use embassy_time::{Delay, Duration, Ticker, Timer};
36use embedded_hal_async::i2c::I2c as I2cBus; 37use embedded_hal_async::i2c::I2c as I2cBus;
37use embedded_hal_bus::spi::ExclusiveDevice; 38use embedded_hal_bus::spi::ExclusiveDevice;
@@ -45,6 +46,7 @@ bind_interrupts!(struct Irqs {
45 I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>; 46 I2C3_EV => i2c::EventInterruptHandler<peripherals::I2C3>;
46 I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>; 47 I2C3_ER => i2c::ErrorInterruptHandler<peripherals::I2C3>;
47 RNG => rng::InterruptHandler<peripherals::RNG>; 48 RNG => rng::InterruptHandler<peripherals::RNG>;
49 EXTI15_10 => exti::InterruptHandler<interrupt::typelevel::EXTI15_10>;
48}); 50});
49 51
50// Basic settings 52// Basic settings
@@ -125,7 +127,7 @@ async fn main(spawner: Spawner) {
125 let spe_cfg1 = Input::new(dp.PC9, Pull::None); 127 let spe_cfg1 = Input::new(dp.PC9, Pull::None);
126 let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low); 128 let _spe_ts_capt = Output::new(dp.PC6, Level::Low, Speed::Low);
127 129
128 let spe_int = exti::ExtiInput::new(dp.PB11, dp.EXTI11, Pull::None); 130 let spe_int = ExtiInput::new(dp.PB11, dp.EXTI11, Pull::None, Irqs);
129 131
130 let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High); 132 let spe_spi_cs_n = Output::new(dp.PB12, Level::High, Speed::High);
131 let spe_spi_sclk = dp.PB13; 133 let spe_spi_sclk = dp.PB13;
diff --git a/examples/stm32l4/src/bin/spi_dma.rs b/examples/stm32l4/src/bin/spi_dma.rs
index 946a759b1..970a0c608 100644
--- a/examples/stm32l4/src/bin/spi_dma.rs
+++ b/examples/stm32l4/src/bin/spi_dma.rs
@@ -34,8 +34,8 @@ async fn main(_spawner: Spawner) {
34 info!("waiting for ready"); 34 info!("waiting for ready");
35 } 35 }
36 36
37 let write = [0x0A; 10]; 37 let write = [0x0Au8; 10];
38 let mut read = [0; 10]; 38 let mut read = [0u8; 10];
39 cs.set_low(); 39 cs.set_low();
40 spi.transfer(&mut read, &write).await.ok(); 40 spi.transfer(&mut read, &write).await.ok();
41 cs.set_high(); 41 cs.set_high();
diff --git a/examples/stm32l5/src/bin/button_exti.rs b/examples/stm32l5/src/bin/button_exti.rs
index e6639d22b..225a7b3fd 100644
--- a/examples/stm32l5/src/bin/button_exti.rs
+++ b/examples/stm32l5/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Down, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32n6/src/bin/blinky.rs b/examples/stm32n6/src/bin/blinky.rs
index 018967f08..a8baf16af 100644
--- a/examples/stm32n6/src/bin/blinky.rs
+++ b/examples/stm32n6/src/bin/blinky.rs
@@ -3,11 +3,17 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::{Level, Output, Pull, Speed}; 7use embassy_stm32::gpio::{Level, Output, Pull, Speed};
8use embassy_stm32::{bind_interrupts, interrupt};
8use embassy_time::Timer; 9use embassy_time::Timer;
9use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
10 11
12bind_interrupts!(
13 pub struct Irqs{
14 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
15});
16
11#[embassy_executor::task] 17#[embassy_executor::task]
12async fn button_task(mut p: ExtiInput<'static>) { 18async fn button_task(mut p: ExtiInput<'static>) {
13 loop { 19 loop {
@@ -22,7 +28,7 @@ async fn main(spawner: Spawner) {
22 info!("Hello World!"); 28 info!("Hello World!");
23 29
24 let mut led = Output::new(p.PG10, Level::High, Speed::Low); 30 let mut led = Output::new(p.PG10, Level::High, Speed::Low);
25 let button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 31 let button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
26 32
27 spawner.spawn(button_task(button).unwrap()); 33 spawner.spawn(button_task(button).unwrap());
28 34
diff --git a/examples/stm32u0/src/bin/button_exti.rs b/examples/stm32u0/src/bin/button_exti.rs
index 34a08bbc6..9d54479da 100644
--- a/examples/stm32u0/src/bin/button_exti.rs
+++ b/examples/stm32u0/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4_15 => exti::InterruptHandler<interrupt::typelevel::EXTI4_15>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wb/src/bin/button_exti.rs b/examples/stm32wb/src/bin/button_exti.rs
index 2871fd55f..3c58eb556 100644
--- a/examples/stm32wb/src/bin/button_exti.rs
+++ b/examples/stm32wb/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI4 => exti::InterruptHandler<interrupt::typelevel::EXTI4>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC4, p.EXTI4, Pull::Up); 21 let mut button = ExtiInput::new(p.PC4, p.EXTI4, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wba/src/bin/button_exti.rs b/examples/stm32wba/src/bin/button_exti.rs
index 34a08bbc6..d63290d42 100644
--- a/examples/stm32wba/src/bin/button_exti.rs
+++ b/examples/stm32wba/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wba6/src/bin/button_exti.rs b/examples/stm32wba6/src/bin/button_exti.rs
index 34a08bbc6..d63290d42 100644
--- a/examples/stm32wba6/src/bin/button_exti.rs
+++ b/examples/stm32wba6/src/bin/button_exti.rs
@@ -3,16 +3,22 @@
3 3
4use defmt::*; 4use defmt::*;
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_stm32::exti::ExtiInput; 6use embassy_stm32::exti::{self, ExtiInput};
7use embassy_stm32::gpio::Pull; 7use embassy_stm32::gpio::Pull;
8use embassy_stm32::{bind_interrupts, interrupt};
8use {defmt_rtt as _, panic_probe as _}; 9use {defmt_rtt as _, panic_probe as _};
9 10
11bind_interrupts!(
12 pub struct Irqs{
13 EXTI13 => exti::InterruptHandler<interrupt::typelevel::EXTI13>;
14});
15
10#[embassy_executor::main] 16#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
12 let p = embassy_stm32::init(Default::default()); 18 let p = embassy_stm32::init(Default::default());
13 info!("Hello World!"); 19 info!("Hello World!");
14 20
15 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up); 21 let mut button = ExtiInput::new(p.PC13, p.EXTI13, Pull::Up, Irqs);
16 22
17 info!("Press the USER button..."); 23 info!("Press the USER button...");
18 24
diff --git a/examples/stm32wl/src/bin/button_exti.rs b/examples/stm32wl/src/bin/button_exti.rs
index 953b13bac..2bb39c709 100644
--- a/examples/stm32wl/src/bin/button_exti.rs
+++ b/examples/stm32wl/src/bin/button_exti.rs
@@ -5,11 +5,16 @@ use core::mem::MaybeUninit;
5 5
6use defmt::*; 6use defmt::*;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::SharedData; 8use embassy_stm32::exti::{self, ExtiInput};
9use embassy_stm32::exti::ExtiInput;
10use embassy_stm32::gpio::Pull; 9use embassy_stm32::gpio::Pull;
10use embassy_stm32::{SharedData, bind_interrupts, interrupt};
11use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
12 12
13bind_interrupts!(
14 pub struct Irqs{
15 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
16});
17
13#[unsafe(link_section = ".shared_data")] 18#[unsafe(link_section = ".shared_data")]
14static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit(); 19static SHARED_DATA: MaybeUninit<SharedData> = MaybeUninit::uninit();
15 20
@@ -18,7 +23,7 @@ async fn main(_spawner: Spawner) {
18 let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA); 23 let p = embassy_stm32::init_primary(Default::default(), &SHARED_DATA);
19 info!("Hello World!"); 24 info!("Hello World!");
20 25
21 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); 26 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
22 27
23 info!("Press the USER button..."); 28 info!("Press the USER button...");
24 29
diff --git a/examples/stm32wle5/src/bin/button_exti.rs b/examples/stm32wle5/src/bin/button_exti.rs
index 878eca7d0..f248b6147 100644
--- a/examples/stm32wle5/src/bin/button_exti.rs
+++ b/examples/stm32wle5/src/bin/button_exti.rs
@@ -5,12 +5,17 @@ use defmt::*;
5#[cfg(feature = "defmt-rtt")] 5#[cfg(feature = "defmt-rtt")]
6use defmt_rtt as _; 6use defmt_rtt as _;
7use embassy_executor::Spawner; 7use embassy_executor::Spawner;
8use embassy_stm32::exti::ExtiInput; 8use embassy_stm32::exti::{self, ExtiInput};
9use embassy_stm32::gpio::Pull; 9use embassy_stm32::gpio::Pull;
10use embassy_stm32::low_power; 10use embassy_stm32::{bind_interrupts, interrupt, low_power};
11use panic_probe as _; 11use panic_probe as _;
12use static_cell::StaticCell; 12use static_cell::StaticCell;
13 13
14bind_interrupts!(
15 pub struct Irqs{
16 EXTI0 => exti::InterruptHandler<interrupt::typelevel::EXTI0>;
17});
18
14#[embassy_executor::main(executor = "low_power::Executor")] 19#[embassy_executor::main(executor = "low_power::Executor")]
15async fn async_main(_spawner: Spawner) { 20async fn async_main(_spawner: Spawner) {
16 let mut config = embassy_stm32::Config::default(); 21 let mut config = embassy_stm32::Config::default();
@@ -64,7 +69,7 @@ async fn async_main(_spawner: Spawner) {
64 69
65 info!("Hello World!"); 70 info!("Hello World!");
66 71
67 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up); 72 let mut button = ExtiInput::new(p.PA0, p.EXTI0, Pull::Up, Irqs);
68 73
69 info!("Press the USER button..."); 74 info!("Press the USER button...");
70 75