Skip to content

Commit 35949ff

Browse files
committed
Move EXTI management to SysCfg module
1 parent 7510c39 commit 35949ff

File tree

5 files changed

+78
-52
lines changed

5 files changed

+78
-52
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
9191
- `triggered_events` returns an `EnumSet` of triggered events.
9292
- Change gpio interrupt API to be more in line with the new serial interrupt
9393
API. ([#262])
94+
- Move EXTI interrupt management to SysCfg. ([#262])
95+
- Becuase EXTI interrupt confiugration could cancel out, make it more obvious
96+
in that SysCfg manages the interrupts, not the pin itself.
97+
Change `make_interrupt_source()` to `SysCfg::select_exti_interrupt_source()`.
9498

9599
## [v0.7.0] - 2021-06-18
96100

examples/gpio_interrupts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn main() -> ! {
4444
let mut user_button = gpioa
4545
.pa0
4646
.into_pull_down_input(&mut gpioa.moder, &mut gpioa.pupdr);
47-
user_button.make_interrupt_source(&mut syscfg);
47+
syscfg.select_exti_interrupt_source(&user_button);
4848
user_button.trigger_on_edge(&mut exti, Edge::Rising);
4949
user_button.enable_interrupt(&mut exti);
5050
let interrupt_num = user_button.nvic(); // hal::pac::Interrupt::EXTI0

src/gpio.rs

Lines changed: 17 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ use crate::{
6666
hal::digital::v2::OutputPin,
6767
pac::{Interrupt, EXTI},
6868
rcc::AHB,
69-
syscfg::SysCfg,
7069
Toggle,
7170
};
7271

@@ -291,8 +290,8 @@ pub enum Edge {
291290

292291
/// Generic pin
293292
pub struct Pin<Gpio, Index, Mode> {
294-
gpio: Gpio,
295-
index: Index,
293+
pub(crate) gpio: Gpio,
294+
pub(crate) index: Index,
296295
_mode: PhantomData<Mode>,
297296
}
298297

@@ -310,17 +309,6 @@ impl<Gpio, Index, Mode> crate::private::Sealed for Pin<Gpio, Index, Mode> {}
310309
/// [examples/gpio_erased.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.7.0/examples/gpio_erased.rs
311310
pub type PXx<Mode> = Pin<Gpiox, Ux, Mode>;
312311

313-
/// Modify specific index of array-like register
314-
macro_rules! modify_at {
315-
($reg:expr, $bitwidth:expr, $index:expr, $value:expr) => {
316-
$reg.modify(|r, w| {
317-
let mask = !(u32::MAX >> (32 - $bitwidth) << ($bitwidth * $index));
318-
let value = $value << ($bitwidth * $index);
319-
w.bits(r.bits() & mask | value)
320-
});
321-
};
322-
}
323-
324312
impl<Gpio, Mode, const X: u8> Pin<Gpio, U<X>, Mode> {
325313
/// Erases the pin number from the type
326314
///
@@ -593,33 +581,10 @@ where
593581
#[cfg(not(feature = "svd-f373"))]
594582
5..=9 => Interrupt::EXTI9_5,
595583
10..=15 => Interrupt::EXTI15_10,
596-
_ => unreachable!(),
584+
_ => crate::unreachable!(),
597585
}
598586
}
599587

600-
/// Make corresponding EXTI line sensitive to this pin.
601-
///
602-
/// # Note
603-
///
604-
/// Only **one** Pin index of all banks can be activated
605-
/// for interrupts simultainously.
606-
///
607-
/// For example, only on of `PA1`, `PB1`, `PC1`, ... can be activated.
608-
pub fn make_interrupt_source(&mut self, syscfg: &mut SysCfg) {
609-
const BITWIDTH: u8 = 4;
610-
let index = self.index.index() % 4;
611-
let extigpionr = self.gpio.port_index() as u32;
612-
match self.index.index() {
613-
// SAFETY: These are all unguarded writes directly to the register,
614-
// without leveraging the safety of stm32f3 generated values.
615-
0..=3 => unsafe { modify_at!(syscfg.exticr1, BITWIDTH, index, extigpionr) },
616-
4..=7 => unsafe { modify_at!(syscfg.exticr2, BITWIDTH, index, extigpionr) },
617-
8..=11 => unsafe { modify_at!(syscfg.exticr3, BITWIDTH, index, extigpionr) },
618-
12..=15 => unsafe { modify_at!(syscfg.exticr4, BITWIDTH, index, extigpionr) },
619-
_ => unreachable!(),
620-
};
621-
}
622-
623588
/// Generate interrupt on rising edge, falling edge, or both
624589
pub fn trigger_on_edge(&mut self, exti: &mut EXTI, edge: Edge) {
625590
const BITWIDTH: u8 = 1;
@@ -631,15 +596,17 @@ where
631596
};
632597
// SAFETY: Unguarded write to the register, but behind a &mut
633598
unsafe {
634-
modify_at!(reg_for_cpu!(exti, rtsr), BITWIDTH, index, rise);
635-
modify_at!(reg_for_cpu!(exti, ftsr), BITWIDTH, index, fall);
599+
crate::modify_at!(reg_for_cpu!(exti, rtsr), BITWIDTH, index, rise);
600+
crate::modify_at!(reg_for_cpu!(exti, ftsr), BITWIDTH, index, fall);
636601
}
637602
}
638603

639604
/// Configure external interrupts from this pin
640605
///
606+
/// # Note
607+
///
641608
/// Remeber to also configure the interrupt pin on
642-
/// the SysCfg site, with [`Pin::make_interrupt_source()`]
609+
/// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`]
643610
pub fn configure_interrupt(&mut self, exti: &mut EXTI, enable: impl Into<Toggle>) {
644611
const BITWIDTH: u8 = 1;
645612

@@ -649,10 +616,15 @@ where
649616
let index = self.index.index();
650617
let value = u32::from(enable);
651618
// SAFETY: Unguarded write to the register, but behind a &mut
652-
unsafe { modify_at!(reg_for_cpu!(exti, imr), BITWIDTH, index, value) };
619+
unsafe { crate::modify_at!(reg_for_cpu!(exti, imr), BITWIDTH, index, value) };
653620
}
654621

655622
/// Enable external interrupts from this pin
623+
///
624+
/// # Note
625+
///
626+
/// Remeber to also configure the interrupt pin on
627+
/// the SysCfg site, with [`crate::syscfg::SysCfg::select_exti_interrupt_source()`]
656628
pub fn enable_interrupt(&mut self, exti: &mut EXTI) {
657629
self.configure_interrupt(exti, Toggle::On)
658630
}
@@ -772,7 +744,7 @@ macro_rules! r_trait {
772744
#[inline]
773745
fn $fn(&mut self, i: u8) {
774746
let value = $gpioy::$xr::$enum::$VARIANT as u32;
775-
unsafe { modify_at!((*$GPIOX::ptr()).$xr, $bitwidth, i, value) };
747+
unsafe { crate::modify_at!((*$GPIOX::ptr()).$xr, $bitwidth, i, value) };
776748
}
777749
)+
778750
}
@@ -913,7 +885,7 @@ macro_rules! gpio {
913885
#[inline]
914886
fn afx(&mut self, i: u8, x: u8) {
915887
const BITWIDTH: u8 = 4;
916-
unsafe { modify_at!((*$GPIOX::ptr()).afrh, BITWIDTH, i - 8, x as u32) };
888+
unsafe { crate::modify_at!((*$GPIOX::ptr()).afrh, BITWIDTH, i - 8, x as u32) };
917889
}
918890
}
919891

@@ -924,7 +896,7 @@ macro_rules! gpio {
924896
#[inline]
925897
fn afx(&mut self, i: u8, x: u8) {
926898
const BITWIDTH: u8 = 4;
927-
unsafe { modify_at!((*$GPIOX::ptr()).afrl, BITWIDTH, i, x as u32) };
899+
unsafe { crate::modify_at!((*$GPIOX::ptr()).afrl, BITWIDTH, i, x as u32) };
928900
}
929901
}
930902

src/lib.rs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,26 @@ pub use nb::block;
9191

9292
pub use embedded_time as time;
9393

94+
mod private {
95+
/// Private sealed trait to seal all GPIO implementations
96+
/// which do implement peripheral functionalities.
97+
pub trait Sealed {}
98+
99+
/// Modify specific index of array-like register
100+
macro_rules! modify_at {
101+
($reg:expr, $bitwidth:expr, $index:expr, $value:expr) => {
102+
$reg.modify(|r, w| {
103+
let mask = !(u32::MAX >> (32 - $bitwidth) << ($bitwidth * $index));
104+
let value = $value << ($bitwidth * $index);
105+
w.bits(r.bits() & mask | value)
106+
});
107+
};
108+
}
109+
pub(crate) use modify_at;
110+
}
111+
112+
pub(crate) use private::modify_at;
113+
94114
/// Peripheral access
95115
#[cfg(feature = "svd-f301")]
96116
pub use stm32f3::stm32f301 as pac;
@@ -196,12 +216,6 @@ cfg_if! {
196216
}
197217
}
198218

199-
mod private {
200-
/// Private sealed trait to seal all GPIO implementations
201-
/// which do implement peripheral functionalities.
202-
pub trait Sealed {}
203-
}
204-
205219
/// Toggle something on or off.
206220
///
207221
/// Convenience enum and wrapper around a bool, which more explicit about the intention to enable

src/syscfg.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use core::ops::Deref;
44

5+
use crate::gpio::{marker, Pin};
56
use crate::{pac::SYSCFG, rcc::APB2};
67

78
/// Extension trait that constrains the `SYSCFG` peripheral
@@ -39,3 +40,38 @@ impl Deref for SysCfg {
3940
&self.0
4041
}
4142
}
43+
44+
impl SysCfg {
45+
/// Make corresponding EXTI (external interrupt) line sensitive to the selected pin.
46+
///
47+
/// # Note
48+
///
49+
/// Only **one** Pin index of all banks can be activated
50+
/// for interrupts at the same time.
51+
///
52+
/// This means, that only on of `PA1`, `PB1`, `PC1`, ... can be activated.
53+
///
54+
/// For example, if first [`crate::gpio::gpioa::PA1`] and than [`crate::gpio::gpiob::PB1`]
55+
/// would be configured, the former configuration would be overwritten.
56+
///
57+
/// But configuring `PA1` and and `PB2` works!
58+
#[doc(alias = "enable_interrupt")]
59+
pub fn select_exti_interrupt_source<Gpio, Index, Mode>(&mut self, pin: &Pin<Gpio, Index, Mode>)
60+
where
61+
Gpio: marker::Gpio,
62+
Index: marker::Index,
63+
{
64+
const BITWIDTH: u8 = 4;
65+
let index = pin.index.index() % 4;
66+
let extigpionr = pin.gpio.port_index() as u32;
67+
match pin.index.index() {
68+
// SAFETY: These are all unguarded writes directly to the register,
69+
// without leveraging the safety of stm32f3 generated values.
70+
0..=3 => unsafe { crate::modify_at!(self.exticr1, BITWIDTH, index, extigpionr) },
71+
4..=7 => unsafe { crate::modify_at!(self.exticr2, BITWIDTH, index, extigpionr) },
72+
8..=11 => unsafe { crate::modify_at!(self.exticr3, BITWIDTH, index, extigpionr) },
73+
12..=15 => unsafe { crate::modify_at!(self.exticr4, BITWIDTH, index, extigpionr) },
74+
_ => crate::unreachable!(),
75+
};
76+
}
77+
}

0 commit comments

Comments
 (0)