Skip to content

Commit

Permalink
Remove pins from Io (#2508)
Browse files Browse the repository at this point in the history
* Split pins off of Io

* Remove the GPIO peripheral

* p.GPIO
  • Loading branch information
bugadani authored Nov 12, 2024
1 parent 321ca2f commit fbc5754
Show file tree
Hide file tree
Showing 134 changed files with 1,217 additions and 1,429 deletions.
2 changes: 2 additions & 0 deletions esp-hal/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- SPI transactions are now cancelled if the transfer object (or async Future) is dropped. (#2216)
- The DMA channel types have been removed from peripherals (#2261)
- `I2C` driver renamed to `I2c` (#2320)
- The GPIO pins are now accessible via `Peripherals` and are no longer part of the `Io` struct (#2508)

### Fixed

Expand Down Expand Up @@ -215,6 +216,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Removed `esp_hal::spi::slave::WithDmaSpiN` traits (#2260)
- The `WithDmaAes` trait has been removed (#2261)
- The `I2s::new_i2s1` constructor has been removed (#2261)
- `Peripherals.GPIO` has been removed (#2508)

## [0.20.1] - 2024-08-30

Expand Down
18 changes: 18 additions & 0 deletions esp-hal/MIGRATING-0.21.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Migration Guide from 0.21.x to v0.22.x

## IO changes

### GPIO pins are now accessible via `Peripherals`

```diff
let peripherals = esp_hal::init(Default::default());
-let io = Io::new(peripherals.GPIO, peripherals.IOMUX);
-let pin = io.pins.gpio5;
+let pin = peripherals.GPIO5;
```

### `Io` constructor changes

- `new_with_priority` and `new_no_bind_interrupts` have been removed.
Use `set_priority` to configure the GPIO interrupt priority.
We no longer overwrite interrupt handlers set by user code during initialization.
- `new` no longer takes `peripherals.GPIO`

## Removed `async`-specific constructors

The following async-specific constuctors have been removed:
Expand Down
8 changes: 3 additions & 5 deletions esp-hal/src/analog/adc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,11 @@
//! # use esp_hal::analog::adc::Attenuation;
//! # use esp_hal::analog::adc::Adc;
//! # use esp_hal::delay::Delay;
//! # use esp_hal::gpio::Io;
//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
#![cfg_attr(esp32, doc = "let analog_pin = io.pins.gpio32;")]
#![cfg_attr(any(esp32s2, esp32s3), doc = "let analog_pin = io.pins.gpio3;")]
#![cfg_attr(esp32, doc = "let analog_pin = peripherals.GPIO32;")]
#![cfg_attr(any(esp32s2, esp32s3), doc = "let analog_pin = peripherals.GPIO3;")]
#![cfg_attr(
not(any(esp32, esp32s2, esp32s3)),
doc = "let analog_pin = io.pins.gpio2;"
doc = "let analog_pin = peripherals.GPIO2;"
)]
//! let mut adc1_config = AdcConfig::new();
//! let mut pin = adc1_config.enable_pin(
Expand Down
7 changes: 2 additions & 5 deletions esp-hal/src/analog/dac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@
//! ### Write a value to a DAC channel
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::gpio::Io;
//! # use esp_hal::analog::dac::Dac;
//! # use esp_hal::delay::Delay;
//! # use embedded_hal::delay::DelayNs;
//!
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
#![cfg_attr(esp32, doc = "let dac1_pin = io.pins.gpio25;")]
#![cfg_attr(esp32s2, doc = "let dac1_pin = io.pins.gpio17;")]
#![cfg_attr(esp32, doc = "let dac1_pin = peripherals.GPIO25;")]
#![cfg_attr(esp32s2, doc = "let dac1_pin = peripherals.GPIO17;")]
//! let mut dac1 = Dac::new(peripherals.DAC1, dac1_pin);
//!
//! let mut delay = Delay::new();
Expand Down
10 changes: 4 additions & 6 deletions esp-hal/src/dma/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,15 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::dma_buffers;
//! # use esp_hal::gpio::Io;
//! # use esp_hal::spi::{master::{Config, Spi}, SpiMode};
//! # use esp_hal::dma::{Dma, DmaPriority};
//! let dma = Dma::new(peripherals.DMA);
#![cfg_attr(any(esp32, esp32s2), doc = "let dma_channel = dma.spi2channel;")]
#![cfg_attr(not(any(esp32, esp32s2)), doc = "let dma_channel = dma.channel0;")]
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//! let sclk = io.pins.gpio0;
//! let miso = io.pins.gpio2;
//! let mosi = io.pins.gpio4;
//! let cs = io.pins.gpio5;
//! let sclk = peripherals.GPIO0;
//! let miso = peripherals.GPIO2;
//! let mosi = peripherals.GPIO4;
//! let cs = peripherals.GPIO5;
//!
//! let mut spi = Spi::new_with_config(
//! peripherals.SPI2,
Expand Down
6 changes: 2 additions & 4 deletions esp-hal/src/etm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,13 @@
//! ## Examples
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::gpio::Io;
//! # use esp_hal::gpio::etm::{Channels, InputConfig, OutputConfig};
//! # use esp_hal::etm::Etm;
//! # use esp_hal::gpio::Pull;
//! # use esp_hal::gpio::Level;
//!
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//! let mut led = io.pins.gpio1;
//! let button = io.pins.gpio9;
//! let mut led = peripherals.GPIO1;
//! let button = peripherals.GPIO9;
//!
//! // setup ETM
//! let gpio_ext = Channels::new(peripherals.GPIO_SD);
Expand Down
6 changes: 2 additions & 4 deletions esp-hal/src/gpio/etm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,15 @@
//! ### Toggle an LED When a Button is Pressed
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::gpio::Io;
//! # use esp_hal::gpio::etm::Channels;
//! # use esp_hal::etm::Etm;
//! # use esp_hal::gpio::etm::InputConfig;
//! # use esp_hal::gpio::etm::OutputConfig;
//! # use esp_hal::gpio::Pull;
//! # use esp_hal::gpio::Level;
//! #
//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//! # let mut led = io.pins.gpio1;
//! # let button = io.pins.gpio9;
//! # let mut led = peripherals.GPIO1;
//! # let button = peripherals.GPIO9;
//!
//! let gpio_ext = Channels::new(peripherals.GPIO_SD);
//! let led_task = gpio_ext.channel0_task.toggle(
Expand Down
7 changes: 4 additions & 3 deletions esp-hal/src/gpio/lp_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,15 @@
//! chip from Deep-sleep.
//!
//! # Example
//!
//! ## Configure a LP Pin as Output
//!
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! use esp_hal::gpio::Io;
//! use esp_hal::gpio::lp_io::LowPowerOutput;
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//! // configure GPIO 1 as LP output pin
//! let lp_pin: LowPowerOutput<'_, 1> = LowPowerOutput::new(io.pins.gpio1);
//! let lp_pin: LowPowerOutput<'_, 1> =
//! LowPowerOutput::new(peripherals.GPIO1);
//! # }
//! ```
Expand Down
104 changes: 42 additions & 62 deletions esp-hal/src/gpio/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
//! GPIO interrupts. For more information, see the
//! [`Io::set_interrupt_handler`].
//!
//! The pins are accessible via [`Io::pins`]. These pins can then be passed to
//! peripherals (such as SPI, UART, I2C, etc.), to pin drivers or can be
//! [`GpioPin::split`] into peripheral signals.
//! The pins are accessible via the [`crate::Peripherals`] struct returned by
//! [`crate::init`]. These pins can then be passed to peripherals (such as
//! SPI, UART, I2C, etc.), to pin drivers or can be [`GpioPin::split`] into
//! peripheral signals.
//!
//! Each pin is a different type initially. Internally, `esp-hal` will often
//! erase their types automatically, but they can also be converted into
Expand Down Expand Up @@ -52,8 +53,7 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::gpio::{Io, Level, Output};
//! let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//! let mut led = Output::new(io.pins.gpio5, Level::High);
//! let mut led = Output::new(peripherals.GPIO5, Level::High);
//! # }
//! ```
//!
Expand All @@ -71,11 +71,18 @@
use portable_atomic::{AtomicPtr, Ordering};
use procmacros::ram;

#[cfg(any(lp_io, rtc_cntl))]
use crate::peripherals::gpio::{handle_rtcio, handle_rtcio_with_resistors};
pub use crate::soc::gpio::*;
use crate::{
interrupt::{self, InterruptHandler, Priority},
peripheral::{Peripheral, PeripheralRef},
peripherals::{Interrupt, GPIO, IO_MUX},
peripherals::{
gpio::{handle_gpio_input, handle_gpio_output, AnyPinInner},
Interrupt,
GPIO,
IO_MUX,
},
private::{self, Sealed},
InterruptConfigurable,
DEFAULT_INTERRUPT_HANDLER,
Expand Down Expand Up @@ -716,6 +723,9 @@ impl Bank1GpioRegisterAccess {
/// GPIO pin
pub struct GpioPin<const GPIONUM: u8>;

/// Type-erased GPIO pin
pub struct AnyPin(pub(crate) AnyPinInner);

impl<const GPIONUM: u8> GpioPin<GPIONUM>
where
Self: Pin,
Expand Down Expand Up @@ -813,17 +823,12 @@ pub(crate) fn bind_default_interrupt_handler() {
/// General Purpose Input/Output driver
pub struct Io {
_io_mux: IO_MUX,
/// The pins available on this chip
pub pins: Pins,
}

impl Io {
/// Initialize the I/O driver.
pub fn new(_gpio: GPIO, _io_mux: IO_MUX) -> Self {
Io {
_io_mux,
pins: unsafe { Pins::steal() },
}
pub fn new(_io_mux: IO_MUX) -> Self {
Io { _io_mux }
}

/// Set the interrupt priority for GPIO interrupts.
Expand Down Expand Up @@ -911,20 +916,20 @@ macro_rules! if_rtcio_pin {
#[macro_export]
macro_rules! io_type {
(Input, $gpionum:literal) => {
impl $crate::gpio::InputPin for GpioPin<$gpionum> {}
impl $crate::gpio::InputPin for $crate::gpio::GpioPin<$gpionum> {}
};
(Output, $gpionum:literal) => {
impl $crate::gpio::OutputPin for GpioPin<$gpionum> {}
impl $crate::gpio::OutputPin for $crate::gpio::GpioPin<$gpionum> {}
};
(Analog, $gpionum:literal) => {
// FIXME: the implementation shouldn't be in the GPIO module
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
impl $crate::gpio::AnalogPin for GpioPin<$gpionum> {
impl $crate::gpio::AnalogPin for $crate::gpio::GpioPin<$gpionum> {
/// Configures the pin for analog mode.
fn set_analog(&self, _: $crate::private::Internal) {
use $crate::peripherals::GPIO;

get_io_mux_reg($gpionum).modify(|_, w| unsafe {
$crate::gpio::get_io_mux_reg($gpionum).modify(|_, w| unsafe {
w.mcu_sel().bits(1);
w.fun_ie().clear_bit();
w.fun_wpu().clear_bit();
Expand Down Expand Up @@ -956,91 +961,70 @@ macro_rules! gpio {
)+
) => {
paste::paste! {
/// Pins available on this chip
pub struct Pins {
$(
#[doc = concat!("GPIO pin number ", $gpionum, ".")]
pub [< gpio $gpionum >] : GpioPin<$gpionum>,
)+
}

impl Pins {
/// Unsafely create GPIO pins.
///
/// # Safety
///
/// The caller must ensure that only one instance of a pin is in use at one time.
pub unsafe fn steal() -> Self {
Self {
$(
[< gpio $gpionum >]: GpioPin::steal(),
)+
}
}
}

$(
$(
$crate::io_type!($type, $gpionum);
)*

impl $crate::gpio::Pin for GpioPin<$gpionum> {
impl $crate::gpio::Pin for $crate::gpio::GpioPin<$gpionum> {
fn number(&self) -> u8 {
$gpionum
}

fn degrade_pin(&self, _: $crate::private::Internal) -> AnyPin {
AnyPin($crate::gpio::AnyPinInner::[< Gpio $gpionum >](unsafe { Self::steal() }))
fn degrade_pin(&self, _: $crate::private::Internal) -> $crate::gpio::AnyPin {
$crate::gpio::AnyPin(AnyPinInner::[< Gpio $gpionum >](unsafe { Self::steal() }))
}

fn gpio_bank(&self, _: $crate::private::Internal) -> $crate::gpio::GpioRegisterAccess {
$crate::gpio::GpioRegisterAccess::from($gpionum)
}

fn output_signals(&self, _: $crate::private::Internal) -> &[(AlternateFunction, OutputSignal)] {
fn output_signals(&self, _: $crate::private::Internal) -> &[($crate::gpio::AlternateFunction, $crate::gpio::OutputSignal)] {
&[
$(
$(
(AlternateFunction::[< Function $af_output_num >], OutputSignal::$af_output_signal ),
(
$crate::gpio::AlternateFunction::[< Function $af_output_num >],
$crate::gpio::OutputSignal::$af_output_signal
),
)*
)?
]
}

fn input_signals(&self, _: $crate::private::Internal) -> &[(AlternateFunction, InputSignal)] {
fn input_signals(&self, _: $crate::private::Internal) -> &[($crate::gpio::AlternateFunction, $crate::gpio::InputSignal)] {
&[
$(
$(
(AlternateFunction::[< Function $af_input_num >], InputSignal::$af_input_signal ),
(
$crate::gpio::AlternateFunction::[< Function $af_input_num >],
$crate::gpio::InputSignal::$af_input_signal
),
)*
)?
]
}
}

impl From<GpioPin<$gpionum>> for AnyPin {
fn from(pin: GpioPin<$gpionum>) -> Self {
use $crate::gpio::Pin;
pin.degrade()
impl From<$crate::gpio::GpioPin<$gpionum>> for $crate::gpio::AnyPin {
fn from(pin: $crate::gpio::GpioPin<$gpionum>) -> Self {
$crate::gpio::Pin::degrade(pin)
}
}
)+

pub(crate) enum AnyPinInner {
$(
[<Gpio $gpionum >](GpioPin<$gpionum>),
[<Gpio $gpionum >]($crate::gpio::GpioPin<$gpionum>),
)+
}

/// Type-erased GPIO pin
pub struct AnyPin(pub(crate) AnyPinInner);

impl $crate::peripheral::Peripheral for AnyPin {
type P = AnyPin;
impl $crate::peripheral::Peripheral for $crate::gpio::AnyPin {
type P = $crate::gpio::AnyPin;
unsafe fn clone_unchecked(&self) -> Self {
match self.0 {
$(AnyPinInner::[<Gpio $gpionum >](_) => {
Self(AnyPinInner::[< Gpio $gpionum >](unsafe { GpioPin::steal() }))
Self(AnyPinInner::[< Gpio $gpionum >](unsafe { $crate::gpio::GpioPin::steal() }))
})+
}
}
Expand All @@ -1049,7 +1033,6 @@ macro_rules! gpio {
// These macros call the code block on the actually contained GPIO pin.

#[doc(hidden)]
#[macro_export]
macro_rules! handle_gpio_output {
($this:expr, $inner:ident, $code:tt) => {
match $this {
Expand All @@ -1066,7 +1049,6 @@ macro_rules! gpio {
}

#[doc(hidden)]
#[macro_export]
macro_rules! handle_gpio_input {
($this:expr, $inner:ident, $code:tt) => {
match $this {
Expand All @@ -1083,7 +1065,6 @@ macro_rules! gpio {
cfg_if::cfg_if! {
if #[cfg(any(lp_io, rtc_cntl))] {
#[doc(hidden)]
#[macro_export]
macro_rules! handle_rtcio {
($this:expr, $inner:ident, $code:tt) => {
match $this {
Expand All @@ -1100,7 +1081,6 @@ macro_rules! gpio {
}

#[doc(hidden)]
#[macro_export]
macro_rules! handle_rtcio_with_resistors {
($this:expr, $inner:ident, $code:tt) => {
match $this {
Expand Down
Loading

0 comments on commit fbc5754

Please sign in to comment.