Skip to content

Commit

Permalink
changed(eic)!: EIC pins no longer need to take a reference to the und…
Browse files Browse the repository at this point in the history
…erlying peripheral (#635)
  • Loading branch information
jbeaurivage authored and sajattack committed Nov 25, 2024
1 parent 4782ad2 commit b1b1087
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 101 deletions.
3 changes: 1 addition & 2 deletions hal/src/gpio/dynpin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
//! Users may try to convert value-level pins back to their type-level
//! equivalents. However, this option is fallible, because the compiler cannot
//! guarantee the pin has the correct ID or is in the correct mode at
//! compile-time. Use [`TryFrom`](core::convert::TryFrom)/
//! [`TryInto`](core::convert::TryInto) for this conversion.
//! compile-time. Use [`TryFrom`]/[`TryInto`] for this conversion.
//!
//! ```
//! // Convert to a `DynPin`
Expand Down
16 changes: 8 additions & 8 deletions hal/src/gpio/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
//! struct.
//!
//! To create the [`Pins`] struct, users must supply the PAC
//! [`Port`](crate::pac::Port) peripheral. The [`Pins`] struct takes
//! [`Port`] peripheral. The [`Pins`] struct takes
//! ownership of the [`Port`] and provides the corresponding pins. Each [`Pin`]
//! within the [`Pins`] struct can be moved out and used individually.
//!
Expand Down Expand Up @@ -123,7 +123,7 @@ use super::reg::RegisterInterface;
///
/// [type-level enum]: crate::typelevel#type-level-enum
pub trait DisabledConfig: Sealed {
/// Corresponding [`DynDisabled`](super::DynDisabled)
/// Corresponding [`DynDisabled`]
const DYN: DynDisabled;
}

Expand Down Expand Up @@ -181,7 +181,7 @@ pub type Reset = FloatingDisabled;
///
/// [type-level enum]: crate::typelevel#type-level-enum
pub trait InputConfig: Sealed {
/// Corresponding [`DynInput`](super::DynInput)
/// Corresponding [`DynInput`]
const DYN: DynInput;
}

Expand Down Expand Up @@ -220,7 +220,7 @@ pub type PullUpInput = Input<PullUp>;

/// Type-level `enum` for Interrupt configurations
pub trait InterruptConfig: Sealed {
/// Corresponding [`DynInterrupt`](super::DynInterrupt)
/// Corresponding [`DynInterrupt`]
const DYN: DynInterrupt;
}

Expand Down Expand Up @@ -264,7 +264,7 @@ pub type PullUpInterrupt = Interrupt<PullUp>;
///
/// [type-level enum]: crate::typelevel#type-level-enum
pub trait OutputConfig: Sealed {
/// Corresponding [`DynOutput`](super::DynOutput)
/// Corresponding [`DynOutput`]
const DYN: DynOutput;
}

Expand Down Expand Up @@ -309,7 +309,7 @@ pub type ReadableOutput = Output<Readable>;
///
/// [type-level enum]: crate::typelevel#type-level-enum
pub trait AlternateConfig: Sealed {
/// Corresponding [`DynAlternate`](super::DynAlternate)
/// Corresponding [`DynAlternate`]
const DYN: DynAlternate;
}

Expand Down Expand Up @@ -368,7 +368,7 @@ impl<C: AlternateConfig> Sealed for Alternate<C> {}
///
/// [type-level enum]: crate::typelevel#type-level-enum
pub trait PinMode: Sealed {
/// Corresponding [`DynPinMode`](super::DynPinMode)
/// Corresponding [`DynPinMode`]
const DYN: DynPinMode;
}

Expand Down Expand Up @@ -404,7 +404,7 @@ impl<C: AlternateConfig> PinMode for Alternate<C> {
///
/// [type-level enum]: crate::typelevel#type-level-enum
pub trait PinId: Sealed {
/// Corresponding [`DynPinId`](super::DynPinId)
/// Corresponding [`DynPinId`]
const DYN: DynPinId;
}

Expand Down
3 changes: 1 addition & 2 deletions hal/src/peripherals/eic/d11/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::clock::EicClock;
use crate::pac;
use crate::{clock::EicClock, pac};

pub mod pin;

Expand Down
53 changes: 30 additions & 23 deletions hal/src/peripherals/eic/d11/pin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use crate::gpio::{
};
use crate::pac;
use atsamd_hal_macros::hal_cfg;
use core::mem::ManuallyDrop;

use super::EIC;

Expand All @@ -18,13 +19,13 @@ pub trait EicPin {
type PullDown;

/// Configure a pin as a floating external interrupt
fn into_floating_ei(self) -> Self::Floating;
fn into_floating_ei(self, eic: &mut EIC) -> Self::Floating;

/// Configure a pin as pulled-up external interrupt
fn into_pull_up_ei(self) -> Self::PullUp;
fn into_pull_up_ei(self, eic: &mut EIC) -> Self::PullUp;

/// Configure a pin as pulled-down external interrupt
fn into_pull_down_ei(self) -> Self::PullDown;
fn into_pull_down_ei(self, eic: &mut EIC) -> Self::PullDown;
}

pub type Sense = pac::eic::config::Sense0select;
Expand Down Expand Up @@ -56,6 +57,7 @@ crate::paste::item! {
where
GPIO: AnyPin,
{
eic: ManuallyDrop<EIC>,
_pin: Pin<GPIO::Id, GPIO::Mode>,
}

Expand All @@ -66,33 +68,38 @@ crate::paste::item! {
/// Construct pad from the appropriate pin in any mode.
/// You may find it more convenient to use the `into_pad` trait
/// and avoid referencing the pad type.
pub fn new(pin: GPIO) -> Self {
pub fn new(pin: GPIO, eic: &mut super::EIC) -> [<$PadType $num>]<GPIO> {
let eic = unsafe {
ManuallyDrop::new(core::ptr::read(eic as *const _))
};

[<$PadType $num>]{
_pin:pin.into()
_pin:pin.into(),
eic,
}
}

/// Configure the eic with options for this external interrupt
pub fn enable_event(&mut self, eic: &mut EIC) {
eic.eic.evctrl().modify(|_, w| {
pub fn enable_event(&mut self) {
self.eic.eic.evctrl().modify(|_, w| {
w.[<extinteo $num>]().set_bit()
});
}

pub fn enable_interrupt(&mut self, eic: &mut EIC) {
eic.eic.intenset().write(|w| {
pub fn enable_interrupt(&mut self) {
self.eic.eic.intenset().write(|w| {
w.[<extint $num>]().set_bit()
});
}

pub fn enable_interrupt_wake(&mut self, eic: &mut EIC) {
eic.eic.wakeup().modify(|_, w| {
pub fn enable_interrupt_wake(&mut self) {
self.eic.eic.wakeup().modify(|_, w| {
w.[<wakeupen $num>]().set_bit()
})
}

pub fn disable_interrupt(&mut self, eic: &mut EIC) {
eic.eic.intenclr().write(|w| {
pub fn disable_interrupt(&mut self) {
self.eic.eic.intenclr().write(|w| {
w.[<extint $num>]().set_bit()
});
}
Expand All @@ -107,10 +114,10 @@ crate::paste::item! {
});
}

pub fn sense(&mut self, _eic: &mut EIC, sense: Sense) {
pub fn sense(&mut self, sense: Sense) {
// Which of the two config blocks this eic config is in
let offset = ($num >> 3) & 0b0001;
let config = unsafe { &(*pac::Eic::ptr()).config(offset) };
let config = &self.eic.eic.config(offset);

config.modify(|_, w| unsafe {
// Which of the eight eic configs in this config block
Expand All @@ -128,10 +135,10 @@ crate::paste::item! {
});
}

pub fn filter(&mut self, _eic: &mut EIC, filter: bool) {
pub fn filter(&mut self, filter: bool) {
// Which of the two config blocks this eic config is in
let offset = ($num >> 3) & 0b0001;
let config = unsafe { &(*pac::Eic::ptr()).config(offset) };
let config = &self.eic.eic.config(offset);

config.modify(|_, w| {
// Which of the eight eic configs in this config block
Expand Down Expand Up @@ -179,16 +186,16 @@ crate::paste::item! {
type PullUp = [<$PadType $num>]<Pin<gpio::$PinType, PullUpInterrupt>>;
type PullDown = [<$PadType $num>]<Pin<gpio::$PinType, PullDownInterrupt>>;

fn into_floating_ei(self) -> Self::Floating {
[<$PadType $num>]::new(self.into_floating_interrupt())
fn into_floating_ei(self, eic: &mut super::EIC) -> Self::Floating {
[<$PadType $num>]::new(self.into_floating_interrupt(), eic)
}

fn into_pull_up_ei(self) -> Self::PullUp {
[<$PadType $num>]::new(self.into_pull_up_interrupt())
fn into_pull_up_ei(self, eic: &mut super::EIC) -> Self::PullUp {
[<$PadType $num>]::new(self.into_pull_up_interrupt(), eic)
}

fn into_pull_down_ei(self) -> Self::PullDown {
[<$PadType $num>]::new(self.into_pull_down_interrupt())
fn into_pull_down_ei(self, eic: &mut super::EIC) -> Self::PullDown {
[<$PadType $num>]::new(self.into_pull_down_interrupt(), eic)
}
}

Expand Down
32 changes: 28 additions & 4 deletions hal/src/peripherals/eic/d5x/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use crate::clock::EicClock;
use crate::pac;
use crate::{clock::EicClock, pac};

pub mod pin;

Expand Down Expand Up @@ -59,7 +58,32 @@ pub fn init_with_ulp32k(mclk: &mut pac::Mclk, _clock: EicClock, eic: pac::Eic) -

/// A configured External Interrupt Controller.
pub struct EIC {
_eic: pac::Eic,
eic: pac::Eic,
}

impl EIC {
/// Run the provided closure with the EIC peripheral disabled. The
/// enable-protected registers, such as CONFIGx, should be accessed through
/// this method.
///
/// # Caution
///
/// You should not re-enable the provided EIC PAC object inside the provided
/// closure.
fn with_disable(&mut self, fun: impl Fn(&mut pac::Eic)) {
self.eic.ctrla().modify(|_, w| w.enable().clear_bit());
self.enable_sync();
fun(&mut self.eic);
self.eic.ctrla().modify(|_, w| w.enable().set_bit());
self.enable_sync();
}

/// Busy-wait until SYNCBUSY.ENABLE clears
fn enable_sync(&mut self) {
while self.eic.syncbusy().read().enable().bit_is_set() {
core::hint::spin_loop();
}
}
}

impl From<ConfigurableEIC> for EIC {
Expand All @@ -69,6 +93,6 @@ impl From<ConfigurableEIC> for EIC {
cortex_m::asm::nop();
}

Self { _eic: eic.eic }
Self { eic: eic.eic }
}
}
Loading

0 comments on commit b1b1087

Please sign in to comment.