Skip to main content

esp_idf_hal/
gpio.rs

1//! GPIO and pin configuration
2
3use core::marker::PhantomData;
4
5#[cfg(feature = "alloc")]
6extern crate alloc;
7
8use esp_idf_sys::*;
9
10use crate::adc::AdcChannel;
11
12pub use chip::*;
13
14pub type PinId = u8;
15
16/// A trait implemented by every pin instance
17pub trait Pin: Sized + Send {
18    /// Return the pin ID
19    fn pin(&self) -> PinId;
20}
21
22/// A marker trait designating a pin which is capable of
23/// operating as an input pin
24pub trait InputPin: Pin {}
25
26/// A marker trait designating a pin which is capable of
27/// operating as an output pin
28pub trait OutputPin: Pin {}
29
30/// A marker trait designating a pin which is capable of
31/// operating as an RTC pin
32pub trait RTCPin: Pin {
33    /// Return the RTC pin ID
34    fn rtc_pin(&self) -> PinId;
35}
36
37/// A marker trait designating a pin which is capable of
38/// operating as an ADC pin
39pub trait ADCPin: Pin {
40    /// Return the ADC channel for this pin
41    type AdcChannel: AdcChannel;
42}
43
44/// A marker trait designating a pin which is capable of
45/// operating as a DAC pin
46#[cfg(any(esp32, esp32s2))]
47pub trait DacChannel: 'static {
48    /// Return the DAC channel for this pin
49    fn dac_channel(&self) -> dac_channel_t;
50}
51
52#[cfg(any(esp32, esp32s2))]
53pub struct DACCH<const N: dac_channel_t>;
54
55#[cfg(any(esp32, esp32s2))]
56impl<const N: dac_channel_t> DacChannel for DACCH<N> {
57    fn dac_channel(&self) -> dac_channel_t {
58        N
59    }
60}
61
62/// A marker trait designating a pin which is capable of
63/// operating as a DAC pin
64#[cfg(any(esp32, esp32s2))]
65pub trait DACPin: Pin {
66    /// Return the DAC channel for this pin
67    type DacChannel: DacChannel;
68}
69
70/// A marker trait designating a pin which is capable of
71/// operating as a touch pin
72#[cfg(any(esp32, esp32s2, esp32s3))]
73pub trait TouchChannel: 'static {
74    /// Return the touch channel for this pin
75    fn touch_channel(&self) -> touch_pad_t;
76}
77
78#[cfg(any(esp32, esp32s2, esp32s3))]
79pub struct TOUCHCH<const N: touch_pad_t>;
80
81#[cfg(any(esp32, esp32s2, esp32s3))]
82impl<const N: touch_pad_t> TouchChannel for TOUCHCH<N> {
83    fn touch_channel(&self) -> touch_pad_t {
84        N
85    }
86}
87
88/// A marker trait designating a pin which is capable of
89/// operating as a touch pin
90#[cfg(any(esp32, esp32s2, esp32s3))]
91pub trait TouchPin: Pin {
92    /// Return the touch channel for this pin
93    type TouchChannel: TouchChannel;
94}
95
96#[allow(unused_macros)]
97macro_rules! impl_any {
98    ($name:ident) => {
99        pub struct $name<'a> {
100            pin: PinId,
101            _t: ::core::marker::PhantomData<&'a mut ()>,
102        }
103
104        impl $name<'_> {
105            /// Unsafely create an instance of this peripheral out of thin air.
106            ///
107            /// # Safety
108            ///
109            /// You must ensure that you're only using one instance of this type at a time.
110            #[inline(always)]
111            pub unsafe fn steal(pin: PinId) -> Self {
112                Self {
113                    pin,
114                    _t: ::core::marker::PhantomData,
115                }
116            }
117
118            /// Creates a new peripheral reference with a shorter lifetime.
119            ///
120            /// Use this method if you would like to keep working with the peripheral after
121            /// you dropped the driver that consumes this.
122            ///
123            /// # Safety
124            ///
125            /// You must ensure that you are not using reborrowed peripherals in drivers which are
126            /// forgotten via `core::mem::forget`.
127            #[inline]
128            #[allow(dead_code)]
129            pub unsafe fn reborrow(&mut self) -> $name<'_> {
130                $name {
131                    pin: self.pin,
132                    _t: ::core::marker::PhantomData,
133                }
134            }
135
136            /// Return `Option::None` for an unconfigured instance of that pin
137            pub const fn none() -> Option<Self> {
138                None
139            }
140        }
141
142        unsafe impl Send for $name<'_> {}
143
144        impl Pin for $name<'_> {
145            fn pin(&self) -> PinId {
146                self.pin as _
147            }
148        }
149    };
150}
151
152impl_any!(AnyIOPin);
153
154impl InputPin for AnyIOPin<'_> {}
155impl OutputPin for AnyIOPin<'_> {}
156
157impl_any!(AnyInputPin);
158
159impl InputPin for AnyInputPin<'_> {}
160
161impl<'a> From<AnyIOPin<'a>> for AnyInputPin<'a> {
162    fn from(pin: AnyIOPin<'a>) -> Self {
163        unsafe { Self::steal(pin.pin()) }
164    }
165}
166
167impl_any!(AnyOutputPin);
168
169impl OutputPin for AnyOutputPin<'_> {}
170
171impl<'a> From<AnyIOPin<'a>> for AnyOutputPin<'a> {
172    fn from(pin: AnyIOPin<'a>) -> Self {
173        unsafe { Self::steal(pin.pin()) }
174    }
175}
176
177/// Interrupt types
178#[derive(Debug, Eq, PartialEq, Copy, Clone)]
179pub enum InterruptType {
180    PosEdge,
181    NegEdge,
182    AnyEdge,
183    LowLevel,
184    HighLevel,
185}
186
187impl From<InterruptType> for gpio_int_type_t {
188    fn from(interrupt_type: InterruptType) -> gpio_int_type_t {
189        match interrupt_type {
190            InterruptType::PosEdge => gpio_int_type_t_GPIO_INTR_POSEDGE,
191            InterruptType::NegEdge => gpio_int_type_t_GPIO_INTR_NEGEDGE,
192            InterruptType::AnyEdge => gpio_int_type_t_GPIO_INTR_ANYEDGE,
193            InterruptType::LowLevel => gpio_int_type_t_GPIO_INTR_LOW_LEVEL,
194            InterruptType::HighLevel => gpio_int_type_t_GPIO_INTR_HIGH_LEVEL,
195        }
196    }
197}
198
199impl From<InterruptType> for u8 {
200    fn from(interrupt_type: InterruptType) -> u8 {
201        let int_type: gpio_int_type_t = interrupt_type.into();
202
203        int_type as u8
204    }
205}
206
207/// Drive strength (values are approximates)
208#[derive(Debug, Eq, PartialEq, Copy, Clone)]
209pub enum DriveStrength {
210    I5mA = 0,
211    I10mA = 1,
212    I20mA = 2,
213    I40mA = 3,
214}
215
216impl From<DriveStrength> for gpio_drive_cap_t {
217    fn from(strength: DriveStrength) -> gpio_drive_cap_t {
218        match strength {
219            DriveStrength::I5mA => gpio_drive_cap_t_GPIO_DRIVE_CAP_0,
220            DriveStrength::I10mA => gpio_drive_cap_t_GPIO_DRIVE_CAP_1,
221            DriveStrength::I20mA => gpio_drive_cap_t_GPIO_DRIVE_CAP_2,
222            DriveStrength::I40mA => gpio_drive_cap_t_GPIO_DRIVE_CAP_3,
223        }
224    }
225}
226
227impl From<gpio_drive_cap_t> for DriveStrength {
228    #[allow(non_upper_case_globals)]
229    fn from(cap: gpio_drive_cap_t) -> DriveStrength {
230        match cap {
231            gpio_drive_cap_t_GPIO_DRIVE_CAP_0 => DriveStrength::I5mA,
232            gpio_drive_cap_t_GPIO_DRIVE_CAP_1 => DriveStrength::I10mA,
233            gpio_drive_cap_t_GPIO_DRIVE_CAP_2 => DriveStrength::I20mA,
234            gpio_drive_cap_t_GPIO_DRIVE_CAP_3 => DriveStrength::I40mA,
235            other => panic!("Unknown GPIO pin drive capability: {other}"),
236        }
237    }
238}
239
240// Pull setting for an input.
241#[derive(Debug, Eq, PartialEq, Copy, Clone)]
242pub enum Pull {
243    Floating,
244    Up,
245    Down,
246    UpDown,
247}
248
249impl From<Pull> for gpio_pull_mode_t {
250    fn from(pull: Pull) -> gpio_pull_mode_t {
251        match pull {
252            Pull::Floating => gpio_pull_mode_t_GPIO_FLOATING,
253            Pull::Up => gpio_pull_mode_t_GPIO_PULLUP_ONLY,
254            Pull::Down => gpio_pull_mode_t_GPIO_PULLDOWN_ONLY,
255            Pull::UpDown => gpio_pull_mode_t_GPIO_PULLUP_PULLDOWN,
256        }
257    }
258}
259
260/// Digital input or output level.
261#[derive(Debug, Eq, PartialEq, Copy, Clone)]
262pub enum Level {
263    Low,
264    High,
265}
266
267impl From<bool> for Level {
268    fn from(val: bool) -> Self {
269        match val {
270            true => Self::High,
271            false => Self::Low,
272        }
273    }
274}
275
276impl From<Level> for bool {
277    fn from(val: Level) -> bool {
278        match val {
279            Level::Low => false,
280            Level::High => true,
281        }
282    }
283}
284
285impl core::ops::Not for Level {
286    type Output = Level;
287
288    fn not(self) -> Self::Output {
289        match self {
290            Level::Low => Level::High,
291            Level::High => Level::Low,
292        }
293    }
294}
295
296impl From<embedded_hal_0_2::digital::v2::PinState> for Level {
297    fn from(state: embedded_hal_0_2::digital::v2::PinState) -> Self {
298        match state {
299            embedded_hal_0_2::digital::v2::PinState::Low => Self::Low,
300            embedded_hal_0_2::digital::v2::PinState::High => Self::High,
301        }
302    }
303}
304
305impl From<Level> for embedded_hal_0_2::digital::v2::PinState {
306    fn from(level: Level) -> Self {
307        match level {
308            Level::Low => Self::Low,
309            Level::High => Self::High,
310        }
311    }
312}
313
314impl From<embedded_hal::digital::PinState> for Level {
315    fn from(state: embedded_hal::digital::PinState) -> Self {
316        match state {
317            embedded_hal::digital::PinState::Low => Self::Low,
318            embedded_hal::digital::PinState::High => Self::High,
319        }
320    }
321}
322
323impl From<Level> for embedded_hal::digital::PinState {
324    fn from(level: Level) -> Self {
325        match level {
326            Level::Low => Self::Low,
327            Level::High => Self::High,
328        }
329    }
330}
331
332pub trait GPIOMode {}
333
334#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
335pub trait RTCMode {}
336
337pub trait InputMode {
338    const RTC: bool;
339}
340
341pub trait OutputMode {
342    const RTC: bool;
343}
344
345pub struct Disabled;
346pub struct Input;
347pub struct Output;
348pub struct InputOutput;
349#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
350pub struct RtcDisabled;
351#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
352pub struct RtcInput;
353#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
354pub struct RtcOutput;
355#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
356pub struct RtcInputOutput;
357
358impl GPIOMode for Disabled {}
359
360impl GPIOMode for Input {}
361
362impl InputMode for Input {
363    const RTC: bool = false;
364}
365
366impl GPIOMode for InputOutput {}
367
368impl InputMode for InputOutput {
369    const RTC: bool = false;
370}
371
372impl OutputMode for InputOutput {
373    const RTC: bool = false;
374}
375
376impl GPIOMode for Output {}
377
378impl OutputMode for Output {
379    const RTC: bool = false;
380}
381
382#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
383impl RTCMode for RtcDisabled {}
384
385#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
386impl RTCMode for RtcInput {}
387
388#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
389impl InputMode for RtcInput {
390    const RTC: bool = true;
391}
392
393#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
394impl RTCMode for RtcInputOutput {}
395
396#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
397impl InputMode for RtcInputOutput {
398    const RTC: bool = true;
399}
400
401#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
402impl OutputMode for RtcInputOutput {
403    const RTC: bool = true;
404}
405
406#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
407impl RTCMode for RtcOutput {}
408
409#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
410impl OutputMode for RtcOutput {
411    const RTC: bool = true;
412}
413
414/// A driver for a GPIO pin.
415///
416/// The driver can set the pin as a disconnected/disabled one, input, or output pin, or both or analog.
417/// On some chips (i.e. esp32 and esp32s*), the driver can also set the pin in RTC IO mode.
418/// Depending on the current operating mode, different sets of functions are available.
419///
420/// The mode-setting depends on the capabilities of the pin as well, i.e. input-only pins cannot be set
421/// into output or input-output mode.
422pub struct PinDriver<'d, MODE> {
423    pin: PinId,
424    _mode: PhantomData<MODE>,
425    _t: PhantomData<&'d mut ()>,
426}
427
428impl<'d, MODE> PinDriver<'d, MODE> {
429    /// Try to convert the pin driver into a disabled pin driver.
430    ///
431    /// Return an error if the pin cannot be disabled.
432    #[inline]
433    pub fn try_into_disabled(self) -> Result<PinDriver<'d, Disabled>, EspError> {
434        PinDriver::new_gpio(self.pin as _, gpio_mode_t_GPIO_MODE_DISABLE)
435    }
436
437    /// Try to convert the pin driver into an input pin driver.
438    ///
439    /// Return an error if the pin cannot be set as input.
440    #[inline]
441    pub fn try_into_input(self, pull: Pull) -> Result<PinDriver<'d, Input>, EspError> {
442        let mut pin = PinDriver::new_gpio(self.pin as _, gpio_mode_t_GPIO_MODE_INPUT)?;
443
444        pin.set_pull(pull)?;
445
446        Ok(pin)
447    }
448
449    /// Try to convert the pin driver into an output pin driver.
450    ///
451    /// Return an error if the pin cannot be set as output.
452    #[inline]
453    pub fn try_into_output(self) -> Result<PinDriver<'d, Output>, EspError> {
454        PinDriver::new_gpio(self.pin as _, gpio_mode_t_GPIO_MODE_OUTPUT)
455    }
456
457    /// Try to convert the pin driver into an input-output pin driver.
458    ///
459    /// Return an error if the pin cannot be set as input-output.
460    #[inline]
461    pub fn try_into_input_output(self, pull: Pull) -> Result<PinDriver<'d, InputOutput>, EspError> {
462        let mut pin = PinDriver::new_gpio(self.pin as _, gpio_mode_t_GPIO_MODE_INPUT_OUTPUT)?;
463
464        pin.set_pull(pull)?;
465
466        Ok(pin)
467    }
468
469    /// Try to convert the pin driver into an output open-drain pin driver.
470    ///
471    /// Return an error if the pin cannot be set as output open-drain.
472    #[inline]
473    pub fn try_into_output_od(self) -> Result<PinDriver<'d, Output>, EspError> {
474        PinDriver::new_gpio(self.pin as _, gpio_mode_t_GPIO_MODE_OUTPUT_OD)
475    }
476
477    /// Try to convert the pin driver into an input-output open-drain pin driver.
478    ///
479    /// Return an error if the pin cannot be set as input-output open-drain.
480    #[inline]
481    pub fn try_into_input_output_od(
482        self,
483        pull: Pull,
484    ) -> Result<PinDriver<'d, InputOutput>, EspError> {
485        let mut pin = PinDriver::new_gpio(self.pin as _, gpio_mode_t_GPIO_MODE_INPUT_OUTPUT_OD)?;
486
487        pin.set_pull(pull)?;
488
489        Ok(pin)
490    }
491
492    /// Try to convert the pin driver into an RTC disabled pin driver.
493    ///
494    /// Return an error if the pin cannot be disabled.
495    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
496    #[inline]
497    pub fn try_into_rtc_disabled(self) -> Result<PinDriver<'d, RtcDisabled>, EspError> {
498        PinDriver::new_rtc(self.pin as _, rtc_gpio_mode_t_RTC_GPIO_MODE_DISABLED)
499    }
500
501    /// Try to convert the pin driver into an RTC input pin driver.
502    ///
503    /// Return an error if the pin cannot be set as RTC input.
504    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
505    #[inline]
506    pub fn try_into_rtc_input(self, pull: Pull) -> Result<PinDriver<'d, RtcInput>, EspError> {
507        let mut pin = PinDriver::new_rtc(self.pin as _, rtc_gpio_mode_t_RTC_GPIO_MODE_INPUT_ONLY)?;
508
509        pin.set_pull(pull)?;
510
511        Ok(pin)
512    }
513
514    /// Try to convert the pin driver into an RTC output pin driver.
515    ///
516    /// Return an error if the pin cannot be set as RTC output.
517    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
518    #[inline]
519    pub fn try_into_rtc_output(self) -> Result<PinDriver<'d, RtcOutput>, EspError> {
520        PinDriver::new_rtc(self.pin as _, rtc_gpio_mode_t_RTC_GPIO_MODE_OUTPUT_ONLY)
521    }
522
523    /// Try to convert the pin driver into an RTC output open-drain pin driver.
524    ///
525    /// Return an error if the pin cannot be set as RTC output open-drain.
526    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
527    #[inline]
528    pub fn try_into_rtc_output_od(self) -> Result<PinDriver<'d, RtcOutput>, EspError> {
529        PinDriver::new_rtc(self.pin as _, rtc_gpio_mode_t_RTC_GPIO_MODE_OUTPUT_OD)
530    }
531
532    /// Try to convert the pin driver into an RTC input-output pin driver.
533    ///
534    /// Return an error if the pin cannot be set as RTC input-output.
535    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
536    #[inline]
537    pub fn try_into_rtc_input_output(
538        self,
539        pull: Pull,
540    ) -> Result<PinDriver<'d, RtcInputOutput>, EspError> {
541        let mut pin =
542            PinDriver::new_rtc(self.pin as _, rtc_gpio_mode_t_RTC_GPIO_MODE_INPUT_OUTPUT)?;
543
544        pin.set_pull(pull)?;
545
546        Ok(pin)
547    }
548
549    /// Try to convert the pin driver into an RTC input-output open-drain pin driver.
550    ///
551    /// Return an error if the pin cannot be set as RTC input-output open-drain.
552    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
553    #[inline]
554    pub fn try_into_rtc_input_output_od(
555        self,
556        pull: Pull,
557    ) -> Result<PinDriver<'d, RtcInputOutput>, EspError> {
558        let mut pin =
559            PinDriver::new_rtc(self.pin as _, rtc_gpio_mode_t_RTC_GPIO_MODE_INPUT_OUTPUT_OD)?;
560
561        pin.set_pull(pull)?;
562
563        Ok(pin)
564    }
565}
566
567impl<'d> PinDriver<'d, Disabled> {
568    /// Creates the driver for a pin in disabled state.
569    #[inline]
570    pub fn disabled<T: Pin + 'd>(pin: T) -> Result<Self, EspError> {
571        Self::new_gpio(pin.pin(), gpio_mode_t_GPIO_MODE_DISABLE)
572    }
573}
574
575impl<'d> PinDriver<'d, Input> {
576    /// Creates the driver for a pin in input state.
577    #[inline]
578    pub fn input<T: InputPin + 'd>(pin: T, pull: Pull) -> Result<Self, EspError> {
579        let mut pin = Self::new_gpio(pin.pin(), gpio_mode_t_GPIO_MODE_INPUT)?;
580
581        pin.set_pull(pull)?;
582
583        Ok(pin)
584    }
585}
586
587impl<'d> PinDriver<'d, InputOutput> {
588    /// Creates the driver for a pin in input-output state.
589    #[inline]
590    pub fn input_output<T: InputPin + OutputPin + 'd>(
591        pin: T,
592        pull: Pull,
593    ) -> Result<Self, EspError> {
594        let mut pin = Self::new_gpio(pin.pin(), gpio_mode_t_GPIO_MODE_INPUT_OUTPUT)?;
595
596        pin.set_pull(pull)?;
597
598        Ok(pin)
599    }
600
601    /// Creates the driver for a pin in input-output open-drain state.
602    #[inline]
603    pub fn input_output_od<T: InputPin + OutputPin + 'd>(
604        pin: T,
605        pull: Pull,
606    ) -> Result<Self, EspError> {
607        let mut pin = Self::new_gpio(pin.pin(), gpio_mode_t_GPIO_MODE_INPUT_OUTPUT_OD)?;
608
609        pin.set_pull(pull)?;
610
611        Ok(pin)
612    }
613}
614
615impl<'d> PinDriver<'d, Output> {
616    /// Creates the driver for a pin in output state.
617    #[inline]
618    pub fn output<T: OutputPin + 'd>(pin: T) -> Result<Self, EspError> {
619        Self::new_gpio(pin.pin(), gpio_mode_t_GPIO_MODE_OUTPUT)
620    }
621
622    /// Creates the driver for a pin in output open-drain state.
623    #[inline]
624    pub fn output_od<T: OutputPin + 'd>(pin: T) -> Result<Self, EspError> {
625        Self::new_gpio(pin.pin(), gpio_mode_t_GPIO_MODE_OUTPUT_OD)
626    }
627}
628
629#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
630impl<'d> PinDriver<'d, RtcDisabled> {
631    /// Creates the driver for a pin in disabled state.
632    #[inline]
633    pub fn rtc_disabled<T: Pin + RTCPin + 'd>(pin: T) -> Result<Self, EspError> {
634        Self::new_rtc(pin.pin(), rtc_gpio_mode_t_RTC_GPIO_MODE_DISABLED)
635    }
636}
637
638#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
639impl<'d> PinDriver<'d, RtcInput> {
640    /// Creates the driver for a pin in RTC input state.
641    #[inline]
642    pub fn rtc_input<T: InputPin + RTCPin + 'd>(pin: T, pull: Pull) -> Result<Self, EspError> {
643        let mut pin = Self::new_rtc(pin.pin(), rtc_gpio_mode_t_RTC_GPIO_MODE_INPUT_ONLY)?;
644
645        pin.set_pull(pull)?;
646
647        Ok(pin)
648    }
649}
650
651#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
652impl<'d> PinDriver<'d, RtcInputOutput> {
653    /// Creates the driver for a pin in RTC input-output state.
654    #[inline]
655    pub fn rtc_input_output<T: InputPin + OutputPin + RTCPin + 'd>(
656        pin: T,
657        pull: Pull,
658    ) -> Result<Self, EspError> {
659        let mut pin = Self::new_rtc(pin.pin(), rtc_gpio_mode_t_RTC_GPIO_MODE_INPUT_OUTPUT)?;
660
661        pin.set_pull(pull)?;
662
663        Ok(pin)
664    }
665
666    /// Creates the driver for a pin in RTC input-output open-drain state.
667    #[inline]
668    pub fn rtc_input_output_od<T: InputPin + OutputPin + RTCPin + 'd>(
669        pin: T,
670        pull: Pull,
671    ) -> Result<Self, EspError> {
672        let mut pin = Self::new_rtc(pin.pin(), rtc_gpio_mode_t_RTC_GPIO_MODE_INPUT_OUTPUT_OD)?;
673
674        pin.set_pull(pull)?;
675
676        Ok(pin)
677    }
678}
679
680#[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
681impl<'d> PinDriver<'d, RtcOutput> {
682    /// Creates the driver for a pin in RTC output state.
683    #[inline]
684    pub fn rtc_output<T: OutputPin + RTCPin + 'd>(pin: T) -> Result<Self, EspError> {
685        Self::new_rtc(pin.pin(), rtc_gpio_mode_t_RTC_GPIO_MODE_OUTPUT_ONLY)
686    }
687
688    /// Creates the driver for a pin in RTC output open-drain state.
689    #[inline]
690    pub fn rtc_output_od<T: OutputPin + RTCPin + 'd>(pin: T) -> Result<Self, EspError> {
691        Self::new_rtc(pin.pin(), rtc_gpio_mode_t_RTC_GPIO_MODE_OUTPUT_OD)
692    }
693}
694
695impl<'d, MODE> PinDriver<'d, MODE> {
696    /// Returns the pin number.
697    pub fn pin(&self) -> PinId {
698        self.pin
699    }
700
701    #[inline]
702    pub fn get_drive_strength(&self) -> Result<DriveStrength, EspError>
703    where
704        MODE: OutputMode,
705    {
706        let mut cap: gpio_drive_cap_t = 0;
707
708        if MODE::RTC {
709            #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
710            esp!(unsafe { rtc_gpio_get_drive_capability(self.pin as _, &mut cap) })?;
711
712            #[cfg(any(esp32c3, esp32c2, esp32h2, esp32h4))]
713            unreachable!();
714        } else {
715            esp!(unsafe { gpio_get_drive_capability(self.pin as _, &mut cap) })?;
716        }
717
718        Ok(cap.into())
719    }
720
721    #[inline]
722    pub fn set_drive_strength(&mut self, strength: DriveStrength) -> Result<(), EspError>
723    where
724        MODE: OutputMode,
725    {
726        if MODE::RTC {
727            #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
728            esp!(unsafe { rtc_gpio_set_drive_capability(self.pin as _, strength.into()) })?;
729
730            #[cfg(any(esp32c3, esp32c2, esp32h2, esp32h4))]
731            unreachable!();
732        } else {
733            esp!(unsafe { gpio_set_drive_capability(self.pin as _, strength.into()) })?;
734        }
735
736        Ok(())
737    }
738
739    #[inline]
740    pub fn is_high(&self) -> bool
741    where
742        MODE: InputMode,
743    {
744        self.get_level().into()
745    }
746
747    #[inline]
748    pub fn is_low(&self) -> bool
749    where
750        MODE: InputMode,
751    {
752        !self.is_high()
753    }
754
755    #[inline]
756    #[allow(clippy::needless_late_init)]
757    pub fn get_level(&self) -> Level
758    where
759        MODE: InputMode,
760    {
761        let res;
762
763        if MODE::RTC {
764            #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
765            {
766                res = if unsafe { rtc_gpio_get_level(self.pin as _) } != 0 {
767                    Level::High
768                } else {
769                    Level::Low
770                };
771            }
772
773            #[cfg(any(esp32c3, esp32c2, esp32h2, esp32h4))]
774            unreachable!();
775        } else if unsafe { gpio_get_level(self.pin as _) } != 0 {
776            res = Level::High;
777        } else {
778            res = Level::Low;
779        }
780
781        res
782    }
783
784    #[inline]
785    pub fn is_set_high(&self) -> bool
786    where
787        MODE: OutputMode,
788    {
789        !self.is_set_low()
790    }
791
792    /// Is the output pin set as low?
793    #[inline]
794    pub fn is_set_low(&self) -> bool
795    where
796        MODE: OutputMode,
797    {
798        self.get_output_level() == Level::Low
799    }
800
801    /// What level output is set to
802    #[inline]
803    fn get_output_level(&self) -> Level
804    where
805        MODE: OutputMode,
806    {
807        // TODO: Implement for RTC mode
808
809        let pin = self.pin as u32;
810
811        #[cfg(any(esp32c3, esp32c2, esp32h2, esp32h4))]
812        let is_set_high = unsafe { (*(GPIO_OUT_REG as *const u32) >> pin) & 0x01 != 0 };
813        #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
814        let is_set_high = if pin <= 31 {
815            // GPIO0 - GPIO31
816            unsafe { (*(GPIO_OUT_REG as *const u32) >> pin) & 0x01 != 0 }
817        } else {
818            // GPIO32+
819            unsafe { (*(GPIO_OUT1_REG as *const u32) >> (pin - 32)) & 0x01 != 0 }
820        };
821
822        if is_set_high {
823            Level::High
824        } else {
825            Level::Low
826        }
827    }
828
829    #[inline]
830    pub fn set_high(&mut self) -> Result<(), EspError>
831    where
832        MODE: OutputMode,
833    {
834        self.set_level(Level::High)
835    }
836
837    /// Set the output as low.
838    #[inline]
839    pub fn set_low(&mut self) -> Result<(), EspError>
840    where
841        MODE: OutputMode,
842    {
843        self.set_level(Level::Low)
844    }
845
846    #[inline]
847    pub fn set_level(&mut self, level: Level) -> Result<(), EspError>
848    where
849        MODE: OutputMode,
850    {
851        let on = match level {
852            Level::Low => 0,
853            Level::High => 1,
854        };
855
856        if MODE::RTC {
857            #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
858            esp!(unsafe { rtc_gpio_set_level(self.pin as _, on) })?;
859
860            #[cfg(any(esp32c3, esp32c2, esp32h2, esp32h4))]
861            unreachable!();
862        } else {
863            esp!(unsafe { gpio_set_level(self.pin as _, on) })?;
864        }
865
866        Ok(())
867    }
868
869    /// Toggle pin output
870    #[inline]
871    pub fn toggle(&mut self) -> Result<(), EspError>
872    where
873        MODE: OutputMode,
874    {
875        if self.is_set_low() {
876            self.set_high()
877        } else {
878            self.set_low()
879        }
880    }
881
882    fn set_pull(&mut self, pull: Pull) -> Result<(), EspError>
883    where
884        MODE: InputMode,
885    {
886        if MODE::RTC {
887            #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
888            unsafe {
889                match pull {
890                    Pull::Down => {
891                        esp!(rtc_gpio_pulldown_en(self.pin as _))?;
892                        esp!(rtc_gpio_pullup_dis(self.pin as _))?;
893                    }
894                    Pull::Up => {
895                        esp!(rtc_gpio_pulldown_dis(self.pin as _))?;
896                        esp!(rtc_gpio_pullup_en(self.pin as _))?;
897                    }
898                    Pull::UpDown => {
899                        esp!(rtc_gpio_pulldown_en(self.pin as _))?;
900                        esp!(rtc_gpio_pullup_en(self.pin as _))?;
901                    }
902                    Pull::Floating => {
903                        esp!(rtc_gpio_pulldown_dis(self.pin as _))?;
904                        esp!(rtc_gpio_pullup_dis(self.pin as _))?;
905                    }
906                }
907            }
908
909            #[cfg(any(esp32c3, esp32c2, esp32h2, esp32h4))]
910            unreachable!();
911        } else {
912            esp!(unsafe { gpio_set_pull_mode(self.pin as _, pull.into()) })?;
913        }
914
915        Ok(())
916    }
917
918    /// Subscribes the provided callback for ISR notifications.
919    /// As a side effect, interrupts will be disabled, so to receive a notification, one has
920    /// to also call `PinDriver::enable_interrupt` after calling this method.
921    ///
922    /// Note that `PinDriver::enable_interrupt` should also be called after
923    /// each received notification **from non-ISR context**, because the driver will automatically
924    /// disable ISR interrupts on each received ISR notification (so as to avoid IWDT triggers).
925    ///
926    /// # Safety
927    ///
928    /// Care should be taken not to call STD, libc or FreeRTOS APIs (except for a few allowed ones)
929    /// in the callback passed to this function, as it is executed in an ISR context.
930    #[cfg(feature = "alloc")]
931    pub unsafe fn subscribe<F: FnMut() + Send + 'static>(
932        &mut self,
933        callback: F,
934    ) -> Result<(), EspError>
935    where
936        MODE: InputMode,
937    {
938        self.internal_subscribe(callback)
939    }
940
941    /// Subscribes the provided callback for ISR notifications.
942    /// As a side effect, interrupts will be disabled, so to receive a notification, one has
943    /// to also call `PinDriver::enable_interrupt` after calling this method.
944    ///
945    /// Note that `PinDriver::enable_interrupt` should also be called after
946    /// each received notification **from non-ISR context**, because the driver will automatically
947    /// disable ISR interrupts on each received ISR notification (so as to avoid IWDT triggers).
948    ///
949    /// # Safety
950    ///
951    /// Care should be taken not to call STD, libc or FreeRTOS APIs (except for a few allowed ones)
952    /// in the callback passed to this function, as it is executed in an ISR context.
953    ///
954    /// Additionally, this method - in contrast to method `subscribe` - allows
955    /// the passed-in callback/closure to be non-`'static`. This enables users to borrow
956    /// - in the closure - variables that live on the stack - or more generally - in the same
957    ///   scope where the driver is created.
958    ///
959    /// HOWEVER: care should be taken NOT to call `core::mem::forget()` on the driver,
960    /// as that would immediately lead to an UB (crash).
961    /// Also note that forgetting the driver might happen with `Rc` and `Arc`
962    /// when circular references are introduced: https://github.com/rust-lang/rust/issues/24456
963    ///
964    /// The reason is that the closure is actually sent and owned by an ISR routine,
965    /// which means that if the driver is forgotten, Rust is free to e.g. unwind the stack
966    /// and the ISR routine will end up with references to variables that no longer exist.
967    ///
968    /// The destructor of the driver takes care - prior to the driver being dropped and e.g.
969    /// the stack being unwind - to unsubscribe the ISR routine.
970    /// Unfortunately, when the driver is forgotten, the un-subscription does not happen
971    /// and invalid references are left dangling.
972    ///
973    /// This "local borrowing" will only be possible to express in a safe way once/if `!Leak` types
974    /// are introduced to Rust (i.e. the impossibility to "forget" a type and thus not call its destructor).
975    #[cfg(feature = "alloc")]
976    pub unsafe fn subscribe_nonstatic<F: FnMut() + Send + 'd>(
977        &mut self,
978        callback: F,
979    ) -> Result<(), EspError>
980    where
981        MODE: InputMode,
982    {
983        self.internal_subscribe(callback)
984    }
985
986    #[cfg(feature = "alloc")]
987    fn internal_subscribe(&mut self, callback: impl FnMut() + Send + 'd) -> Result<(), EspError>
988    where
989        MODE: InputMode,
990    {
991        extern crate alloc;
992
993        self.disable_interrupt()?;
994
995        let callback: alloc::boxed::Box<dyn FnMut() + Send + 'd> = alloc::boxed::Box::new(callback);
996        unsafe {
997            chip::PIN_ISR_HANDLER[self.pin as usize] = Some(core::mem::transmute::<
998                alloc::boxed::Box<dyn FnMut() + Send>,
999                alloc::boxed::Box<dyn FnMut() + Send>,
1000            >(callback));
1001        }
1002
1003        Ok(())
1004    }
1005
1006    pub fn unsubscribe(&mut self) -> Result<(), EspError>
1007    where
1008        MODE: InputMode,
1009    {
1010        unsafe {
1011            unsubscribe_pin(self.pin as _)?;
1012        }
1013
1014        Ok(())
1015    }
1016
1017    /// Enables or re-enables the interrupt
1018    ///
1019    /// Note that the interrupt is automatically disabled each time an interrupt is triggered
1020    /// (or else we risk entering a constant interrupt processing loop while the pin is in low/high state
1021    /// and the interrupt type is set to non-edge)
1022    ///
1023    /// Therefore - to continue receiving ISR interrupts - user needs to call `enable_interrupt`
1024    /// - **from a non-ISR context** - after each successful interrupt triggering.
1025    pub fn enable_interrupt(&mut self) -> Result<(), EspError>
1026    where
1027        MODE: InputMode,
1028    {
1029        enable_isr_service()?;
1030
1031        unsafe {
1032            esp!(gpio_isr_handler_add(
1033                self.pin as _,
1034                Some(Self::handle_isr),
1035                self.pin as u32 as *mut core::ffi::c_void,
1036            ))
1037        }
1038    }
1039
1040    pub fn disable_interrupt(&mut self) -> Result<(), EspError>
1041    where
1042        MODE: InputMode,
1043    {
1044        use core::sync::atomic::Ordering;
1045
1046        if ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
1047            esp!(unsafe { gpio_isr_handler_remove(self.pin as _) })?;
1048        }
1049
1050        Ok(())
1051    }
1052
1053    pub fn set_interrupt_type(&mut self, interrupt_type: InterruptType) -> Result<(), EspError>
1054    where
1055        MODE: InputMode,
1056    {
1057        esp!(unsafe { gpio_set_intr_type(self.pin as _, interrupt_type.into()) })?;
1058
1059        Ok(())
1060    }
1061
1062    #[inline]
1063    fn new_gpio(pin: PinId, mode: gpio_mode_t) -> Result<Self, EspError>
1064    where
1065        MODE: GPIOMode,
1066    {
1067        if mode != gpio_mode_t_GPIO_MODE_DISABLE {
1068            // `gpio_set_direction` wires up the GPIO matrix and the output
1069            // enable, but it never touches `IO_MUX.MCU_SEL`. A pad that boots
1070            // on an alternate function - JTAG, SPI flash, UART - therefore
1071            // stays on that function and never sees what the driver writes.
1072            // Route it to the GPIO function first, which is what `gpio_config`
1073            // does for every pin it is handed.
1074            unsafe { esp_rom_gpio_pad_select_gpio(pin as _) };
1075
1076            esp!(unsafe { gpio_set_direction(pin as _, mode) })?;
1077        }
1078
1079        Ok(Self {
1080            pin,
1081            _mode: PhantomData,
1082            _t: PhantomData,
1083        })
1084    }
1085
1086    #[inline]
1087    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
1088    fn new_rtc(pin: PinId, mode: rtc_gpio_mode_t) -> Result<Self, EspError>
1089    where
1090        MODE: RTCMode,
1091    {
1092        esp!(unsafe { rtc_gpio_init(pin as _) })?;
1093        esp!(unsafe { rtc_gpio_set_direction(pin as _, mode) })?;
1094
1095        Ok(PinDriver {
1096            pin,
1097            _mode: PhantomData,
1098            _t: PhantomData,
1099        })
1100    }
1101
1102    unsafe extern "C" fn handle_isr(user_ctx: *mut core::ffi::c_void) {
1103        let pin = user_ctx as u32;
1104
1105        // IMPORTANT: MUST be done or else the ESP IDF GPIO driver will continue calling us in a loop
1106        // - particularly when the interrupt type is set to non-edge triggering (pin high or low) -
1107        // which will eventually cause the Interrupt WatchDog to kick in
1108        gpio_intr_disable(pin as _);
1109
1110        PIN_NOTIF[pin as usize].notify_lsb();
1111
1112        #[cfg(feature = "alloc")]
1113        {
1114            if let Some(unsafe_callback) = unsafe { &mut PIN_ISR_HANDLER[pin as usize] } {
1115                (unsafe_callback)();
1116            }
1117        }
1118    }
1119}
1120
1121impl<MODE: InputMode> PinDriver<'_, MODE> {
1122    pub async fn wait_for(&mut self, interrupt_type: InterruptType) -> Result<(), EspError> {
1123        self.disable_interrupt()?;
1124
1125        let notif = &chip::PIN_NOTIF[self.pin as usize];
1126
1127        notif.reset();
1128
1129        match interrupt_type {
1130            InterruptType::LowLevel if self.is_low() => return Ok(()),
1131            InterruptType::HighLevel if self.is_high() => return Ok(()),
1132            _ => (),
1133        }
1134
1135        self.set_interrupt_type(interrupt_type)?;
1136        self.enable_interrupt()?;
1137
1138        notif.wait().await;
1139
1140        Ok(())
1141    }
1142
1143    pub async fn wait_for_high(&mut self) -> Result<(), EspError> {
1144        self.wait_for(InterruptType::HighLevel).await
1145    }
1146
1147    pub async fn wait_for_low(&mut self) -> Result<(), EspError> {
1148        self.wait_for(InterruptType::LowLevel).await
1149    }
1150
1151    pub async fn wait_for_rising_edge(&mut self) -> Result<(), EspError> {
1152        self.wait_for(InterruptType::PosEdge).await
1153    }
1154
1155    pub async fn wait_for_falling_edge(&mut self) -> Result<(), EspError> {
1156        self.wait_for(InterruptType::NegEdge).await
1157    }
1158
1159    pub async fn wait_for_any_edge(&mut self) -> Result<(), EspError> {
1160        self.wait_for(InterruptType::AnyEdge).await
1161    }
1162}
1163
1164impl<MODE> Drop for PinDriver<'_, MODE> {
1165    fn drop(&mut self) {
1166        gpio_reset_without_pull(self.pin as _).unwrap();
1167    }
1168}
1169
1170unsafe impl<MODE> Send for PinDriver<'_, MODE> {}
1171
1172impl<MODE> embedded_hal_0_2::digital::v2::InputPin for PinDriver<'_, MODE>
1173where
1174    MODE: InputMode,
1175{
1176    type Error = EspError;
1177
1178    fn is_high(&self) -> Result<bool, Self::Error> {
1179        Ok(PinDriver::is_high(self))
1180    }
1181
1182    fn is_low(&self) -> Result<bool, Self::Error> {
1183        Ok(PinDriver::is_low(self))
1184    }
1185}
1186
1187use crate::embedded_hal_error;
1188embedded_hal_error!(
1189    GpioError,
1190    embedded_hal::digital::Error,
1191    embedded_hal::digital::ErrorKind
1192);
1193
1194fn to_gpio_err(err: EspError) -> GpioError {
1195    GpioError::other(err)
1196}
1197
1198impl<MODE> embedded_hal::digital::ErrorType for PinDriver<'_, MODE> {
1199    type Error = GpioError;
1200}
1201
1202impl<MODE> embedded_hal::digital::InputPin for PinDriver<'_, MODE>
1203where
1204    MODE: InputMode,
1205{
1206    fn is_high(&mut self) -> Result<bool, Self::Error> {
1207        Ok(PinDriver::is_high(self))
1208    }
1209
1210    fn is_low(&mut self) -> Result<bool, Self::Error> {
1211        Ok(PinDriver::is_low(self))
1212    }
1213}
1214
1215impl<MODE> embedded_hal::digital::InputPin for &PinDriver<'_, MODE>
1216where
1217    MODE: InputMode,
1218{
1219    fn is_high(&mut self) -> Result<bool, Self::Error> {
1220        Ok(PinDriver::is_high(self))
1221    }
1222
1223    fn is_low(&mut self) -> Result<bool, Self::Error> {
1224        Ok(PinDriver::is_low(self))
1225    }
1226}
1227
1228impl<MODE> embedded_hal_0_2::digital::v2::OutputPin for PinDriver<'_, MODE>
1229where
1230    MODE: OutputMode,
1231{
1232    type Error = EspError;
1233
1234    fn set_high(&mut self) -> Result<(), Self::Error> {
1235        self.set_level(Level::High)
1236    }
1237
1238    fn set_low(&mut self) -> Result<(), Self::Error> {
1239        self.set_level(Level::Low)
1240    }
1241}
1242
1243impl<MODE> embedded_hal::digital::OutputPin for PinDriver<'_, MODE>
1244where
1245    MODE: OutputMode,
1246{
1247    fn set_high(&mut self) -> Result<(), Self::Error> {
1248        self.set_level(Level::High).map_err(to_gpio_err)
1249    }
1250
1251    fn set_low(&mut self) -> Result<(), Self::Error> {
1252        self.set_level(Level::Low).map_err(to_gpio_err)
1253    }
1254}
1255
1256impl<MODE> embedded_hal::digital::StatefulOutputPin for PinDriver<'_, MODE>
1257where
1258    MODE: OutputMode,
1259{
1260    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
1261        Ok(self.get_output_level().into())
1262    }
1263
1264    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
1265        Ok(!bool::from(self.get_output_level()))
1266    }
1267}
1268
1269// TODO: Will become possible once the `PinDriver::setXXX`` methods become non-`&mut`, which they really are, internally
1270// impl<'d, T: Pin, MODE> embedded_hal::digital::StatefulOutputPin for &PinDriver<'d, T, MODE>
1271// where
1272//     MODE: OutputMode,
1273// {
1274//     fn is_set_high(&mut self) -> Result<bool, Self::Error> {
1275//         Ok(self.get_output_level().into())
1276//     }
1277
1278//     fn is_set_low(&mut self) -> Result<bool, Self::Error> {
1279//         Ok(!bool::from(self.get_output_level()))
1280//     }
1281// }
1282
1283impl<MODE> embedded_hal_0_2::digital::v2::StatefulOutputPin for PinDriver<'_, MODE>
1284where
1285    MODE: OutputMode,
1286{
1287    fn is_set_high(&self) -> Result<bool, Self::Error> {
1288        Ok(self.get_output_level().into())
1289    }
1290
1291    fn is_set_low(&self) -> Result<bool, Self::Error> {
1292        Ok(!bool::from(self.get_output_level()))
1293    }
1294}
1295
1296impl<MODE> embedded_hal_0_2::digital::v2::ToggleableOutputPin for PinDriver<'_, MODE>
1297where
1298    MODE: OutputMode,
1299{
1300    type Error = EspError;
1301
1302    fn toggle(&mut self) -> Result<(), Self::Error> {
1303        self.set_level(Level::from(!bool::from(self.get_output_level())))
1304    }
1305}
1306
1307impl<MODE: InputMode> embedded_hal_async::digital::Wait for PinDriver<'_, MODE> {
1308    async fn wait_for_high(&mut self) -> Result<(), GpioError> {
1309        self.wait_for_high().await?;
1310
1311        Ok(())
1312    }
1313
1314    async fn wait_for_low(&mut self) -> Result<(), GpioError> {
1315        self.wait_for_low().await?;
1316
1317        Ok(())
1318    }
1319
1320    async fn wait_for_rising_edge(&mut self) -> Result<(), GpioError> {
1321        self.wait_for_rising_edge().await?;
1322
1323        Ok(())
1324    }
1325
1326    async fn wait_for_falling_edge(&mut self) -> Result<(), GpioError> {
1327        self.wait_for_falling_edge().await?;
1328
1329        Ok(())
1330    }
1331
1332    async fn wait_for_any_edge(&mut self) -> Result<(), GpioError> {
1333        self.wait_for_any_edge().await?;
1334
1335        Ok(())
1336    }
1337}
1338
1339static ISR_ALLOC_FLAGS: core::sync::atomic::AtomicU32 = core::sync::atomic::AtomicU32::new(0);
1340
1341static ISR_SERVICE_ENABLED: core::sync::atomic::AtomicBool =
1342    core::sync::atomic::AtomicBool::new(false);
1343
1344static ISR_SERVICE_ENABLED_CS: crate::task::CriticalSection = crate::task::CriticalSection::new();
1345
1346pub fn init_isr_alloc_flags(flags: enumset::EnumSet<crate::interrupt::InterruptType>) {
1347    ISR_ALLOC_FLAGS.store(
1348        crate::interrupt::InterruptType::to_native(flags),
1349        core::sync::atomic::Ordering::SeqCst,
1350    );
1351}
1352
1353pub fn enable_isr_service() -> Result<(), EspError> {
1354    use core::sync::atomic::Ordering;
1355
1356    if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
1357        let _guard = ISR_SERVICE_ENABLED_CS.enter();
1358
1359        if !ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
1360            esp!(unsafe { gpio_install_isr_service(ISR_ALLOC_FLAGS.load(Ordering::SeqCst) as _) })?;
1361
1362            ISR_SERVICE_ENABLED.store(true, Ordering::SeqCst);
1363        }
1364    }
1365
1366    Ok(())
1367}
1368
1369/// Notifies this GPIO driver that the GPIO ISR service has already been initialized.
1370/// This prevents an error as this driver would otherwise attempt to initialize it again.
1371///
1372/// # Safety
1373///
1374/// The caller must ensure that `gpio_install_isr_service` has already
1375/// been invoked elsewhere. This should only be ever needed when
1376/// interfacing external code that touches the GPIO ISR service.
1377pub unsafe fn set_isr_service_flag_unchecked() {
1378    ISR_SERVICE_ENABLED.store(true, core::sync::atomic::Ordering::SeqCst);
1379}
1380
1381pub(crate) unsafe fn rtc_reset_pin(pin: i32) -> Result<(), EspError> {
1382    gpio_reset_without_pull(pin)?;
1383
1384    #[cfg(not(any(esp32c3, esp32c2, esp32h2, esp32h4)))]
1385    esp!(rtc_gpio_init(pin))?;
1386
1387    Ok(())
1388}
1389
1390// The default esp-idf gpio_reset function sets a pull-up. If that behaviour is
1391// not desired this function can be used instead.
1392#[inline]
1393fn gpio_reset_without_pull(pin: gpio_num_t) -> Result<(), EspError> {
1394    let cfg = gpio_config_t {
1395        pin_bit_mask: (1u64 << pin),
1396        mode: esp_idf_sys::gpio_mode_t_GPIO_MODE_DISABLE,
1397        pull_up_en: esp_idf_sys::gpio_pullup_t_GPIO_PULLUP_DISABLE,
1398        pull_down_en: esp_idf_sys::gpio_pulldown_t_GPIO_PULLDOWN_DISABLE,
1399        intr_type: esp_idf_sys::gpio_int_type_t_GPIO_INTR_DISABLE,
1400        #[cfg(all(
1401            esp_idf_soc_gpio_support_pin_hys_filter,
1402            not(esp_idf_version_major = "4")
1403        ))]
1404        hys_ctrl_mode: esp_idf_sys::gpio_hys_ctrl_mode_t_GPIO_HYS_SOFT_DISABLE,
1405    };
1406
1407    unsafe {
1408        unsubscribe_pin(pin)?;
1409        esp!(gpio_config(&cfg))?;
1410    }
1411    Ok(())
1412}
1413
1414unsafe fn unsubscribe_pin(pin: gpio_num_t) -> Result<(), EspError> {
1415    use core::sync::atomic::Ordering;
1416
1417    if ISR_SERVICE_ENABLED.load(Ordering::SeqCst) {
1418        esp!(gpio_isr_handler_remove(pin as _))?;
1419
1420        chip::PIN_NOTIF[pin as usize].reset();
1421
1422        #[cfg(feature = "alloc")]
1423        {
1424            chip::PIN_ISR_HANDLER[pin as usize] = None;
1425        }
1426    }
1427
1428    Ok(())
1429}
1430
1431#[cfg(feature = "alloc")]
1432#[allow(clippy::declare_interior_mutable_const)] // OK because this is only used as an array initializer
1433const PIN_ISR_INIT: Option<alloc::boxed::Box<dyn FnMut() + Send + 'static>> = None;
1434
1435#[allow(clippy::declare_interior_mutable_const)] // OK because this is only used as an array initializer
1436const PIN_NOTIF_INIT: crate::interrupt::asynch::HalIsrNotification =
1437    crate::interrupt::asynch::HalIsrNotification::new();
1438
1439macro_rules! impl_input {
1440    ($pxi:ident: $pin:expr) => {
1441        $crate::impl_peripheral!($pxi);
1442
1443        impl $pxi<'static> {
1444            /// Return `Option::None` for an unconfigured instance of that pin
1445            pub const fn none() -> Option<Self> {
1446                None
1447            }
1448        }
1449
1450        impl Pin for $pxi<'_> {
1451            fn pin(&self) -> PinId {
1452                $pin as _
1453            }
1454        }
1455
1456        impl InputPin for $pxi<'_> {}
1457
1458        impl<'a> From<$pxi<'a>> for AnyInputPin<'a> {
1459            fn from(pin: $pxi) -> Self {
1460                unsafe { Self::steal(pin.pin()) }
1461            }
1462        }
1463
1464        impl<'a> $pxi<'a> {
1465            pub fn degrade_input(self) -> AnyInputPin<'a> {
1466                self.into()
1467            }
1468        }
1469    };
1470}
1471
1472macro_rules! impl_input_output {
1473    ($pxi:ident: $pin:expr) => {
1474        impl_input!($pxi: $pin);
1475
1476        impl<'a> $pxi<'a> {
1477            pub fn degrade_output(self) -> AnyOutputPin<'a> {
1478                self.into()
1479            }
1480
1481            pub fn degrade_input_output(self) -> AnyIOPin<'a> {
1482                self.into()
1483            }
1484        }
1485
1486        impl OutputPin for $pxi<'_> {}
1487
1488        impl<'a> From<$pxi<'a>> for AnyOutputPin<'a> {
1489            fn from(pin: $pxi) -> Self {
1490                unsafe { Self::steal(pin.pin()) }
1491            }
1492        }
1493
1494        impl<'a> From<$pxi<'a>> for AnyIOPin<'a> {
1495            fn from(pin: $pxi) -> Self {
1496                unsafe { Self::steal(pin.pin()) }
1497            }
1498        }
1499    };
1500}
1501
1502macro_rules! impl_rtc {
1503    ($pxi:ident: $pin:expr, RTC: $rtc:expr) => {
1504        impl RTCPin for $pxi<'_> {
1505            fn rtc_pin(&self) -> PinId {
1506                $rtc
1507            }
1508        }
1509    };
1510
1511    ($pxi:ident: $pin:expr, NORTC: $rtc:expr) => {};
1512}
1513
1514macro_rules! impl_adc {
1515    ($pxi:ident: $pin:expr, ADC1: $channel:ident) => {
1516        impl ADCPin for $pxi<'_> {
1517            type AdcChannel = $crate::adc::$channel<$crate::adc::ADCU1>;
1518        }
1519    };
1520
1521    ($pxi:ident: $pin:expr, ADC2: $channel:ident) => {
1522        impl ADCPin for $pxi<'_> {
1523            type AdcChannel = $crate::adc::$channel<$crate::adc::ADCU2>;
1524        }
1525    };
1526
1527    ($pxi:ident: $pin:expr, NOADC: $channel:ident) => {};
1528}
1529
1530macro_rules! impl_dac {
1531    ($pxi:ident: $pin:expr, DAC: $dac:expr) => {
1532        #[cfg(any(esp32, esp32s2))]
1533        impl DACPin for $pxi<'_> {
1534            type DacChannel = DACCH<$dac>;
1535        }
1536    };
1537
1538    ($pxi:ident: $pin:expr, NODAC: $dac:expr) => {};
1539}
1540
1541macro_rules! impl_touch {
1542    ($pxi:ident: $pin:expr, TOUCH: $touch:expr) => {
1543        #[cfg(any(esp32, esp32s2, esp32s3))]
1544        impl TouchPin for $pxi<'_> {
1545            type TouchChannel = TOUCHCH<$touch>;
1546        }
1547    };
1548
1549    ($pxi:ident: $pin:expr, NOTOUCH: $touch:expr) => {};
1550}
1551
1552macro_rules! pin {
1553    ($pxi:ident: $pin:expr, Input, $rtc:ident: $rtcno:expr, $adc:ident: $adcno:ident, $dac:ident: $dacno:expr, $touch:ident: $touchno:expr) => {
1554        impl_input!($pxi: $pin);
1555        impl_rtc!($pxi: $pin, $rtc: $rtcno);
1556        impl_adc!($pxi: $pin, $adc: $adcno);
1557        impl_dac!($pxi: $pin, $dac: $dacno);
1558        impl_touch!($pxi: $pin, $touch: $touchno);
1559    };
1560
1561    ($pxi:ident: $pin:expr, IO, $rtc:ident: $rtcno:expr, $adc:ident: $adcno:ident, $dac:ident: $dacno:expr, $touch:ident: $touchno:expr) => {
1562        impl_input_output!($pxi: $pin);
1563        impl_rtc!($pxi: $pin, $rtc: $rtcno);
1564        impl_adc!($pxi: $pin, $adc: $adcno);
1565        impl_dac!($pxi: $pin, $dac: $dacno);
1566        impl_touch!($pxi: $pin, $touch: $touchno);
1567    };
1568}
1569
1570#[cfg(esp32)]
1571mod chip {
1572    #[cfg(feature = "alloc")]
1573    extern crate alloc;
1574
1575    #[cfg(feature = "alloc")]
1576    use alloc::boxed::Box;
1577
1578    use crate::interrupt::asynch::HalIsrNotification;
1579
1580    use super::*;
1581
1582    #[allow(clippy::type_complexity)]
1583    #[cfg(feature = "alloc")]
1584    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 40] =
1585        [PIN_ISR_INIT; 40];
1586
1587    #[allow(clippy::type_complexity)]
1588    pub(crate) static PIN_NOTIF: [HalIsrNotification; 40] = [PIN_NOTIF_INIT; 40];
1589
1590    // NOTE: Gpio26 - Gpio32 are used by SPI0/SPI1 for external PSRAM/SPI Flash and
1591    //       are not recommended for other uses
1592    pin!(Gpio0:0, IO, RTC:11, ADC2:ADCCH1, NODAC:0, TOUCH:1);
1593    pin!(Gpio1:1, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1594    pin!(Gpio2:2, IO, RTC:12, ADC2:ADCCH2, NODAC:0, TOUCH:2);
1595    pin!(Gpio3:3, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1596    pin!(Gpio4:4, IO, RTC:10, ADC2:ADCCH0, NODAC:0, TOUCH:0);
1597    pin!(Gpio5:5, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1598    pin!(Gpio6:6, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1599    pin!(Gpio7:7, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1600    pin!(Gpio8:8, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1601    pin!(Gpio9:9, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1602    pin!(Gpio10:10, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1603    pin!(Gpio11:11, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1604    pin!(Gpio12:12, IO, RTC:15, ADC2:ADCCH5, NODAC:0, TOUCH:5);
1605    pin!(Gpio13:13, IO, RTC:14, ADC2:ADCCH4, NODAC:0, TOUCH:4);
1606    pin!(Gpio14:14, IO, RTC:16, ADC2:ADCCH6, NODAC:0, TOUCH:6);
1607    pin!(Gpio15:15, IO, RTC:13, ADC2:ADCCH3, NODAC:0, TOUCH:3);
1608    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1609    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1610    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1611    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1612    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1613    pin!(Gpio21:21, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1614    pin!(Gpio22:22, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1615    pin!(Gpio23:23, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1616    pin!(Gpio25:25, IO, RTC:6, ADC2:ADCCH8, DAC:1, NOTOUCH:0);
1617    pin!(Gpio26:26, IO, RTC:7, ADC2:ADCCH9, DAC:2, NOTOUCH:0);
1618    pin!(Gpio27:27, IO, RTC:17, ADC2:ADCCH7, NODAC:0, TOUCH:7);
1619    pin!(Gpio32:32, IO, RTC:9, ADC1:ADCCH4, NODAC:0, TOUCH:9);
1620    pin!(Gpio33:33, IO, RTC:8, ADC1:ADCCH5, NODAC:0, TOUCH:8);
1621    pin!(Gpio34:34, Input, RTC:4, ADC1:ADCCH6, NODAC:0, NOTOUCH:0);
1622    pin!(Gpio35:35, Input, RTC:5, ADC1:ADCCH7, NODAC:0, NOTOUCH:0);
1623    pin!(Gpio36:36, Input, RTC:0, ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
1624    pin!(Gpio37:37, Input, RTC:1, ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
1625    pin!(Gpio38:38, Input, RTC:2, ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
1626    pin!(Gpio39:39, Input, RTC:3, ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
1627
1628    pub struct Pins {
1629        pub gpio0: Gpio0<'static>,
1630        pub gpio1: Gpio1<'static>,
1631        pub gpio2: Gpio2<'static>,
1632        pub gpio3: Gpio3<'static>,
1633        pub gpio4: Gpio4<'static>,
1634        pub gpio5: Gpio5<'static>,
1635        pub gpio6: Gpio6<'static>,
1636        pub gpio7: Gpio7<'static>,
1637        pub gpio8: Gpio8<'static>,
1638        pub gpio9: Gpio9<'static>,
1639        pub gpio10: Gpio10<'static>,
1640        pub gpio11: Gpio11<'static>,
1641        pub gpio12: Gpio12<'static>,
1642        pub gpio13: Gpio13<'static>,
1643        pub gpio14: Gpio14<'static>,
1644        pub gpio15: Gpio15<'static>,
1645        pub gpio16: Gpio16<'static>,
1646        pub gpio17: Gpio17<'static>,
1647        pub gpio18: Gpio18<'static>,
1648        pub gpio19: Gpio19<'static>,
1649        pub gpio20: Gpio20<'static>,
1650        pub gpio21: Gpio21<'static>,
1651        pub gpio22: Gpio22<'static>,
1652        pub gpio23: Gpio23<'static>,
1653        pub gpio25: Gpio25<'static>,
1654        pub gpio26: Gpio26<'static>,
1655        pub gpio27: Gpio27<'static>,
1656        pub gpio32: Gpio32<'static>,
1657        pub gpio33: Gpio33<'static>,
1658        pub gpio34: Gpio34<'static>,
1659        pub gpio35: Gpio35<'static>,
1660        pub gpio36: Gpio36<'static>,
1661        pub gpio37: Gpio37<'static>,
1662        pub gpio38: Gpio38<'static>,
1663        pub gpio39: Gpio39<'static>,
1664    }
1665
1666    impl Pins {
1667        /// # Safety
1668        ///
1669        /// Care should be taken not to instantiate the Pins structure, if it is
1670        /// already instantiated and used elsewhere
1671        pub unsafe fn new() -> Self {
1672            Self {
1673                gpio0: Gpio0::steal(),
1674                gpio1: Gpio1::steal(),
1675                gpio2: Gpio2::steal(),
1676                gpio3: Gpio3::steal(),
1677                gpio4: Gpio4::steal(),
1678                gpio5: Gpio5::steal(),
1679                gpio6: Gpio6::steal(),
1680                gpio7: Gpio7::steal(),
1681                gpio8: Gpio8::steal(),
1682                gpio9: Gpio9::steal(),
1683                gpio10: Gpio10::steal(),
1684                gpio11: Gpio11::steal(),
1685                gpio12: Gpio12::steal(),
1686                gpio13: Gpio13::steal(),
1687                gpio14: Gpio14::steal(),
1688                gpio15: Gpio15::steal(),
1689                gpio16: Gpio16::steal(),
1690                gpio17: Gpio17::steal(),
1691                gpio18: Gpio18::steal(),
1692                gpio19: Gpio19::steal(),
1693                gpio20: Gpio20::steal(),
1694                gpio21: Gpio21::steal(),
1695                gpio22: Gpio22::steal(),
1696                gpio23: Gpio23::steal(),
1697                gpio25: Gpio25::steal(),
1698                gpio26: Gpio26::steal(),
1699                gpio27: Gpio27::steal(),
1700                gpio32: Gpio32::steal(),
1701                gpio33: Gpio33::steal(),
1702                gpio34: Gpio34::steal(),
1703                gpio35: Gpio35::steal(),
1704                gpio36: Gpio36::steal(),
1705                gpio37: Gpio37::steal(),
1706                gpio38: Gpio38::steal(),
1707                gpio39: Gpio39::steal(),
1708            }
1709        }
1710    }
1711}
1712
1713#[cfg(any(esp32s2, esp32s3))]
1714mod chip {
1715    #[cfg(feature = "alloc")]
1716    extern crate alloc;
1717
1718    #[cfg(feature = "alloc")]
1719    use alloc::boxed::Box;
1720
1721    use crate::interrupt::asynch::HalIsrNotification;
1722
1723    use super::*;
1724
1725    #[allow(clippy::type_complexity)]
1726    #[cfg(feature = "alloc")]
1727    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 49] =
1728        [PIN_ISR_INIT; 49];
1729
1730    #[allow(clippy::type_complexity)]
1731    pub(crate) static PIN_NOTIF: [HalIsrNotification; 49] = [PIN_NOTIF_INIT; 49];
1732
1733    // NOTE: Gpio26 - Gpio32 (and Gpio33 - Gpio37 if using Octal RAM/Flash) are used
1734    //       by SPI0/SPI1 for external PSRAM/SPI Flash and are not recommended for
1735    //       other uses
1736    pin!(Gpio0:0, IO, RTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1737    pin!(Gpio1:1, IO, RTC:1, ADC1:ADCCH0, NODAC:0, TOUCH:1);
1738    pin!(Gpio2:2, IO, RTC:2, ADC1:ADCCH1, NODAC:0, TOUCH:2);
1739    pin!(Gpio3:3, IO, RTC:3, ADC1:ADCCH2, NODAC:0, TOUCH:3);
1740    pin!(Gpio4:4, IO, RTC:4, ADC1:ADCCH3, NODAC:0, TOUCH:4);
1741    pin!(Gpio5:5, IO, RTC:5, ADC1:ADCCH4, NODAC:0, TOUCH:5);
1742    pin!(Gpio6:6, IO, RTC:6, ADC1:ADCCH5, NODAC:0, TOUCH:6);
1743    pin!(Gpio7:7, IO, RTC:7, ADC1:ADCCH6, NODAC:0, TOUCH:7);
1744    pin!(Gpio8:8, IO, RTC:8, ADC1:ADCCH7, NODAC:0, TOUCH:8);
1745    pin!(Gpio9:9, IO, RTC:9, ADC1:ADCCH8, NODAC:0, TOUCH:9);
1746    pin!(Gpio10:10, IO, RTC:10, ADC1:ADCCH9, NODAC:0, TOUCH:10);
1747    pin!(Gpio11:11, IO, RTC:11, ADC2:ADCCH0, NODAC:0, TOUCH:11);
1748    pin!(Gpio12:12, IO, RTC:12, ADC2:ADCCH1, NODAC:0, TOUCH:12);
1749    pin!(Gpio13:13, IO, RTC:13, ADC2:ADCCH2, NODAC:0, TOUCH:13);
1750    pin!(Gpio14:14, IO, RTC:14, ADC2:ADCCH3, NODAC:0, TOUCH:14);
1751    pin!(Gpio15:15, IO, RTC:15, ADC2:ADCCH4, NODAC:0, NOTOUCH:0);
1752    pin!(Gpio16:16, IO, RTC:16, ADC2:ADCCH5, NODAC:0, NOTOUCH:0);
1753    #[cfg(esp32s2)]
1754    pin!(Gpio17:17, IO, RTC:17, ADC2:ADCCH6, DAC:1, NOTOUCH:0);
1755    #[cfg(esp32s3)]
1756    pin!(Gpio17:17, IO, RTC:17, ADC2:ADCCH6, NODAC:0, NOTOUCH:0);
1757    #[cfg(esp32s2)]
1758    pin!(Gpio18:18, IO, RTC:18, ADC2:ADCCH7, DAC:2, NOTOUCH:0);
1759    #[cfg(esp32s3)]
1760    pin!(Gpio18:18, IO, RTC:18, ADC2:ADCCH7, NODAC:0, NOTOUCH:0);
1761    pin!(Gpio19:19, IO, RTC:19, ADC2:ADCCH8, NODAC:0, NOTOUCH:0);
1762    pin!(Gpio20:20, IO, RTC:20, ADC2:ADCCH9, NODAC:0, NOTOUCH:0);
1763    pin!(Gpio21:21, IO, RTC:21, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1764    pin!(Gpio26:26, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1765    pin!(Gpio27:27, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1766    pin!(Gpio28:28, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1767    pin!(Gpio29:29, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1768    pin!(Gpio30:30, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1769    pin!(Gpio31:31, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1770    pin!(Gpio32:32, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1771    pin!(Gpio33:33, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1772    pin!(Gpio34:34, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1773    pin!(Gpio35:35, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1774    pin!(Gpio36:36, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1775    pin!(Gpio37:37, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1776    pin!(Gpio38:38, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1777    pin!(Gpio39:39, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1778    pin!(Gpio40:40, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1779    pin!(Gpio41:41, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1780    pin!(Gpio42:42, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1781    pin!(Gpio43:43, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1782    pin!(Gpio44:44, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1783    pin!(Gpio45:45, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1784    #[cfg(esp32s2)]
1785    pin!(Gpio46:46, Input, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1786    #[cfg(esp32s3)]
1787    pin!(Gpio46:46, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1788    #[cfg(esp32s3)]
1789    pin!(Gpio47:47, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1790    #[cfg(esp32s3)]
1791    pin!(Gpio48:48, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1792
1793    pub struct Pins {
1794        pub gpio0: Gpio0<'static>,
1795        pub gpio1: Gpio1<'static>,
1796        pub gpio2: Gpio2<'static>,
1797        pub gpio3: Gpio3<'static>,
1798        pub gpio4: Gpio4<'static>,
1799        pub gpio5: Gpio5<'static>,
1800        pub gpio6: Gpio6<'static>,
1801        pub gpio7: Gpio7<'static>,
1802        pub gpio8: Gpio8<'static>,
1803        pub gpio9: Gpio9<'static>,
1804        pub gpio10: Gpio10<'static>,
1805        pub gpio11: Gpio11<'static>,
1806        pub gpio12: Gpio12<'static>,
1807        pub gpio13: Gpio13<'static>,
1808        pub gpio14: Gpio14<'static>,
1809        pub gpio15: Gpio15<'static>,
1810        pub gpio16: Gpio16<'static>,
1811        pub gpio17: Gpio17<'static>,
1812        pub gpio18: Gpio18<'static>,
1813        pub gpio19: Gpio19<'static>,
1814        pub gpio20: Gpio20<'static>,
1815        pub gpio21: Gpio21<'static>,
1816        pub gpio26: Gpio26<'static>,
1817        pub gpio27: Gpio27<'static>,
1818        pub gpio28: Gpio28<'static>,
1819        pub gpio29: Gpio29<'static>,
1820        pub gpio30: Gpio30<'static>,
1821        pub gpio31: Gpio31<'static>,
1822        pub gpio32: Gpio32<'static>,
1823        pub gpio33: Gpio33<'static>,
1824        pub gpio34: Gpio34<'static>,
1825        pub gpio35: Gpio35<'static>,
1826        pub gpio36: Gpio36<'static>,
1827        pub gpio37: Gpio37<'static>,
1828        pub gpio38: Gpio38<'static>,
1829        pub gpio39: Gpio39<'static>,
1830        pub gpio40: Gpio40<'static>,
1831        pub gpio41: Gpio41<'static>,
1832        pub gpio42: Gpio42<'static>,
1833        pub gpio43: Gpio43<'static>,
1834        pub gpio44: Gpio44<'static>,
1835        pub gpio45: Gpio45<'static>,
1836        pub gpio46: Gpio46<'static>,
1837        #[cfg(esp32s3)]
1838        pub gpio47: Gpio47<'static>,
1839        #[cfg(esp32s3)]
1840        pub gpio48: Gpio48<'static>,
1841    }
1842
1843    impl Pins {
1844        /// # Safety
1845        ///
1846        /// Care should be taken not to instantiate the Pins structure, if it is
1847        /// already instantiated and used elsewhere
1848        pub unsafe fn new() -> Self {
1849            Self {
1850                gpio0: Gpio0::steal(),
1851                gpio1: Gpio1::steal(),
1852                gpio2: Gpio2::steal(),
1853                gpio3: Gpio3::steal(),
1854                gpio4: Gpio4::steal(),
1855                gpio5: Gpio5::steal(),
1856                gpio6: Gpio6::steal(),
1857                gpio7: Gpio7::steal(),
1858                gpio8: Gpio8::steal(),
1859                gpio9: Gpio9::steal(),
1860                gpio10: Gpio10::steal(),
1861                gpio11: Gpio11::steal(),
1862                gpio12: Gpio12::steal(),
1863                gpio13: Gpio13::steal(),
1864                gpio14: Gpio14::steal(),
1865                gpio15: Gpio15::steal(),
1866                gpio16: Gpio16::steal(),
1867                gpio17: Gpio17::steal(),
1868                gpio18: Gpio18::steal(),
1869                gpio19: Gpio19::steal(),
1870                gpio20: Gpio20::steal(),
1871                gpio21: Gpio21::steal(),
1872                gpio26: Gpio26::steal(),
1873                gpio27: Gpio27::steal(),
1874                gpio28: Gpio28::steal(),
1875                gpio29: Gpio29::steal(),
1876                gpio30: Gpio30::steal(),
1877                gpio31: Gpio31::steal(),
1878                gpio32: Gpio32::steal(),
1879                gpio33: Gpio33::steal(),
1880                gpio34: Gpio34::steal(),
1881                gpio35: Gpio35::steal(),
1882                gpio36: Gpio36::steal(),
1883                gpio37: Gpio37::steal(),
1884                gpio38: Gpio38::steal(),
1885                gpio39: Gpio39::steal(),
1886                gpio40: Gpio40::steal(),
1887                gpio41: Gpio41::steal(),
1888                gpio42: Gpio42::steal(),
1889                gpio43: Gpio43::steal(),
1890                gpio44: Gpio44::steal(),
1891                gpio45: Gpio45::steal(),
1892                gpio46: Gpio46::steal(),
1893                #[cfg(esp32s3)]
1894                gpio47: Gpio47::steal(),
1895                #[cfg(esp32s3)]
1896                gpio48: Gpio48::steal(),
1897            }
1898        }
1899    }
1900}
1901
1902#[cfg(esp32c3)]
1903mod chip {
1904    #[cfg(feature = "alloc")]
1905    extern crate alloc;
1906
1907    #[cfg(feature = "alloc")]
1908    use alloc::boxed::Box;
1909
1910    use crate::interrupt::asynch::HalIsrNotification;
1911
1912    use super::*;
1913
1914    #[allow(clippy::type_complexity)]
1915    #[cfg(feature = "alloc")]
1916    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 22] =
1917        [PIN_ISR_INIT; 22];
1918
1919    pub(crate) static PIN_NOTIF: [HalIsrNotification; 22] = [PIN_NOTIF_INIT; 22];
1920
1921    // NOTE: Gpio12 - Gpio17 are used by SPI0/SPI1 for external PSRAM/SPI Flash and
1922    //       are not recommended for other uses
1923    pin!(Gpio0:0,   IO,   RTC:0, ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
1924    pin!(Gpio1:1,   IO,   RTC:1, ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
1925    pin!(Gpio2:2,   IO,   RTC:2, ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
1926    pin!(Gpio3:3,   IO,   RTC:3, ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
1927    pin!(Gpio4:4,   IO,   RTC:4, ADC1:ADCCH4, NODAC:0, NOTOUCH:0);
1928    pin!(Gpio5:5,   IO,   RTC:5, ADC2:ADCCH0, NODAC:0, NOTOUCH:0);
1929    pin!(Gpio6:6,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1930    pin!(Gpio7:7,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1931    pin!(Gpio8:8,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1932    pin!(Gpio9:9,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1933    pin!(Gpio10:10, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1934    pin!(Gpio11:11, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1935    pin!(Gpio12:12, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1936    pin!(Gpio13:13, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1937    pin!(Gpio14:14, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1938    pin!(Gpio15:15, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1939    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1940    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1941    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1942    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1943    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1944    pin!(Gpio21:21, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
1945
1946    pub struct Pins {
1947        pub gpio0: Gpio0<'static>,
1948        pub gpio1: Gpio1<'static>,
1949        pub gpio2: Gpio2<'static>,
1950        pub gpio3: Gpio3<'static>,
1951        pub gpio4: Gpio4<'static>,
1952        pub gpio5: Gpio5<'static>,
1953        pub gpio6: Gpio6<'static>,
1954        pub gpio7: Gpio7<'static>,
1955        pub gpio8: Gpio8<'static>,
1956        pub gpio9: Gpio9<'static>,
1957        pub gpio10: Gpio10<'static>,
1958        pub gpio11: Gpio11<'static>,
1959        pub gpio12: Gpio12<'static>,
1960        pub gpio13: Gpio13<'static>,
1961        pub gpio14: Gpio14<'static>,
1962        pub gpio15: Gpio15<'static>,
1963        pub gpio16: Gpio16<'static>,
1964        pub gpio17: Gpio17<'static>,
1965        pub gpio18: Gpio18<'static>,
1966        pub gpio19: Gpio19<'static>,
1967        pub gpio20: Gpio20<'static>,
1968        pub gpio21: Gpio21<'static>,
1969    }
1970
1971    impl Pins {
1972        pub(crate) unsafe fn new() -> Self {
1973            Self {
1974                gpio0: Gpio0::steal(),
1975                gpio1: Gpio1::steal(),
1976                gpio2: Gpio2::steal(),
1977                gpio3: Gpio3::steal(),
1978                gpio4: Gpio4::steal(),
1979                gpio5: Gpio5::steal(),
1980                gpio6: Gpio6::steal(),
1981                gpio7: Gpio7::steal(),
1982                gpio8: Gpio8::steal(),
1983                gpio9: Gpio9::steal(),
1984                gpio10: Gpio10::steal(),
1985                gpio11: Gpio11::steal(),
1986                gpio12: Gpio12::steal(),
1987                gpio13: Gpio13::steal(),
1988                gpio14: Gpio14::steal(),
1989                gpio15: Gpio15::steal(),
1990                gpio16: Gpio16::steal(),
1991                gpio17: Gpio17::steal(),
1992                gpio18: Gpio18::steal(),
1993                gpio19: Gpio19::steal(),
1994                gpio20: Gpio20::steal(),
1995                gpio21: Gpio21::steal(),
1996            }
1997        }
1998    }
1999}
2000
2001#[cfg(esp32c2)]
2002mod chip {
2003    #[cfg(feature = "alloc")]
2004    extern crate alloc;
2005
2006    #[cfg(feature = "alloc")]
2007    use alloc::boxed::Box;
2008
2009    use crate::interrupt::asynch::HalIsrNotification;
2010
2011    use super::*;
2012
2013    #[allow(clippy::type_complexity)]
2014    #[cfg(feature = "alloc")]
2015    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 21] =
2016        [PIN_ISR_INIT; 21];
2017
2018    pub(crate) static PIN_NOTIF: [HalIsrNotification; 21] = [PIN_NOTIF_INIT; 21];
2019
2020    // NOTE: Gpio12 - Gpio17 are used by SPI0/SPI1 for external PSRAM/SPI Flash and
2021    //       are not recommended for other uses
2022    pin!(Gpio0:0,   IO,   RTC:0,  ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
2023    pin!(Gpio1:1,   IO,   RTC:1,  ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
2024    pin!(Gpio2:2,   IO,   RTC:2,  ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
2025    pin!(Gpio3:3,   IO,   RTC:3,  ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
2026    pin!(Gpio4:4,   IO,   RTC:4,  ADC1:ADCCH4, NODAC:0, NOTOUCH:0);
2027    pin!(Gpio5:5,   IO,   RTC:5, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2028    pin!(Gpio6:6,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2029    pin!(Gpio7:7,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2030    pin!(Gpio8:8,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2031    pin!(Gpio9:9,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2032    pin!(Gpio10:10, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2033    pin!(Gpio11:11, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2034    pin!(Gpio12:12, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2035    pin!(Gpio13:13, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2036    pin!(Gpio14:14, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2037    pin!(Gpio15:15, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2038    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2039    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2040    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2041    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2042    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2043
2044    pub struct Pins {
2045        pub gpio0: Gpio0<'static>,
2046        pub gpio1: Gpio1<'static>,
2047        pub gpio2: Gpio2<'static>,
2048        pub gpio3: Gpio3<'static>,
2049        pub gpio4: Gpio4<'static>,
2050        pub gpio5: Gpio5<'static>,
2051        pub gpio6: Gpio6<'static>,
2052        pub gpio7: Gpio7<'static>,
2053        pub gpio8: Gpio8<'static>,
2054        pub gpio9: Gpio9<'static>,
2055        pub gpio10: Gpio10<'static>,
2056        pub gpio11: Gpio11<'static>,
2057        pub gpio12: Gpio12<'static>,
2058        pub gpio13: Gpio13<'static>,
2059        pub gpio14: Gpio14<'static>,
2060        pub gpio15: Gpio15<'static>,
2061        pub gpio16: Gpio16<'static>,
2062        pub gpio17: Gpio17<'static>,
2063        pub gpio18: Gpio18<'static>,
2064        pub gpio19: Gpio19<'static>,
2065        pub gpio20: Gpio20<'static>,
2066    }
2067
2068    impl Pins {
2069        /// # Safety
2070        ///
2071        /// Care should be taken not to instantiate the Pins structure, if it is
2072        /// already instantiated and used elsewhere
2073        pub unsafe fn new() -> Self {
2074            Self {
2075                gpio0: Gpio0::steal(),
2076                gpio1: Gpio1::steal(),
2077                gpio2: Gpio2::steal(),
2078                gpio3: Gpio3::steal(),
2079                gpio4: Gpio4::steal(),
2080                gpio5: Gpio5::steal(),
2081                gpio6: Gpio6::steal(),
2082                gpio7: Gpio7::steal(),
2083                gpio8: Gpio8::steal(),
2084                gpio9: Gpio9::steal(),
2085                gpio10: Gpio10::steal(),
2086                gpio11: Gpio11::steal(),
2087                gpio12: Gpio12::steal(),
2088                gpio13: Gpio13::steal(),
2089                gpio14: Gpio14::steal(),
2090                gpio15: Gpio15::steal(),
2091                gpio16: Gpio16::steal(),
2092                gpio17: Gpio17::steal(),
2093                gpio18: Gpio18::steal(),
2094                gpio19: Gpio19::steal(),
2095                gpio20: Gpio20::steal(),
2096            }
2097        }
2098    }
2099}
2100
2101#[cfg(any(esp32h2, esp32h4))]
2102mod chip {
2103    #[cfg(feature = "alloc")]
2104    extern crate alloc;
2105
2106    #[cfg(feature = "alloc")]
2107    use alloc::boxed::Box;
2108
2109    use crate::interrupt::asynch::HalIsrNotification;
2110
2111    use super::*;
2112
2113    #[allow(clippy::type_complexity)]
2114    #[cfg(feature = "alloc")]
2115    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 28] =
2116        [PIN_ISR_INIT; 28];
2117
2118    pub(crate) static PIN_NOTIF: [HalIsrNotification; 28] = [PIN_NOTIF_INIT; 28];
2119
2120    // NOTE: Following pins have special meaning and are not recommended for other uses. But one may use them with care.
2121    //  - Gpio12 - Gpio17 are used by SPI0/SPI1 for external PSRAM/SPI Flash
2122    //  - Gpio21 seems not to be exposed physically
2123    //  - Gpio23 + Gpio24 are used by serial debug interface
2124    //  - Gpio26 + Gpio27 are used by USB debug interface
2125    pin!(Gpio0:0,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2126    pin!(Gpio1:1,   IO, NORTC:0,  ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
2127    pin!(Gpio2:2,   IO, NORTC:0,  ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
2128    pin!(Gpio3:3,   IO, NORTC:0,  ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
2129    pin!(Gpio4:4,   IO, NORTC:0,  ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
2130    pin!(Gpio5:5,   IO, NORTC:0,  ADC1:ADCCH4, NODAC:0, NOTOUCH:0);
2131    pin!(Gpio6:6,   IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2132    pin!(Gpio7:7,   IO,   RTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2133    pin!(Gpio8:8,   IO,   RTC:1, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2134    pin!(Gpio9:9,   IO,   RTC:2, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2135    pin!(Gpio10:10, IO,   RTC:3, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2136    pin!(Gpio11:11, IO,   RTC:4, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2137    pin!(Gpio12:12, IO,   RTC:5, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2138    pin!(Gpio13:13, IO,   RTC:6, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2139    pin!(Gpio14:14, IO,   RTC:7, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2140    pin!(Gpio15:15, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2141    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2142    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2143    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2144    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2145    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2146    pin!(Gpio21:21, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2147    pin!(Gpio22:22, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2148    pin!(Gpio23:23, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2149    pin!(Gpio24:24, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2150    pin!(Gpio25:25, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2151    pin!(Gpio26:26, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2152    pin!(Gpio27:27, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2153
2154    pub struct Pins {
2155        pub gpio0: Gpio0<'static>,
2156        pub gpio1: Gpio1<'static>,
2157        pub gpio2: Gpio2<'static>,
2158        pub gpio3: Gpio3<'static>,
2159        pub gpio4: Gpio4<'static>,
2160        pub gpio5: Gpio5<'static>,
2161        pub gpio6: Gpio6<'static>,
2162        pub gpio7: Gpio7<'static>,
2163        pub gpio8: Gpio8<'static>,
2164        pub gpio9: Gpio9<'static>,
2165        pub gpio10: Gpio10<'static>,
2166        pub gpio11: Gpio11<'static>,
2167        pub gpio12: Gpio12<'static>,
2168        pub gpio13: Gpio13<'static>,
2169        pub gpio14: Gpio14<'static>,
2170        pub gpio15: Gpio15<'static>,
2171        pub gpio16: Gpio16<'static>,
2172        pub gpio17: Gpio17<'static>,
2173        pub gpio18: Gpio18<'static>,
2174        pub gpio19: Gpio19<'static>,
2175        pub gpio20: Gpio20<'static>,
2176        pub gpio21: Gpio21<'static>,
2177        pub gpio22: Gpio22<'static>,
2178        pub gpio23: Gpio23<'static>,
2179        pub gpio24: Gpio24<'static>,
2180        pub gpio25: Gpio25<'static>,
2181        pub gpio26: Gpio26<'static>,
2182        pub gpio27: Gpio27<'static>,
2183    }
2184
2185    impl Pins {
2186        /// # Safety
2187        ///
2188        /// Care should be taken not to instantiate the Pins structure, if it is
2189        /// already instantiated and used elsewhere
2190        pub unsafe fn new() -> Self {
2191            Self {
2192                gpio0: Gpio0::steal(),
2193                gpio1: Gpio1::steal(),
2194                gpio2: Gpio2::steal(),
2195                gpio3: Gpio3::steal(),
2196                gpio4: Gpio4::steal(),
2197                gpio5: Gpio5::steal(),
2198                gpio6: Gpio6::steal(),
2199                gpio7: Gpio7::steal(),
2200                gpio8: Gpio8::steal(),
2201                gpio9: Gpio9::steal(),
2202                gpio10: Gpio10::steal(),
2203                gpio11: Gpio11::steal(),
2204                gpio12: Gpio12::steal(),
2205                gpio13: Gpio13::steal(),
2206                gpio14: Gpio14::steal(),
2207                gpio15: Gpio15::steal(),
2208                gpio16: Gpio16::steal(),
2209                gpio17: Gpio17::steal(),
2210                gpio18: Gpio18::steal(),
2211                gpio19: Gpio19::steal(),
2212                gpio20: Gpio20::steal(),
2213                gpio21: Gpio21::steal(),
2214                gpio22: Gpio22::steal(),
2215                gpio23: Gpio23::steal(),
2216                gpio24: Gpio24::steal(),
2217                gpio25: Gpio25::steal(),
2218                gpio26: Gpio26::steal(),
2219                gpio27: Gpio27::steal(),
2220            }
2221        }
2222    }
2223}
2224
2225#[cfg(esp32c5)]
2226mod chip {
2227    #[cfg(feature = "alloc")]
2228    extern crate alloc;
2229
2230    #[cfg(feature = "alloc")]
2231    use alloc::boxed::Box;
2232
2233    use crate::interrupt::asynch::HalIsrNotification;
2234
2235    use super::*;
2236
2237    #[allow(clippy::type_complexity)]
2238    #[cfg(feature = "alloc")]
2239    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 29] =
2240        [PIN_ISR_INIT; 29];
2241
2242    #[allow(clippy::type_complexity)]
2243    pub(crate) static PIN_NOTIF: [HalIsrNotification; 29] = [PIN_NOTIF_INIT; 29];
2244
2245    // NOTE: Gpio26 - Gpio32 (and Gpio33 - Gpio37 if using Octal RAM/Flash) are used
2246    //       by SPI0/SPI1 for external PSRAM/SPI Flash and are not recommended for
2247    //       other uses
2248    pin!(Gpio0:0, IO, RTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2249    pin!(Gpio1:1, IO, RTC:1, ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
2250    pin!(Gpio2:2, IO, RTC:2, ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
2251    pin!(Gpio3:3, IO, RTC:3, ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
2252    pin!(Gpio4:4, IO, RTC:4, ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
2253    pin!(Gpio5:5, IO, RTC:5, ADC1:ADCCH4, NODAC:0, NOTOUCH:0);
2254    pin!(Gpio6:6, IO, RTC:6, ADC1:ADCCH5, NODAC:0, NOTOUCH:0);
2255    pin!(Gpio7:7, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2256    pin!(Gpio8:8, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2257    pin!(Gpio9:9, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2258    pin!(Gpio10:10, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2259    pin!(Gpio11:11, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2260    pin!(Gpio12:12, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2261    pin!(Gpio13:13, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2262    pin!(Gpio14:14, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2263    pin!(Gpio15:15, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2264    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2265    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2266    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2267    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2268    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2269    pin!(Gpio21:21, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2270    pin!(Gpio22:22, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2271    pin!(Gpio23:23, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2272    pin!(Gpio24:24, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2273    pin!(Gpio25:25, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2274    pin!(Gpio26:26, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2275    pin!(Gpio27:27, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2276    pin!(Gpio28:28, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2277
2278    pub struct Pins {
2279        pub gpio0: Gpio0<'static>,
2280        pub gpio1: Gpio1<'static>,
2281        pub gpio2: Gpio2<'static>,
2282        pub gpio3: Gpio3<'static>,
2283        pub gpio4: Gpio4<'static>,
2284        pub gpio5: Gpio5<'static>,
2285        pub gpio6: Gpio6<'static>,
2286        pub gpio7: Gpio7<'static>,
2287        pub gpio8: Gpio8<'static>,
2288        pub gpio9: Gpio9<'static>,
2289        pub gpio10: Gpio10<'static>,
2290        pub gpio11: Gpio11<'static>,
2291        pub gpio12: Gpio12<'static>,
2292        pub gpio13: Gpio13<'static>,
2293        pub gpio14: Gpio14<'static>,
2294        pub gpio15: Gpio15<'static>,
2295        pub gpio16: Gpio16<'static>,
2296        pub gpio17: Gpio17<'static>,
2297        pub gpio18: Gpio18<'static>,
2298        pub gpio19: Gpio19<'static>,
2299        pub gpio20: Gpio20<'static>,
2300        pub gpio21: Gpio21<'static>,
2301        pub gpio22: Gpio22<'static>,
2302        pub gpio23: Gpio23<'static>,
2303        pub gpio24: Gpio24<'static>,
2304        pub gpio25: Gpio25<'static>,
2305        pub gpio26: Gpio26<'static>,
2306        pub gpio27: Gpio27<'static>,
2307        pub gpio28: Gpio28<'static>,
2308    }
2309
2310    impl Pins {
2311        /// # Safety
2312        ///
2313        /// Care should be taken not to instantiate the Pins structure, if it is
2314        /// already instantiated and used elsewhere
2315        pub unsafe fn new() -> Self {
2316            Self {
2317                gpio0: Gpio0::steal(),
2318                gpio1: Gpio1::steal(),
2319                gpio2: Gpio2::steal(),
2320                gpio3: Gpio3::steal(),
2321                gpio4: Gpio4::steal(),
2322                gpio5: Gpio5::steal(),
2323                gpio6: Gpio6::steal(),
2324                gpio7: Gpio7::steal(),
2325                gpio8: Gpio8::steal(),
2326                gpio9: Gpio9::steal(),
2327                gpio10: Gpio10::steal(),
2328                gpio11: Gpio11::steal(),
2329                gpio12: Gpio12::steal(),
2330                gpio13: Gpio13::steal(),
2331                gpio14: Gpio14::steal(),
2332                gpio15: Gpio15::steal(),
2333                gpio16: Gpio16::steal(),
2334                gpio17: Gpio17::steal(),
2335                gpio18: Gpio18::steal(),
2336                gpio19: Gpio19::steal(),
2337                gpio20: Gpio20::steal(),
2338                gpio21: Gpio21::steal(),
2339                gpio22: Gpio22::steal(),
2340                gpio23: Gpio23::steal(),
2341                gpio24: Gpio24::steal(),
2342                gpio25: Gpio25::steal(),
2343                gpio26: Gpio26::steal(),
2344                gpio27: Gpio27::steal(),
2345                gpio28: Gpio28::steal(),
2346            }
2347        }
2348    }
2349}
2350
2351#[cfg(esp32c6)]
2352mod chip {
2353    // TODO: Implement esp32c6 glitch filters
2354
2355    #[cfg(feature = "alloc")]
2356    extern crate alloc;
2357
2358    #[cfg(feature = "alloc")]
2359    use alloc::boxed::Box;
2360
2361    use crate::interrupt::asynch::HalIsrNotification;
2362
2363    use super::*;
2364
2365    #[allow(clippy::type_complexity)]
2366    #[cfg(feature = "alloc")]
2367    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 31] =
2368        [PIN_ISR_INIT; 31];
2369
2370    #[allow(clippy::type_complexity)]
2371    pub(crate) static PIN_NOTIF: [HalIsrNotification; 31] = [PIN_NOTIF_INIT; 31];
2372
2373    pin!(Gpio0:0, IO, RTC:0, ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
2374    pin!(Gpio1:1, IO, RTC:1, ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
2375    pin!(Gpio2:2, IO, RTC:2, ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
2376    pin!(Gpio3:3, IO, RTC:3, ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
2377    pin!(Gpio4:4, IO, RTC:4, ADC1:ADCCH4, NODAC:0, NOTOUCH:0);
2378    pin!(Gpio5:5, IO, RTC:5, ADC1:ADCCH5, NODAC:0, NOTOUCH:0);
2379    pin!(Gpio6:6, IO, RTC:6, ADC1:ADCCH6, NODAC:0, NOTOUCH:0);
2380    pin!(Gpio7:7, IO, RTC:7, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2381    pin!(Gpio8:8, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2382    pin!(Gpio9:9, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2383    pin!(Gpio10:10, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2384    pin!(Gpio11:11, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2385    pin!(Gpio12:12, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2386    pin!(Gpio13:13, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2387    pin!(Gpio14:14, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2388    pin!(Gpio15:15, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2389    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2390    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2391    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2392    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2393    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2394    pin!(Gpio21:21, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2395    pin!(Gpio22:22, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2396    pin!(Gpio23:23, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2397    pin!(Gpio24:24, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2398    pin!(Gpio25:25, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2399    pin!(Gpio26:26, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2400    pin!(Gpio27:27, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2401    pin!(Gpio28:28, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2402    pin!(Gpio29:29, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2403    pin!(Gpio30:30, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2404
2405    pub struct Pins {
2406        pub gpio0: Gpio0<'static>,
2407        pub gpio1: Gpio1<'static>,
2408        pub gpio2: Gpio2<'static>,
2409        pub gpio3: Gpio3<'static>,
2410        pub gpio4: Gpio4<'static>,
2411        pub gpio5: Gpio5<'static>,
2412        pub gpio6: Gpio6<'static>,
2413        pub gpio7: Gpio7<'static>,
2414        pub gpio8: Gpio8<'static>,
2415        pub gpio9: Gpio9<'static>,
2416        pub gpio10: Gpio10<'static>,
2417        pub gpio11: Gpio11<'static>,
2418        pub gpio12: Gpio12<'static>,
2419        pub gpio13: Gpio13<'static>,
2420        pub gpio14: Gpio14<'static>,
2421        pub gpio15: Gpio15<'static>,
2422        pub gpio16: Gpio16<'static>,
2423        pub gpio17: Gpio17<'static>,
2424        pub gpio18: Gpio18<'static>,
2425        pub gpio19: Gpio19<'static>,
2426        pub gpio20: Gpio20<'static>,
2427        pub gpio21: Gpio21<'static>,
2428        pub gpio22: Gpio22<'static>,
2429        pub gpio23: Gpio23<'static>,
2430        pub gpio24: Gpio24<'static>,
2431        pub gpio25: Gpio25<'static>,
2432        pub gpio26: Gpio26<'static>,
2433        pub gpio27: Gpio27<'static>,
2434        pub gpio28: Gpio28<'static>,
2435        pub gpio29: Gpio29<'static>,
2436        pub gpio30: Gpio30<'static>,
2437    }
2438
2439    impl Pins {
2440        /// # Safety
2441        ///
2442        /// Care should be taken not to instantiate the Pins structure, if it is
2443        /// already instantiated and used elsewhere
2444        pub unsafe fn new() -> Self {
2445            Self {
2446                gpio0: Gpio0::steal(),
2447                gpio1: Gpio1::steal(),
2448                gpio2: Gpio2::steal(),
2449                gpio3: Gpio3::steal(),
2450                gpio4: Gpio4::steal(),
2451                gpio5: Gpio5::steal(),
2452                gpio6: Gpio6::steal(),
2453                gpio7: Gpio7::steal(),
2454                gpio8: Gpio8::steal(),
2455                gpio9: Gpio9::steal(),
2456                gpio10: Gpio10::steal(),
2457                gpio11: Gpio11::steal(),
2458                gpio12: Gpio12::steal(),
2459                gpio13: Gpio13::steal(),
2460                gpio14: Gpio14::steal(),
2461                gpio15: Gpio15::steal(),
2462                gpio16: Gpio16::steal(),
2463                gpio17: Gpio17::steal(),
2464                gpio18: Gpio18::steal(),
2465                gpio19: Gpio19::steal(),
2466                gpio20: Gpio20::steal(),
2467                gpio21: Gpio21::steal(),
2468                gpio22: Gpio22::steal(),
2469                gpio23: Gpio23::steal(),
2470                gpio24: Gpio24::steal(),
2471                gpio25: Gpio25::steal(),
2472                gpio26: Gpio26::steal(),
2473                gpio27: Gpio27::steal(),
2474                gpio28: Gpio28::steal(),
2475                gpio29: Gpio29::steal(),
2476                gpio30: Gpio30::steal(),
2477            }
2478        }
2479    }
2480}
2481
2482#[cfg(esp32c61)]
2483mod chip {
2484    #[cfg(feature = "alloc")]
2485    extern crate alloc;
2486
2487    #[cfg(feature = "alloc")]
2488    use alloc::boxed::Box;
2489
2490    use crate::interrupt::asynch::HalIsrNotification;
2491
2492    use super::*;
2493
2494    #[allow(clippy::type_complexity)]
2495    #[cfg(feature = "alloc")]
2496    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 30] =
2497        [PIN_ISR_INIT; 30];
2498
2499    #[allow(clippy::type_complexity)]
2500    pub(crate) static PIN_NOTIF: [HalIsrNotification; 30] = [PIN_NOTIF_INIT; 30];
2501
2502    pin!(Gpio0:0, IO, RTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2503    pin!(Gpio1:1, IO, RTC:1, ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
2504    pin!(Gpio2:2, IO, RTC:2, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2505    pin!(Gpio3:3, IO, RTC:3, ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
2506    pin!(Gpio4:4, IO, RTC:4, ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
2507    pin!(Gpio5:5, IO, RTC:5, ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
2508    pin!(Gpio6:6, IO, RTC:6, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2509    pin!(Gpio7:7, IO, RTC:7, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2510    pin!(Gpio8:8, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2511    pin!(Gpio9:9, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2512    pin!(Gpio10:10, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2513    pin!(Gpio11:11, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2514    pin!(Gpio12:12, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2515    pin!(Gpio13:13, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2516    pin!(Gpio14:14, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2517    pin!(Gpio15:15, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2518    pin!(Gpio16:16, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2519    pin!(Gpio17:17, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2520    pin!(Gpio18:18, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2521    pin!(Gpio19:19, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2522    pin!(Gpio20:20, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2523    pin!(Gpio21:21, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2524    pin!(Gpio22:22, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2525    pin!(Gpio23:23, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2526    pin!(Gpio24:24, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2527    pin!(Gpio25:25, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2528    pin!(Gpio26:26, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2529    pin!(Gpio27:27, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2530    pin!(Gpio28:28, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2531    pin!(Gpio29:29, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2532
2533    pub struct Pins {
2534        pub gpio0: Gpio0<'static>,
2535        pub gpio1: Gpio1<'static>,
2536        pub gpio2: Gpio2<'static>,
2537        pub gpio3: Gpio3<'static>,
2538        pub gpio4: Gpio4<'static>,
2539        pub gpio5: Gpio5<'static>,
2540        pub gpio6: Gpio6<'static>,
2541        pub gpio7: Gpio7<'static>,
2542        pub gpio8: Gpio8<'static>,
2543        pub gpio9: Gpio9<'static>,
2544        pub gpio10: Gpio10<'static>,
2545        pub gpio11: Gpio11<'static>,
2546        pub gpio12: Gpio12<'static>,
2547        pub gpio13: Gpio13<'static>,
2548        pub gpio14: Gpio14<'static>,
2549        pub gpio15: Gpio15<'static>,
2550        pub gpio16: Gpio16<'static>,
2551        pub gpio17: Gpio17<'static>,
2552        pub gpio18: Gpio18<'static>,
2553        pub gpio19: Gpio19<'static>,
2554        pub gpio20: Gpio20<'static>,
2555        pub gpio21: Gpio21<'static>,
2556        pub gpio22: Gpio22<'static>,
2557        pub gpio23: Gpio23<'static>,
2558        pub gpio24: Gpio24<'static>,
2559        pub gpio25: Gpio25<'static>,
2560        pub gpio26: Gpio26<'static>,
2561        pub gpio27: Gpio27<'static>,
2562        pub gpio28: Gpio28<'static>,
2563        pub gpio29: Gpio29<'static>,
2564    }
2565
2566    impl Pins {
2567        /// # Safety
2568        ///
2569        /// Care should be taken not to instantiate the Pins structure, if it is
2570        /// already instantiated and used elsewhere
2571        pub unsafe fn new() -> Self {
2572            Self {
2573                gpio0: Gpio0::steal(),
2574                gpio1: Gpio1::steal(),
2575                gpio2: Gpio2::steal(),
2576                gpio3: Gpio3::steal(),
2577                gpio4: Gpio4::steal(),
2578                gpio5: Gpio5::steal(),
2579                gpio6: Gpio6::steal(),
2580                gpio7: Gpio7::steal(),
2581                gpio8: Gpio8::steal(),
2582                gpio9: Gpio9::steal(),
2583                gpio10: Gpio10::steal(),
2584                gpio11: Gpio11::steal(),
2585                gpio12: Gpio12::steal(),
2586                gpio13: Gpio13::steal(),
2587                gpio14: Gpio14::steal(),
2588                gpio15: Gpio15::steal(),
2589                gpio16: Gpio16::steal(),
2590                gpio17: Gpio17::steal(),
2591                gpio18: Gpio18::steal(),
2592                gpio19: Gpio19::steal(),
2593                gpio20: Gpio20::steal(),
2594                gpio21: Gpio21::steal(),
2595                gpio22: Gpio22::steal(),
2596                gpio23: Gpio23::steal(),
2597                gpio24: Gpio24::steal(),
2598                gpio25: Gpio25::steal(),
2599                gpio26: Gpio26::steal(),
2600                gpio27: Gpio27::steal(),
2601                gpio28: Gpio28::steal(),
2602                gpio29: Gpio29::steal(),
2603            }
2604        }
2605    }
2606}
2607
2608#[cfg(esp32p4)]
2609mod chip {
2610    #[cfg(feature = "alloc")]
2611    extern crate alloc;
2612
2613    #[cfg(feature = "alloc")]
2614    use alloc::boxed::Box;
2615
2616    use crate::interrupt::asynch::HalIsrNotification;
2617
2618    use super::*;
2619
2620    #[allow(clippy::type_complexity)]
2621    #[cfg(feature = "alloc")]
2622    pub(crate) static mut PIN_ISR_HANDLER: [Option<Box<dyn FnMut() + Send + 'static>>; 54] =
2623        [PIN_ISR_INIT; 54];
2624
2625    #[allow(clippy::type_complexity)]
2626    pub(crate) static PIN_NOTIF: [HalIsrNotification; 54] = [PIN_NOTIF_INIT; 54];
2627
2628    pin!(Gpio0:0, IO, RTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2629    pin!(Gpio1:1, IO, RTC:1, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2630    pin!(Gpio2:2, IO, RTC:2, NOADC:NOADC, NODAC:0, TOUCH:0);
2631    pin!(Gpio3:3, IO, RTC:3, NOADC:NOADC, NODAC:0, TOUCH:1);
2632    pin!(Gpio4:4, IO, RTC:4, NOADC:NOADC, NODAC:0, TOUCH:2);
2633    pin!(Gpio5:5, IO, RTC:5, NOADC:NOADC, NODAC:0, TOUCH:3);
2634    pin!(Gpio6:6, IO, RTC:6, NOADC:NOADC, NODAC:0, TOUCH:4);
2635    pin!(Gpio7:7, IO, RTC:7, NOADC:NOADC, NODAC:0, TOUCH:5);
2636    pin!(Gpio8:8, IO, RTC:8, NOADC:NOADC, NODAC:0, TOUCH:6);
2637    pin!(Gpio9:9, IO, RTC:9, NOADC:NOADC, NODAC:0, TOUCH:7);
2638
2639    pin!(Gpio10:10, IO, RTC:10, NOADC:NOADC, NODAC:0, TOUCH:8);
2640    pin!(Gpio11:11, IO, RTC:11, NOADC:NOADC, NODAC:0, TOUCH:9);
2641    pin!(Gpio12:12, IO, RTC:12, NOADC:NOADC, NODAC:0, TOUCH:10);
2642    pin!(Gpio13:13, IO, RTC:13, NOADC:NOADC, NODAC:0, TOUCH:11);
2643    pin!(Gpio14:14, IO, RTC:14, NOADC:NOADC, NODAC:0, TOUCH:12);
2644    pin!(Gpio15:15, IO, RTC:15, NOADC:NOADC, NODAC:0, TOUCH:13);
2645    pin!(Gpio16:16, IO, NORTC:0, ADC1:ADCCH0, NODAC:0, NOTOUCH:0);
2646    pin!(Gpio17:17, IO, NORTC:0, ADC1:ADCCH1, NODAC:0, NOTOUCH:0);
2647    pin!(Gpio18:18, IO, NORTC:0, ADC1:ADCCH2, NODAC:0, NOTOUCH:0);
2648    pin!(Gpio19:19, IO, NORTC:0, ADC1:ADCCH3, NODAC:0, NOTOUCH:0);
2649
2650    pin!(Gpio20:20, IO, NORTC:0, ADC1:ADCCH4, NODAC:0, NOTOUCH:0);
2651    pin!(Gpio21:21, IO, NORTC:0, ADC1:ADCCH5, NODAC:0, NOTOUCH:0);
2652    pin!(Gpio22:22, IO, NORTC:0, ADC1:ADCCH6, NODAC:0, NOTOUCH:0);
2653    pin!(Gpio23:23, IO, NORTC:0, ADC1:ADCCH7, NODAC:0, NOTOUCH:0);
2654    pin!(Gpio24:24, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2655    pin!(Gpio25:25, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2656    pin!(Gpio26:26, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2657    pin!(Gpio27:27, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2658    pin!(Gpio28:28, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2659    pin!(Gpio29:29, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2660
2661    pin!(Gpio30:30, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2662    pin!(Gpio31:31, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2663    pin!(Gpio32:32, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2664    pin!(Gpio33:33, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2665    pin!(Gpio34:34, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2666    pin!(Gpio35:35, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2667    pin!(Gpio36:36, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2668    pin!(Gpio37:37, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2669    pin!(Gpio38:38, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2670    pin!(Gpio39:39, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2671
2672    pin!(Gpio40:40, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2673    pin!(Gpio41:41, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2674    pin!(Gpio42:42, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2675    pin!(Gpio43:43, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2676    pin!(Gpio44:44, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2677    pin!(Gpio45:45, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2678    pin!(Gpio46:46, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2679    pin!(Gpio47:47, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2680    pin!(Gpio48:48, IO, NORTC:0, NOADC:NOADC, NODAC:0, NOTOUCH:0);
2681    pin!(Gpio49:49, IO, NORTC:0, ADC2:ADCCH0, NODAC:0, NOTOUCH:0);
2682
2683    pin!(Gpio50:50, IO, NORTC:0, ADC2:ADCCH1, NODAC:0, NOTOUCH:0);
2684    pin!(Gpio51:51, IO, NORTC:0, ADC2:ADCCH2, NODAC:0, NOTOUCH:0);
2685    pin!(Gpio52:52, IO, NORTC:0, ADC2:ADCCH3, NODAC:0, NOTOUCH:0);
2686    pin!(Gpio53:53, IO, NORTC:0, ADC2:ADCCH4, NODAC:0, NOTOUCH:0);
2687    pin!(Gpio54:54, IO, NORTC:0, ADC2:ADCCH5, NODAC:0, NOTOUCH:0);
2688
2689    pub struct Pins {
2690        pub gpio0: Gpio0<'static>,
2691        pub gpio1: Gpio1<'static>,
2692        pub gpio2: Gpio2<'static>,
2693        pub gpio3: Gpio3<'static>,
2694        pub gpio4: Gpio4<'static>,
2695        pub gpio5: Gpio5<'static>,
2696        pub gpio6: Gpio6<'static>,
2697        pub gpio7: Gpio7<'static>,
2698        pub gpio8: Gpio8<'static>,
2699        pub gpio9: Gpio9<'static>,
2700
2701        pub gpio10: Gpio10<'static>,
2702        pub gpio11: Gpio11<'static>,
2703        pub gpio12: Gpio12<'static>,
2704        pub gpio13: Gpio13<'static>,
2705        pub gpio14: Gpio14<'static>,
2706        pub gpio15: Gpio15<'static>,
2707        pub gpio16: Gpio16<'static>,
2708        pub gpio17: Gpio17<'static>,
2709        pub gpio18: Gpio18<'static>,
2710        pub gpio19: Gpio19<'static>,
2711
2712        pub gpio20: Gpio20<'static>,
2713        pub gpio21: Gpio21<'static>,
2714        pub gpio22: Gpio22<'static>,
2715        pub gpio23: Gpio23<'static>,
2716        pub gpio24: Gpio24<'static>,
2717        pub gpio25: Gpio25<'static>,
2718        pub gpio26: Gpio26<'static>,
2719        pub gpio27: Gpio27<'static>,
2720        pub gpio28: Gpio28<'static>,
2721        pub gpio29: Gpio29<'static>,
2722
2723        pub gpio30: Gpio30<'static>,
2724        pub gpio31: Gpio31<'static>,
2725        pub gpio32: Gpio32<'static>,
2726        pub gpio33: Gpio33<'static>,
2727        pub gpio34: Gpio34<'static>,
2728        pub gpio35: Gpio35<'static>,
2729        pub gpio36: Gpio36<'static>,
2730        pub gpio37: Gpio37<'static>,
2731        pub gpio38: Gpio38<'static>,
2732        pub gpio39: Gpio39<'static>,
2733
2734        pub gpio40: Gpio40<'static>,
2735        pub gpio41: Gpio41<'static>,
2736        pub gpio42: Gpio42<'static>,
2737        pub gpio43: Gpio43<'static>,
2738        pub gpio44: Gpio44<'static>,
2739        pub gpio45: Gpio45<'static>,
2740        pub gpio46: Gpio46<'static>,
2741        pub gpio47: Gpio47<'static>,
2742        pub gpio48: Gpio48<'static>,
2743        pub gpio49: Gpio49<'static>,
2744
2745        pub gpio50: Gpio50<'static>,
2746        pub gpio51: Gpio51<'static>,
2747        pub gpio52: Gpio52<'static>,
2748        pub gpio53: Gpio53<'static>,
2749        pub gpio54: Gpio54<'static>,
2750    }
2751
2752    impl Pins {
2753        /// # Safety
2754        ///
2755        /// Care should be taken not to instantiate the Pins structure, if it is
2756        /// already instantiated and used elsewhere
2757        pub unsafe fn new() -> Self {
2758            Self {
2759                gpio0: Gpio0::steal(),
2760                gpio1: Gpio1::steal(),
2761                gpio2: Gpio2::steal(),
2762                gpio3: Gpio3::steal(),
2763                gpio4: Gpio4::steal(),
2764                gpio5: Gpio5::steal(),
2765                gpio6: Gpio6::steal(),
2766                gpio7: Gpio7::steal(),
2767                gpio8: Gpio8::steal(),
2768                gpio9: Gpio9::steal(),
2769
2770                gpio10: Gpio10::steal(),
2771                gpio11: Gpio11::steal(),
2772                gpio12: Gpio12::steal(),
2773                gpio13: Gpio13::steal(),
2774                gpio14: Gpio14::steal(),
2775                gpio15: Gpio15::steal(),
2776                gpio16: Gpio16::steal(),
2777                gpio17: Gpio17::steal(),
2778                gpio18: Gpio18::steal(),
2779                gpio19: Gpio19::steal(),
2780
2781                gpio20: Gpio20::steal(),
2782                gpio21: Gpio21::steal(),
2783                gpio22: Gpio22::steal(),
2784                gpio23: Gpio23::steal(),
2785                gpio24: Gpio24::steal(),
2786                gpio25: Gpio25::steal(),
2787                gpio26: Gpio26::steal(),
2788                gpio27: Gpio27::steal(),
2789                gpio28: Gpio28::steal(),
2790                gpio29: Gpio29::steal(),
2791
2792                gpio30: Gpio30::steal(),
2793                gpio31: Gpio31::steal(),
2794                gpio32: Gpio32::steal(),
2795                gpio33: Gpio33::steal(),
2796                gpio34: Gpio34::steal(),
2797                gpio35: Gpio35::steal(),
2798                gpio36: Gpio36::steal(),
2799                gpio37: Gpio37::steal(),
2800                gpio38: Gpio38::steal(),
2801                gpio39: Gpio39::steal(),
2802
2803                gpio40: Gpio40::steal(),
2804                gpio41: Gpio41::steal(),
2805                gpio42: Gpio42::steal(),
2806                gpio43: Gpio43::steal(),
2807                gpio44: Gpio44::steal(),
2808                gpio45: Gpio45::steal(),
2809                gpio46: Gpio46::steal(),
2810                gpio47: Gpio47::steal(),
2811                gpio48: Gpio48::steal(),
2812                gpio49: Gpio49::steal(),
2813
2814                gpio50: Gpio50::steal(),
2815                gpio51: Gpio51::steal(),
2816                gpio52: Gpio52::steal(),
2817                gpio53: Gpio53::steal(),
2818                gpio54: Gpio54::steal(),
2819            }
2820        }
2821    }
2822}