Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove pins from Io #2508

Merged
merged 3 commits into from
Nov 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading