Skip to main content

esp_hal/gpio/lp_io/low_level/
esp32h2.rs

1use crate::{
2    gpio::{AlternateFunction, LpPin, lp_io::LpFunction},
3    peripherals::{GPIO, IO_MUX, LP_AON},
4};
5
6for_each_lp_function! {
7    (($_lp:ident, LP_GPIOn, $pin:literal), $gpio:ident, $_af:ident, $_lp_in:tt $_lp_out:tt) => {
8        #[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
9        impl LpPin for crate::peripherals::$gpio<'_> {
10            fn lp_number(&self) -> u8 {
11                $pin
12            }
13        }
14    };
15}
16
17// One register holds every pad, and it numbers the pads the way the digital registers do.
18pub(crate) fn pad_hold(lp: u8, enable: bool) {
19    digital_pad_hold(lp_pin_to_gpio(lp), enable);
20}
21
22/// Returns whether something holds the pad.
23pub(crate) fn is_pad_held(lp: u8) -> bool {
24    is_digital_pad_held(lp_pin_to_gpio(lp))
25}
26
27/// Takes or releases the hold of the pad of `gpio`.
28pub(crate) fn digital_pad_hold(gpio: u8, enable: bool) {
29    let mask = 1 << gpio;
30    LP_AON::regs().gpio_hold0().modify(|r, w| unsafe {
31        let bits = r.gpio_hold0().bits();
32        w.gpio_hold0()
33            .bits(if enable { bits | mask } else { bits & !mask })
34    });
35}
36
37/// Returns whether something holds the pad of `gpio`.
38pub(crate) fn is_digital_pad_held(gpio: u8) -> bool {
39    LP_AON::regs().gpio_hold0().read().gpio_hold0().bits() & (1 << gpio) != 0
40}
41
42/// Configures the pad.
43///
44/// The low-power domain reaches the pad through the digital IO MUX. There is thus no low-power
45/// function to select.
46pub(crate) fn set_config(lp: u8, input_enable: bool, _mux: bool, _func: LpFunction) {
47    IO_MUX::regs()
48        .gpio(lp_pin_to_gpio(lp) as usize)
49        .modify(|_, w| unsafe {
50            w.slp_sel().bit(false);
51            w.mcu_sel().bits(AlternateFunction::GPIO as u8);
52            w.fun_ie().bit(input_enable)
53        });
54}
55
56#[expect(dead_code)]
57pub(crate) fn init_pin(lp: u8, enable_input: bool) -> u8 {
58    input_enable(lp, enable_input);
59    lp
60}
61
62fn lp_pin_to_gpio(lp: u8) -> u8 {
63    lp + 7
64}
65
66#[expect(dead_code)]
67pub(crate) fn output_enable(lp: u8, enable: bool) {
68    let gpio = lp_pin_to_gpio(lp);
69    if enable {
70        GPIO::regs()
71            .enable_w1ts()
72            .write(|w| unsafe { w.enable_w1ts().bits(1 << gpio) });
73    } else {
74        GPIO::regs()
75            .enable_w1tc()
76            .write(|w| unsafe { w.enable_w1tc().bits(1 << gpio) });
77    }
78}
79
80pub(crate) fn input_enable(lp: u8, enable: bool) {
81    IO_MUX::regs()
82        .gpio(lp_pin_to_gpio(lp) as usize)
83        .modify(|_, w| w.fun_ie().bit(enable));
84}
85
86#[expect(dead_code)]
87pub(crate) fn pullup_enable(lp: u8, enable: bool) {
88    IO_MUX::regs()
89        .gpio(lp_pin_to_gpio(lp) as usize)
90        .modify(|_, w| w.fun_wpu().bit(enable));
91}
92
93#[expect(dead_code)]
94pub(crate) fn pulldown_enable(lp: u8, enable: bool) {
95    IO_MUX::regs()
96        .gpio(lp_pin_to_gpio(lp) as usize)
97        .modify(|_, w| w.fun_wpd().bit(enable));
98}
99
100// The pad driver bit is part of the digital GPIO peripheral, and this chip gives a pad a different
101// low-power number, so this function takes the digital number.
102#[expect(dead_code)]
103pub(crate) fn set_open_drain_output(gpio: u8, enable: bool) {
104    GPIO::regs()
105        .pin(gpio as usize)
106        .modify(|_, w| w.pad_driver().bit(enable));
107}