From 7219df4a5f9a666c6b0114eb9e86b6ab088fdeaa Mon Sep 17 00:00:00 2001 From: i509VCB Date: Sun, 6 Jul 2025 22:39:44 -0500 Subject: [PATCH] nxp: feature gate lpc55 gpio and pint to lpc55 --- embassy-nxp/Cargo.toml | 6 + embassy-nxp/src/chips/lpc55.rs | 70 ++++ embassy-nxp/src/gpio.rs | 357 +----------------- .../src/{pac_utils.rs => gpio/lpc55.rs} | 354 +++++++++++++++++ embassy-nxp/src/lib.rs | 90 +---- embassy-nxp/src/pint.rs | 3 +- 6 files changed, 451 insertions(+), 429 deletions(-) create mode 100644 embassy-nxp/src/chips/lpc55.rs rename embassy-nxp/src/{pac_utils.rs => gpio/lpc55.rs} (51%) diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index 010607914..18e9d989c 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml @@ -22,5 +22,11 @@ rt = ["lpc55-pac?/rt"] ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] +## Reexport the PAC for the currently enabled chip at `embassy_nxp::pac` (unstable) +unstable-pac = [] +# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version. +# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC. +# There are no plans to make this stable. + #! ### Chip selection features lpc55 = ["lpc55-pac"] diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs new file mode 100644 index 000000000..c95218af0 --- /dev/null +++ b/embassy-nxp/src/chips/lpc55.rs @@ -0,0 +1,70 @@ +pub use lpc55_pac as pac; + +embassy_hal_internal::peripherals! { + // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other + // peripheral types (e.g. I2C). + PIO0_0, + PIO0_1, + PIO0_2, + PIO0_3, + PIO0_4, + PIO0_5, + PIO0_6, + PIO0_7, + PIO0_8, + PIO0_9, + PIO0_10, + PIO0_11, + PIO0_12, + PIO0_13, + PIO0_14, + PIO0_15, + PIO0_16, + PIO0_17, + PIO0_18, + PIO0_19, + PIO0_20, + PIO0_21, + PIO0_22, + PIO0_23, + PIO0_24, + PIO0_25, + PIO0_26, + PIO0_27, + PIO0_28, + PIO0_29, + PIO0_30, + PIO0_31, + PIO1_0, + PIO1_1, + PIO1_2, + PIO1_3, + PIO1_4, + PIO1_5, + PIO1_6, + PIO1_7, + PIO1_8, + PIO1_9, + PIO1_10, + PIO1_11, + PIO1_12, + PIO1_13, + PIO1_14, + PIO1_15, + PIO1_16, + PIO1_17, + PIO1_18, + PIO1_19, + PIO1_20, + PIO1_21, + PIO1_22, + PIO1_23, + PIO1_24, + PIO1_25, + PIO1_26, + PIO1_27, + PIO1_28, + PIO1_29, + PIO1_30, + PIO1_31, +} diff --git a/embassy-nxp/src/gpio.rs b/embassy-nxp/src/gpio.rs index c7c78ce61..809903d97 100644 --- a/embassy-nxp/src/gpio.rs +++ b/embassy-nxp/src/gpio.rs @@ -1,354 +1,5 @@ -use embassy_hal_internal::{impl_peripheral, PeripheralType}; +//! General purpose input/output (GPIO) driver. -use crate::pac_utils::*; -use crate::{peripherals, Peri}; - -pub(crate) fn init() { - // Enable clocks for GPIO, PINT, and IOCON - syscon_reg() - .ahbclkctrl0 - .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); -} - -/// The GPIO pin level for pins set on "Digital" mode. -#[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum Level { - /// Logical low. Corresponds to 0V. - Low, - /// Logical high. Corresponds to VDD. - High, -} - -/// Pull setting for a GPIO input set on "Digital" mode. -#[derive(Debug, Clone, Copy, Eq, PartialEq)] -pub enum Pull { - /// No pull. - None, - /// Internal pull-up resistor. - Up, - /// Internal pull-down resistor. - Down, -} - -/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks. -#[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum Bank { - Bank0 = 0, - Bank1 = 1, -} - -/// GPIO output driver. Internally, this is a specialized [Flex] pin. -pub struct Output<'d> { - pub(crate) pin: Flex<'d>, -} - -impl<'d> Output<'d> { - /// Create GPIO output driver for a [Pin] with the provided [initial output](Level). - #[inline] - pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self { - let mut pin = Flex::new(pin); - pin.set_as_output(); - let mut result = Self { pin }; - - match initial_output { - Level::High => result.set_high(), - Level::Low => result.set_low(), - }; - - result - } - - pub fn set_high(&mut self) { - gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) - } - - pub fn set_low(&mut self) { - gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) - } - - pub fn toggle(&mut self) { - gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) - } - - /// Get the current output level of the pin. Note that the value returned by this function is - /// the voltage level reported by the pin, not the value set by the output driver. - pub fn level(&self) -> Level { - let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); - if bits & self.pin.bit() != 0 { - Level::High - } else { - Level::Low - } - } -} - -/// GPIO input driver. Internally, this is a specialized [Flex] pin. -pub struct Input<'d> { - pub(crate) pin: Flex<'d>, -} - -impl<'d> Input<'d> { - /// Create GPIO output driver for a [Pin] with the provided [Pull]. - #[inline] - pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self { - let mut pin = Flex::new(pin); - pin.set_as_input(); - let mut result = Self { pin }; - result.set_pull(pull); - - result - } - - /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. - pub fn set_pull(&mut self, pull: Pull) { - match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { - register.modify(|_, w| match pull { - Pull::None => w.mode().inactive(), - Pull::Up => w.mode().pull_up(), - Pull::Down => w.mode().pull_down(), - }); - }); - } - - /// Get the current input level of the pin. - pub fn read(&self) -> Level { - let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); - if bits & self.pin.bit() != 0 { - Level::High - } else { - Level::Low - } - } -} - -/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a -/// reference to a type-erased pin called ["AnyPin"](AnyPin). -pub struct Flex<'d> { - pub(crate) pin: Peri<'d, AnyPin>, -} - -impl<'d> Flex<'d> { - /// Wrap the pin in a `Flex`. - /// - /// Note: you cannot assume that the pin will be in Digital mode after this call. - #[inline] - pub fn new(pin: Peri<'d, impl Pin>) -> Self { - Self { pin: pin.into() } - } - - /// Get the bank of this pin. See also [Bank]. - /// - /// # Example - /// - /// ``` - /// use embassy_nxp::gpio::{Bank, Flex}; - /// - /// let p = embassy_nxp::init(Default::default()); - /// let pin = Flex::new(p.PIO1_15); - /// - /// assert_eq!(pin.pin_bank(), Bank::Bank1); - /// ``` - pub fn pin_bank(&self) -> Bank { - self.pin.pin_bank() - } - - /// Get the number of this pin within its bank. See also [Bank]. - /// - /// # Example - /// - /// ``` - /// use embassy_nxp::gpio::Flex; - /// - /// let p = embassy_nxp::init(Default::default()); - /// let pin = Flex::new(p.PIO1_15); - /// - /// assert_eq!(pin.pin_number(), 15 as u8); - /// ``` - pub fn pin_number(&self) -> u8 { - self.pin.pin_number() - } - - /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note: - /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc. - /// - /// # Example - /// - /// ``` - /// use embassy_nxp::gpio::Flex; - /// - /// let p = embassy_nxp::init(Default::default()); - /// let pin = Flex::new(p.PIO1_3); - /// - /// assert_eq!(pin.bit(), 0b0000_1000); - /// ``` - pub fn bit(&self) -> u32 { - 1 << self.pin.pin_number() - } - - /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default - /// setting for pins is (usually) non-digital. - fn set_as_digital(&mut self) { - match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { - register.modify(|_, w| w.digimode().digital()); - }); - } - - /// Set the pin in output mode. This implies setting the pin to digital mode, which this - /// function handles itself. - pub fn set_as_output(&mut self) { - self.set_as_digital(); - gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) - } - - pub fn set_as_input(&mut self) { - self.set_as_digital(); - gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) - } -} - -/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate. -pub(crate) trait SealedPin: Sized { - fn pin_bank(&self) -> Bank; - fn pin_number(&self) -> u8; -} - -/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an -/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the -/// `embassy-nxp` crate due to the [SealedPin] trait. -#[allow(private_bounds)] -pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { - /// Returns the pin number within a bank - #[inline] - fn pin(&self) -> u8 { - self.pin_number() - } - - /// Returns the bank of this pin - #[inline] - fn bank(&self) -> Bank { - self.pin_bank() - } -} - -/// Type-erased GPIO pin. -pub struct AnyPin { - pin_bank: Bank, - pin_number: u8, -} - -impl AnyPin { - /// Unsafely create a new type-erased pin. - /// - /// # Safety - /// - /// You must ensure that you’re only using one instance of this type at a time. - pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> { - Peri::new_unchecked(Self { pin_bank, pin_number }) - } -} - -impl_peripheral!(AnyPin); - -impl Pin for AnyPin {} -impl SealedPin for AnyPin { - #[inline] - fn pin_bank(&self) -> Bank { - self.pin_bank - } - - #[inline] - fn pin_number(&self) -> u8 { - self.pin_number - } -} - -macro_rules! impl_pin { - ($name:ident, $bank:expr, $pin_num:expr) => { - impl Pin for peripherals::$name {} - impl SealedPin for peripherals::$name { - #[inline] - fn pin_bank(&self) -> Bank { - $bank - } - - #[inline] - fn pin_number(&self) -> u8 { - $pin_num - } - } - - impl From for crate::gpio::AnyPin { - fn from(val: peripherals::$name) -> Self { - Self { - pin_bank: val.pin_bank(), - pin_number: val.pin_number(), - } - } - } - }; -} - -impl_pin!(PIO0_0, Bank::Bank0, 0); -impl_pin!(PIO0_1, Bank::Bank0, 1); -impl_pin!(PIO0_2, Bank::Bank0, 2); -impl_pin!(PIO0_3, Bank::Bank0, 3); -impl_pin!(PIO0_4, Bank::Bank0, 4); -impl_pin!(PIO0_5, Bank::Bank0, 5); -impl_pin!(PIO0_6, Bank::Bank0, 6); -impl_pin!(PIO0_7, Bank::Bank0, 7); -impl_pin!(PIO0_8, Bank::Bank0, 8); -impl_pin!(PIO0_9, Bank::Bank0, 9); -impl_pin!(PIO0_10, Bank::Bank0, 10); -impl_pin!(PIO0_11, Bank::Bank0, 11); -impl_pin!(PIO0_12, Bank::Bank0, 12); -impl_pin!(PIO0_13, Bank::Bank0, 13); -impl_pin!(PIO0_14, Bank::Bank0, 14); -impl_pin!(PIO0_15, Bank::Bank0, 15); -impl_pin!(PIO0_16, Bank::Bank0, 16); -impl_pin!(PIO0_17, Bank::Bank0, 17); -impl_pin!(PIO0_18, Bank::Bank0, 18); -impl_pin!(PIO0_19, Bank::Bank0, 19); -impl_pin!(PIO0_20, Bank::Bank0, 20); -impl_pin!(PIO0_21, Bank::Bank0, 21); -impl_pin!(PIO0_22, Bank::Bank0, 22); -impl_pin!(PIO0_23, Bank::Bank0, 23); -impl_pin!(PIO0_24, Bank::Bank0, 24); -impl_pin!(PIO0_25, Bank::Bank0, 25); -impl_pin!(PIO0_26, Bank::Bank0, 26); -impl_pin!(PIO0_27, Bank::Bank0, 27); -impl_pin!(PIO0_28, Bank::Bank0, 28); -impl_pin!(PIO0_29, Bank::Bank0, 29); -impl_pin!(PIO0_30, Bank::Bank0, 30); -impl_pin!(PIO0_31, Bank::Bank0, 31); -impl_pin!(PIO1_0, Bank::Bank1, 0); -impl_pin!(PIO1_1, Bank::Bank1, 1); -impl_pin!(PIO1_2, Bank::Bank1, 2); -impl_pin!(PIO1_3, Bank::Bank1, 3); -impl_pin!(PIO1_4, Bank::Bank1, 4); -impl_pin!(PIO1_5, Bank::Bank1, 5); -impl_pin!(PIO1_6, Bank::Bank1, 6); -impl_pin!(PIO1_7, Bank::Bank1, 7); -impl_pin!(PIO1_8, Bank::Bank1, 8); -impl_pin!(PIO1_9, Bank::Bank1, 9); -impl_pin!(PIO1_10, Bank::Bank1, 10); -impl_pin!(PIO1_11, Bank::Bank1, 11); -impl_pin!(PIO1_12, Bank::Bank1, 12); -impl_pin!(PIO1_13, Bank::Bank1, 13); -impl_pin!(PIO1_14, Bank::Bank1, 14); -impl_pin!(PIO1_15, Bank::Bank1, 15); -impl_pin!(PIO1_16, Bank::Bank1, 16); -impl_pin!(PIO1_17, Bank::Bank1, 17); -impl_pin!(PIO1_18, Bank::Bank1, 18); -impl_pin!(PIO1_19, Bank::Bank1, 19); -impl_pin!(PIO1_20, Bank::Bank1, 20); -impl_pin!(PIO1_21, Bank::Bank1, 21); -impl_pin!(PIO1_22, Bank::Bank1, 22); -impl_pin!(PIO1_23, Bank::Bank1, 23); -impl_pin!(PIO1_24, Bank::Bank1, 24); -impl_pin!(PIO1_25, Bank::Bank1, 25); -impl_pin!(PIO1_26, Bank::Bank1, 26); -impl_pin!(PIO1_27, Bank::Bank1, 27); -impl_pin!(PIO1_28, Bank::Bank1, 28); -impl_pin!(PIO1_29, Bank::Bank1, 29); -impl_pin!(PIO1_30, Bank::Bank1, 30); -impl_pin!(PIO1_31, Bank::Bank1, 31); +#[cfg_attr(feature = "lpc55", path = "./gpio/lpc55.rs")] +mod inner; +pub use inner::*; diff --git a/embassy-nxp/src/pac_utils.rs b/embassy-nxp/src/gpio/lpc55.rs similarity index 51% rename from embassy-nxp/src/pac_utils.rs rename to embassy-nxp/src/gpio/lpc55.rs index 86a807f6c..94cd8b7f8 100644 --- a/embassy-nxp/src/pac_utils.rs +++ b/embassy-nxp/src/gpio/lpc55.rs @@ -1,3 +1,266 @@ +use embassy_hal_internal::{impl_peripheral, PeripheralType}; + +use crate::{peripherals, Peri}; + +pub(crate) fn init() { + // Enable clocks for GPIO, PINT, and IOCON + syscon_reg() + .ahbclkctrl0 + .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); +} + +/// The GPIO pin level for pins set on "Digital" mode. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum Level { + /// Logical low. Corresponds to 0V. + Low, + /// Logical high. Corresponds to VDD. + High, +} + +/// Pull setting for a GPIO input set on "Digital" mode. +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum Pull { + /// No pull. + None, + /// Internal pull-up resistor. + Up, + /// Internal pull-down resistor. + Down, +} + +/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks. +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum Bank { + Bank0 = 0, + Bank1 = 1, +} + +/// GPIO output driver. Internally, this is a specialized [Flex] pin. +pub struct Output<'d> { + pub(crate) pin: Flex<'d>, +} + +impl<'d> Output<'d> { + /// Create GPIO output driver for a [Pin] with the provided [initial output](Level). + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self { + let mut pin = Flex::new(pin); + pin.set_as_output(); + let mut result = Self { pin }; + + match initial_output { + Level::High => result.set_high(), + Level::Low => result.set_low(), + }; + + result + } + + pub fn set_high(&mut self) { + gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + } + + pub fn set_low(&mut self) { + gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + } + + pub fn toggle(&mut self) { + gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) + } + + /// Get the current output level of the pin. Note that the value returned by this function is + /// the voltage level reported by the pin, not the value set by the output driver. + pub fn level(&self) -> Level { + let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); + if bits & self.pin.bit() != 0 { + Level::High + } else { + Level::Low + } + } +} + +/// GPIO input driver. Internally, this is a specialized [Flex] pin. +pub struct Input<'d> { + pub(crate) pin: Flex<'d>, +} + +impl<'d> Input<'d> { + /// Create GPIO output driver for a [Pin] with the provided [Pull]. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self { + let mut pin = Flex::new(pin); + pin.set_as_input(); + let mut result = Self { pin }; + result.set_pull(pull); + + result + } + + /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. + pub fn set_pull(&mut self, pull: Pull) { + match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { + register.modify(|_, w| match pull { + Pull::None => w.mode().inactive(), + Pull::Up => w.mode().pull_up(), + Pull::Down => w.mode().pull_down(), + }); + }); + } + + /// Get the current input level of the pin. + pub fn read(&self) -> Level { + let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); + if bits & self.pin.bit() != 0 { + Level::High + } else { + Level::Low + } + } +} + +/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a +/// reference to a type-erased pin called ["AnyPin"](AnyPin). +pub struct Flex<'d> { + pub(crate) pin: Peri<'d, AnyPin>, +} + +impl<'d> Flex<'d> { + /// Wrap the pin in a `Flex`. + /// + /// Note: you cannot assume that the pin will be in Digital mode after this call. + #[inline] + pub fn new(pin: Peri<'d, impl Pin>) -> Self { + Self { pin: pin.into() } + } + + /// Get the bank of this pin. See also [Bank]. + /// + /// # Example + /// + /// ``` + /// use embassy_nxp::gpio::{Bank, Flex}; + /// + /// let p = embassy_nxp::init(Default::default()); + /// let pin = Flex::new(p.PIO1_15); + /// + /// assert_eq!(pin.pin_bank(), Bank::Bank1); + /// ``` + pub fn pin_bank(&self) -> Bank { + self.pin.pin_bank() + } + + /// Get the number of this pin within its bank. See also [Bank]. + /// + /// # Example + /// + /// ``` + /// use embassy_nxp::gpio::Flex; + /// + /// let p = embassy_nxp::init(Default::default()); + /// let pin = Flex::new(p.PIO1_15); + /// + /// assert_eq!(pin.pin_number(), 15 as u8); + /// ``` + pub fn pin_number(&self) -> u8 { + self.pin.pin_number() + } + + /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note: + /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc. + /// + /// # Example + /// + /// ``` + /// use embassy_nxp::gpio::Flex; + /// + /// let p = embassy_nxp::init(Default::default()); + /// let pin = Flex::new(p.PIO1_3); + /// + /// assert_eq!(pin.bit(), 0b0000_1000); + /// ``` + pub fn bit(&self) -> u32 { + 1 << self.pin.pin_number() + } + + /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default + /// setting for pins is (usually) non-digital. + fn set_as_digital(&mut self) { + match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { + register.modify(|_, w| w.digimode().digital()); + }); + } + + /// Set the pin in output mode. This implies setting the pin to digital mode, which this + /// function handles itself. + pub fn set_as_output(&mut self) { + self.set_as_digital(); + gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) + } + + pub fn set_as_input(&mut self) { + self.set_as_digital(); + gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) + } +} + +/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate. +pub(crate) trait SealedPin: Sized { + fn pin_bank(&self) -> Bank; + fn pin_number(&self) -> u8; +} + +/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an +/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the +/// `embassy-nxp` crate due to the [SealedPin] trait. +#[allow(private_bounds)] +pub trait Pin: PeripheralType + Into + SealedPin + Sized + 'static { + /// Returns the pin number within a bank + #[inline] + fn pin(&self) -> u8 { + self.pin_number() + } + + /// Returns the bank of this pin + #[inline] + fn bank(&self) -> Bank { + self.pin_bank() + } +} + +/// Type-erased GPIO pin. +pub struct AnyPin { + pin_bank: Bank, + pin_number: u8, +} + +impl AnyPin { + /// Unsafely create a new type-erased pin. + /// + /// # Safety + /// + /// You must ensure that you’re only using one instance of this type at a time. + pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> { + Peri::new_unchecked(Self { pin_bank, pin_number }) + } +} + +impl_peripheral!(AnyPin); + +impl Pin for AnyPin {} +impl SealedPin for AnyPin { + #[inline] + fn pin_bank(&self) -> Bank { + self.pin_bank + } + + #[inline] + fn pin_number(&self) -> u8 { + self.pin_number + } +} + /// Get the GPIO register block. This is used to configure all GPIO pins. /// /// # Safety @@ -321,3 +584,94 @@ macro_rules! match_iocon { } pub(crate) use match_iocon; + +macro_rules! impl_pin { + ($name:ident, $bank:expr, $pin_num:expr) => { + impl Pin for peripherals::$name {} + impl SealedPin for peripherals::$name { + #[inline] + fn pin_bank(&self) -> Bank { + $bank + } + + #[inline] + fn pin_number(&self) -> u8 { + $pin_num + } + } + + impl From for crate::gpio::AnyPin { + fn from(val: peripherals::$name) -> Self { + Self { + pin_bank: val.pin_bank(), + pin_number: val.pin_number(), + } + } + } + }; +} + +impl_pin!(PIO0_0, Bank::Bank0, 0); +impl_pin!(PIO0_1, Bank::Bank0, 1); +impl_pin!(PIO0_2, Bank::Bank0, 2); +impl_pin!(PIO0_3, Bank::Bank0, 3); +impl_pin!(PIO0_4, Bank::Bank0, 4); +impl_pin!(PIO0_5, Bank::Bank0, 5); +impl_pin!(PIO0_6, Bank::Bank0, 6); +impl_pin!(PIO0_7, Bank::Bank0, 7); +impl_pin!(PIO0_8, Bank::Bank0, 8); +impl_pin!(PIO0_9, Bank::Bank0, 9); +impl_pin!(PIO0_10, Bank::Bank0, 10); +impl_pin!(PIO0_11, Bank::Bank0, 11); +impl_pin!(PIO0_12, Bank::Bank0, 12); +impl_pin!(PIO0_13, Bank::Bank0, 13); +impl_pin!(PIO0_14, Bank::Bank0, 14); +impl_pin!(PIO0_15, Bank::Bank0, 15); +impl_pin!(PIO0_16, Bank::Bank0, 16); +impl_pin!(PIO0_17, Bank::Bank0, 17); +impl_pin!(PIO0_18, Bank::Bank0, 18); +impl_pin!(PIO0_19, Bank::Bank0, 19); +impl_pin!(PIO0_20, Bank::Bank0, 20); +impl_pin!(PIO0_21, Bank::Bank0, 21); +impl_pin!(PIO0_22, Bank::Bank0, 22); +impl_pin!(PIO0_23, Bank::Bank0, 23); +impl_pin!(PIO0_24, Bank::Bank0, 24); +impl_pin!(PIO0_25, Bank::Bank0, 25); +impl_pin!(PIO0_26, Bank::Bank0, 26); +impl_pin!(PIO0_27, Bank::Bank0, 27); +impl_pin!(PIO0_28, Bank::Bank0, 28); +impl_pin!(PIO0_29, Bank::Bank0, 29); +impl_pin!(PIO0_30, Bank::Bank0, 30); +impl_pin!(PIO0_31, Bank::Bank0, 31); +impl_pin!(PIO1_0, Bank::Bank1, 0); +impl_pin!(PIO1_1, Bank::Bank1, 1); +impl_pin!(PIO1_2, Bank::Bank1, 2); +impl_pin!(PIO1_3, Bank::Bank1, 3); +impl_pin!(PIO1_4, Bank::Bank1, 4); +impl_pin!(PIO1_5, Bank::Bank1, 5); +impl_pin!(PIO1_6, Bank::Bank1, 6); +impl_pin!(PIO1_7, Bank::Bank1, 7); +impl_pin!(PIO1_8, Bank::Bank1, 8); +impl_pin!(PIO1_9, Bank::Bank1, 9); +impl_pin!(PIO1_10, Bank::Bank1, 10); +impl_pin!(PIO1_11, Bank::Bank1, 11); +impl_pin!(PIO1_12, Bank::Bank1, 12); +impl_pin!(PIO1_13, Bank::Bank1, 13); +impl_pin!(PIO1_14, Bank::Bank1, 14); +impl_pin!(PIO1_15, Bank::Bank1, 15); +impl_pin!(PIO1_16, Bank::Bank1, 16); +impl_pin!(PIO1_17, Bank::Bank1, 17); +impl_pin!(PIO1_18, Bank::Bank1, 18); +impl_pin!(PIO1_19, Bank::Bank1, 19); +impl_pin!(PIO1_20, Bank::Bank1, 20); +impl_pin!(PIO1_21, Bank::Bank1, 21); +impl_pin!(PIO1_22, Bank::Bank1, 22); +impl_pin!(PIO1_23, Bank::Bank1, 23); +impl_pin!(PIO1_24, Bank::Bank1, 24); +impl_pin!(PIO1_25, Bank::Bank1, 25); +impl_pin!(PIO1_26, Bank::Bank1, 26); +impl_pin!(PIO1_27, Bank::Bank1, 27); +impl_pin!(PIO1_28, Bank::Bank1, 28); +impl_pin!(PIO1_29, Bank::Bank1, 29); +impl_pin!(PIO1_30, Bank::Bank1, 30); +impl_pin!(PIO1_31, Bank::Bank1, 31); diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index ad2056c06..433aca9e0 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs @@ -1,11 +1,19 @@ #![no_std] pub mod gpio; -mod pac_utils; +#[cfg(feature = "lpc55")] pub mod pint; -pub use embassy_hal_internal::Peri; -pub use lpc55_pac as pac; +// This mod MUST go last, so that it sees all the `impl_foo!` macros +#[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] +mod chip; + +#[cfg(feature = "unstable-pac")] +pub use chip::pac; +#[cfg(not(feature = "unstable-pac"))] +pub(crate) use chip::pac; +pub use chip::{peripherals, Peripherals}; +pub use embassy_hal_internal::{Peri, PeripheralType}; /// Initialize the `embassy-nxp` HAL with the provided configuration. /// @@ -13,81 +21,15 @@ pub use lpc55_pac as pac; /// /// This should only be called once and at startup, otherwise it panics. pub fn init(_config: config::Config) -> Peripherals { - gpio::init(); - pint::init(); + #[cfg(feature = "lpc55")] + { + gpio::init(); + pint::init(); + } crate::Peripherals::take() } -embassy_hal_internal::peripherals! { - // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other - // peripheral types (e.g. I2C). - PIO0_0, - PIO0_1, - PIO0_2, - PIO0_3, - PIO0_4, - PIO0_5, - PIO0_6, - PIO0_7, - PIO0_8, - PIO0_9, - PIO0_10, - PIO0_11, - PIO0_12, - PIO0_13, - PIO0_14, - PIO0_15, - PIO0_16, - PIO0_17, - PIO0_18, - PIO0_19, - PIO0_20, - PIO0_21, - PIO0_22, - PIO0_23, - PIO0_24, - PIO0_25, - PIO0_26, - PIO0_27, - PIO0_28, - PIO0_29, - PIO0_30, - PIO0_31, - PIO1_0, - PIO1_1, - PIO1_2, - PIO1_3, - PIO1_4, - PIO1_5, - PIO1_6, - PIO1_7, - PIO1_8, - PIO1_9, - PIO1_10, - PIO1_11, - PIO1_12, - PIO1_13, - PIO1_14, - PIO1_15, - PIO1_16, - PIO1_17, - PIO1_18, - PIO1_19, - PIO1_20, - PIO1_21, - PIO1_22, - PIO1_23, - PIO1_24, - PIO1_25, - PIO1_26, - PIO1_27, - PIO1_28, - PIO1_29, - PIO1_30, - PIO1_31, -} - /// HAL configuration for the NXP board. pub mod config { #[derive(Default)] diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs index 8d6dc1277..dc117e7e3 100644 --- a/embassy-nxp/src/pint.rs +++ b/embassy-nxp/src/pint.rs @@ -7,9 +7,8 @@ use core::task::{Context, Poll}; use critical_section::Mutex; use embassy_sync::waitqueue::AtomicWaker; -use crate::gpio::{self, AnyPin, Level, SealedPin}; +use crate::gpio::{self, inputmux_reg, pint_reg, syscon_reg, AnyPin, Level, SealedPin}; use crate::pac::interrupt; -use crate::pac_utils::*; use crate::Peri; struct PinInterrupt {