1
#![cfg_attr(docsrs, procmacros::doc_replace(
2
    "etm_availability" => {
3
        cfg(etm_driver_supported) => "The GPIO pins also provide tasks and events via the ETM interconnect system. For more information, see the [etm] module."
4
    }
5
))]
6
//! # General Purpose Input/Output (GPIO)
7
//!
8
//! ## Overview
9
//!
10
//! Each pin can be used as a general-purpose I/O, or be connected to one or
11
//! more internal peripheral signals.
12
//! # {etm_availability}
13
//! ## Working with pins
14
//!
15
//! After initializing the HAL, you can access the individual pins using the
16
//! [`crate::Peripherals`] struct. These pins can then be used as general
17
//! purpose digital IO using pin drivers, or they can be passed to peripherals
18
//! (such as SPI, UART, I2C, etc.), or can be [`split`]
19
//! into peripheral signals for advanced use.
20
//!
21
//! Pin drivers can be created using [`Flex::new`], [`Input::new`] and
22
//! [`Output::new`].
23
//!
24
//! Output pins can be configured to either push-pull or open-drain (active low)
25
//! mode, with configurable drive strength and pull-up/pull-down resistors.
26
//!
27
//! Each pin is a different type initially. Internally, `esp-hal` will erase
28
//! their types automatically, but they can also be converted into [`AnyPin`]
29
//! manually by calling [`Pin::degrade`].
30
//!
31
//! The [`Io`] struct can also be used to configure the interrupt handler for
32
//! GPIO interrupts. For more information, see the
33
//! [`InterruptConfigurable::set_interrupt_handler`](crate::interrupt::InterruptConfigurable::set_interrupt_handler).
34
//!
35
//! This driver also implements pin-related traits from [embedded-hal] and
36
//! [Wait](embedded_hal_async::digital::Wait) trait from [embedded-hal-async].
37
//!
38
//! ## GPIO interconnect
39
//!
40
//! Sometimes you may want to connect peripherals together without using
41
//! external hardware. The [`interconnect`] module provides tools to achieve
42
//! this using GPIO pins.
43
//!
44
//! To obtain peripheral signals, use the [`split`] method to split a
45
//! pin into an input and output signal. Alternatively, you may use
46
//! [`Flex::split`], [`Flex::into_peripheral_output`],
47
//! [`Flex::peripheral_input`], and similar methods to split a pin driver into
48
//! an input and output signal. You can then pass these signals to the
49
//! peripheral drivers similar to how you would pass a pin.
50
//!
51
//! [embedded-hal]: embedded_hal
52
//! [embedded-hal-async]: embedded_hal_async
53
//! [`split`]: crate::peripherals::GPIO0::split
54

            
55
crate::unstable_module! {
56
    pub mod interconnect;
57

            
58
    #[cfg(etm_driver_supported)]
59
    pub mod etm;
60

            
61
    #[cfg(lp_io_driver_supported)]
62
    pub mod lp_io;
63

            
64
    #[cfg(dedicated_gpio_driver_supported)]
65
    pub mod dedicated;
66
}
67
use interconnect::PeripheralOutput;
68

            
69
mod asynch;
70
mod embedded_hal_impls;
71
pub(crate) mod interrupt;
72
mod low_level;
73
use interrupt::*;
74
pub use low_level::GpioBank;
75
use low_level::{gpio_intr_enable, is_int_enabled, set_int_enable};
76

            
77
mod placeholder;
78

            
79
#[cfg(sleep_driver_supported)]
80
pub(crate) mod wakeup;
81
use core::fmt::Display;
82

            
83
use esp_sync::RawMutex;
84
pub use placeholder::NoPin;
85
#[cfg(sleep_driver_supported)]
86
#[instability::unstable]
87
pub use wakeup::WakeupConfig;
88

            
89
use crate::{
90
    asynch::AtomicWaker,
91
    interrupt::{InterruptHandler, Priority},
92
    peripherals::{GPIO, IO_MUX},
93
    private::{self, Sealed},
94
};
95

            
96
126
define_io_mux_signals!();
97

            
98
pub(crate) static GPIO_LOCK: RawMutex = RawMutex::new();
99

            
100
/// Represents a pin-peripheral connection that, when dropped, disconnects the
101
/// peripheral from the pin.
102
///
103
/// This only needs to be applied to output signals, as it is not possible to connect multiple
104
/// inputs to the same peripheral signal.
105
#[derive(Debug)]
106
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
107
pub(crate) struct PinGuard {
108
    pin: u8,
109
}
110

            
111
impl crate::private::Sealed for PinGuard {}
112

            
113
impl PinGuard {
114
    // This must only be used with a pin currently configured for output, and the PinGuard must be
115
    // dropped before the pin can be reconfigured (e.g. for input).
116
    fn new(pin: AnyPin<'_>) -> Self {
117
        Self { pin: pin.number() }
118
    }
119

            
120
    pub(crate) const fn new_unconnected() -> Self {
121
        Self { pin: u8::MAX }
122
    }
123

            
124
    #[allow(unused)]
125
    pub(crate) fn pin_number(&self) -> Option<u8> {
126
4
        if self.pin == u8::MAX {
127
            None
128
        } else {
129
            Some(self.pin)
130
        }
131
    }
132
}
133

            
134
impl Drop for PinGuard {
135
623
    fn drop(&mut self) {
136
623
        if self.pin != u8::MAX {
137
            let pin = unsafe { AnyPin::steal(self.pin) };
138
            pin.disconnect_from_peripheral_output();
139
        }
140
623
    }
141
}
142

            
143
/// Event used to trigger interrupts.
144
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
145
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
146
#[instability::unstable]
147
pub enum Event {
148
    /// Interrupts trigger on rising pin edge.
149
    RisingEdge  = 1,
150
    /// Interrupts trigger on falling pin edge.
151
    FallingEdge = 2,
152
    /// Interrupts trigger on either rising or falling pin edges.
153
    AnyEdge     = 3,
154
    /// Interrupts trigger on low level
155
    LowLevel    = 4,
156
    /// Interrupts trigger on high level
157
    HighLevel   = 5,
158
}
159

            
160
/// Digital input or output level.
161
///
162
/// `Level` can be used to control a GPIO output, and it can act as a peripheral
163
/// signal and be connected to peripheral inputs and outputs.
164
///
165
/// When connected to a peripheral
166
/// input, the peripheral will read the corresponding level from that signal.
167
///
168
/// When connected to a peripheral output, the level will be ignored.
169
10
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
170
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
171
pub enum Level {
172
    /// Low
173
    Low,
174
    /// High
175
    High,
176
}
177

            
178
impl Sealed for Level {}
179

            
180
impl core::ops::Not for Level {
181
    type Output = Self;
182

            
183
    fn not(self) -> Self {
184
        match self {
185
            Self::Low => Self::High,
186
            Self::High => Self::Low,
187
        }
188
    }
189
}
190

            
191
impl Level {
192
    /// Creates a new [`Level`] from [`bool`].
193
    ///
194
    /// Like `<Level as From<bool>>::from(val)`, but `const`.
195
    pub(crate) const fn const_from(val: bool) -> Self {
196
2
        match val {
197
            true => Self::High,
198
            false => Self::Low,
199
        }
200
    }
201

            
202
    /// Converts a [`Level`] to [`bool`].
203
    ///
204
    /// Like `<bool as From<Level>>::from(self)`, but `const`.
205
    pub(crate) const fn const_into(self) -> bool {
206
        match self {
207
            Level::Low => false,
208
            Level::High => true,
209
        }
210
    }
211
}
212

            
213
impl From<bool> for Level {
214
    fn from(val: bool) -> Self {
215
        Self::const_from(val)
216
    }
217
}
218

            
219
impl From<Level> for bool {
220
    fn from(level: Level) -> bool {
221
        level.const_into()
222
    }
223
}
224

            
225
/// Errors that can occur when configuring a pin to be a wakeup source.
226
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
227
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
228
#[instability::unstable]
229
#[non_exhaustive]
230
pub enum WakeConfigError {
231
    /// The pad has no low-power path. It cannot wake the chip while the high-performance GPIO
232
    /// peripheral is powered down.
233
    NoLowPowerPath,
234
}
235

            
236
impl Display for WakeConfigError {
237
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
238
        match self {
239
            WakeConfigError::NoLowPowerPath => {
240
                write!(f, "The pad is not a low-power pad")
241
            }
242
        }
243
    }
244
}
245

            
246
impl core::error::Error for WakeConfigError {}
247

            
248
/// Pull setting for a GPIO.
249
77
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
250
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
251
pub enum Pull {
252
    /// No pull
253
    None,
254
    /// Pull up
255
    Up,
256
    /// Pull down
257
    Down,
258
}
259

            
260
/// Drive strength (values are approximates)
261
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash, PartialOrd, Ord)]
262
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
263
pub enum DriveStrength {
264
    /// Drive strength of approximately 5mA.
265
    _5mA  = 0,
266
    /// Drive strength of approximately 10mA.
267
    _10mA = 1,
268
    /// Drive strength of approximately 20mA.
269
    _20mA = 2,
270
    /// Drive strength of approximately 40mA.
271
    _40mA = 3,
272
}
273

            
274
/// Alternate functions
275
///
276
/// GPIO pins can be configured for various functions, such as GPIO
277
/// or being directly connected to a peripheral's signal like UART, SPI, etc.
278
/// The `AlternateFunction` enum allows selecting one of several functions that
279
/// a pin can perform, rather than using it as a general-purpose input or
280
/// output.
281
///
282
/// The different variants correspond to different functionality depending on
283
/// the chip and the specific pin. For more information, refer to the chip's
284
#[doc(hidden)]
285
#[doc = crate::trm_markdown_link!("iomuxgpio")]
286
156
#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)]
287
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
288
pub enum AlternateFunction {
289
    /// Alternate function 0.
290
    _0 = 0,
291
    /// Alternate function 1.
292
    _1 = 1,
293
    /// Alternate function 2.
294
    _2 = 2,
295
    /// Alternate function 3.
296
    _3 = 3,
297
    /// Alternate function 4.
298
    _4 = 4,
299
    /// Alternate function 5.
300
    _5 = 5,
301
}
302

            
303
impl AlternateFunction {
304
    pub(crate) const GPIO: Self = match Self::const_try_from(property!("gpio.gpio_function")) {
305
        Ok(func) => func,
306
        Err(_) => ::core::panic!("Invalid GPIO function"),
307
    };
308

            
309
    const fn const_try_from(value: usize) -> Result<Self, ()> {
310
        match value {
311
            0 => Ok(Self::_0),
312
            1 => Ok(Self::_1),
313
            2 => Ok(Self::_2),
314
            3 => Ok(Self::_3),
315
            4 => Ok(Self::_4),
316
            5 => Ok(Self::_5),
317
            _ => Err(()),
318
        }
319
    }
320
}
321

            
322
impl TryFrom<usize> for AlternateFunction {
323
    type Error = ();
324

            
325
    fn try_from(value: usize) -> Result<Self, Self::Error> {
326
        Self::const_try_from(value)
327
    }
328
}
329

            
330
/// Trait implemented by the pins that the low-power domain can reach.
331
///
332
/// The low-power domain has its own numbers for these pads, and the low-power registers take such a
333
/// number. Only some chips give a pad the same number in both domains, so do not mix the two
334
/// numbers. Give [`Self::lp_number`] to the low-power registers, and [`Pin::number`] to the digital
335
/// registers.
336
#[instability::unstable]
337
#[cfg(lp_io_driver_supported)]
338
pub trait LpPin: Pin {
339
    /// LP number of the pin
340
    fn lp_number(&self) -> u8;
341
}
342

            
343
/// Common trait implemented by pins
344
pub trait Pin: Sealed {
345
    /// GPIO number
346
    fn number(&self) -> u8;
347

            
348
    #[procmacros::doc_replace]
349
    /// Type-erases this pin into an [`AnyPin`].
350
    ///
351
    /// Converts pin singletons (`GPIO0<'_>`, …), which are all different types,
352
    /// into the same type. Useful for creating arrays of pins, or avoiding
353
    /// generics.
354
    ///
355
    /// # Examples
356
    ///
357
    /// ```rust, no_run
358
    /// # {before_snippet}
359
    /// use esp_hal::{
360
    ///     delay::Delay,
361
    ///     gpio::{AnyPin, Level, Output, OutputConfig, Pin},
362
    /// };
363
    ///
364
    /// fn toggle_pins(pins: [AnyPin; 2], delay: &mut Delay) {
365
    ///     let [red, blue] = pins;
366
    ///     let mut red = Output::new(red, Level::High, OutputConfig::default());
367
    ///     let mut blue = Output::new(blue, Level::Low, OutputConfig::default());
368
    ///
369
    ///     loop {
370
    ///         red.toggle();
371
    ///         blue.toggle();
372
    ///         delay.delay_millis(500);
373
    ///     }
374
    /// }
375
    ///
376
    /// let pins: [AnyPin; 2] = [peripherals.GPIO5.degrade(), peripherals.GPIO4.degrade()];
377
    ///
378
    /// let mut delay = Delay::new();
379
    /// toggle_pins(pins, &mut delay);
380
    /// # {after_snippet}
381
    /// ```
382
    fn degrade<'d>(self) -> AnyPin<'d>
383
    where
384
        Self: Sized + 'd,
385
    {
386
120
        unsafe { AnyPin::steal(self.number()) }
387
    }
388

            
389
    #[doc(hidden)]
390
    fn output_signals(&self, _: private::Internal) -> &'static [(AlternateFunction, OutputSignal)];
391

            
392
    #[doc(hidden)]
393
    fn input_signals(&self, _: private::Internal) -> &'static [(AlternateFunction, InputSignal)];
394
}
395

            
396
/// Trait implemented by pins which can be used as inputs.
397
pub trait InputPin: Pin {
398
    #[doc(hidden)]
399
    fn waker(&self) -> &'static AtomicWaker;
400
}
401

            
402
/// Trait implemented by pins which can be used as outputs.
403
pub trait OutputPin: Pin {}
404

            
405
/// Trait implemented by pins which can be used as analog pins.
406
#[instability::unstable]
407
pub trait AnalogPin: Pin {
408
    /// Configures the pin for analog operation.
409
    #[doc(hidden)]
410
    fn set_analog(&self, _: private::Internal);
411
}
412

            
413
/// Trait implemented by pins which can be used as Touchpad pins.
414
#[cfg(touch_driver_supported)]
415
#[instability::unstable]
416
pub trait TouchPin: Pin {
417
    /// Configures the pin for analog operation.
418
    #[doc(hidden)]
419
    fn set_touch(&self, _: private::Internal);
420

            
421
    /// Reads the pin's touch measurement register.
422
    #[doc(hidden)]
423
    fn touch_measurement(&self, _: private::Internal) -> u16;
424

            
425
    /// Maps the pin nr to the touch pad nr.
426
    #[doc(hidden)]
427
    fn touch_nr(&self, _: private::Internal) -> u8;
428

            
429
    /// Sets a pins touch threshold for interrupts.
430
    #[doc(hidden)]
431
    fn set_threshold(&self, threshold: u16, _: private::Internal);
432
}
433

            
434
/// Any GPIO pin.
435
#[derive(Debug)]
436
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
437
pub struct AnyPin<'lt> {
438
    pub(crate) pin: u8,
439
    pub(crate) _lifetime: core::marker::PhantomData<&'lt mut ()>,
440
}
441

            
442
/// General Purpose Input/Output driver.
443
#[derive(Debug)]
444
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
445
#[instability::unstable]
446
pub struct Io<'d> {
447
    _io_mux: IO_MUX<'d>,
448
}
449

            
450
impl<'d> Io<'d> {
451
    /// Initializes the I/O driver.
452
    #[instability::unstable]
453
    pub fn new(_io_mux: IO_MUX<'d>) -> Self {
454
        Io { _io_mux }
455
    }
456

            
457
    #[doc = cfg_select!{
458
        any(single_core, esp32s3) => "Sets the interrupt priority and enables GPIO interrupts.",
459
        _ => "Sets the interrupt priority and enables GPIO interrupts on all cores.",
460
    }]
461
    #[instability::unstable]
462
    pub fn set_interrupt_priority(&self, prio: Priority) {
463
        low_level::set_interrupt_priority(prio);
464
    }
465

            
466
    #[doc = cfg_select!{
467
        any(single_core, esp32s3) => "Registers an interrupt handler for all GPIO pins.",
468
        _ => "Registers an interrupt handler for all GPIO pins. Enables interrupts on all cores.",
469
    }]
470
    #[doc = ""]
471
    /// When using interrupt handlers registered by this method, or by defining a
472
    /// `#[no_mangle] unsafe extern "C" fn GPIO()` function, the interrupt status
473
    /// register and the interrupt enable setting for the GPIO pin are **not**
474
    /// cleared automatically. Based on the use case, do one of the following:
475
    ///
476
    /// - Disabling the interrupt enable setting for the GPIO pin lets an event be handled once per
477
    ///   call to [`listen()`]. Using this method, the [`is_interrupt_set()`] method returns `true`
478
    ///   if the interrupt is set even after the handler has finished running.
479
    /// - Clearing the interrupt status register lets an event be handled repeatedly after
480
    ///   [`listen()`] is called. Using this method, [`is_interrupt_set()`] returns `false` after
481
    ///   the handler has finished running.
482
    ///
483
    /// [`listen()`]: Input::listen
484
    /// [`is_interrupt_set()`]: Input::is_interrupt_set
485
    #[instability::unstable]
486
    pub fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
487
        USER_INTERRUPT_HANDLER.store(handler.handler().callback());
488
        low_level::enable_interrupt(InterruptHandler::new(
489
            user_gpio_interrupt_handler,
490
            handler.priority(),
491
        ));
492
5
    }
493
}
494

            
495
impl crate::private::Sealed for Io<'_> {}
496

            
497
#[instability::unstable]
498
impl crate::interrupt::InterruptConfigurable for Io<'_> {
499
    fn set_interrupt_handler(&mut self, handler: InterruptHandler) {
500
        self.set_interrupt_handler(handler);
501
    }
502
}
503

            
504
/// Drives the GPIO async API from a user-installed raw GPIO interrupt handler.
505
///
506
/// Entry point for code that bypasses esp-hal's GPIO ISR dispatch (typically
507
/// by defining a custom `#[unsafe(no_mangle)] unsafe extern "C" fn GPIO()`, or
508
/// by registering a handler via [`crate::interrupt::bind_handler`]) and needs
509
/// the GPIO async API to keep working.
510
///
511
/// # Safety
512
///
513
/// Must be called from a GPIO interrupt context.
514
#[instability::unstable]
515
5
pub unsafe fn handle_gpio_interrupt() {
516
5
    unsafe { interrupt::handle_gpio_interrupt_impl() }
517
}
518

            
519
/// Completes any in-flight async wait on a single GPIO pin.
520
///
521
/// Per-pin counterpart of [`handle_gpio_interrupt`].
522
///
523
/// # Safety
524
///
525
/// Must be called from a GPIO interrupt context.
526
#[instability::unstable]
527
5
pub unsafe fn wake_pin(pin: u8) {
528
5
    unsafe { interrupt::wake_pin_impl(pin) }
529
}
530

            
531
for_each_analog_function! {
532
    (($_ch:ident, ADCn_CHm, $_n:literal, $_m:literal), $gpio:ident) => {
533
        #[instability::unstable]
534
        impl $crate::gpio::AnalogPin for crate::peripherals::$gpio<'_> {
535
18
            fn set_analog(&self, _: private::Internal) {
536
                cfg_select! {
537
                    xtensa => { self.set_analog_impl(); }
538
                    riscv => {
539
                        // Just configure as a floating GPIO.
540
18
                        unsafe { AnyPin::steal(self.number()) }.init_gpio();
541
                        io_mux_reg(self.number()).modify(|_, w| {
542
                            w.fun_wpu().clear_bit();
543
                            w.fun_wpd().clear_bit()
544
                        });
545
                    }
546
                }
547
18
            }
548
        }
549
    };
550
}
551

            
552
/// The drive mode of the output pin.
553
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
554
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
555
pub enum DriveMode {
556
    /// Push-pull output.
557
    ///
558
    /// The driver actively sets the output voltage level for both high and low
559
    /// logical [`Level`]s.
560
    PushPull,
561

            
562
    /// Open drain output.
563
    ///
564
    /// The driver actively pulls the output voltage level low for the low
565
    /// logical [`Level`], but leaves the high level floating, which is then
566
    /// determined by external hardware, or internal pull-up/pull-down
567
    /// resistors.
568
    #[cfg_attr(
569
        feature = "unstable",
570
        doc = "\n\nEnable the input related functionality by using [Output::into_flex] and enabling input via [Flex::set_input_enable]"
571
    )]
572
    OpenDrain,
573
}
574

            
575
/// Output pin configuration.
576
///
577
/// Configures the drive mode, drive strength, and pull direction of an output
578
/// pin. By default, the configuration is set to:
579
/// - Drive mode: [`DriveMode::PushPull`]
580
/// - Drive strength: [`DriveStrength::_20mA`]
581
/// - Pull direction: [`Pull::None`] (no pull resistors connected)
582
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
583
#[derive(Debug, Clone, Copy, PartialEq, Eq, procmacros::BuilderLite)]
584
#[non_exhaustive]
585
pub struct OutputConfig {
586
    /// Output drive mode.
587
    drive_mode: DriveMode,
588

            
589
    /// Pin drive strength.
590
    drive_strength: DriveStrength,
591

            
592
    /// Pin pull direction.
593
    pull: Pull,
594
}
595

            
596
impl Default for OutputConfig {
597
    fn default() -> Self {
598
        Self {
599
            drive_mode: DriveMode::PushPull,
600
            drive_strength: DriveStrength::_20mA,
601
            pull: Pull::None,
602
        }
603
    }
604
}
605

            
606
/// Push-pull digital output.
607
///
608
/// This driver configures the GPIO pin to be an output driver.
609
#[derive(Debug)]
610
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
611
pub struct Output<'d> {
612
    pin: Flex<'d>,
613
}
614

            
615
impl private::Sealed for Output<'_> {}
616
impl private::Sealed for &mut Output<'_> {}
617

            
618
impl<'d> Output<'d> {
619
    #[procmacros::doc_replace]
620
    /// Creates a new GPIO output driver.
621
    ///
622
    /// The `initial_level` parameter sets the initial output level of the pin.
623
    /// The `config` parameter sets the drive mode, drive strength, and pull
624
    /// direction of the pin.
625
    ///
626
    /// # Examples
627
    ///
628
    /// The following example configures `GPIO5` to pulse a LED once. The
629
    /// example assumes that the LED is connected such that it is on when
630
    /// the pin is low.
631
    ///
632
    /// ```rust, no_run
633
    /// # {before_snippet}
634
    /// use esp_hal::{
635
    ///     delay::Delay,
636
    ///     gpio::{Level, Output, OutputConfig},
637
    /// };
638
    ///
639
    /// fn blink_once(led: &mut Output<'_>, delay: &mut Delay) {
640
    ///     led.set_low();
641
    ///     delay.delay_millis(500);
642
    ///     led.set_high();
643
    /// }
644
    ///
645
    /// let config = OutputConfig::default();
646
    /// let mut led = Output::new(peripherals.GPIO5, Level::High, config);
647
    /// let mut delay = Delay::new();
648
    ///
649
    /// blink_once(&mut led, &mut delay);
650
    /// # {after_snippet}
651
    /// ```
652
    #[inline]
653
44
    pub fn new(pin: impl OutputPin + 'd, initial_level: Level, config: OutputConfig) -> Self {
654
        // Set up the pin
655
        let mut this = Self {
656
            pin: Flex::new(pin),
657
        };
658
        this.set_level(initial_level);
659
        this.apply_config(&config);
660
        this.pin.pin.set_output_enable(true);
661

            
662
        this
663
44
    }
664

            
665
    #[procmacros::doc_replace]
666
    /// Turns the pin object into a peripheral
667
    /// [output][interconnect::OutputSignal].
668
    ///
669
    /// The output signal can be passed to peripherals in place of an output
670
    /// pin.
671
    ///
672
    /// The returned signal is [frozen](interconnect::OutputSignal::freeze).
673
    ///
674
    /// # Examples
675
    ///
676
    /// ```rust, no_run
677
    /// # {before_snippet}
678
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
679
    /// # let config = OutputConfig::default();
680
    /// let pin1_gpio = Output::new(peripherals.GPIO1, Level::High, config);
681
    /// let output = pin1_gpio.into_peripheral_output();
682
    /// # {after_snippet}
683
    /// ```
684
    #[inline]
685
    #[instability::unstable]
686
    pub fn into_peripheral_output(self) -> interconnect::OutputSignal<'d> {
687
        self.pin.into_peripheral_output()
688
    }
689

            
690
    #[procmacros::doc_replace]
691
    /// Changes the configuration.
692
    ///
693
    /// # Examples
694
    ///
695
    /// ```rust, no_run
696
    /// # {before_snippet}
697
    /// use esp_hal::gpio::{DriveMode, Level, Output, OutputConfig};
698
    /// let mut pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
699
    ///
700
    /// pin.apply_config(&OutputConfig::default().with_drive_mode(DriveMode::OpenDrain));
701
    ///
702
    /// # {after_snippet}
703
    /// ```
704
    #[inline]
705
    pub fn apply_config(&mut self, config: &OutputConfig) {
706
        self.pin.apply_output_config(config)
707
    }
708
    #[procmacros::doc_replace]
709
    /// Sets the output as high.
710
    ///
711
    /// # Examples
712
    ///
713
    /// ```rust, no_run
714
    /// # {before_snippet}
715
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
716
    /// let mut pin = Output::new(peripherals.GPIO5, Level::Low, OutputConfig::default());
717
    /// pin.set_high();
718
    ///
719
    /// # {after_snippet}
720
    /// ```
721
    #[inline]
722
    pub fn set_high(&mut self) {
723
        self.set_level(Level::High)
724
    }
725

            
726
    #[procmacros::doc_replace]
727
    /// Sets the output as low.
728
    ///
729
    /// # Examples
730
    ///
731
    /// ```rust, no_run
732
    /// # {before_snippet}
733
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
734
    /// let mut pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
735
    /// pin.set_low();
736
    ///
737
    /// # {after_snippet}
738
    /// ```
739
    #[inline]
740
    pub fn set_low(&mut self) {
741
        self.set_level(Level::Low)
742
    }
743

            
744
    #[procmacros::doc_replace]
745
    /// Sets the output level.
746
    ///
747
    /// # Examples
748
    ///
749
    /// ```rust, no_run
750
    /// # {before_snippet}
751
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
752
    /// let mut pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
753
    /// pin.set_level(Level::Low);
754
    ///
755
    /// # {after_snippet}
756
    /// ```
757
    #[inline]
758
    pub fn set_level(&mut self, level: Level) {
759
        self.pin.set_level(level)
760
    }
761

            
762
    #[procmacros::doc_replace]
763
    /// Returns whether the pin is set to high level.
764
    ///
765
    /// Reads back the value set using `set_level`, `set_high` or `set_low`. Does
766
    /// not need the input stage to be enabled.
767
    ///
768
    /// # Examples
769
    ///
770
    /// ```rust, no_run
771
    /// # {before_snippet}
772
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
773
    /// let pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
774
    /// let is_high = pin.is_set_high();
775
    ///
776
    /// # {after_snippet}
777
    /// ```
778
    #[inline]
779
    pub fn is_set_high(&self) -> bool {
780
        self.output_level() == Level::High
781
    }
782

            
783
    #[procmacros::doc_replace]
784
    /// Returns whether the pin is set to low level.
785
    ///
786
    /// Reads back the value set using `set_level`, `set_high` or `set_low`. Does
787
    /// not need the input stage to be enabled.
788
    ///
789
    /// # Examples
790
    ///
791
    /// ```rust, no_run
792
    /// # {before_snippet}
793
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
794
    /// let pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
795
    /// let is_low = pin.is_set_low();
796
    ///
797
    /// # {after_snippet}
798
    /// ```
799
    #[inline]
800
    pub fn is_set_low(&self) -> bool {
801
        self.output_level() == Level::Low
802
    }
803

            
804
    #[procmacros::doc_replace]
805
    /// Returns which level the pin is set to.
806
    ///
807
    /// Reads back the value set using `set_level`, `set_high` or `set_low`. Does
808
    /// not need the input stage to be enabled.
809
    ///
810
    /// # Examples
811
    ///
812
    /// ```rust, no_run
813
    /// # {before_snippet}
814
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
815
    /// let pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
816
    /// let level = pin.output_level();
817
    ///
818
    /// # {after_snippet}
819
    /// ```
820
    #[inline]
821
    pub fn output_level(&self) -> Level {
822
        self.pin.output_level()
823
    }
824

            
825
    #[procmacros::doc_replace]
826
    /// Toggles the pin output.
827
    ///
828
    /// If the pin was previously set to high, it will be set to low, and vice
829
    /// versa.
830
    ///
831
    /// # Examples
832
    ///
833
    /// ```rust, no_run
834
    /// # {before_snippet}
835
    /// use esp_hal::gpio::{Level, Output, OutputConfig};
836
    /// let mut pin = Output::new(peripherals.GPIO5, Level::High, OutputConfig::default());
837
    /// pin.toggle();
838
    ///
839
    /// # {after_snippet}
840
    /// ```
841
    #[inline]
842
    pub fn toggle(&mut self) {
843
        self.pin.toggle();
844
    }
845

            
846
    /// Takes or releases the hold of the pad.
847
    ///
848
    /// A held pad keeps its level, its function and its resistors, and it ignores this driver.
849
    #[inline]
850
    #[instability::unstable]
851
    #[cfg(lp_io_driver_supported)]
852
    pub fn set_pad_hold(&mut self, enable: bool) {
853
        self.pin.set_pad_hold(enable);
854
    }
855

            
856
    /// Returns whether something holds the pad.
857
    #[inline]
858
    #[instability::unstable]
859
    #[cfg(lp_io_driver_supported)]
860
    pub fn is_pad_held(&self) -> bool {
861
        self.pin.is_pad_held()
862
    }
863

            
864
    /// Converts the pin driver into a [`Flex`] driver.
865
    #[inline]
866
    #[instability::unstable]
867
    pub fn into_flex(self) -> Flex<'d> {
868
        self.pin
869
    }
870
}
871

            
872
/// Configures the clock edge used in one of the two input synchronization stages to synchronize the
873
/// GPIO input signal to the system clock, reducing metastability.
874
///
875
/// See [`InputConfig::with_input_sync_stage1`] and
876
/// [`InputConfig::with_input_sync_stage2`].
877
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
878
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
879
#[instability::unstable]
880
#[cfg(gpio_has_input_sync)]
881
pub enum InputSync {
882
    /// Stage is disabled; the signal passes through without latching (hardware
883
    /// default).
884
    #[default]
885
    Disabled     = 0,
886
    /// Stage latches on the falling edge of the GPIO clock.
887
    NegativeEdge = 1,
888
    /// Stage latches on the rising edge of the GPIO clock.
889
    PositiveEdge = 2,
890
}
891

            
892
/// Input pin configuration.
893
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
894
1
#[derive(Debug, Clone, Copy, PartialEq, Eq, procmacros::BuilderLite)]
895
#[non_exhaustive]
896
pub struct InputConfig {
897
    /// Initial pull of the pin.
898
    pull: Pull,
899

            
900
    /// First input synchronization stage.
901
    ///
902
    /// Default value: [`InputSync::Disabled`].
903
    #[cfg(gpio_has_input_sync)]
904
    #[builder_lite(unstable)]
905
    input_sync_stage1: InputSync,
906

            
907
    /// Second input synchronization stage.
908
    ///
909
    /// Default value: [`InputSync::Disabled`].
910
    #[cfg(gpio_has_input_sync)]
911
    #[builder_lite(unstable)]
912
    input_sync_stage2: InputSync,
913
}
914

            
915
impl Default for InputConfig {
916
    fn default() -> Self {
917
        Self {
918
            pull: Pull::None,
919
            #[cfg(gpio_has_input_sync)]
920
            input_sync_stage1: Default::default(),
921
            #[cfg(gpio_has_input_sync)]
922
            input_sync_stage2: Default::default(),
923
        }
924
    }
925
}
926

            
927
/// Digital input.
928
///
929
/// This driver configures the GPIO pin to be an input. Input drivers read the
930
/// voltage of their pins and convert it to a logical [`Level`].
931
#[derive(Debug)]
932
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
933
pub struct Input<'d> {
934
    pin: Flex<'d>,
935
}
936

            
937
impl private::Sealed for Input<'_> {}
938
impl private::Sealed for &mut Input<'_> {}
939

            
940
impl<'d> Input<'d> {
941
    #[procmacros::doc_replace]
942
    /// Creates a new GPIO input.
943
    ///
944
    /// The `pull` parameter configures internal pull-up or pull-down
945
    /// resistors.
946
    ///
947
    /// # Examples
948
    ///
949
    /// The following example configures `GPIO5` to read a button press. The
950
    /// example assumes that the button is connected such that the pin is low
951
    /// when the button is pressed.
952
    ///
953
    /// ```rust, no_run
954
    /// # {before_snippet}
955
    /// use esp_hal::{
956
    ///     delay::Delay,
957
    ///     gpio::{Input, InputConfig, Level, Pull},
958
    /// };
959
    ///
960
    /// fn print_when_pressed(button: &mut Input<'_>, delay: &mut Delay) {
961
    ///     let mut was_pressed = false;
962
    ///     loop {
963
    ///         let is_pressed = button.is_low();
964
    ///         if is_pressed && !was_pressed {
965
    ///             println!("Button pressed!");
966
    ///         }
967
    ///         was_pressed = is_pressed;
968
    ///         delay.delay_millis(100);
969
    ///     }
970
    /// }
971
    ///
972
    /// let config = InputConfig::default().with_pull(Pull::Up);
973
    /// let mut button = Input::new(peripherals.GPIO5, config);
974
    /// let mut delay = Delay::new();
975
    ///
976
    /// print_when_pressed(&mut button, &mut delay);
977
    /// # {after_snippet}
978
    /// ```
979
    #[inline]
980
83
    pub fn new(pin: impl InputPin + 'd, config: InputConfig) -> Self {
981
        let mut pin = Flex::new(pin);
982

            
983
        pin.set_output_enable(false);
984
        pin.set_input_enable(true);
985
        pin.apply_input_config(&config);
986

            
987
        Self { pin }
988
83
    }
989

            
990
    #[procmacros::doc_replace]
991
    /// Returns a peripheral [input][interconnect::InputSignal] connected to
992
    /// this pin.
993
    ///
994
    /// The input signal can be passed to peripherals in place of an input pin.
995
    ///
996
    /// The returned signal is [frozen](interconnect::InputSignal::freeze).
997
    ///
998
    /// # Examples
999
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// #
    /// use esp_hal::gpio::{Input, InputConfig, Pull};
    /// let config = InputConfig::default().with_pull(Pull::Up);
    /// let pin1_gpio = Input::new(peripherals.GPIO1, config);
    /// let pin1 = pin1_gpio.peripheral_input();
    /// #
    /// # {after_snippet}
    /// ```
    #[inline]
    #[instability::unstable]
    pub fn peripheral_input(&self) -> interconnect::InputSignal<'d> {
        self.pin.peripheral_input()
    }
    #[procmacros::doc_replace]
    /// Returns whether the pin input level is high.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::{Input, InputConfig};
    /// let pin = Input::new(peripherals.GPIO5, InputConfig::default());
    /// let is_high = pin.is_high();
    ///
    /// # {after_snippet}
    /// ```
    #[inline]
    pub fn is_high(&self) -> bool {
        self.level() == Level::High
    }
    #[procmacros::doc_replace]
    /// Returns whether the pin input level is low.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::{Input, InputConfig};
    /// let pin = Input::new(peripherals.GPIO5, InputConfig::default());
    /// let is_low = pin.is_low();
    ///
    /// # {after_snippet}
    /// ```
    #[inline]
    pub fn is_low(&self) -> bool {
        self.level() == Level::Low
    }
    #[procmacros::doc_replace]
    /// Returns the current pin input level.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::{Input, InputConfig, Level};
    /// let pin = Input::new(peripherals.GPIO5, InputConfig::default());
    /// let level = pin.level();
    ///
    /// # {after_snippet}
    /// ```
    #[inline]
    pub fn level(&self) -> Level {
        self.pin.level()
    }
    #[procmacros::doc_replace]
    /// Changes the configuration.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::{Input, InputConfig, Level, Pull};
    /// let mut pin = Input::new(peripherals.GPIO5, InputConfig::default());
    /// pin.apply_config(&InputConfig::default().with_pull(Pull::Up));
    ///
    /// # {after_snippet}
    /// ```
    pub fn apply_config(&mut self, config: &InputConfig) {
        self.pin.apply_input_config(config)
2
    }
    #[procmacros::doc_replace]
    /// Listens for interrupts.
    ///
    /// The interrupts will be handled by the handler set using
    /// [`Io::set_interrupt_handler`]. All GPIO pins share the same
    /// interrupt handler.
    ///
    /// [`Event::LowLevel`] and [`Event::HighLevel`] are fired continuously when
    /// the pin is low or high, respectively. A custom interrupt handler is
    /// required to stop listening for these events; otherwise the program can
    /// remain in a loop as long as the pin reads the corresponding level.
    ///
    /// A listening pin also ends a light sleep. On most chips, sleep entry must give the trigger as
    /// a level, so an edge trigger becomes the level at the end of the edge. A rising edge becomes
    /// a high level, a falling edge becomes a low level, and any edge becomes the level that
    /// the pin is not at when the sleep starts. A pin that listens for a rising edge on a line
    /// that is already high therefore ends each light sleep immediately, and without an
    /// interrupt, because no edge occurred. Automatic light sleep then makes no sleep at all.
    ///
    /// # Examples
    ///
    /// ### Print something when a button is pressed.
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::{Event, Input, InputConfig, Io, Pull};
    ///
    /// let mut io = Io::new(peripherals.IO_MUX);
    /// io.set_interrupt_handler(handler);
    ///
    /// // Set up the input and store it in the static variable.
    /// // This example uses a push button that is high when not
    /// // pressed and low when pressed.
    /// let config = InputConfig::default().with_pull(Pull::Up);
    /// let mut button = Input::new(peripherals.GPIO5, config);
    ///
    /// critical_section::with(|cs| {
    ///     // Here we are listening for a low level to demonstrate
    ///     // that you need to stop listening for level interrupts,
    ///     // but usually you'd probably use `FallingEdge`.
    ///     button.listen(Event::LowLevel);
    ///     BUTTON.borrow_ref_mut(cs).replace(button);
    /// });
    /// # {after_snippet}
    ///
    /// // Outside of your `main` function:
    ///
    /// use core::cell::RefCell;
    ///
    /// use critical_section::Mutex;
    /// use esp_hal::gpio::Input;
    ///
    /// // You will need to store the `Input` object in a static variable so
    /// // that the interrupt handler can access it.
    /// static BUTTON: Mutex<RefCell<Option<Input>>> = Mutex::new(RefCell::new(None));
    ///
    /// #[esp_hal::handler]
    /// fn handler() {
    ///     critical_section::with(|cs| {
    ///         let mut button = BUTTON.borrow_ref_mut(cs);
    ///         let Some(button) = button.as_mut() else {
    ///             // Some other interrupt has occurred
    ///             // before the button was set up.
    ///             return;
    ///         };
    ///
    ///         if button.is_interrupt_set() {
    ///             print!("Button pressed");
    ///
    ///             // If you want to stop listening for interrupts, you need to
    ///             // call `unlisten` here. If you comment this line, the
    ///             // interrupt will fire continuously while the button
    ///             // is pressed.
    ///             button.unlisten();
    ///         }
    ///     });
    /// }
    /// ```
    #[inline]
    #[instability::unstable]
    pub fn listen(&mut self, event: Event) {
        self.pin.listen(event);
    }
    /// Stops listening for interrupts.
    #[inline]
    #[instability::unstable]
    pub fn unlisten(&mut self) {
        self.pin.unlisten();
    }
    /// Clears the interrupt status bit for this Pin.
    #[inline]
    #[instability::unstable]
    pub fn clear_interrupt(&mut self) {
        self.pin.clear_interrupt();
    }
    /// Returns whether the interrupt status bit for this Pin is set.
    #[inline]
    #[instability::unstable]
    pub fn is_interrupt_set(&self) -> bool {
        self.pin.is_interrupt_set()
    }
    /// Configures whether the pin can wake the chip from sleep.
    ///
    /// [`Flex::apply_wakeup_config`] describes the configuration, and the conditions that wake the
    /// chip.
    ///
    /// # Errors
    ///
    /// [`WakeConfigError::NoLowPowerPath`] when the configuration requests the low-power path
    /// for a pad that has no such path.
    #[cfg(sleep_driver_supported)]
    #[instability::unstable]
    #[inline]
    pub fn apply_wakeup_config(&mut self, config: &WakeupConfig) -> Result<(), WakeConfigError> {
        self.pin.apply_wakeup_config(config)
    }
    /// Returns whether this pin ended the most recent sleep.
    ///
    /// See [`Flex::caused_wakeup`].
    #[cfg(sleep_driver_supported)]
    #[instability::unstable]
    #[inline]
    pub fn caused_wakeup(&self) -> bool {
        self.pin.caused_wakeup()
    }
    /// Takes or releases the hold of the pad.
    ///
    /// A held pad keeps its level, its function and its resistors, and it ignores this driver.
    #[inline]
    #[instability::unstable]
    #[cfg(lp_io_driver_supported)]
    pub fn set_pad_hold(&mut self, enable: bool) {
        self.pin.set_pad_hold(enable);
    }
    /// Returns whether something holds the pad.
    #[inline]
    #[instability::unstable]
    #[cfg(lp_io_driver_supported)]
    pub fn is_pad_held(&self) -> bool {
        self.pin.is_pad_held()
    }
    /// Converts the pin driver into a [`Flex`] driver.
    #[inline]
    #[instability::unstable]
    pub fn into_flex(self) -> Flex<'d> {
        self.pin
    }
}
/// Flexible pin driver.
///
/// This pin driver can act as either input, or output, or both at the same
/// time. The input and output are (not counting the shared pull direction)
/// separately configurable, and they have independent enable states.
///
/// Enabling the input stage does not change the output stage, and vice versa.
/// Disabling the input or output stages do not forget their configuration.
/// Disabling the output stage will not change the output level, but it will
/// disable the driver.
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[instability::unstable]
pub struct Flex<'d> {
    pin: AnyPin<'d>,
}
impl private::Sealed for Flex<'_> {}
impl private::Sealed for &mut Flex<'_> {}
impl<'d> Flex<'d> {
    /// Creates flexible pin driver for a [Pin].
    /// No mode change happens.
    #[inline]
    #[instability::unstable]
    pub fn new(pin: impl Pin + 'd) -> Self {
102
        let pin = pin.degrade();
        // Before each use, reset the GPIO to a known state.
        pin.init_gpio();
2
        Self { pin }
    }
    // Input functions
    /// Applies the given input configuration to the pin.
    ///
    /// Does not set the pin as input (does not enable the input buffer). The pull
    /// direction is common between the input and output configuration.
    #[inline]
    #[instability::unstable]
    pub fn apply_input_config(&mut self, config: &InputConfig) {
2
        self.pin.apply_input_config(config);
    }
    /// Enables or disables the GPIO pin input buffer.
    #[inline]
    #[instability::unstable]
    pub fn set_input_enable(&mut self, enable_input: bool) {
        self.pin.set_input_enable(enable_input);
    }
    /// Takes or releases the hold of the pad.
    ///
    /// A held pad keeps its level, its function and its resistors, and it ignores this driver.
    #[inline]
    #[instability::unstable]
    #[cfg(lp_io_driver_supported)]
    pub fn set_pad_hold(&mut self, enable: bool) {
2
        self.pin.set_pad_hold(enable);
    }
    /// Returns whether something holds the pad.
    #[inline]
    #[instability::unstable]
    #[cfg(lp_io_driver_supported)]
    pub fn is_pad_held(&self) -> bool {
2
        self.pin.is_pad_held()
    }
    /// Returns whether the pin input level is high.
    #[inline]
    #[instability::unstable]
    pub fn is_high(&self) -> bool {
        self.level() == Level::High
    }
    /// Returns whether the pin input level is low.
    #[inline]
    #[instability::unstable]
    pub fn is_low(&self) -> bool {
        self.level() == Level::Low
    }
    /// Returns the current pin input level.
    #[inline]
    #[instability::unstable]
    pub fn level(&self) -> Level {
        self.pin.is_input_high().into()
    }
    /// Listens for interrupts.
    ///
    /// See [`Input::listen`] for more information and an example.
    #[inline]
    #[instability::unstable]
    pub fn listen(&mut self, event: Event) {
1
        self.pin.listen(event);
    }
    /// Stops listening for interrupts.
    #[inline]
    #[instability::unstable]
    pub fn unlisten(&mut self) {
        GPIO_LOCK.lock(|| {
1
            set_int_enable(self.pin.number(), Some(0), 0, false);
        });
    }
1
    fn unlisten_and_clear(&mut self) {
        GPIO_LOCK.lock(|| {
            set_int_enable(self.pin.number(), Some(0), 0, false);
            self.clear_interrupt();
        });
1
    }
    /// Returns whether the pin is listening for interrupts.
    #[inline]
    #[instability::unstable]
    pub fn is_listening(&self) -> bool {
39
        is_int_enabled(self.pin.number())
    }
    /// Clears the interrupt status bit for this Pin.
    #[inline]
    #[instability::unstable]
    pub fn clear_interrupt(&mut self) {
        self.pin
            .bank()
9
            .write_interrupt_status_clear(self.pin.mask());
    }
    /// Returns whether the interrupt status bit for this Pin is set.
    #[inline]
    #[instability::unstable]
    pub fn is_interrupt_set(&self) -> bool {
39
        self.pin.bank().read_interrupt_status() & self.pin.mask() != 0
    }
    /// Configures whether the pin can wake the chip from sleep.
    ///
    /// The configuration selects the hardware paths that the pin can use. The wake condition is the
    /// interrupt trigger, so **a pin that does not listen is not a wakeup source**. A pin that
    /// listens already wakes the chip from light sleep through the digital path. See
    /// [`WakeupConfig`].
    ///
    /// The configuration stays after the driver is dropped, because a pad that wakes the chip from
    /// deep sleep must continue to do so while no driver owns it. To remove the configuration, call
    /// this function again with [`WakeupConfig::default()`].
    ///
    /// # Errors
    ///
    /// [`WakeConfigError::NoLowPowerPath`] when the configuration requests the low-power path
    /// for a pad that has no such path.
    #[cfg(sleep_driver_supported)]
    #[inline]
    #[instability::unstable]
    pub fn apply_wakeup_config(&mut self, config: &WakeupConfig) -> Result<(), WakeConfigError> {
        wakeup::apply_config(&self.pin, config)
    }
    /// Returns whether this pin ended the most recent sleep.
    ///
    /// More than one pin can end a sleep, so this function can return `true` for several pins. It
    /// returns `false` if the chip did not wake from a sleep, and `false` for a pin that ended an
    /// earlier sleep only.
    ///
    /// esp-hal reads the result while the sleep ends, so a later clear of the interrupt of the pin
    /// does not change it. One case depends on the interrupt status: a pin that ends a light sleep
    /// without [`WakeupConfig::low_power_path`]. The interrupt handler of that pin clears the
    /// status, so the pin reports `false` if the handler runs before the sleep call returns.
    /// This can only occur if interrupts were enabled during the sleep.
    #[cfg(sleep_driver_supported)]
    #[inline]
    #[instability::unstable]
    pub fn caused_wakeup(&self) -> bool {
        wakeup::caused_wakeup(&self.pin)
    }
    // Output functions
    /// Applies the given output configuration to the pin.
    ///
    /// Does not set the pin to output (does not enable the output driver). The
    /// pull direction is common between the input and output configuration.
    #[inline]
    #[instability::unstable]
    pub fn apply_output_config(&mut self, config: &OutputConfig) {
        self.pin.apply_output_config(config);
    }
    /// Enables or disables the GPIO pin output driver.
    ///
    /// The output level will be set to the last value. Use [`Self::set_high`],
    /// [`Self::set_low`] or [`Self::set_level`] to set the output level before
    /// enabling the output.
    ///
    /// Does not disable the input buffer.
    #[inline]
    #[instability::unstable]
    pub fn set_output_enable(&mut self, enable_output: bool) {
        self.pin.set_output_enable(enable_output);
    }
    /// Sets the output as high.
    #[inline]
    #[instability::unstable]
    pub fn set_high(&mut self) {
        self.set_level(Level::High)
    }
    /// Sets the output as low.
    #[inline]
    #[instability::unstable]
    pub fn set_low(&mut self) {
        self.set_level(Level::Low)
    }
    /// Sets the output level.
    #[inline]
    #[instability::unstable]
    pub fn set_level(&mut self, level: Level) {
        self.pin.set_output_high(level.into());
    }
    /// Is the output pin set as high?
    #[inline]
    #[instability::unstable]
    pub fn is_set_high(&self) -> bool {
        self.output_level() == Level::High
    }
    /// Is the output pin set as low?
    #[inline]
    #[instability::unstable]
    pub fn is_set_low(&self) -> bool {
        self.output_level() == Level::Low
    }
    /// What level output is set to.
    #[inline]
    #[instability::unstable]
    pub fn output_level(&self) -> Level {
        self.pin.is_set_high().into()
    }
    /// Toggles pin output.
    #[inline]
    #[instability::unstable]
    pub fn toggle(&mut self) {
        let level = self.output_level();
        self.set_level(!level);
    }
    // Other/common functions
    #[procmacros::doc_replace]
    /// Returns a peripheral [input][interconnect::InputSignal] connected to
    /// this pin.
    ///
    /// The input signal can be passed to peripherals in place of an input pin.
    ///
    /// The returned signal is [frozen](interconnect::InputSignal::freeze).
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::Flex;
    /// let pin1_gpio = Flex::new(peripherals.GPIO1);
    /// // Can be passed as an input.
    /// let pin1 = pin1_gpio.peripheral_input();
    /// // You can keep using the Flex, as well as connect the pin to a
    /// // peripheral input.
    /// # {after_snippet}
    /// ```
    #[inline]
    #[instability::unstable]
    pub fn peripheral_input(&self) -> interconnect::InputSignal<'d> {
        self.pin.set_input_enable(true);
        unsafe {
            // Safety: the signal is frozen by this function.
2
            self.pin.clone_unchecked().split_no_init().0.freeze()
        }
    }
    #[procmacros::doc_replace]
    /// Splits the pin into an input and output signal pair.
    ///
    /// Peripheral signals allow connecting peripherals together without using
    /// external hardware.
    ///
    /// The returned signals are [frozen](interconnect::InputSignal::freeze).
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::Flex;
    /// let pin1 = Flex::new(peripherals.GPIO1);
    /// let (input, output) = pin1.split();
    /// # {after_snippet}
    /// ```
    #[inline]
    #[instability::unstable]
    pub fn split(
        self,
    ) -> (
        interconnect::InputSignal<'d>,
        interconnect::OutputSignal<'d>,
    ) {
        let input = self.peripheral_input();
        let output = self.into_peripheral_output();
        (input, output)
    }
    /// Splits the pin into an [Input] and an [Output] driver pair.
    ///
    /// The returned input signal is [frozen](interconnect::InputSignal::freeze). The
    /// pin driver is free to change settings.
    ///
    /// Lets an input-output pin be configured, then keeps working with the output
    /// half. Mainly intended for testing, to drive a peripheral from a signal
    /// generated by software.
    ///
    /// # Safety
    ///
    /// The caller must ensure that the pins are not being configured via their
    /// `apply_config` functions in the same time in multiple places. The pin
    /// drivers must not be turned back into `Flex`, unless one of the
    /// drivers is dropped first.
    // TODO is this enough? Register-wise config is the only non-atomic operation, but is it
    // actually safe to have two drivers on the same pin, otherwise? Perhaps it would be better
    // to implement ehal traits for signals?
    #[inline]
    #[instability::unstable]
    pub unsafe fn split_into_drivers(self) -> (Input<'d>, Output<'d>) {
        self.pin.set_input_enable(true);
        let input = Input {
            pin: Flex {
                pin: unsafe { self.pin.clone_unchecked() },
            },
        };
        let output = Output { pin: self };
        (input, output)
    }
    #[procmacros::doc_replace]
    /// Turns the pin object into a peripheral
    /// [output][interconnect::OutputSignal].
    ///
    /// The output signal can be passed to peripherals in place of an output
    /// pin.
    ///
    /// The returned signal is [frozen](interconnect::OutputSignal::freeze).
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::Flex;
    /// let pin1_gpio = Flex::new(peripherals.GPIO1);
    /// // Can be passed as an output.
    /// let pin1 = pin1_gpio.into_peripheral_output();
    /// # {after_snippet}
    /// ```
    #[inline]
    #[instability::unstable]
    pub fn into_peripheral_output(self) -> interconnect::OutputSignal<'d> {
        unsafe {
            // Safety: the signals are frozen by this function.
            self.pin.split_no_init().1.freeze()
        }
    }
}
impl private::Sealed for AnyPin<'_> {}
impl<'lt> AnyPin<'lt> {
    fn bank(&self) -> GpioBank {
        low_level::bank(self.number())
    }
    pub(crate) fn disable_usb_pads(&self) {
        #[cfg(soc_has_usb_device)]
        {
            /// Workaround to make D+ and D- work when the pin is assigned to
            /// the `USB_SERIAL_JTAG` peripheral by default.
            fn disable_usb_pads(_gpionum: u8) {
                crate::peripherals::USB_DEVICE::regs()
                    .conf0()
                    .modify(|_, w| {
                        w.usb_pad_enable().clear_bit();
                        w.dm_pullup().clear_bit();
                        w.dm_pulldown().clear_bit();
                        w.dp_pullup().clear_bit();
                        w.dp_pulldown().clear_bit()
                    });
            }
            #[cfg(any(esp32h4, esp32p4))]
            fn disable_usb_fs_pads(_gpionum: u8) {
                crate::peripherals::USB_WRAP::regs()
                    .otg_conf()
                    .modify(|_, w| {
                        w.pad_pull_override().set_bit();
                        w.dm_pullup().clear_bit();
                        w.dm_pulldown().clear_bit();
                        w.dp_pullup().clear_bit();
                        w.dp_pulldown().clear_bit()
                    });
            }
            #[cfg(soc_has_usb_fs)]
            macro_rules! disable_usb_fs_pads {
                ($gpio:ident) => {
                    if self.number() == crate::peripherals::$gpio::NUMBER {
                        cfg_select! {
                            any(esp32h4, esp32p4) => {
                                disable_usb_fs_pads(crate::peripherals::$gpio::NUMBER);
                            }
                            _ => {
                                disable_usb_pads(crate::peripherals::$gpio::NUMBER);
                            }
                        }
                    }
                };
            }
425
            for_each_analog_function! {
                (USJ_DM, $gpio:ident) => {
                    if self.number() == crate::peripherals::$gpio::NUMBER {
                        disable_usb_pads(crate::peripherals::$gpio::NUMBER);
                    }
                };
                (USJ_DP, $gpio:ident) => {
                    if self.number() == crate::peripherals::$gpio::NUMBER {
                        disable_usb_pads(crate::peripherals::$gpio::NUMBER);
                    }
                };
                (USB_FS_DM, $gpio:ident) => { disable_usb_fs_pads!($gpio) };
                (USB_FS_DP, $gpio:ident) => { disable_usb_fs_pads!($gpio) };
            }
        }
393
    }
    /// Takes or releases the hold of the pad.
    ///
    /// A held pad keeps its level, its function and its resistors, and it ignores its driver. Sleep
    /// takes the hold of a wakeup pad, because a deep sleep powers the circuit that drives the pad
    /// down.
    ///
    /// A pad that the low-power registers reach keeps its hold in the low-power domain, and every
    /// other pad has a bit in a register of the digital pads.
    #[cfg(lp_io_driver_supported)]
395
    pub(crate) fn set_pad_hold(&self, enable: bool) {
        GPIO_LOCK.lock(|| {
            if let Some(lp) = lp_io::lp_number(self.number()) {
                lp_io::low_level::pad_hold(lp, enable);
            } else {
                lp_io::low_level::digital_pad_hold(self.number(), enable);
            }
        })
394
    }
    /// Returns whether something holds the pad.
    #[cfg(lp_io_driver_supported)]
    pub(crate) fn is_pad_held(&self) -> bool {
        // No lock necessary, as this pin cannot be written
        // while this function is being called.
        if let Some(lp) = lp_io::lp_number(self.number()) {
            lp_io::low_level::is_pad_held(lp)
        } else {
            lp_io::low_level::is_digital_pad_held(self.number())
        }
1
    }
    #[inline]
    /// Resets the GPIO to a known state.
    ///
    /// Must be called before using the GPIO pin:
    /// - Before converting it into signals
    /// - Before using it as an input or output
24
    pub(crate) fn init_gpio(&self) {
24
        self.set_output_enable(false);
104
        self.disable_usb_pads();
        // A held pad ignores every configuration that follows the hold, and only a power-on reset
        // releases the hold by itself. Without this, a pad that an earlier program held keeps its
        // level for the rest of the life of the chip.
        #[cfg(lp_io_driver_supported)]
104
        self.set_pad_hold(false);
        #[cfg(lp_io_driver_supported)]
128
        for_each_lp_function! {
            (($_signal:ident, LP_GPIOn, $lp_pin:literal), $gpio:ident, $af:ident, $_lp_in:tt $_lp_out:tt) => {
                if self.number() == crate::peripherals::$gpio::NUMBER {
                    lp_io::low_level::set_config($lp_pin, false, false, lp_io::LpFunction::$af);
                }
            };
        }
        GPIO::regs()
            .func_out_sel_cfg(self.number() as usize)
            .write(|w| unsafe { w.out_sel().bits(OutputSignal::GPIO as _) });
        // Use RMW to not overwrite sleep configuration
        io_mux_reg(self.number()).modify(|_, w| unsafe {
            w.mcu_sel().bits(AlternateFunction::GPIO as u8);
            w.fun_ie().clear_bit();
            w.slp_sel().clear_bit()
        });
24
    }
    #[procmacros::doc_replace]
    /// Splits the pin into an input and output signal.
    ///
    /// Peripheral signals allow connecting peripherals together without
    /// using external hardware.
    ///
    /// Creating an input signal enables the pin's input buffer.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// use esp_hal::gpio::{AnyPin, Pin};
    /// let pin1 = peripherals.GPIO1.degrade();
    /// let (input, output) = unsafe { pin1.split() };
    /// # {after_snippet}
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if the pin is not an output pin.
    ///
    /// # Safety
    ///
    /// The caller must ensure that peripheral drivers do not configure the same
    /// GPIO at the same time in multiple places. This includes clones of the
    /// `InputSignal` struct, as well as the `OutputSignal` struct
    #[inline]
    #[instability::unstable]
    pub unsafe fn split(
        self,
    ) -> (
        interconnect::InputSignal<'lt>,
        interconnect::OutputSignal<'lt>,
    ) {
        assert!(self.is_output());
        // Before each use, reset the GPIO to a known state.
6
        self.init_gpio();
        self.set_input_enable(true);
        let (input, output) = unsafe { self.split_no_init() };
        // We don't know if the input signal(s) will support bypassing the GPIO matrix.
        // Since the bypass option is common between input and output halves of
        // a single GPIO, we can't assume anything about the output, either.
        let output = output.with_gpio_matrix_forced(true);
6
        (input, output)
    }
    /// Converts the pin into an input signal.
    ///
    /// Peripheral signals allow connecting peripherals together without
    /// using external hardware.
    ///
    /// Creating an input signal enables the pin's input buffer.
    ///
    /// # Safety
    ///
    /// The caller must ensure that peripheral drivers do not configure the same
    /// GPIO at the same time in multiple places. This includes clones of the
    /// `InputSignal` struct.
    #[inline]
    #[instability::unstable]
46
    pub unsafe fn into_input_signal(self) -> interconnect::InputSignal<'lt> {
        // Before each use, reset the GPIO to a known state.
        self.init_gpio();
        self.set_input_enable(true);
48
        let (input, _) = unsafe { self.split_no_init() };
        input
46
    }
    /// Converts the pin into an output signal.
    ///
    /// Peripheral signals allow connecting peripherals together without
    /// using external hardware.
    ///
    /// # Panics
    ///
    /// Panics if the pin is not an output pin.
    #[inline]
    #[instability::unstable]
    pub fn into_output_signal(self) -> interconnect::OutputSignal<'lt> {
51
        assert!(self.is_output());
        // Before each use, reset the GPIO to a known state.
        self.init_gpio();
        // AnyPin is used as output only, we can allow bypassing the GPIO matrix.
51
        let (_, output) = unsafe { self.split_no_init() };
        output
    }
175
    unsafe fn split_no_init(
        self,
    ) -> (
        interconnect::InputSignal<'lt>,
        interconnect::OutputSignal<'lt>,
    ) {
        let input = interconnect::InputSignal::new(unsafe { self.clone_unchecked() });
        let output = interconnect::OutputSignal::new(self);
        // Since InputSignal can be cloned, we have no way of knowing how many signals
        // end up being configured, and in what order. If multiple signals are
        // passed to peripherals, and one of them would allow GPIO alternate
        // function configurations, it would mean that the GPIO MCU_SEL bit's
        // final value would depend on the order of operations.
        let input = input.with_gpio_matrix_forced(true);
175
        (input, output)
175
    }
    #[inline]
    pub(crate) fn set_alternate_function(&self, alternate: AlternateFunction) {
        io_mux_reg(self.number()).modify(|_, w| unsafe { w.mcu_sel().bits(alternate as u8) });
    }
    // /// Enable/disable sleep-mode
    // #[inline]
    // fn sleep_mode(&mut self, on: bool, _: private::Internal) {
    //     io_mux_reg(self.number()).modify(|_, w| w.slp_sel().bit(on));
    // }
    /// Enables or disables the GPIO pin output buffer.
    #[inline]
    pub(crate) fn set_output_enable(&self, enable: bool) {
6
        assert!(self.is_output() || !enable);
132
        self.bank().write_out_en(self.mask(), enable);
    }
    /// Enables input for the pin.
    #[inline]
    pub(crate) fn set_input_enable(&self, on: bool) {
        io_mux_reg(self.number()).modify(|_, w| w.fun_ie().bit(on));
    }
    #[inline]
    pub(crate) fn apply_input_config(&self, config: &InputConfig) {
        let pull_up = config.pull == Pull::Up;
        let pull_down = config.pull == Pull::Down;
        low_level::prepare_pin_pull(self, pull_up, pull_down);
        io_mux_reg(self.number()).modify(|_, w| {
            w.fun_wpd().bit(pull_down);
            w.fun_wpu().bit(pull_up)
        });
        #[cfg(gpio_has_input_sync)]
2
        self.with_gpio_lock(|| {
            GPIO::regs()
                .pin(self.number() as usize)
                .modify(|_, w| unsafe {
                    w.sync1_bypass().bits(config.input_sync_stage1 as u8);
                    w.sync2_bypass().bits(config.input_sync_stage2 as u8)
                });
        });
    }
    fn clear_interrupt(&self) {
        self.bank().write_interrupt_status_clear(self.mask());
    }
    fn with_gpio_lock<F, R>(&self, f: F) -> R
    where
        F: FnOnce() -> R,
    {
        // If the pin is listening, we need to take a critical section to prevent racing
        // with the interrupt handler.
152
        if is_int_enabled(self.number()) {
            GPIO_LOCK.lock(f)
        } else {
            f()
        }
    }
    /// Starts to listen for `event`, which also makes the pin a light-sleep wakeup source.
    ///
    /// One register write sets the interrupt enable and the wakeup enable of the pad. A pin that
    /// cannot end a light sleep also cannot deliver its interrupt. A pin that listens therefore
    /// always wakes the chip through the digital path, and needs no configuration for that.
42
    fn listen(&self, event: Event) {
42
        self.with_gpio_lock(|| {
            // Clear the interrupt status bit for this Pin, just in case the user forgot.
            // Since we disabled the interrupt in the handler, it's not possible to
            // trigger a new interrupt before we re-enable it here.
            self.clear_interrupt();
            set_int_enable(
                self.number(),
                Some(gpio_intr_enable(true)),
                event as u8,
                true,
            );
        });
        // The mask bit tells sleep entry to look at the pads.
        #[cfg(sleep_driver_supported)]
        wakeup::enable();
39
    }
    #[inline]
    fn apply_output_config(&self, config: &OutputConfig) {
        let pull_up = config.pull == Pull::Up;
        let pull_down = config.pull == Pull::Down;
        low_level::prepare_pin_pull(self, pull_up, pull_down);
        io_mux_reg(self.number()).modify(|_, w| {
            unsafe { w.fun_drv().bits(config.drive_strength as u8) };
            w.fun_wpu().bit(pull_up);
            w.fun_wpd().bit(pull_down);
            w
        });
        self.with_gpio_lock(|| {
            GPIO::regs().pin(self.number() as usize).modify(|_, w| {
                w.pad_driver()
                    .bit(config.drive_mode == DriveMode::OpenDrain)
            });
        });
    }
    #[inline]
    fn mask(&self) -> u32 {
170
        1 << (self.number() % 32)
    }
    /// The current state of the input.
    #[inline]
    pub(crate) fn is_input_high(&self) -> bool {
67
        self.bank().read_input() & self.mask() != 0
    }
    /// Sets the pin's level to high or low.
    #[inline]
    pub(crate) fn set_output_high(&self, high: bool) {
119
        self.bank().write_output(self.mask(), high);
    }
    /// Is the output set to high.
    #[inline]
    pub(crate) fn is_set_high(&self) -> bool {
4
        self.bank().read_output() & self.mask() != 0
    }
}
impl Pin for AnyPin<'_> {
    #[inline(always)]
    fn number(&self) -> u8 {
20169
        self.pin
    }
    fn output_signals(
        &self,
        private: private::Internal,
    ) -> &'static [(AlternateFunction, OutputSignal)] {
150
        for_each_gpio! {
            (all $( ($n:literal, $gpio:ident $in_afs:tt $out_afs:tt ($input:tt [$($is_output:ident)?]) ) ),* ) => {
                match self.number() {
                    $($(
                        $n => {
                            crate::ignore!($is_output);
                            let inner = unsafe { crate::peripherals::$gpio::steal() };
                            return Pin::output_signals(&inner, private);
                        }
                    )?)*
                    other => panic!("Pin {} is not an OutputPin", other)
                }
            };
        }
    }
    fn input_signals(
        &self,
        private: private::Internal,
    ) -> &'static [(AlternateFunction, InputSignal)] {
58
        for_each_gpio! {
            (all $( ($n:literal, $gpio:ident $in_afs:tt $out_afs:tt ([$($is_input:ident)?] $output:tt) ) ),* ) => {
                match self.number() {
                    $($(
                        $n => {
                            crate::ignore!($is_input);
                            let inner = unsafe { crate::peripherals::$gpio::steal() };
                            return Pin::input_signals(&inner, private);
                        }
                    )?)*
                    other => panic!("Pin {} is not an InputPin", other)
                }
            };
        }
    }
}
impl InputPin for AnyPin<'_> {
    fn waker(&self) -> &'static AtomicWaker {
20123
        for_each_gpio! {
            (all $( ($n:literal, $gpio:ident $in_afs:tt $out_afs:tt ([$($is_input:ident)?] $output:tt) ) ),* ) => {
                match self.number() {
                    $($(
                        $n => {
                            crate::ignore!($is_input);
                            let inner = unsafe { crate::peripherals::$gpio::steal() };
                            return InputPin::waker(&inner);
                        }
                    )?)*
                    other => panic!("Pin {} is not an InputPin", other)
                }
            };
        }
    }
}
impl OutputPin for AnyPin<'_> {}
for_each_gpio! {
    ($n:literal, $gpio:ident $($_rest:tt)*) => {
        impl<'lt> TryFrom<AnyPin<'lt>> for crate::peripherals::$gpio<'lt> {
            type Error = AnyPin<'lt>;
            fn try_from(any_pin: AnyPin<'lt>) -> Result<Self, Self::Error> {
                if any_pin.number() == $n {
                    Ok(unsafe { Self::steal() })
                } else {
                    Err(any_pin)
                }
            }
        }
    };
}
impl AnyPin<'_> {
    #[procmacros::doc_replace]
    /// Attempts to downcast the pin into the underlying GPIO instance.
    ///
    /// # Examples
    ///
    /// ```rust,no_run
    /// # {before_snippet}
    /// #
    /// use esp_hal::{
    ///     gpio::AnyPin,
    ///     peripherals::{GPIO2, GPIO4},
    /// };
    ///
    /// let any_pin2 = AnyPin::from(peripherals.GPIO2);
    /// let any_pin3 = AnyPin::from(peripherals.GPIO3);
    ///
    /// let gpio2 = any_pin2
    ///     .downcast::<GPIO2>()
    ///     .expect("This downcast succeeds because AnyPin was created from GPIO2");
    /// let gpio4 = any_pin3
    ///     .downcast::<GPIO4>()
    ///     .expect_err("This AnyPin was created from GPIO3, it cannot be downcast to GPIO4");
    /// #
    /// # {after_snippet}
    /// ```
    #[inline]
    pub fn downcast<P: Pin>(self) -> Result<P, Self>
    where
        Self: TryInto<P, Error = Self>,
    {
        self.try_into()
    }
    #[procmacros::doc_replace]
    /// Conjure a new GPIO pin out of thin air.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// #
    /// use esp_hal::gpio::AnyPin;
    /// let pin = unsafe { AnyPin::steal(1) };
    /// #
    /// # {after_snippet}
    /// ```
    ///
    /// # Panics
    ///
    /// Panics if the pin with the given number does not exist.
    ///
    /// # Safety
    ///
    /// The caller must ensure that only one instance of a pin is in use at one time.
482
    pub unsafe fn steal(pin: u8) -> Self {
        for_each_gpio! {
            (all $( ($n:literal $($any:tt)*) ),*) => { const PINS: &[u8] = &[ $($n),* ]; };
        };
514
        assert!(PINS.contains(&pin), "Pin {} does not exist", pin);
        Self {
            pin,
            _lifetime: core::marker::PhantomData,
        }
482
    }
    #[procmacros::doc_replace]
    /// Unsafely clone the pin.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// #
    /// use esp_hal::gpio::{AnyPin, Pin};
    /// let pin = peripherals.GPIO1.degrade();
    /// let pin_cloned = unsafe { pin.clone_unchecked() };
    /// #
    /// # {after_snippet}
    /// ```
    ///
    /// # Safety
    ///
    /// The caller must ensure that only one instance of a pin is in use at one time.
    pub unsafe fn clone_unchecked(&self) -> Self {
        Self {
            pin: self.pin,
            _lifetime: core::marker::PhantomData,
        }
    }
    #[procmacros::doc_replace]
    /// Creates a new AnyPin object that is limited to the lifetime of the
    /// passed reference.
    ///
    /// # Examples
    ///
    /// ```rust, no_run
    /// # {before_snippet}
    /// #
    /// use esp_hal::gpio::{AnyPin, Pin};
    /// let mut pin = peripherals.GPIO1.degrade();
    /// let pin_reborrowed = pin.reborrow();
    /// #
    /// # {after_snippet}
    /// ```
    pub fn reborrow(&mut self) -> AnyPin<'_> {
        unsafe { self.clone_unchecked() }
    }
    pub(crate) fn is_output(&self) -> bool {
57
        for_each_gpio! {
            (all $( ($n:literal, $gpio:ident $in_afs:tt $out_afs:tt ($input:tt [$($is_output:ident)?]) ) ),* ) => {
                return match self.number() {
                    $($(
                        // This code is generated if the Output attribute is present
                        $n => {
                            crate::ignore!($is_output);
                            true
                        }
                    )?)*
                    other => false,
                };
            };
        }
    }
}
for_each_gpio! {
    ($n:literal, $gpio:ident $af_ins:tt $af_outs:tt ([Input] $output:tt)) => {
        impl InputPin for crate::peripherals::$gpio<'_> {
            #[doc(hidden)]
            #[inline]
            fn waker(&self) -> &'static $crate::asynch::AtomicWaker {
                static WAKER: $crate::asynch::AtomicWaker = $crate::asynch::AtomicWaker::new();
                &WAKER
            }
        }
    };
}
for_each_gpio! {
    ($n:literal, $gpio:ident $af_ins:tt $af_outs:tt ($input:tt [Output])) => {
        impl OutputPin for crate::peripherals::$gpio<'_> {}
    };
}
for_each_gpio! {
    ($n:literal, $gpio:ident ($( $af_input_num:ident => $af_input_signal:ident )*) ($( $af_output_num:ident => $af_output_signal:ident )*) $attrs:tt) => {
        impl<'d> crate::peripherals::$gpio<'d> {
            #[allow(unused)]
            pub(crate) const NUMBER: u8 = $n;
            #[procmacros::doc_replace]
            /// Splits the pin into an input and output signal.
            ///
            /// Peripheral signals allow connecting peripherals together without using
            /// external hardware.
            ///
            /// # Safety
            ///
            /// The caller must ensure that peripheral drivers do not configure the same
            /// GPIO at the same time in multiple places. This includes clones of the
            /// `InputSignal` struct, as well as the `OutputSignal` struct.
            ///
            /// ```rust, no_run
            /// # {before_snippet}
            /// #
            /// let (rx, tx) = unsafe { peripherals.GPIO2.split() };
            /// // rx and tx can then be passed to different peripherals to connect them.
            /// #
            /// # {after_snippet}
            /// ```
            #[instability::unstable]
6
            pub unsafe fn split(self) -> (interconnect::InputSignal<'d>, interconnect::OutputSignal<'d>) {
                // FIXME: we should implement this in the gpio macro for output pins, but we
                // should also have an input-only alternative for pins that can't be used as
                // outputs.
                // This goes through AnyPin which calls `init_gpio` as needed.
6
                unsafe { self.degrade().split() }
6
            }
        }
        impl Pin for crate::peripherals::$gpio<'_> {
            #[inline(always)]
            fn number(&self) -> u8 {
                $n
            }
            fn output_signals(&self, _: crate::private::Internal) -> &'static [(AlternateFunction, OutputSignal)] {
                &[$(
                    (AlternateFunction::$af_output_num, OutputSignal::$af_output_signal),
                )*]
            }
            fn input_signals(&self, _: crate::private::Internal) -> &'static [(AlternateFunction, InputSignal)] {
                &[$(
                    (AlternateFunction::$af_input_num, InputSignal::$af_input_signal),
                )*]
            }
        }
        impl<'lt> From<crate::peripherals::$gpio<'lt>> for AnyPin<'lt> {
26
            fn from(pin: crate::peripherals::$gpio<'lt>) -> Self {
                Pin::degrade(pin)
26
            }
        }
    };
}
37
define_io_mux_reg!();
// documentation only - renders nicer than the blanket implementation, but
// doesn't prevent generic code from working.
#[cfg(docsrs)]
mod io_matrix_impls {
    use crate::gpio::{
        self,
        AnyPin,
        interconnect::{
            InputSignal,
            OutputSignal,
            PeripheralInput,
            PeripheralOutput,
            PeripheralSignal,
        },
    };
    impl<'d> PeripheralSignal<'d> for AnyPin<'d> {
        fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
            let pin = unsafe { self.clone_unchecked() };
            InputSignal::new(pin).connect_input_to_peripheral(signal);
        }
    }
    impl<'d> PeripheralInput<'d> for AnyPin<'d> {}
    impl<'d> PeripheralOutput<'d> for AnyPin<'d> {
        fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
            let pin = unsafe { self.clone_unchecked() };
            OutputSignal::new(pin).connect_peripheral_to_output(signal);
        }
        fn disconnect_from_peripheral_output(&self) {
            let pin = unsafe { self.clone_unchecked() };
            OutputSignal::new(pin).disconnect_from_peripheral_output();
        }
    }
    for_each_gpio! {
        ($n:literal, $gpio:ident $($_rest:tt)*) => {
            impl<'d> PeripheralSignal<'d> for crate::peripherals::$gpio<'d> {
                fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
                    let pin = unsafe { AnyPin::steal($n) };
                    pin.connect_input_to_peripheral(signal);
                }
            }
            impl<'d> PeripheralInput<'d> for crate::peripherals::$gpio<'d> {}
        };
    }
    for_each_gpio! {
        ($n:literal, $gpio:ident $_af_ins:tt $_af_outs:tt ($input:tt [Output])) => {
            impl<'d> PeripheralOutput<'d> for crate::peripherals::$gpio<'d>
            {
                fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
                    let pin = unsafe { AnyPin::steal($n) };
                    pin.connect_peripheral_to_output(signal);
                }
                fn disconnect_from_peripheral_output(&self) {
                    let pin = unsafe { AnyPin::steal($n) };
                    pin.disconnect_from_peripheral_output();
                }
            }
        };
    }
}
#[cfg(not(docsrs))]
mod io_matrix_impls {
    use crate::gpio::{
        self,
        AnyPin,
        InputPin,
        OutputPin,
        Pin,
        interconnect::{
            InputSignal,
            OutputSignal,
            PeripheralInput,
            PeripheralOutput,
            PeripheralSignal,
        },
    };
    // Pins
    impl<'d, P> PeripheralSignal<'d> for P
    where
        P: Pin + 'd,
    {
        fn connect_input_to_peripheral(&self, signal: gpio::InputSignal) {
            let pin = unsafe { AnyPin::steal(self.number()) };
            InputSignal::new(pin).connect_input_to_peripheral(signal);
        }
    }
    impl<'d, P> PeripheralInput<'d> for P where P: InputPin + 'd {}
    impl<'d, P> PeripheralOutput<'d> for P
    where
        P: OutputPin + 'd,
    {
        fn connect_peripheral_to_output(&self, signal: gpio::OutputSignal) {
            let pin = unsafe { AnyPin::steal(self.number()) };
8
            OutputSignal::new(pin).connect_peripheral_to_output(signal);
        }
        fn disconnect_from_peripheral_output(&self) {
            let pin = unsafe { AnyPin::steal(self.number()) };
            OutputSignal::new(pin).disconnect_from_peripheral_output();
        }
    }
}