esp_hal/gpio/
mod.rs

1//! # General Purpose Input/Output (GPIO)
2//!
3//! ## Overview
4//!
5//! Each pin can be used as a general-purpose I/O, or be connected to one or
6//! more internal peripheral signals.
7#![cfg_attr(
8    soc_etm,
9    doc = "The GPIO pins also provide tasks and events via the ETM interconnect system. For more information, see the [etm] module."
10)]
11#![doc = ""]
12//! ## Working with pins
13//!
14//! After initializing the HAL, you can access the individual pins using the
15//! [`crate::Peripherals`] struct. These pins can then be used as general
16//! purpose digital IO using pin drivers, or they can be passed to peripherals
17//! (such as SPI, UART, I2C, etc.), or can be [`GpioPin::split`]
18//! into peripheral signals for advanced use.
19//!
20//! Pin drivers can be created using [`Flex::new`], [`Input::new`] and
21//! [`Output::new`].
22//!
23//! Output pins can be configured to either push-pull or open-drain (active low)
24//! mode, with configurable drive strength and pull-up/pull-down resistors.
25//!
26//! Each pin is a different type initially. Internally, `esp-hal` will erase
27//! their types automatically, but they can also be converted into [`AnyPin`]
28//! manually by calling [`Pin::degrade`].
29//!
30//! The [`Io`] struct can also be used to configure the interrupt handler for
31//! GPIO interrupts. For more information, see the
32//! [`InterruptConfigurable::set_interrupt_handler`](crate::interrupt::InterruptConfigurable::set_interrupt_handler).
33//!
34//! This driver also implements pin-related traits from [embedded-hal] and
35//! [Wait](embedded_hal_async::digital::Wait) trait from [embedded-hal-async].
36//!
37//! ## GPIO interconnect
38//!
39//! Sometimes you may want to connect peripherals together without using
40//! external hardware. The [`interconnect`] module provides tools to achieve
41//! this using GPIO pins.
42//!
43//! To obtain peripheral signals, use the [`GpioPin::split`] method to split a
44//! pin into an input and output signal. Alternatively, you may use
45//! [`Flex::split`], [`Flex::into_peripheral_output`],
46//! [`Flex::peripheral_input`], and similar methods to split a pin driver into
47//! an input and output signal. You can then pass these signals to the
48//! peripheral drivers similar to how you would pass a pin.
49//!
50//! [embedded-hal]: embedded_hal
51//! [embedded-hal-async]: embedded_hal_async
52
53use core::fmt::Display;
54
55use portable_atomic::{AtomicU32, Ordering};
56use procmacros::ram;
57use strum::EnumCount;
58
59#[cfg(any(lp_io, rtc_cntl))]
60use crate::peripherals::gpio::{handle_rtcio, handle_rtcio_with_resistors};
61pub use crate::soc::gpio::*;
62use crate::{
63    interrupt::{self, InterruptHandler, Priority, DEFAULT_INTERRUPT_HANDLER},
64    peripheral::{Peripheral, PeripheralRef},
65    peripherals::{
66        gpio::{handle_gpio_input, handle_gpio_output},
67        Interrupt,
68        GPIO,
69        IO_MUX,
70    },
71    private::{self, Sealed},
72};
73
74mod placeholder;
75
76pub use placeholder::NoPin;
77
78crate::unstable_module! {
79    pub mod interconnect;
80
81    #[cfg(soc_etm)]
82    pub mod etm;
83
84    #[cfg(lp_io)]
85    pub mod lp_io;
86
87    #[cfg(all(rtc_io, not(esp32)))]
88    pub mod rtc_io;
89}
90
91mod user_irq {
92    use portable_atomic::{AtomicPtr, Ordering};
93    use procmacros::ram;
94
95    /// Convenience constant for `Option::None` pin
96    pub(super) static USER_INTERRUPT_HANDLER: CFnPtr = CFnPtr::new();
97
98    pub(super) struct CFnPtr(AtomicPtr<()>);
99    impl CFnPtr {
100        pub const fn new() -> Self {
101            Self(AtomicPtr::new(core::ptr::null_mut()))
102        }
103
104        pub fn store(&self, f: extern "C" fn()) {
105            self.0.store(f as *mut (), Ordering::Relaxed);
106        }
107
108        pub fn call(&self) {
109            let ptr = self.0.load(Ordering::Relaxed);
110            if !ptr.is_null() {
111                unsafe { (core::mem::transmute::<*mut (), extern "C" fn()>(ptr))() };
112            }
113        }
114    }
115
116    #[ram]
117    pub(super) extern "C" fn user_gpio_interrupt_handler() {
118        super::handle_pin_interrupts(|| USER_INTERRUPT_HANDLER.call());
119    }
120}
121
122/// Represents a pin-peripheral connection that, when dropped, disconnects the
123/// peripheral from the pin.
124///
125/// This only needs to be applied to output signals, as it's not possible to
126/// connect multiple inputs to the same peripheral signal.
127#[derive(Debug)]
128#[cfg_attr(feature = "defmt", derive(defmt::Format))]
129pub(crate) struct PinGuard {
130    pin: u8,
131    signal: OutputSignal,
132}
133
134impl crate::private::Sealed for PinGuard {}
135impl Peripheral for PinGuard {
136    type P = Self;
137
138    unsafe fn clone_unchecked(&self) -> Self::P {
139        Self {
140            pin: self.pin,
141            signal: self.signal,
142        }
143    }
144}
145
146impl PinGuard {
147    pub(crate) fn new(mut pin: AnyPin, signal: OutputSignal) -> Self {
148        signal.connect_to(&mut pin);
149        Self {
150            pin: pin.number(),
151            signal,
152        }
153    }
154
155    pub(crate) fn new_unconnected(signal: OutputSignal) -> Self {
156        Self {
157            pin: u8::MAX,
158            signal,
159        }
160    }
161}
162
163impl Drop for PinGuard {
164    fn drop(&mut self) {
165        if self.pin != u8::MAX {
166            let mut pin = unsafe { AnyPin::steal(self.pin) };
167            self.signal.disconnect_from(&mut pin);
168        }
169    }
170}
171
172/// Event used to trigger interrupts.
173#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
174#[cfg_attr(feature = "defmt", derive(defmt::Format))]
175pub enum Event {
176    /// Interrupts trigger on rising pin edge.
177    RisingEdge  = 1,
178    /// Interrupts trigger on falling pin edge.
179    FallingEdge = 2,
180    /// Interrupts trigger on either rising or falling pin edges.
181    AnyEdge     = 3,
182    /// Interrupts trigger on low level
183    LowLevel    = 4,
184    /// Interrupts trigger on high level
185    HighLevel   = 5,
186}
187
188impl From<WakeEvent> for Event {
189    fn from(value: WakeEvent) -> Self {
190        match value {
191            WakeEvent::LowLevel => Event::LowLevel,
192            WakeEvent::HighLevel => Event::HighLevel,
193        }
194    }
195}
196
197/// Event used to wake up from light sleep.
198#[instability::unstable]
199#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
200#[cfg_attr(feature = "defmt", derive(defmt::Format))]
201pub enum WakeEvent {
202    /// Wake on low level
203    LowLevel  = 4,
204    /// Wake on high level
205    HighLevel = 5,
206}
207
208/// Digital input or output level.
209///
210/// `Level` can be used to control a GPIO output, and it can act as a peripheral
211/// signal and be connected to peripheral inputs and outputs.
212///
213/// When connected to a peripheral
214/// input, the peripheral will read the corresponding level from that signal.
215///
216/// When connected to a peripheral output, the level will be ignored.
217#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
218#[cfg_attr(feature = "defmt", derive(defmt::Format))]
219pub enum Level {
220    /// Low
221    Low,
222    /// High
223    High,
224}
225
226impl Sealed for Level {}
227
228impl core::ops::Not for Level {
229    type Output = Self;
230
231    fn not(self) -> Self {
232        match self {
233            Self::Low => Self::High,
234            Self::High => Self::Low,
235        }
236    }
237}
238
239impl From<bool> for Level {
240    fn from(val: bool) -> Self {
241        match val {
242            true => Self::High,
243            false => Self::Low,
244        }
245    }
246}
247
248impl From<Level> for bool {
249    fn from(level: Level) -> bool {
250        match level {
251            Level::Low => false,
252            Level::High => true,
253        }
254    }
255}
256
257/// Errors that can occur when configuring a pin to be a wakeup source.
258#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
259#[cfg_attr(feature = "defmt", derive(defmt::Format))]
260#[instability::unstable]
261#[non_exhaustive]
262pub enum WakeConfigError {
263    /// Returned when trying to configure a pin to wake up from light sleep on
264    /// an edge trigger, which is not supported.
265    EdgeTriggeringNotSupported,
266}
267
268impl Display for WakeConfigError {
269    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
270        match self {
271            WakeConfigError::EdgeTriggeringNotSupported => {
272                write!(
273                    f,
274                    "Edge triggering is not supported for wake-up from light sleep"
275                )
276            }
277        }
278    }
279}
280
281impl core::error::Error for WakeConfigError {}
282
283/// Pull setting for a GPIO.
284#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
285#[cfg_attr(feature = "defmt", derive(defmt::Format))]
286pub enum Pull {
287    /// No pull
288    None,
289    /// Pull up
290    Up,
291    /// Pull down
292    Down,
293}
294
295/// Drive strength (values are approximates)
296#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, PartialOrd, Ord)]
297#[cfg_attr(feature = "defmt", derive(defmt::Format))]
298pub enum DriveStrength {
299    /// Drive strength of approximately 5mA.
300    _5mA  = 0,
301    /// Drive strength of approximately 10mA.
302    _10mA = 1,
303    /// Drive strength of approximately 20mA.
304    _20mA = 2,
305    /// Drive strength of approximately 40mA.
306    _40mA = 3,
307}
308
309/// Alternate functions
310///
311/// GPIO pins can be configured for various functions, such as GPIO
312/// or being directly connected to a peripheral's signal like UART, SPI, etc.
313/// The `AlternateFunction` enum allows selecting one of several functions that
314/// a pin can perform, rather than using it as a general-purpose input or
315/// output.
316///
317/// The different variants correspond to different functionality depending on
318/// the chip and the specific pin. For more information, refer to your chip's
319#[doc(hidden)]
320#[doc = crate::trm_markdown_link!("iomuxgpio")]
321#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
322#[cfg_attr(feature = "defmt", derive(defmt::Format))]
323pub enum AlternateFunction {
324    /// Alternate function 0.
325    _0 = 0,
326    /// Alternate function 1.
327    _1 = 1,
328    /// Alternate function 2.
329    _2 = 2,
330    /// Alternate function 3.
331    _3 = 3,
332    /// Alternate function 4.
333    _4 = 4,
334    /// Alternate function 5.
335    _5 = 5,
336}
337
338impl TryFrom<usize> for AlternateFunction {
339    type Error = ();
340
341    fn try_from(value: usize) -> Result<Self, Self::Error> {
342        match value {
343            0 => Ok(AlternateFunction::_0),
344            1 => Ok(AlternateFunction::_1),
345            2 => Ok(AlternateFunction::_2),
346            3 => Ok(AlternateFunction::_3),
347            4 => Ok(AlternateFunction::_4),
348            5 => Ok(AlternateFunction::_5),
349            _ => Err(()),
350        }
351    }
352}
353
354/// RTC function
355#[instability::unstable]
356#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
357#[cfg_attr(feature = "defmt", derive(defmt::Format))]
358pub enum RtcFunction {
359    /// RTC mode.
360    Rtc     = 0,
361    /// Digital mode.
362    Digital = 1,
363}
364
365/// Trait implemented by RTC pins
366#[instability::unstable]
367pub trait RtcPin: Pin {
368    /// RTC number of the pin
369    #[cfg(xtensa)]
370    fn rtc_number(&self) -> u8;
371
372    /// Configure the pin
373    #[cfg(any(xtensa, esp32c6))]
374    #[doc(hidden)]
375    fn rtc_set_config(&self, input_enable: bool, mux: bool, func: RtcFunction);
376
377    /// Enable or disable PAD_HOLD
378    #[doc(hidden)]
379    fn rtcio_pad_hold(&self, enable: bool);
380
381    /// # Safety
382    ///
383    /// The `level` argument needs to be a valid setting for the
384    /// `rtc_cntl.gpio_wakeup.gpio_pinX_int_type`.
385    #[cfg(any(esp32c3, esp32c2, esp32c6))]
386    #[doc(hidden)]
387    unsafe fn apply_wakeup(&self, wakeup: bool, level: u8);
388}
389
390/// Trait implemented by RTC pins which supporting internal pull-up / pull-down
391/// resistors.
392#[instability::unstable]
393#[cfg(any(lp_io, rtc_cntl))]
394pub trait RtcPinWithResistors: RtcPin {
395    /// Enable/disable the internal pull-up resistor
396    #[doc(hidden)]
397    fn rtcio_pullup(&self, enable: bool);
398    /// Enable/disable the internal pull-down resistor
399    #[doc(hidden)]
400    fn rtcio_pulldown(&self, enable: bool);
401}
402
403/// Common trait implemented by pins
404pub trait Pin: Sealed {
405    /// GPIO number
406    fn number(&self) -> u8;
407
408    /// Type-erase (degrade) this pin into an [`AnyPin`].
409    ///
410    /// This converts pin singletons (`GpioPin<0>`, …), which are all different
411    /// types, into the same type. It is useful for creating arrays of pins,
412    /// or avoiding generics.
413    ///
414    /// ## Example
415    ///
416    /// ```rust, no_run
417    #[doc = crate::before_snippet!()]
418    /// use esp_hal::gpio::{AnyPin, Pin, Output, OutputConfig, Level};
419    /// use esp_hal::delay::Delay;
420    ///
421    /// fn toggle_pins(pins: [AnyPin; 2], delay: &mut Delay) {
422    ///     let [red, blue] = pins;
423    ///     let mut red = Output::new(
424    ///         red,
425    ///         Level::High,
426    ///         OutputConfig::default(),
427    ///     );
428    ///     let mut blue = Output::new(
429    ///         blue,
430    ///         Level::Low,
431    ///         OutputConfig::default(),
432    ///     );
433    ///
434    ///     loop {
435    ///         red.toggle();
436    ///         blue.toggle();
437    ///         delay.delay_millis(500);
438    ///     }
439    /// }
440    ///
441    /// let pins: [AnyPin; 2] = [
442    ///    peripherals.GPIO5.degrade(),
443    ///    peripherals.GPIO6.degrade(),
444    /// ];
445    ///
446    /// let mut delay = Delay::new();
447    /// toggle_pins(pins, &mut delay);
448    /// # Ok(())
449    /// # }
450    /// ```
451    fn degrade(self) -> AnyPin
452    where
453        Self: Sized,
454    {
455        unsafe { AnyPin::steal(self.number()) }
456    }
457
458    #[doc(hidden)]
459    fn output_signals(&self, _: private::Internal) -> &'static [(AlternateFunction, OutputSignal)];
460
461    #[doc(hidden)]
462    fn input_signals(&self, _: private::Internal) -> &'static [(AlternateFunction, InputSignal)];
463}
464
465/// Trait implemented by pins which can be used as inputs.
466pub trait InputPin: Pin + Into<AnyPin> + 'static {}
467
468/// Trait implemented by pins which can be used as outputs.
469pub trait OutputPin: Pin + Into<AnyPin> + 'static {}
470
471/// Trait implemented by pins which can be used as analog pins
472#[instability::unstable]
473pub trait AnalogPin: Pin {
474    /// Configure the pin for analog operation
475    #[doc(hidden)]
476    fn set_analog(&self, _: private::Internal);
477}
478
479/// Trait implemented by pins which can be used as Touchpad pins
480#[cfg(touch)]
481#[instability::unstable]
482pub trait TouchPin: Pin {
483    /// Configure the pin for analog operation
484    #[doc(hidden)]
485    fn set_touch(&self, _: private::Internal);
486
487    /// Reads the pin's touch measurement register
488    #[doc(hidden)]
489    fn touch_measurement(&self, _: private::Internal) -> u16;
490
491    /// Maps the pin nr to the touch pad nr
492    #[doc(hidden)]
493    fn touch_nr(&self, _: private::Internal) -> u8;
494
495    /// Set a pins touch threshold for interrupts.
496    #[doc(hidden)]
497    fn set_threshold(&self, threshold: u16, _: private::Internal);
498}
499
500#[doc(hidden)]
501#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, EnumCount)]
502#[cfg_attr(feature = "defmt", derive(defmt::Format))]
503pub enum GpioBank {
504    _0,
505    #[cfg(gpio_bank_1)]
506    _1,
507}
508
509impl GpioBank {
510    fn async_operations(self) -> &'static AtomicU32 {
511        static FLAGS: [AtomicU32; GpioBank::COUNT] = [const { AtomicU32::new(0) }; GpioBank::COUNT];
512
513        &FLAGS[self as usize]
514    }
515
516    fn offset(self) -> u8 {
517        match self {
518            Self::_0 => 0,
519            #[cfg(gpio_bank_1)]
520            Self::_1 => 32,
521        }
522    }
523
524    fn write_out_en(self, word: u32, enable: bool) {
525        if enable {
526            self.write_out_en_set(word);
527        } else {
528            self.write_out_en_clear(word);
529        }
530    }
531
532    fn write_out_en_clear(self, word: u32) {
533        match self {
534            Self::_0 => GPIO::regs()
535                .enable_w1tc()
536                .write(|w| unsafe { w.bits(word) }),
537            #[cfg(gpio_bank_1)]
538            Self::_1 => GPIO::regs()
539                .enable1_w1tc()
540                .write(|w| unsafe { w.bits(word) }),
541        };
542    }
543
544    fn write_out_en_set(self, word: u32) {
545        match self {
546            Self::_0 => GPIO::regs()
547                .enable_w1ts()
548                .write(|w| unsafe { w.bits(word) }),
549            #[cfg(gpio_bank_1)]
550            Self::_1 => GPIO::regs()
551                .enable1_w1ts()
552                .write(|w| unsafe { w.bits(word) }),
553        };
554    }
555
556    fn read_input(self) -> u32 {
557        match self {
558            Self::_0 => GPIO::regs().in_().read().bits(),
559            #[cfg(gpio_bank_1)]
560            Self::_1 => GPIO::regs().in1().read().bits(),
561        }
562    }
563
564    fn read_output(self) -> u32 {
565        match self {
566            Self::_0 => GPIO::regs().out().read().bits(),
567            #[cfg(gpio_bank_1)]
568            Self::_1 => GPIO::regs().out1().read().bits(),
569        }
570    }
571
572    fn read_interrupt_status(self) -> u32 {
573        match self {
574            Self::_0 => GPIO::regs().status().read().bits(),
575            #[cfg(gpio_bank_1)]
576            Self::_1 => GPIO::regs().status1().read().bits(),
577        }
578    }
579
580    fn write_interrupt_status_clear(self, word: u32) {
581        match self {
582            Self::_0 => GPIO::regs()
583                .status_w1tc()
584                .write(|w| unsafe { w.bits(word) }),
585            #[cfg(gpio_bank_1)]
586            Self::_1 => GPIO::regs()
587                .status1_w1tc()
588                .write(|w| unsafe { w.bits(word) }),
589        };
590    }
591
592    fn write_output(self, word: u32, set: bool) {
593        if set {
594            self.write_output_set(word);
595        } else {
596            self.write_output_clear(word);
597        }
598    }
599
600    fn write_output_set(self, word: u32) {
601        match self {
602            Self::_0 => GPIO::regs().out_w1ts().write(|w| unsafe { w.bits(word) }),
603            #[cfg(gpio_bank_1)]
604            Self::_1 => GPIO::regs().out1_w1ts().write(|w| unsafe { w.bits(word) }),
605        };
606    }
607
608    fn write_output_clear(self, word: u32) {
609        match self {
610            Self::_0 => GPIO::regs().out_w1tc().write(|w| unsafe { w.bits(word) }),
611            #[cfg(gpio_bank_1)]
612            Self::_1 => GPIO::regs().out1_w1tc().write(|w| unsafe { w.bits(word) }),
613        };
614    }
615}
616
617/// GPIO pin
618#[non_exhaustive]
619#[derive(Debug)]
620#[cfg_attr(feature = "defmt", derive(defmt::Format))]
621pub struct GpioPin<const GPIONUM: u8>;
622
623/// Type-erased GPIO pin
624#[derive(Debug)]
625#[cfg_attr(feature = "defmt", derive(defmt::Format))]
626pub struct AnyPin(pub(crate) u8);
627
628impl<const GPIONUM: u8> GpioPin<GPIONUM>
629where
630    Self: Pin,
631{
632    /// Create a pin out of thin air.
633    ///
634    /// # Safety
635    ///
636    /// Ensure that only one instance of a pin exists at one time.
637    pub unsafe fn steal() -> Self {
638        Self
639    }
640
641    /// Split the pin into an input and output signal.
642    ///
643    /// Peripheral signals allow connecting peripherals together without using
644    /// external hardware.
645    ///
646    /// ```rust, no_run
647    #[doc = crate::before_snippet!()]
648    /// let (rx, tx) = peripherals.GPIO2.split();
649    /// # Ok(())
650    /// # }
651    /// ```
652    #[instability::unstable]
653    pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
654        // FIXME: we should implement this in the gpio macro for output pins, but we
655        // should also have an input-only alternative for pins that can't be used as
656        // outputs.
657        self.degrade().split()
658    }
659}
660
661/// Workaround to make D+ and D- work on the ESP32-C3 and ESP32-S3, which by
662/// default are assigned to the `USB_SERIAL_JTAG` peripheral.
663#[cfg(usb_device)]
664fn disable_usb_pads(gpionum: u8) {
665    cfg_if::cfg_if! {
666        if #[cfg(esp32c3)] {
667            let pins = [18, 19];
668        } else if #[cfg(esp32c6)] {
669            let pins = [12, 13];
670        } else if #[cfg(esp32h2)] {
671            let pins = [26, 27];
672        } else if #[cfg(esp32s3)] {
673            let pins = [19, 20];
674        } else {
675            compile_error!("Please define USB pins for this chip");
676        }
677    }
678
679    if pins.contains(&gpionum) {
680        crate::peripherals::USB_DEVICE::regs()
681            .conf0()
682            .modify(|_, w| {
683                w.usb_pad_enable().clear_bit();
684                w.dm_pullup().clear_bit();
685                w.dm_pulldown().clear_bit();
686                w.dp_pullup().clear_bit();
687                w.dp_pulldown().clear_bit()
688            });
689    }
690}
691
692impl<const GPIONUM: u8> Peripheral for GpioPin<GPIONUM>
693where
694    Self: Pin,
695{
696    type P = GpioPin<GPIONUM>;
697
698    unsafe fn clone_unchecked(&self) -> Self::P {
699        core::ptr::read(self as *const _)
700    }
701}
702
703impl<const GPIONUM: u8> private::Sealed for GpioPin<GPIONUM> {}
704
705pub(crate) fn bind_default_interrupt_handler() {
706    // We first check if a handler is set in the vector table.
707    if let Some(handler) = interrupt::bound_handler(Interrupt::GPIO) {
708        let handler = handler as *const unsafe extern "C" fn();
709
710        // We only allow binding the default handler if nothing else is bound.
711        // This prevents silently overwriting RTIC's interrupt handler, if using GPIO.
712        if !core::ptr::eq(handler, DEFAULT_INTERRUPT_HANDLER.handler() as _) {
713            // The user has configured an interrupt handler they wish to use.
714            info!("Not using default GPIO interrupt handler: already bound in vector table");
715            return;
716        }
717    }
718    // The vector table doesn't contain a custom entry.Still, the
719    // peripheral interrupt may already be bound to something else.
720    if interrupt::bound_cpu_interrupt_for(crate::system::Cpu::current(), Interrupt::GPIO).is_some()
721    {
722        info!("Not using default GPIO interrupt handler: peripheral interrupt already in use");
723        return;
724    }
725
726    unsafe { interrupt::bind_interrupt(Interrupt::GPIO, default_gpio_interrupt_handler) };
727    // By default, we use lowest priority
728    unwrap!(interrupt::enable(Interrupt::GPIO, Priority::min()));
729}
730
731/// General Purpose Input/Output driver
732#[derive(Debug)]
733#[cfg_attr(feature = "defmt", derive(defmt::Format))]
734#[instability::unstable]
735pub struct Io {
736    _io_mux: IO_MUX,
737}
738
739impl Io {
740    /// Initialize the I/O driver.
741    #[instability::unstable]
742    pub fn new(_io_mux: IO_MUX) -> Self {
743        Io { _io_mux }
744    }
745
746    /// Set the interrupt priority for GPIO interrupts.
747    ///
748    /// # Panics
749    ///
750    /// Panics if passed interrupt handler is invalid (e.g. has priority
751    /// `None`)
752    #[instability::unstable]
753    pub fn set_interrupt_priority(&self, prio: Priority) {
754        unwrap!(interrupt::enable(Interrupt::GPIO, prio));
755    }
756
757    #[cfg_attr(
758        not(multi_core),
759        doc = "Registers an interrupt handler for all GPIO pins."
760    )]
761    #[cfg_attr(
762        multi_core,
763        doc = "Registers an interrupt handler for all GPIO pins on the current core."
764    )]
765    #[doc = ""]
766    /// Note that when using interrupt handlers registered by this function,
767    /// we clear the interrupt status register for you. This is NOT the case
768    /// if you register the interrupt handler directly, by defining a
769    /// `#[no_mangle] unsafe extern "C" fn GPIO()` function.
770    ///
771    /// # Panics
772    ///
773    /// Panics if passed interrupt handler is invalid (e.g. has priority
774    /// `None`)
775    #[instability::unstable]
776    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
777        for core in crate::system::Cpu::other() {
778            crate::interrupt::disable(core, Interrupt::GPIO);
779        }
780        self.set_interrupt_priority(handler.priority());
781        unsafe {
782            interrupt::bind_interrupt(Interrupt::GPIO, user_irq::user_gpio_interrupt_handler)
783        };
784        user_irq::USER_INTERRUPT_HANDLER.store(handler.handler());
785    }
786}
787
788impl crate::private::Sealed for Io {}
789
790#[instability::unstable]
791impl crate::interrupt::InterruptConfigurable for Io {
792    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
793        self.set_interrupt_handler(handler);
794    }
795}
796
797#[ram]
798extern "C" fn default_gpio_interrupt_handler() {
799    handle_pin_interrupts(|| ());
800}
801
802#[ram]
803fn handle_pin_interrupts(user_handler: fn()) {
804    let intrs_bank0 = InterruptStatusRegisterAccess::Bank0.interrupt_status_read();
805
806    #[cfg(gpio_bank_1)]
807    let intrs_bank1 = InterruptStatusRegisterAccess::Bank1.interrupt_status_read();
808
809    user_handler();
810
811    let banks = [
812        (GpioBank::_0, intrs_bank0),
813        #[cfg(gpio_bank_1)]
814        (GpioBank::_1, intrs_bank1),
815    ];
816
817    for (bank, intrs) in banks {
818        // Get the mask of active async pins and also unmark them in the same go.
819        let async_pins = bank.async_operations().fetch_and(!intrs, Ordering::Relaxed);
820
821        // Wake up the tasks
822        let mut intr_bits = intrs & async_pins;
823        while intr_bits != 0 {
824            let pin_pos = intr_bits.trailing_zeros();
825            intr_bits -= 1 << pin_pos;
826
827            let pin_nr = pin_pos as u8 + bank.offset();
828
829            crate::interrupt::free(|| {
830                asynch::PIN_WAKERS[pin_nr as usize].wake();
831                set_int_enable(pin_nr, Some(0), 0, false);
832            });
833        }
834
835        bank.write_interrupt_status_clear(intrs);
836    }
837}
838
839#[doc(hidden)]
840#[macro_export]
841macro_rules! if_output_pin {
842    // Base case: not an Output pin, substitute the else branch
843    ({ $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
844
845    // First is an Output pin, skip checking and substitute the then branch
846    (Output $(, $other:ident)* { $($then:tt)* } else { $($else:tt)* }) => { $($then)* };
847
848    // First is not an Output pin, check the rest
849    ($not:ident $(, $other:ident)* { $($then:tt)* } else { $($else:tt)* }) => {
850        $crate::if_output_pin!($($other),* { $($then)* } else { $($else)* })
851    };
852}
853
854#[doc(hidden)]
855#[macro_export]
856macro_rules! if_rtcio_pin {
857    // Base case: not an RtcIo pin, substitute the else branch
858    ({ $($then:tt)* } else { $($else:tt)* }) => { $($else)* };
859
860    // First is an RtcIo pin, skip checking and substitute the then branch
861    (RtcIo $(, $other:ident)* { $($then:tt)* } else { $($else:tt)* }) => { $($then)* };
862    (RtcIoInput $(, $other:ident)* { $($then:tt)* } else { $($else:tt)* }) => { $($then)* };
863
864    // First is not an RtcIo pin, check the rest
865    ($not:ident $(, $other:ident)* { $($then:tt)* } else { $($else:tt)* }) => {
866        $crate::if_rtcio_pin!($($other),* { $($then)* } else { $($else)* })
867    };
868}
869
870#[doc(hidden)]
871#[macro_export]
872macro_rules! io_type {
873    (Input, $gpionum:literal) => {
874        impl $crate::gpio::InputPin for $crate::gpio::GpioPin<$gpionum> {}
875    };
876    (Output, $gpionum:literal) => {
877        impl $crate::gpio::OutputPin for $crate::gpio::GpioPin<$gpionum> {}
878    };
879    (Analog, $gpionum:literal) => {
880        // FIXME: the implementation shouldn't be in the GPIO module
881        #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2))]
882        #[cfg(any(doc, feature = "unstable"))]
883        #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
884        impl $crate::gpio::AnalogPin for $crate::gpio::GpioPin<$gpionum> {
885            /// Configures the pin for analog mode.
886            fn set_analog(&self, _: $crate::private::Internal) {
887                use $crate::peripherals::GPIO;
888
889                $crate::gpio::io_mux_reg($gpionum).modify(|_, w| unsafe {
890                    w.mcu_sel().bits(1);
891                    w.fun_ie().clear_bit();
892                    w.fun_wpu().clear_bit();
893                    w.fun_wpd().clear_bit()
894                });
895
896                GPIO::regs()
897                    .enable_w1tc()
898                    .write(|w| unsafe { w.bits(1 << $gpionum) });
899            }
900        }
901    };
902    ($other:ident, $gpionum:literal) => {
903        // TODO
904    };
905}
906
907#[doc(hidden)]
908#[macro_export]
909macro_rules! gpio {
910    (
911        $(
912            ($gpionum:literal, [$($type:tt),*]
913                $(
914                    ( $( $af_input_num:literal => $af_input_signal:ident )* )
915                    ( $( $af_output_num:literal => $af_output_signal:ident )* )
916                )?
917            )
918        )+
919    ) => {
920        paste::paste! {
921            $(
922                $(
923                    $crate::io_type!($type, $gpionum);
924                )*
925
926                impl $crate::gpio::Pin for $crate::gpio::GpioPin<$gpionum> {
927                    #[inline(always)]
928                    fn number(&self) -> u8 {
929                        $gpionum
930                    }
931
932                    fn output_signals(&self, _: $crate::private::Internal) -> &'static [($crate::gpio::AlternateFunction, $crate::gpio::OutputSignal)] {
933                        &[
934                            $(
935                                $(
936                                    (
937                                        $crate::gpio::AlternateFunction::[< _ $af_output_num >],
938                                        $crate::gpio::OutputSignal::$af_output_signal
939                                    ),
940                                )*
941                            )?
942                        ]
943                    }
944
945                    fn input_signals(&self, _: $crate::private::Internal) -> &'static [($crate::gpio::AlternateFunction, $crate::gpio::InputSignal)] {
946                        &[
947                            $(
948                                $(
949                                    (
950                                        $crate::gpio::AlternateFunction::[< _ $af_input_num >],
951                                        $crate::gpio::InputSignal::$af_input_signal
952                                    ),
953                                )*
954                            )?
955                        ]
956                    }
957                }
958
959                impl From<$crate::gpio::GpioPin<$gpionum>> for $crate::gpio::AnyPin {
960                    fn from(pin: $crate::gpio::GpioPin<$gpionum>) -> Self {
961                        $crate::gpio::Pin::degrade(pin)
962                    }
963                }
964            )+
965
966            impl $crate::peripheral::Peripheral for $crate::gpio::AnyPin {
967                type P = $crate::gpio::AnyPin;
968                unsafe fn clone_unchecked(&self) ->  Self {
969                    Self(self.0)
970                }
971            }
972
973            impl $crate::gpio::AnyPin {
974                /// Conjure a new GPIO pin out of thin air.
975                ///
976                /// # Safety
977                ///
978                /// The caller must ensure that only one instance of a pin is in use at one time.
979                ///
980                /// # Panics
981                ///
982                /// Panics if the pin with the given number does not exist.
983                pub unsafe fn steal(pin: u8) ->  Self {
984                    const PINS: &[u8] = &[$($gpionum),*];
985                    assert!(PINS.contains(&pin), "Pin {} does not exist", pin);
986                    Self(pin)
987                }
988
989                pub(crate) fn is_output(&self) -> bool {
990                    match self.0 {
991                        $(
992                            $gpionum => $crate::if_output_pin!($($type),* { true } else { false }),
993                        )+
994                        _ => false,
995                    }
996                }
997            }
998
999            // These macros call the code block on the actually contained GPIO pin.
1000
1001            #[doc(hidden)]
1002            macro_rules! handle_gpio_output {
1003                ($this:expr, $inner:ident, $code:tt) => {
1004                    match $this.number() {
1005                        $(
1006                            $gpionum => $crate::if_output_pin!($($type),* {{
1007                                #[allow(unused_mut)]
1008                                let mut $inner = unsafe { GpioPin::<$gpionum>::steal() };
1009                                $code
1010                            }} else {{
1011                                panic!("Unsupported")
1012                            }}),
1013                        )+
1014                        _ => unreachable!(),
1015                    }
1016                }
1017            }
1018
1019            #[doc(hidden)]
1020            macro_rules! handle_gpio_input {
1021                ($this:expr, $inner:ident, $code:tt) => {
1022                    match $this.number() {
1023                        $(
1024                            $gpionum => {{
1025                                #[allow(unused_mut)]
1026                                let mut $inner = unsafe { GpioPin::<$gpionum>::steal() };
1027                                $code
1028                            }},
1029                        )+
1030                        _ => unreachable!(),
1031                    }
1032                }
1033            }
1034
1035            pub(crate) use handle_gpio_output;
1036            pub(crate) use handle_gpio_input;
1037
1038            cfg_if::cfg_if! {
1039                if #[cfg(any(lp_io, rtc_cntl))] {
1040                    #[doc(hidden)]
1041                    macro_rules! handle_rtcio {
1042                        ($this:expr, $inner:ident, $code:tt) => {
1043                            match $this.number() {
1044                                $(
1045                                    $gpionum => $crate::if_rtcio_pin!($($type),* {{
1046                                        #[allow(unused_mut)]
1047                                        let mut $inner = unsafe { GpioPin::<$gpionum>::steal() };
1048                                        $code
1049                                    }} else {{
1050                                        panic!("Unsupported")
1051                                    }}),
1052                                )+
1053                                _ => unreachable!(),
1054                            }
1055                        }
1056                    }
1057
1058                    #[doc(hidden)]
1059                    macro_rules! handle_rtcio_with_resistors {
1060                        ($this:expr, $inner:ident, $code:tt) => {
1061                            match $this.number() {
1062                                $(
1063                                    $gpionum => $crate::if_rtcio_pin!($($type),* {
1064                                        $crate::if_output_pin!($($type),* {{
1065                                            #[allow(unused_mut)]
1066                                            let mut $inner = unsafe { GpioPin::<$gpionum>::steal() };
1067                                            $code
1068                                        }} else {{
1069                                            panic!("Unsupported")
1070                                        }})
1071                                    } else {{
1072                                        panic!("Unsupported")
1073                                    }}),
1074                                )+
1075                                _ => unreachable!(),
1076                            }
1077                        }
1078                    }
1079
1080                    pub(crate) use handle_rtcio;
1081                    pub(crate) use handle_rtcio_with_resistors;
1082                }
1083            }
1084        }
1085    };
1086}
1087
1088/// The drive mode of the output pin.
1089#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1090#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1091pub enum DriveMode {
1092    /// Push-pull output.
1093    ///
1094    /// The driver actively sets the output voltage level for both high and low
1095    /// logical [`Level`]s.
1096    PushPull,
1097
1098    /// Open drain output.
1099    ///
1100    /// The driver actively pulls the output voltage level low for the low
1101    /// logical [`Level`], but leaves the high level floating, which is then
1102    /// determined by external hardware, or internal pull-up/pull-down
1103    /// resistors.
1104    OpenDrain,
1105}
1106
1107/// Output pin configuration.
1108///
1109/// This struct is used to configure the drive mode, drive strength, and pull
1110/// direction of an output pin. By default, the configuration is set to:
1111/// - Drive mode: [`DriveMode::PushPull`]
1112/// - Drive strength: [`DriveStrength::_20mA`]
1113/// - Pull direction: [`Pull::None`] (no pull resistors connected)
1114#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1115#[derive(Debug, Clone, Copy, PartialEq, Eq, procmacros::BuilderLite)]
1116#[non_exhaustive]
1117pub struct OutputConfig {
1118    /// Output drive mode.
1119    drive_mode: DriveMode,
1120
1121    /// Pin drive strength.
1122    drive_strength: DriveStrength,
1123
1124    /// Pin pull direction.
1125    pull: Pull,
1126}
1127
1128impl Default for OutputConfig {
1129    fn default() -> Self {
1130        Self {
1131            drive_mode: DriveMode::PushPull,
1132            drive_strength: DriveStrength::_20mA,
1133            pull: Pull::None,
1134        }
1135    }
1136}
1137
1138/// Push-pull digital output.
1139///
1140/// This driver configures the GPIO pin to be an output driver.
1141#[derive(Debug)]
1142#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1143pub struct Output<'d> {
1144    pin: Flex<'d>,
1145}
1146
1147impl private::Sealed for Output<'_> {}
1148
1149impl<'d> Peripheral for Output<'d> {
1150    type P = Flex<'d>;
1151    unsafe fn clone_unchecked(&self) -> Self::P {
1152        self.pin.clone_unchecked()
1153    }
1154}
1155
1156impl<'d> Output<'d> {
1157    /// Creates a new GPIO output driver.
1158    ///
1159    /// The `initial_level` parameter sets the initial output level of the pin.
1160    /// The `config` parameter sets the drive mode, drive strength, and pull
1161    /// direction of the pin.
1162    ///
1163    /// ## Example
1164    ///
1165    /// The following example configures `GPIO5` to pulse a LED once. The
1166    /// example assumes that the LED is connected such that it is on when
1167    /// the pin is low.
1168    ///
1169    /// ```rust, no_run
1170    #[doc = crate::before_snippet!()]
1171    /// use esp_hal::gpio::{Level, Output, OutputConfig};
1172    /// use esp_hal::delay::Delay;
1173    ///
1174    /// fn blink_once(led: &mut Output<'_>, delay: &mut Delay) {
1175    ///     led.set_low();
1176    ///     delay.delay_millis(500);
1177    ///     led.set_high();
1178    /// }
1179    ///
1180    /// let config = OutputConfig::default();
1181    /// let mut led = Output::new(peripherals.GPIO5, Level::High, config);
1182    /// let mut delay = Delay::new();
1183    ///
1184    /// blink_once(&mut led, &mut delay);
1185    /// # Ok(())
1186    /// # }
1187    /// ```
1188    // FIXME: when https://github.com/esp-rs/esp-hal/issues/2839 is resolved, add an appropriate `# Error` entry.
1189    #[inline]
1190    pub fn new(
1191        pin: impl Peripheral<P = impl OutputPin> + 'd,
1192        initial_level: Level,
1193        config: OutputConfig,
1194    ) -> Self {
1195        // Set up the pin
1196        let mut this = Self {
1197            pin: Flex::new(pin),
1198        };
1199        this.set_level(initial_level);
1200        this.apply_config(&config);
1201        this.pin.pin.enable_output(true);
1202
1203        this
1204    }
1205
1206    /// Split the pin into an input and output signal.
1207    ///
1208    /// Peripheral signals allow connecting peripherals together without using
1209    /// external hardware.
1210    /// ```rust, no_run
1211    #[doc = crate::before_snippet!()]
1212    /// # use esp_hal::gpio::{Output, OutputConfig, Level};
1213    /// # let config = OutputConfig::default();
1214    /// let pin1 = Output::new(peripherals.GPIO1, Level::High, config);
1215    /// let (input, output) = pin1.split();
1216    /// # Ok(())
1217    /// # }
1218    /// ```
1219    #[inline]
1220    #[instability::unstable]
1221    pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
1222        self.pin.split()
1223    }
1224
1225    /// Returns a peripheral [input][interconnect::InputSignal] connected to
1226    /// this pin.
1227    ///
1228    /// The input signal can be passed to peripherals in place of an input pin.
1229    /// ```rust, no_run
1230    #[doc = crate::before_snippet!()]
1231    /// # use esp_hal::gpio::{Output, OutputConfig, Level};
1232    /// # let config = OutputConfig::default();
1233    /// let pin1_gpio = Output::new(peripherals.GPIO1, Level::High, config);
1234    /// // Can be passed as an input.
1235    /// let input = pin1_gpio.peripheral_input();
1236    /// # Ok(())
1237    /// # }
1238    /// ```
1239    #[inline]
1240    #[instability::unstable]
1241    pub fn peripheral_input(&self) -> interconnect::InputSignal {
1242        self.pin.peripheral_input()
1243    }
1244
1245    /// Turns the pin object into a peripheral
1246    /// [output][interconnect::OutputSignal].
1247    ///
1248    /// The output signal can be passed to peripherals in place of an output
1249    /// pin.
1250    /// ```rust, no_run
1251    #[doc = crate::before_snippet!()]
1252    /// # use esp_hal::gpio::{Output, OutputConfig, Level};
1253    /// # let config = OutputConfig::default();
1254    /// let pin1_gpio = Output::new(peripherals.GPIO1, Level::High, config);
1255    /// let output = pin1_gpio.into_peripheral_output();
1256    /// # Ok(())
1257    /// # }
1258    /// ```
1259    #[inline]
1260    #[instability::unstable]
1261    pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
1262        self.pin.into_peripheral_output()
1263    }
1264
1265    /// Change the configuration.
1266    #[inline]
1267    pub fn apply_config(&mut self, config: &OutputConfig) {
1268        self.pin.apply_output_config(config)
1269    }
1270
1271    /// Set the output as high.
1272    #[inline]
1273    pub fn set_high(&mut self) {
1274        self.set_level(Level::High)
1275    }
1276
1277    /// Set the output as low.
1278    #[inline]
1279    pub fn set_low(&mut self) {
1280        self.set_level(Level::Low)
1281    }
1282
1283    /// Set the output level.
1284    #[inline]
1285    pub fn set_level(&mut self, level: Level) {
1286        self.pin.set_level(level)
1287    }
1288
1289    /// Returns whether the pin is set to high level.
1290    ///
1291    /// This function reads back the value set using `set_level`, `set_high` or
1292    /// `set_low`. It does not need the input stage to be enabled.
1293    #[inline]
1294    pub fn is_set_high(&self) -> bool {
1295        self.output_level() == Level::High
1296    }
1297
1298    /// Returns whether the pin is set to low level.
1299    ///
1300    /// This function reads back the value set using `set_level`, `set_high` or
1301    /// `set_low`. It does not need the input stage to be enabled.
1302    #[inline]
1303    pub fn is_set_low(&self) -> bool {
1304        self.output_level() == Level::Low
1305    }
1306
1307    /// Returns which level the pin is set to.
1308    ///
1309    /// This function reads back the value set using `set_level`, `set_high` or
1310    /// `set_low`. It does not need the input stage to be enabled.
1311    #[inline]
1312    pub fn output_level(&self) -> Level {
1313        self.pin.output_level()
1314    }
1315
1316    /// Toggles the pin output.
1317    ///
1318    /// If the pin was previously set to high, it will be set to low, and vice
1319    /// versa.
1320    #[inline]
1321    pub fn toggle(&mut self) {
1322        self.pin.toggle();
1323    }
1324
1325    /// Converts the pin driver into a [`Flex`] driver.
1326    #[inline]
1327    #[instability::unstable]
1328    pub fn into_flex(self) -> Flex<'d> {
1329        self.pin
1330    }
1331}
1332
1333/// Input pin configuration.
1334#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1335#[derive(Debug, Clone, Copy, PartialEq, Eq, procmacros::BuilderLite)]
1336#[non_exhaustive]
1337pub struct InputConfig {
1338    /// Initial pull of the pin.
1339    pull: Pull,
1340}
1341
1342impl Default for InputConfig {
1343    fn default() -> Self {
1344        Self { pull: Pull::None }
1345    }
1346}
1347
1348/// Digital input.
1349///
1350/// This driver configures the GPIO pin to be an input. Input drivers read the
1351/// voltage of their pins and convert it to a logical [`Level`].
1352#[derive(Debug)]
1353#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1354pub struct Input<'d> {
1355    pin: Flex<'d>,
1356}
1357
1358impl private::Sealed for Input<'_> {}
1359
1360impl<'d> Peripheral for Input<'d> {
1361    type P = Flex<'d>;
1362    unsafe fn clone_unchecked(&self) -> Self::P {
1363        self.pin.clone_unchecked()
1364    }
1365}
1366
1367impl<'d> Input<'d> {
1368    /// Creates a new GPIO input.
1369    ///
1370    /// The `pull` parameter configures internal pull-up or pull-down
1371    /// resistors.
1372    ///
1373    /// ## Example
1374    ///
1375    /// The following example configures `GPIO5` to read a button press. The
1376    /// example assumes that the button is connected such that the pin is low
1377    /// when the button is pressed.
1378    ///
1379    /// ```rust, no_run
1380    #[doc = crate::before_snippet!()]
1381    /// use esp_hal::gpio::{Level, Input, InputConfig, Pull};
1382    /// use esp_hal::delay::Delay;
1383    ///
1384    /// fn print_when_pressed(button: &mut Input<'_>, delay: &mut Delay) {
1385    ///     let mut was_pressed = false;
1386    ///     loop {
1387    ///         let is_pressed = button.is_low();
1388    ///         if is_pressed && !was_pressed {
1389    ///             println!("Button pressed!");
1390    ///         }
1391    ///         was_pressed = is_pressed;
1392    ///         delay.delay_millis(100);
1393    ///     }
1394    /// }
1395    ///
1396    /// let config = InputConfig::default().with_pull(Pull::Up);
1397    /// let mut button = Input::new(peripherals.GPIO5, config);
1398    /// let mut delay = Delay::new();
1399    ///
1400    /// print_when_pressed(&mut button, &mut delay);
1401    /// # Ok(())
1402    /// # }
1403    /// ```
1404    // FIXME: when https://github.com/esp-rs/esp-hal/issues/2839 is resolved, add an appropriate `# Error` entry.
1405    #[inline]
1406    pub fn new(pin: impl Peripheral<P = impl InputPin> + 'd, config: InputConfig) -> Self {
1407        let mut pin = Flex::new(pin);
1408
1409        pin.pin.enable_output(false);
1410        pin.enable_input(true);
1411        pin.apply_input_config(&config);
1412
1413        Self { pin }
1414    }
1415
1416    /// Returns a peripheral [input][interconnect::InputSignal] connected to
1417    /// this pin.
1418    ///
1419    /// The input signal can be passed to peripherals in place of an input pin.
1420    /// ```rust, no_run
1421    #[doc = crate::before_snippet!()]
1422    /// # use esp_hal::gpio::{Input, InputConfig, Pull};
1423    /// let config = InputConfig::default().with_pull(Pull::Up);
1424    /// let pin1_gpio = Input::new(peripherals.GPIO1, config);
1425    /// let pin1 = pin1_gpio.peripheral_input();
1426    /// # Ok(())
1427    /// # }
1428    /// ```
1429    #[inline]
1430    #[instability::unstable]
1431    pub fn peripheral_input(&self) -> interconnect::InputSignal {
1432        self.pin.peripheral_input()
1433    }
1434
1435    /// Get whether the pin input level is high.
1436    #[inline]
1437    pub fn is_high(&self) -> bool {
1438        self.level() == Level::High
1439    }
1440
1441    /// Get whether the pin input level is low.
1442    #[inline]
1443    pub fn is_low(&self) -> bool {
1444        self.level() == Level::Low
1445    }
1446
1447    /// Get the current pin input level.
1448    #[inline]
1449    pub fn level(&self) -> Level {
1450        self.pin.level()
1451    }
1452
1453    /// Change the configuration.
1454    pub fn apply_config(&mut self, config: &InputConfig) {
1455        self.pin.apply_input_config(config)
1456    }
1457
1458    /// Listen for interrupts.
1459    ///
1460    /// The interrupts will be handled by the handler set using
1461    /// [`Io::set_interrupt_handler`]. All GPIO pins share the same
1462    /// interrupt handler.
1463    ///
1464    /// Note that [`Event::LowLevel`] and [`Event::HighLevel`] are fired
1465    /// continuously when the pin is low or high, respectively. You must use
1466    /// a custom interrupt handler to stop listening for these events,
1467    /// otherwise your program will be stuck in a loop as long as the pin is
1468    /// reading the corresponding level.
1469    ///
1470    /// ## Examples
1471    ///
1472    /// ### Print something when a button is pressed.
1473    /// ```rust, no_run
1474    #[doc = crate::before_snippet!()]
1475    /// use esp_hal::gpio::{Event, Input, InputConfig, Pull, Io};
1476    ///
1477    /// let mut io = Io::new(peripherals.IO_MUX);
1478    /// io.set_interrupt_handler(handler);
1479    ///
1480    /// // Set up the input and store it in the static variable.
1481    /// // This example uses a push button that is high when not
1482    /// // pressed and low when pressed.
1483    /// let config = InputConfig::default().with_pull(Pull::Up);
1484    /// let mut button = Input::new(peripherals.GPIO5, config);
1485    ///
1486    /// critical_section::with(|cs| {
1487    ///     // Here we are listening for a low level to demonstrate
1488    ///     // that you need to stop listening for level interrupts,
1489    ///     // but usually you'd probably use `FallingEdge`.
1490    ///     button.listen(Event::LowLevel);
1491    ///     BUTTON.borrow_ref_mut(cs).replace(button);
1492    /// });
1493    /// # Ok(())
1494    /// # }
1495    ///
1496    /// // Outside of your `main` function:
1497    ///
1498    /// # use esp_hal::gpio::Input;
1499    /// use core::cell::RefCell;
1500    /// use critical_section::Mutex;
1501    ///
1502    /// // You will need to store the `Input` object in a static variable so
1503    /// // that the interrupt handler can access it.
1504    /// static BUTTON: Mutex<RefCell<Option<Input>>> =
1505    ///     Mutex::new(RefCell::new(None));
1506    ///
1507    /// #[handler]
1508    /// fn handler() {
1509    ///     critical_section::with(|cs| {
1510    ///         let mut button = BUTTON.borrow_ref_mut(cs);
1511    ///         let Some(button) = button.as_mut() else {
1512    ///             // Some other interrupt has occurred
1513    ///             // before the button was set up.
1514    ///             return;
1515    ///         };
1516    ///
1517    ///         if button.is_interrupt_set() {
1518    ///             print!("Button pressed");
1519    ///
1520    ///             // If you want to stop listening for interrupts, you need to
1521    ///             // call `unlisten` here. If you comment this line, the
1522    ///             // interrupt will fire continuously while the button
1523    ///             // is pressed.
1524    ///             button.unlisten();
1525    ///         }
1526    ///     });
1527    /// }
1528    /// ```
1529    #[inline]
1530    #[instability::unstable]
1531    pub fn listen(&mut self, event: Event) {
1532        self.pin.listen(event);
1533    }
1534
1535    /// Stop listening for interrupts
1536    #[inline]
1537    #[instability::unstable]
1538    pub fn unlisten(&mut self) {
1539        self.pin.unlisten();
1540    }
1541
1542    /// Clear the interrupt status bit for this Pin
1543    #[inline]
1544    #[instability::unstable]
1545    pub fn clear_interrupt(&mut self) {
1546        self.pin.clear_interrupt();
1547    }
1548
1549    /// Checks if the interrupt status bit for this Pin is set
1550    #[inline]
1551    #[instability::unstable]
1552    pub fn is_interrupt_set(&self) -> bool {
1553        self.pin.is_interrupt_set()
1554    }
1555
1556    /// Enable as a wake-up source.
1557    ///
1558    /// This will unlisten for interrupts
1559    ///
1560    /// # Error
1561    /// Configuring pin to wake up from light sleep on an edge
1562    /// trigger is currently not supported, corresponding variant of
1563    /// [`WakeConfigError`] will be returned.
1564    #[instability::unstable]
1565    #[inline]
1566    pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) -> Result<(), WakeConfigError> {
1567        self.pin.wakeup_enable(enable, event)
1568    }
1569
1570    /// Split the pin into an input and output signal.
1571    ///
1572    /// Peripheral signals allow connecting peripherals together without using
1573    /// external hardware.
1574    /// ```rust, no_run
1575    #[doc = crate::before_snippet!()]
1576    /// # use esp_hal::gpio::{Input, InputConfig, Pull};
1577    /// let config = InputConfig::default().with_pull(Pull::Up);
1578    /// let pin1 = Input::new(peripherals.GPIO1, config);
1579    /// let (input, output) = pin1.split();
1580    /// # Ok(())
1581    /// # }
1582    /// ```
1583    #[inline]
1584    #[instability::unstable]
1585    pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
1586        self.pin.split()
1587    }
1588
1589    /// Turns the pin object into a peripheral
1590    /// [output][interconnect::OutputSignal].
1591    ///
1592    /// The output signal can be passed to peripherals in place of an output
1593    /// pin.
1594    /// ```rust, no_run
1595    #[doc = crate::before_snippet!()]
1596    /// # use esp_hal::gpio::{Input, InputConfig, Pull};
1597    /// let config = InputConfig::default().with_pull(Pull::Up);
1598    /// let pin1_gpio = Input::new(peripherals.GPIO1, config);
1599    /// // Can be passed as an output.
1600    /// let pin1 = pin1_gpio.into_peripheral_output();
1601    /// # Ok(())
1602    /// # }
1603    /// ```
1604    #[inline]
1605    #[instability::unstable]
1606    pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
1607        self.pin.into_peripheral_output()
1608    }
1609
1610    /// Converts the pin driver into a [`Flex`] driver.
1611    #[inline]
1612    #[instability::unstable]
1613    pub fn into_flex(self) -> Flex<'d> {
1614        self.pin
1615    }
1616}
1617
1618/// Flexible pin driver.
1619///
1620/// This driver allows changing the pin mode between input and output.
1621#[derive(Debug)]
1622#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1623pub struct Flex<'d> {
1624    pin: PeripheralRef<'d, AnyPin>,
1625}
1626
1627impl private::Sealed for Flex<'_> {}
1628
1629impl Peripheral for Flex<'_> {
1630    type P = Self;
1631    unsafe fn clone_unchecked(&self) -> Self::P {
1632        Self {
1633            pin: PeripheralRef::new(AnyPin(self.pin.number())),
1634        }
1635    }
1636}
1637
1638impl<'d> Flex<'d> {
1639    /// Create flexible pin driver for a [Pin].
1640    /// No mode change happens.
1641    #[inline]
1642    #[instability::unstable]
1643    pub fn new(pin: impl Peripheral<P = impl Into<AnyPin>> + 'd) -> Self {
1644        crate::into_mapped_ref!(pin);
1645
1646        #[cfg(usb_device)]
1647        disable_usb_pads(pin.number());
1648
1649        GPIO::regs()
1650            .func_out_sel_cfg(pin.number() as usize)
1651            .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) });
1652
1653        // Use RMW to not overwrite sleep configuration
1654        io_mux_reg(pin.number()).modify(|_, w| unsafe {
1655            w.mcu_sel().bits(GPIO_FUNCTION as u8);
1656            w.fun_ie().clear_bit();
1657            w.slp_sel().clear_bit()
1658        });
1659
1660        Self { pin }
1661    }
1662
1663    fn number(&self) -> u8 {
1664        self.pin.number()
1665    }
1666
1667    /// Returns a peripheral [input][interconnect::InputSignal] connected to
1668    /// this pin.
1669    ///
1670    /// The input signal can be passed to peripherals in place of an input pin.
1671    /// ```rust, no_run
1672    #[doc = crate::before_snippet!()]
1673    /// # use esp_hal::gpio::Flex;
1674    /// let pin1_gpio = Flex::new(peripherals.GPIO1);
1675    /// // Can be passed as an input.
1676    /// let pin1 = pin1_gpio.peripheral_input();
1677    /// # Ok(())
1678    /// # }
1679    /// ```
1680    #[inline]
1681    #[instability::unstable]
1682    pub fn peripheral_input(&self) -> interconnect::InputSignal {
1683        unsafe { AnyPin::steal(self.number()) }.split().0
1684    }
1685
1686    /// Get whether the pin input level is high.
1687    #[inline]
1688    #[instability::unstable]
1689    pub fn is_high(&self) -> bool {
1690        self.level() == Level::High
1691    }
1692
1693    /// Get whether the pin input level is low.
1694    #[inline]
1695    #[instability::unstable]
1696    pub fn is_low(&self) -> bool {
1697        self.level() == Level::Low
1698    }
1699
1700    /// Get the current pin input level.
1701    #[inline]
1702    #[instability::unstable]
1703    pub fn level(&self) -> Level {
1704        self.pin.is_input_high().into()
1705    }
1706
1707    fn listen_with_options(
1708        &self,
1709        event: Event,
1710        int_enable: bool,
1711        nmi_enable: bool,
1712        wake_up_from_light_sleep: bool,
1713    ) -> Result<(), WakeConfigError> {
1714        if wake_up_from_light_sleep {
1715            match event {
1716                Event::AnyEdge | Event::RisingEdge | Event::FallingEdge => {
1717                    return Err(WakeConfigError::EdgeTriggeringNotSupported);
1718                }
1719                _ => {}
1720            }
1721        }
1722
1723        set_int_enable(
1724            self.pin.number(),
1725            Some(gpio_intr_enable(int_enable, nmi_enable)),
1726            event as u8,
1727            wake_up_from_light_sleep,
1728        );
1729
1730        Ok(())
1731    }
1732
1733    /// Listen for interrupts.
1734    ///
1735    /// See [`Input::listen`] for more information and an example.
1736    #[inline]
1737    #[instability::unstable]
1738    pub fn listen(&mut self, event: Event) {
1739        // Unwrap can't fail currently as listen_with_options is only supposed to return
1740        // an error if wake_up_from_light_sleep is true.
1741        unwrap!(self.listen_with_options(event, true, false, false));
1742    }
1743
1744    /// Stop listening for interrupts.
1745    #[inline]
1746    #[instability::unstable]
1747    pub fn unlisten(&mut self) {
1748        set_int_enable(self.pin.number(), Some(0), 0, false);
1749    }
1750
1751    /// Check if the pin is listening for interrupts.
1752    #[inline]
1753    #[instability::unstable]
1754    pub fn is_listening(&self) -> bool {
1755        is_int_enabled(self.pin.number())
1756    }
1757
1758    /// Clear the interrupt status bit for this Pin
1759    #[inline]
1760    #[instability::unstable]
1761    pub fn clear_interrupt(&mut self) {
1762        self.pin
1763            .bank()
1764            .write_interrupt_status_clear(self.pin.mask());
1765    }
1766
1767    /// Checks if the interrupt status bit for this Pin is set
1768    #[inline]
1769    #[instability::unstable]
1770    pub fn is_interrupt_set(&self) -> bool {
1771        self.pin.bank().read_interrupt_status() & self.pin.mask() != 0
1772    }
1773
1774    /// Enable as a wake-up source.
1775    ///
1776    /// This will unlisten for interrupts
1777    ///
1778    /// # Error
1779    /// Configuring pin to wake up from light sleep on an edge
1780    /// trigger is currently not supported, corresponding variant of
1781    /// [`WakeConfigError`] will be returned.
1782    #[inline]
1783    #[instability::unstable]
1784    pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) -> Result<(), WakeConfigError> {
1785        self.listen_with_options(event.into(), false, false, enable)
1786    }
1787
1788    /// Set the GPIO to output mode.
1789    #[inline]
1790    #[instability::unstable]
1791    pub fn set_as_output(&mut self) {
1792        self.pin.set_to_push_pull_output();
1793    }
1794
1795    /// Set the output as high.
1796    #[inline]
1797    #[instability::unstable]
1798    pub fn set_high(&mut self) {
1799        self.set_level(Level::High)
1800    }
1801
1802    /// Set the output as low.
1803    #[inline]
1804    #[instability::unstable]
1805    pub fn set_low(&mut self) {
1806        self.set_level(Level::Low)
1807    }
1808
1809    /// Set the output level.
1810    #[inline]
1811    #[instability::unstable]
1812    pub fn set_level(&mut self, level: Level) {
1813        self.pin.set_output_high(level.into());
1814    }
1815
1816    /// Is the output pin set as high?
1817    #[inline]
1818    #[instability::unstable]
1819    pub fn is_set_high(&self) -> bool {
1820        self.output_level() == Level::High
1821    }
1822
1823    /// Is the output pin set as low?
1824    #[inline]
1825    #[instability::unstable]
1826    pub fn is_set_low(&self) -> bool {
1827        self.output_level() == Level::Low
1828    }
1829
1830    /// What level output is set to
1831    #[inline]
1832    #[instability::unstable]
1833    pub fn output_level(&self) -> Level {
1834        self.pin.is_set_high().into()
1835    }
1836
1837    /// Toggle pin output
1838    #[inline]
1839    #[instability::unstable]
1840    pub fn toggle(&mut self) {
1841        let level = self.output_level();
1842        self.set_level(!level);
1843    }
1844
1845    /// Configure the [DriveStrength] of the pin
1846    #[inline]
1847    #[instability::unstable]
1848    pub fn set_drive_strength(&mut self, strength: DriveStrength) {
1849        self.pin.set_drive_strength(strength);
1850    }
1851
1852    /// Set the GPIO to open-drain mode.
1853    #[inline]
1854    #[instability::unstable]
1855    pub fn set_as_open_drain(&mut self, pull: Pull) {
1856        self.pin.set_to_open_drain_output();
1857        self.pin.pull_direction(pull);
1858    }
1859
1860    /// Configure pullup/pulldown resistors.
1861    #[inline]
1862    #[instability::unstable]
1863    pub fn pull_direction(&mut self, pull: Pull) {
1864        self.pin.pull_direction(pull);
1865    }
1866
1867    /// Enable or disable the GPIO pin input buffer.
1868    #[inline]
1869    #[instability::unstable]
1870    pub fn enable_input(&mut self, enable_input: bool) {
1871        self.pin.enable_input(enable_input);
1872    }
1873
1874    /// Applies the given output configuration to the pin.
1875    #[inline]
1876    #[instability::unstable]
1877    pub fn apply_output_config(&mut self, config: &OutputConfig) {
1878        let pull_up = config.pull == Pull::Up;
1879        let pull_down = config.pull == Pull::Down;
1880
1881        #[cfg(esp32)]
1882        crate::soc::gpio::errata36(AnyPin(self.pin.0), pull_up, pull_down);
1883
1884        io_mux_reg(self.number()).modify(|_, w| {
1885            unsafe { w.fun_drv().bits(config.drive_strength as u8) };
1886            w.fun_wpu().bit(pull_up);
1887            w.fun_wpd().bit(pull_down);
1888            w
1889        });
1890
1891        GPIO::regs().pin(self.number() as usize).modify(|_, w| {
1892            w.pad_driver()
1893                .bit(config.drive_mode == DriveMode::OpenDrain)
1894        });
1895    }
1896
1897    /// Applies the given input configuration to the pin.
1898    #[inline]
1899    #[instability::unstable]
1900    pub fn apply_input_config(&mut self, config: &InputConfig) {
1901        self.pin.pull_direction(config.pull);
1902    }
1903
1904    /// Split the pin into an input and output signal.
1905    ///
1906    /// Peripheral signals allow connecting peripherals together without using
1907    /// external hardware.
1908    /// ```rust, no_run
1909    #[doc = crate::before_snippet!()]
1910    /// # use esp_hal::gpio::Flex;
1911    /// let pin1 = Flex::new(peripherals.GPIO1);
1912    /// let (input, output) = pin1.split();
1913    /// # Ok(())
1914    /// # }
1915    /// ```
1916    #[inline]
1917    #[instability::unstable]
1918    pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
1919        assert!(self.pin.is_output());
1920        unsafe { AnyPin::steal(self.number()) }.split()
1921    }
1922
1923    /// Turns the pin object into a peripheral
1924    /// [output][interconnect::OutputSignal].
1925    ///
1926    /// The output signal can be passed to peripherals in place of an output
1927    /// pin.
1928    /// ```rust, no_run
1929    #[doc = crate::before_snippet!()]
1930    /// # use esp_hal::gpio::Flex;
1931    /// let pin1_gpio = Flex::new(peripherals.GPIO1);
1932    /// // Can be passed as an output.
1933    /// let pin1 = pin1_gpio.into_peripheral_output();
1934    /// # Ok(())
1935    /// # }
1936    /// ```
1937    #[inline]
1938    #[instability::unstable]
1939    pub fn into_peripheral_output(self) -> interconnect::OutputSignal {
1940        self.split().1
1941    }
1942}
1943
1944impl private::Sealed for AnyPin {}
1945
1946impl AnyPin {
1947    fn bank(&self) -> GpioBank {
1948        #[cfg(gpio_bank_1)]
1949        if self.number() >= 32 {
1950            return GpioBank::_1;
1951        }
1952
1953        GpioBank::_0
1954    }
1955
1956    /// Init as input with the given pull-up/pull-down
1957    #[inline]
1958    pub(crate) fn init_input(&self, pull: Pull) {
1959        self.pull_direction(pull);
1960
1961        #[cfg(usb_device)]
1962        disable_usb_pads(self.number());
1963
1964        io_mux_reg(self.number()).modify(|_, w| unsafe {
1965            w.mcu_sel().bits(GPIO_FUNCTION as u8);
1966            w.fun_ie().set_bit();
1967            w.slp_sel().clear_bit()
1968        });
1969    }
1970
1971    /// Split the pin into an input and output signal.
1972    ///
1973    /// Peripheral signals allow connecting peripherals together without
1974    /// using external hardware.
1975    /// ```rust, no_run
1976    #[doc = crate::before_snippet!()]
1977    /// # use esp_hal::gpio::{AnyPin, Pin};
1978    /// let pin1 = peripherals.GPIO1.degrade();
1979    /// let (input, output) = pin1.split();
1980    /// # Ok(())
1981    /// # }
1982    /// ```
1983    #[inline]
1984    #[instability::unstable]
1985    pub fn split(self) -> (interconnect::InputSignal, interconnect::OutputSignal) {
1986        assert!(self.is_output());
1987        (
1988            interconnect::InputSignal::new(Self(self.0)),
1989            interconnect::OutputSignal::new(Self(self.0)),
1990        )
1991    }
1992
1993    #[inline]
1994    pub(crate) fn set_alternate_function(&self, alternate: AlternateFunction) {
1995        io_mux_reg(self.number()).modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) });
1996    }
1997
1998    // /// Enable/disable sleep-mode
1999    // #[inline]
2000    // fn sleep_mode(&mut self, on: bool, _: private::Internal) {
2001    //     io_mux_reg(self.number()).modify(|_, w| w.slp_sel().bit(on));
2002    // }
2003
2004    /// Enable or disable the GPIO pin output buffer.
2005    #[inline]
2006    pub(crate) fn enable_output(&self, enable: bool) {
2007        assert!(self.is_output() || !enable);
2008        self.bank().write_out_en(self.mask(), enable);
2009    }
2010
2011    /// Enable input for the pin
2012    #[inline]
2013    pub(crate) fn enable_input(&self, on: bool) {
2014        io_mux_reg(self.number()).modify(|_, w| w.fun_ie().bit(on));
2015    }
2016
2017    #[inline]
2018    pub(crate) fn pull_direction(&self, pull: Pull) {
2019        let pull_up = pull == Pull::Up;
2020        let pull_down = pull == Pull::Down;
2021
2022        #[cfg(esp32)]
2023        crate::soc::gpio::errata36(Self(self.0), pull_up, pull_down);
2024
2025        io_mux_reg(self.number()).modify(|_, w| {
2026            w.fun_wpd().bit(pull_down);
2027            w.fun_wpu().bit(pull_up)
2028        });
2029    }
2030
2031    #[inline]
2032    fn mask(&self) -> u32 {
2033        1 << (self.number() % 32)
2034    }
2035
2036    /// The current state of the input
2037    #[inline]
2038    pub(crate) fn is_input_high(&self) -> bool {
2039        self.bank().read_input() & self.mask() != 0
2040    }
2041
2042    /// Set up as output
2043    #[inline]
2044    pub(crate) fn init_output(
2045        &self,
2046        alternate: AlternateFunction,
2047        open_drain: bool,
2048        input_enable: Option<bool>,
2049    ) {
2050        self.enable_output(true);
2051
2052        let gpio = GPIO::regs();
2053
2054        gpio.pin(self.number() as usize)
2055            .modify(|_, w| w.pad_driver().bit(open_drain));
2056
2057        gpio.func_out_sel_cfg(self.number() as usize)
2058            .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) });
2059
2060        #[cfg(usb_device)]
2061        disable_usb_pads(self.number());
2062
2063        io_mux_reg(self.number()).modify(|_, w| unsafe {
2064            w.mcu_sel().bits(alternate as u8);
2065            if let Some(input_enable) = input_enable {
2066                w.fun_ie().bit(input_enable);
2067            }
2068            w.fun_drv().bits(DriveStrength::_20mA as u8);
2069            w.slp_sel().clear_bit()
2070        });
2071    }
2072
2073    /// Configure open-drain mode
2074    #[inline]
2075    pub(crate) fn set_to_open_drain_output(&self) {
2076        self.init_output(GPIO_FUNCTION, true, Some(true));
2077    }
2078
2079    /// Configure output mode
2080    #[inline]
2081    pub(crate) fn set_to_push_pull_output(&self) {
2082        self.init_output(GPIO_FUNCTION, false, None);
2083    }
2084
2085    /// Set the pin's level to high or low
2086    #[inline]
2087    pub(crate) fn set_output_high(&self, high: bool) {
2088        self.bank().write_output(self.mask(), high);
2089    }
2090
2091    /// Configure the [DriveStrength] of the pin
2092    #[inline]
2093    pub(crate) fn set_drive_strength(&self, strength: DriveStrength) {
2094        io_mux_reg(self.number()).modify(|_, w| unsafe { w.fun_drv().bits(strength as u8) });
2095    }
2096
2097    /// Enable/disable open-drain mode
2098    #[inline]
2099    pub(crate) fn enable_open_drain(&self, on: bool) {
2100        GPIO::regs()
2101            .pin(self.number() as usize)
2102            .modify(|_, w| w.pad_driver().bit(on));
2103    }
2104
2105    /// Is the output set to high
2106    #[inline]
2107    pub(crate) fn is_set_high(&self) -> bool {
2108        self.bank().read_output() & self.mask() != 0
2109    }
2110}
2111
2112impl Pin for AnyPin {
2113    #[inline(always)]
2114    fn number(&self) -> u8 {
2115        self.0
2116    }
2117
2118    fn output_signals(&self, _: private::Internal) -> &'static [(AlternateFunction, OutputSignal)] {
2119        handle_gpio_output!(self, target, {
2120            Pin::output_signals(&target, private::Internal)
2121        })
2122    }
2123
2124    fn input_signals(&self, _: private::Internal) -> &'static [(AlternateFunction, InputSignal)] {
2125        handle_gpio_input!(self, target, {
2126            Pin::input_signals(&target, private::Internal)
2127        })
2128    }
2129}
2130
2131impl InputPin for AnyPin {}
2132impl OutputPin for AnyPin {}
2133
2134#[cfg(any(lp_io, rtc_cntl))]
2135impl RtcPin for AnyPin {
2136    #[cfg(xtensa)]
2137    #[allow(unused_braces, reason = "False positive")]
2138    fn rtc_number(&self) -> u8 {
2139        handle_rtcio!(self, target, { RtcPin::rtc_number(&target) })
2140    }
2141
2142    #[cfg(any(xtensa, esp32c6))]
2143    fn rtc_set_config(&self, input_enable: bool, mux: bool, func: RtcFunction) {
2144        handle_rtcio!(self, target, {
2145            RtcPin::rtc_set_config(&target, input_enable, mux, func)
2146        })
2147    }
2148
2149    #[allow(unused_braces, reason = "False positive")]
2150    fn rtcio_pad_hold(&self, enable: bool) {
2151        handle_rtcio!(self, target, { RtcPin::rtcio_pad_hold(&target, enable) })
2152    }
2153
2154    #[cfg(any(esp32c2, esp32c3, esp32c6))]
2155    unsafe fn apply_wakeup(&self, wakeup: bool, level: u8) {
2156        handle_rtcio!(self, target, {
2157            RtcPin::apply_wakeup(&target, wakeup, level)
2158        })
2159    }
2160}
2161
2162#[cfg(any(lp_io, rtc_cntl))]
2163impl RtcPinWithResistors for AnyPin {
2164    fn rtcio_pullup(&self, enable: bool) {
2165        handle_rtcio_with_resistors!(self, target, {
2166            RtcPinWithResistors::rtcio_pullup(&target, enable)
2167        })
2168    }
2169
2170    fn rtcio_pulldown(&self, enable: bool) {
2171        handle_rtcio_with_resistors!(self, target, {
2172            RtcPinWithResistors::rtcio_pulldown(&target, enable)
2173        })
2174    }
2175}
2176
2177/// Set GPIO event listening.
2178///
2179/// - `gpio_num`: the pin to configure
2180/// - `int_ena`: maskable and non-maskable CPU interrupt bits. None to leave
2181///   unchanged.
2182/// - `int_type`: interrupt type, see [Event] (or 0 to disable)
2183/// - `wake_up_from_light_sleep`: whether to wake up from light sleep
2184fn set_int_enable(gpio_num: u8, int_ena: Option<u8>, int_type: u8, wake_up_from_light_sleep: bool) {
2185    GPIO::regs().pin(gpio_num as usize).modify(|_, w| unsafe {
2186        if let Some(int_ena) = int_ena {
2187            w.int_ena().bits(int_ena);
2188        }
2189        w.int_type().bits(int_type);
2190        w.wakeup_enable().bit(wake_up_from_light_sleep)
2191    });
2192}
2193
2194fn is_int_enabled(gpio_num: u8) -> bool {
2195    GPIO::regs().pin(gpio_num as usize).read().int_ena().bits() != 0
2196}
2197
2198mod asynch {
2199    use core::{
2200        future::poll_fn,
2201        task::{Context, Poll},
2202    };
2203
2204    use super::*;
2205    use crate::asynch::AtomicWaker;
2206
2207    #[ram]
2208    pub(super) static PIN_WAKERS: [AtomicWaker; NUM_PINS] =
2209        [const { AtomicWaker::new() }; NUM_PINS];
2210
2211    impl Flex<'_> {
2212        /// Wait until the pin experiences a particular [`Event`].
2213        ///
2214        /// The GPIO driver will disable listening for the event once it occurs,
2215        /// or if the `Future` is dropped.
2216        ///
2217        /// Note that calling this function will overwrite previous
2218        /// [`listen`][Self::listen] operations for this pin.
2219        #[inline]
2220        #[instability::unstable]
2221        pub async fn wait_for(&mut self, event: Event) {
2222            // We construct the Future first, because its `Drop` implementation
2223            // is load-bearing if `wait_for` is dropped during the initialization.
2224            let mut future = PinFuture {
2225                pin: Flex {
2226                    pin: unsafe { self.pin.clone_unchecked() },
2227                },
2228            };
2229
2230            // Make sure this pin is not being processed by an interrupt handler.
2231            if future.pin.is_listening() {
2232                set_int_enable(
2233                    future.pin.number(),
2234                    None, // Do not disable handling pending interrupts.
2235                    0,    // Disable generating new events
2236                    false,
2237                );
2238                poll_fn(|cx| {
2239                    if future.pin.is_interrupt_set() {
2240                        cx.waker().wake_by_ref();
2241                        Poll::Pending
2242                    } else {
2243                        Poll::Ready(())
2244                    }
2245                })
2246                .await;
2247            }
2248
2249            // At this point the pin is no longer listening, we can safely
2250            // do our setup.
2251
2252            // Mark pin as async.
2253            future
2254                .bank()
2255                .async_operations()
2256                .fetch_or(future.mask(), Ordering::Relaxed);
2257
2258            future.pin.listen(event);
2259
2260            future.await
2261        }
2262
2263        /// Wait until the pin is high.
2264        ///
2265        /// See [Self::wait_for] for more information.
2266        #[inline]
2267        #[instability::unstable]
2268        pub async fn wait_for_high(&mut self) {
2269            self.wait_for(Event::HighLevel).await
2270        }
2271
2272        /// Wait until the pin is low.
2273        ///
2274        /// See [Self::wait_for] for more information.
2275        #[inline]
2276        #[instability::unstable]
2277        pub async fn wait_for_low(&mut self) {
2278            self.wait_for(Event::LowLevel).await
2279        }
2280
2281        /// Wait for the pin to undergo a transition from low to high.
2282        ///
2283        /// See [Self::wait_for] for more information.
2284        #[inline]
2285        #[instability::unstable]
2286        pub async fn wait_for_rising_edge(&mut self) {
2287            self.wait_for(Event::RisingEdge).await
2288        }
2289
2290        /// Wait for the pin to undergo a transition from high to low.
2291        ///
2292        /// See [Self::wait_for] for more information.
2293        #[inline]
2294        #[instability::unstable]
2295        pub async fn wait_for_falling_edge(&mut self) {
2296            self.wait_for(Event::FallingEdge).await
2297        }
2298
2299        /// Wait for the pin to undergo any transition, i.e low to high OR high
2300        /// to low.
2301        ///
2302        /// See [Self::wait_for] for more information.
2303        #[inline]
2304        #[instability::unstable]
2305        pub async fn wait_for_any_edge(&mut self) {
2306            self.wait_for(Event::AnyEdge).await
2307        }
2308    }
2309
2310    impl Input<'_> {
2311        /// Wait until the pin experiences a particular [`Event`].
2312        ///
2313        /// The GPIO driver will disable listening for the event once it occurs,
2314        /// or if the `Future` is dropped.
2315        ///
2316        /// Note that calling this function will overwrite previous
2317        /// [`listen`][Self::listen] operations for this pin.
2318        #[inline]
2319        pub async fn wait_for(&mut self, event: Event) {
2320            self.pin.wait_for(event).await
2321        }
2322
2323        /// Wait until the pin is high.
2324        ///
2325        /// See [Self::wait_for] for more information.
2326        #[inline]
2327        pub async fn wait_for_high(&mut self) {
2328            self.pin.wait_for_high().await
2329        }
2330
2331        /// Wait until the pin is low.
2332        ///
2333        /// See [Self::wait_for] for more information.
2334        #[inline]
2335        pub async fn wait_for_low(&mut self) {
2336            self.pin.wait_for_low().await
2337        }
2338
2339        /// Wait for the pin to undergo a transition from low to high.
2340        ///
2341        /// See [Self::wait_for] for more information.
2342        #[inline]
2343        pub async fn wait_for_rising_edge(&mut self) {
2344            self.pin.wait_for_rising_edge().await
2345        }
2346
2347        /// Wait for the pin to undergo a transition from high to low.
2348        ///
2349        /// See [Self::wait_for] for more information.
2350        #[inline]
2351        pub async fn wait_for_falling_edge(&mut self) {
2352            self.pin.wait_for_falling_edge().await
2353        }
2354
2355        /// Wait for the pin to undergo any transition, i.e low to high OR high
2356        /// to low.
2357        ///
2358        /// See [Self::wait_for] for more information.
2359        #[inline]
2360        pub async fn wait_for_any_edge(&mut self) {
2361            self.pin.wait_for_any_edge().await
2362        }
2363    }
2364
2365    #[must_use = "futures do nothing unless you `.await` or poll them"]
2366    struct PinFuture<'d> {
2367        pin: Flex<'d>,
2368    }
2369
2370    impl PinFuture<'_> {
2371        fn number(&self) -> u8 {
2372            self.pin.number()
2373        }
2374
2375        fn bank(&self) -> GpioBank {
2376            self.pin.pin.bank()
2377        }
2378
2379        fn mask(&self) -> u32 {
2380            self.pin.pin.mask()
2381        }
2382
2383        fn is_done(&self) -> bool {
2384            // Only the interrupt handler should clear the async bit, and only if the
2385            // specific pin is handling an interrupt.
2386            self.bank().async_operations().load(Ordering::Acquire) & self.mask() == 0
2387        }
2388    }
2389
2390    impl core::future::Future for PinFuture<'_> {
2391        type Output = ();
2392
2393        fn poll(self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
2394            PIN_WAKERS[self.number() as usize].register(cx.waker());
2395
2396            if self.is_done() {
2397                Poll::Ready(())
2398            } else {
2399                Poll::Pending
2400            }
2401        }
2402    }
2403
2404    impl Drop for PinFuture<'_> {
2405        fn drop(&mut self) {
2406            // If the pin isn't listening, the future has either been dropped before setup,
2407            // or the interrupt has already been handled.
2408            if self.pin.is_listening() {
2409                // Make sure the future isn't dropped while the interrupt is being handled.
2410                // This prevents tricky drop-and-relisten scenarios.
2411
2412                set_int_enable(
2413                    self.number(),
2414                    None, // Do not disable handling pending interrupts.
2415                    0,    // Disable generating new events
2416                    false,
2417                );
2418
2419                while self.pin.is_interrupt_set() {}
2420
2421                // Unmark pin as async
2422                self.bank()
2423                    .async_operations()
2424                    .fetch_and(!self.mask(), Ordering::Relaxed);
2425            }
2426        }
2427    }
2428}
2429
2430mod embedded_hal_impls {
2431    use embedded_hal::digital;
2432
2433    use super::*;
2434
2435    impl digital::ErrorType for Input<'_> {
2436        type Error = core::convert::Infallible;
2437    }
2438
2439    impl digital::InputPin for Input<'_> {
2440        fn is_high(&mut self) -> Result<bool, Self::Error> {
2441            Ok(Self::is_high(self))
2442        }
2443
2444        fn is_low(&mut self) -> Result<bool, Self::Error> {
2445            Ok(Self::is_low(self))
2446        }
2447    }
2448
2449    impl digital::ErrorType for Output<'_> {
2450        type Error = core::convert::Infallible;
2451    }
2452
2453    impl digital::OutputPin for Output<'_> {
2454        fn set_low(&mut self) -> Result<(), Self::Error> {
2455            Self::set_low(self);
2456            Ok(())
2457        }
2458
2459        fn set_high(&mut self) -> Result<(), Self::Error> {
2460            Self::set_high(self);
2461            Ok(())
2462        }
2463    }
2464
2465    impl digital::StatefulOutputPin for Output<'_> {
2466        fn is_set_high(&mut self) -> Result<bool, Self::Error> {
2467            Ok(Self::is_set_high(self))
2468        }
2469
2470        fn is_set_low(&mut self) -> Result<bool, Self::Error> {
2471            Ok(Self::is_set_low(self))
2472        }
2473    }
2474
2475    #[instability::unstable]
2476    impl digital::InputPin for Flex<'_> {
2477        fn is_high(&mut self) -> Result<bool, Self::Error> {
2478            Ok(Self::is_high(self))
2479        }
2480
2481        fn is_low(&mut self) -> Result<bool, Self::Error> {
2482            Ok(Self::is_low(self))
2483        }
2484    }
2485
2486    #[instability::unstable]
2487    impl digital::ErrorType for Flex<'_> {
2488        type Error = core::convert::Infallible;
2489    }
2490
2491    #[instability::unstable]
2492    impl digital::OutputPin for Flex<'_> {
2493        fn set_low(&mut self) -> Result<(), Self::Error> {
2494            Self::set_low(self);
2495            Ok(())
2496        }
2497
2498        fn set_high(&mut self) -> Result<(), Self::Error> {
2499            Self::set_high(self);
2500            Ok(())
2501        }
2502    }
2503
2504    #[instability::unstable]
2505    impl digital::StatefulOutputPin for Flex<'_> {
2506        fn is_set_high(&mut self) -> Result<bool, Self::Error> {
2507            Ok(Self::is_set_high(self))
2508        }
2509
2510        fn is_set_low(&mut self) -> Result<bool, Self::Error> {
2511            Ok(Self::is_set_low(self))
2512        }
2513    }
2514}
2515
2516mod embedded_hal_async_impls {
2517    use embedded_hal_async::digital::Wait;
2518
2519    use super::*;
2520
2521    #[instability::unstable]
2522    impl Wait for Flex<'_> {
2523        async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
2524            Self::wait_for_high(self).await;
2525            Ok(())
2526        }
2527
2528        async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
2529            Self::wait_for_low(self).await;
2530            Ok(())
2531        }
2532
2533        async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
2534            Self::wait_for_rising_edge(self).await;
2535            Ok(())
2536        }
2537
2538        async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
2539            Self::wait_for_falling_edge(self).await;
2540            Ok(())
2541        }
2542
2543        async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
2544            Self::wait_for_any_edge(self).await;
2545            Ok(())
2546        }
2547    }
2548
2549    impl Wait for Input<'_> {
2550        async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
2551            Self::wait_for_high(self).await;
2552            Ok(())
2553        }
2554
2555        async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
2556            Self::wait_for_low(self).await;
2557            Ok(())
2558        }
2559
2560        async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
2561            Self::wait_for_rising_edge(self).await;
2562            Ok(())
2563        }
2564
2565        async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
2566            Self::wait_for_falling_edge(self).await;
2567            Ok(())
2568        }
2569
2570        async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
2571            Self::wait_for_any_edge(self).await;
2572            Ok(())
2573        }
2574    }
2575}