esp_hal/gpio/lp_io/low_level/
esp32s31.rs1#[cfg(all(lp_io_has_gpio_matrix, lp_uart_driver_supported))]
2use crate::gpio::lp_io::{LpInputSignal, LpOutputSignal};
3use crate::{
4 gpio::{LpPin, lp_io::LpFunction},
5 peripherals::{LP_GPIO, LP_IO_MUX, LP_PERI, LP_SYS},
6};
7
8const LP_PAD_COUNT: u8 = 8;
10
11for_each_lp_function! {
12 (($_lp_pin_name:ident, LP_GPIOn, $lp_pin:literal), $gpio:ident, $_af:ident, $_lp_in:tt $_lp_out:tt) => {
13 impl LpPin for crate::peripherals::$gpio<'_> {
14 fn lp_number(&self) -> u8 {
15 $lp_pin
16 }
17 }
18 };
19
20 (LP_GPIOn $((
22 ($_lp_pin_name:ident, LP_GPIOn, $lp_pin:literal),
23 $gpio:ident,
24 $_af:ident,
25 ($( $lp_in_af:ident => $lp_in_signal:ident )*)
26 ($( $lp_out_af:ident => $lp_out_signal:ident )*)
27 )),*) => {
28 #[cfg(all(lp_io_has_gpio_matrix, lp_uart_driver_supported))]
29 pub(crate) fn input_signals(lp: u8) -> &'static [(LpFunction, LpInputSignal)] {
30 match lp {
31 $( $lp_pin => &[$( (LpFunction::$lp_in_af, LpInputSignal::$lp_in_signal) ),*], )*
32 _ => unreachable!(),
33 }
34 }
35
36 #[cfg(all(lp_io_has_gpio_matrix, lp_uart_driver_supported))]
37 pub(crate) fn output_signals(lp: u8) -> &'static [(LpFunction, LpOutputSignal)] {
38 match lp {
39 $( $lp_pin => &[$( (LpFunction::$lp_out_af, LpOutputSignal::$lp_out_signal) ),*], )*
40 _ => unreachable!(),
41 }
42 }
43 };
44}
45
46fn enable_io_clock() {
47 LP_PERI::regs()
48 .iomux_ctrl()
49 .modify(|_, w| w.lp_iomux_clk_en().set_bit());
50 LP_GPIO::regs()
51 .clock_gate()
52 .modify(|_, w| w.clk_en().set_bit());
53 while LP_PERI::regs()
54 .iomux_ctrl()
55 .read()
56 .lp_iomux_clk_en()
57 .bit_is_clear()
58 || LP_GPIO::regs().clock_gate().read().clk_en().bit_is_clear()
59 {}
60}
61
62pub(crate) fn set_config(lp: u8, input_enable: bool, mux: bool, func: LpFunction) {
63 if mux {
64 enable_io_clock();
65 }
66
67 LP_SYS::regs().padctrl().modify(|r, w| unsafe {
68 let mut sel = r.pad_mux_sel().bits();
69 if mux {
70 sel |= 1u8 << lp;
71 } else {
72 sel &= !(1u8 << lp);
73 }
74 w.pad_mux_sel().bits(sel)
75 });
76
77 LP_IO_MUX::regs().gpio(lp as usize).modify(|_, w| unsafe {
78 w.slp_sel().bit(false);
79 w.fun_ie().bit(input_enable);
80 w.mcu_sel().bits(func as u8)
81 });
82}
83
84#[cfg(lp_io_has_gpio_matrix)]
85pub(crate) fn init_pin(lp: u8, input_enable: bool) -> u8 {
86 set_config(lp, input_enable, true, LpFunction::LP_GPIO);
87 lp
88}
89
90#[cfg(lp_io_has_gpio_matrix)]
91pub(crate) fn output_enable(lp: u8, enable: bool) {
92 if enable {
93 LP_GPIO::regs()
94 .enable_w1ts()
95 .write(|w| unsafe { w.enable_w1ts().bits(1u8 << lp) });
96 } else {
97 LP_GPIO::regs()
98 .enable_w1tc()
99 .write(|w| unsafe { w.enable_w1tc().bits(1u8 << lp) });
100 }
101}
102
103#[cfg(lp_io_has_gpio_matrix)]
104pub(crate) fn input_enable(lp: u8, enable: bool) {
105 LP_IO_MUX::regs()
106 .gpio(lp as usize)
107 .modify(|_, w| w.fun_ie().bit(enable));
108}
109
110pub(crate) fn pullup_enable(lp: u8, enable: bool) {
111 LP_IO_MUX::regs()
112 .gpio(lp as usize)
113 .modify(|_, w| w.fun_wpu().bit(enable));
114}
115
116pub(crate) fn pulldown_enable(lp: u8, enable: bool) {
117 LP_IO_MUX::regs()
118 .gpio(lp as usize)
119 .modify(|_, w| w.fun_wpd().bit(enable));
120}
121
122pub(crate) fn pad_hold(lp: u8, enable: bool) {
123 LP_SYS::regs().padctrl().modify(|r, w| unsafe {
124 let mut hold = r.pad_hold().bits();
125 if enable {
126 hold |= 1u8 << lp;
127 } else {
128 hold &= !(1u8 << lp);
129 }
130 w.pad_hold().bits(hold)
131 });
132}
133
134pub(crate) fn is_pad_held(lp: u8) -> bool {
136 LP_SYS::regs().padctrl().read().pad_hold().bits() & (1u8 << lp) != 0
137}
138
139pub(crate) fn digital_pad_hold(gpio: u8, enable: bool) {
143 let Some(bit) = gpio.checked_sub(LP_PAD_COUNT) else {
144 return;
145 };
146
147 if bit < 32 {
148 let mask = 1 << bit;
149 LP_SYS::regs().hp_gpio_o_hold_ctrl0().modify(|r, w| unsafe {
150 let bits = r.hp_gpio_0_hold_ctrl0().bits();
151 w.hp_gpio_0_hold_ctrl0()
152 .bits(if enable { bits | mask } else { bits & !mask })
153 });
154 } else {
155 let mask = 1 << (bit - 32);
156 LP_SYS::regs().hp_gpio_o_hold_ctrl1().modify(|r, w| unsafe {
157 let bits = r.hp_gpio_0_hold_ctrl1().bits();
158 w.hp_gpio_0_hold_ctrl1()
159 .bits(if enable { bits | mask } else { bits & !mask })
160 });
161 }
162}
163
164pub(crate) fn is_digital_pad_held(gpio: u8) -> bool {
166 let Some(bit) = gpio.checked_sub(LP_PAD_COUNT) else {
167 return false;
168 };
169
170 if bit < 32 {
171 LP_SYS::regs()
172 .hp_gpio_o_hold_ctrl0()
173 .read()
174 .hp_gpio_0_hold_ctrl0()
175 .bits()
176 & (1 << bit)
177 != 0
178 } else {
179 LP_SYS::regs()
180 .hp_gpio_o_hold_ctrl1()
181 .read()
182 .hp_gpio_0_hold_ctrl1()
183 .bits()
184 & (1 << (bit - 32))
185 != 0
186 }
187}
188
189#[cfg(lp_io_has_gpio_matrix)]
190pub(crate) fn set_open_drain_output(lp: u8, enable: bool) {
191 LP_GPIO::regs()
192 .pin(lp as usize)
193 .modify(|_, w| w.pad_driver().bit(enable));
194}