//! # GPIO configuration module (ESP32-S2) //! //! ## Overview //! //! The `GPIO` module provides functions and configurations for controlling the //! `General Purpose Input/Output` pins on the `ESP32-S2` chip. It allows you to //! configure pins as inputs or outputs, set their state and read their state. //! //! Let's get through the functionality and configurations provided by this GPIO //! module: //! - `get_io_mux_reg(gpio_num: u8) -> &'static //! crate::peripherals::io_mux::GPIO0:`: //! * This function returns a reference to the GPIO register associated //! with the given GPIO number. It uses unsafe code and transmutation to //! access the GPIO registers based on the provided GPIO number. //! - `gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8`: //! * This function enables or disables GPIO interrupts and Non-Maskable //! Interrupts (NMI). It takes two boolean arguments int_enable and //! nmi_enable to control the interrupt and NMI enable settings. The //! function returns an u8 value representing the interrupt enable //! settings. //! - `impl_get_rtc_pad`: //! * This macro_rule generates a function to get a specific RTC pad. It //! takes a single argument `$pad_name`, which is an identifier //! representing the name of the pad. Returns a reference to the //! corresponding RTC pad. //! - `impl_get_rtc_pad_indexed`: //! * This macro_rule generates a function similar to the previous one but //! for indexed RTC pads. It takes two arguments: `$pad_name`, which //! represents the name of the pad, and `$idx`, which is the index of //! the specific pad. Returns a reference to the indexed RTC pad. //! - `gpio` block: //! * Defines the pin configurations for various GPIO pins. Each line //! represents a pin and its associated options such as input/output //! mode, analog capability, and corresponding functions. //! - `analog` block: //! * Block defines the analog capabilities of various GPIO pins. Each //! line represents a pin and its associated options such as mux //! selection, function selection, and input enable. //! - `enum InputSignal`: //! * This enumeration defines input signals for the GPIO mux. Each input //! signal is assigned a specific value. //! - `enum OutputSignal`: //! * This enumeration defines output signals for the GPIO mux. Each //! output signal is assigned a specific value. //! //! This module also implements the `InterruptStatusRegisterAccess` trait for //! two different banks: //! * `InterruptStatusRegisterAccessBank0` //! * `InterruptStatusRegisterAccessBank1`. //! This trait provides functions to read the interrupt status and NMI status //! registers for both the `PRO CPU` and `APP CPU`. The implementation uses the //! `gpio` peripheral to access the appropriate registers. use crate::{ gpio::{ AlternateFunction, GpioPin, InterruptStatusRegisterAccess, InterruptStatusRegisterAccessBank0, InterruptStatusRegisterAccessBank1, Unknown, }, peripherals::GPIO, }; pub const NUM_PINS: usize = 46; pub type OutputSignalType = u16; pub const OUTPUT_SIGNAL_MAX: u16 = 256; pub const INPUT_SIGNAL_MAX: u16 = 204; pub const ONE_INPUT: u8 = 0x38; pub const ZERO_INPUT: u8 = 0x3c; pub(crate) const GPIO_FUNCTION: AlternateFunction = AlternateFunction::Function1; pub(crate) const fn get_io_mux_reg(gpio_num: u8) -> &'static crate::peripherals::io_mux::GPIO0 { unsafe { let iomux = &*crate::peripherals::IO_MUX::PTR; match gpio_num { 0 => core::mem::transmute(&(iomux.gpio0)), 1 => core::mem::transmute(&(iomux.gpio1)), 2 => core::mem::transmute(&(iomux.gpio2)), 3 => core::mem::transmute(&(iomux.gpio3)), 4 => core::mem::transmute(&(iomux.gpio4)), 5 => core::mem::transmute(&(iomux.gpio5)), 6 => core::mem::transmute(&(iomux.gpio6)), 7 => core::mem::transmute(&(iomux.gpio7)), 8 => core::mem::transmute(&(iomux.gpio8)), 9 => core::mem::transmute(&(iomux.gpio9)), 10 => core::mem::transmute(&(iomux.gpio10)), 11 => core::mem::transmute(&(iomux.gpio11)), 12 => core::mem::transmute(&(iomux.gpio12)), 13 => core::mem::transmute(&(iomux.gpio13)), 14 => core::mem::transmute(&(iomux.gpio14)), 15 => core::mem::transmute(&(iomux.gpio15)), 16 => core::mem::transmute(&(iomux.gpio16)), 17 => core::mem::transmute(&(iomux.gpio17)), 18 => core::mem::transmute(&(iomux.gpio18)), 19 => core::mem::transmute(&(iomux.gpio19)), 20 => core::mem::transmute(&(iomux.gpio20)), 21 => core::mem::transmute(&(iomux.gpio21)), 26 => core::mem::transmute(&(iomux.gpio26)), 27 => core::mem::transmute(&(iomux.gpio27)), 32 => core::mem::transmute(&(iomux.gpio32)), 33 => core::mem::transmute(&(iomux.gpio33)), 34 => core::mem::transmute(&(iomux.gpio34)), 35 => core::mem::transmute(&(iomux.gpio35)), 36 => core::mem::transmute(&(iomux.gpio36)), 37 => core::mem::transmute(&(iomux.gpio37)), 38 => core::mem::transmute(&(iomux.gpio38)), 39 => core::mem::transmute(&(iomux.gpio39)), 40 => core::mem::transmute(&(iomux.gpio40)), 41 => core::mem::transmute(&(iomux.gpio41)), 42 => core::mem::transmute(&(iomux.gpio42)), 43 => core::mem::transmute(&(iomux.gpio43)), 44 => core::mem::transmute(&(iomux.gpio44)), 45 => core::mem::transmute(&(iomux.gpio45)), 46 => core::mem::transmute(&(iomux.gpio46)), _ => panic!(), } } } pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 { int_enable as u8 | ((nmi_enable as u8) << 1) | (int_enable as u8) << 2 | ((nmi_enable as u8) << 3) } /// Peripheral input signals for the GPIO mux #[allow(non_camel_case_types)] #[derive(PartialEq, Copy, Clone)] pub enum InputSignal { SPIQ = 0, SPID = 1, SPIHD = 2, SPIWP = 3, SPID4 = 7, SPID5 = 8, SPID6 = 9, SPID7 = 10, SPIDQS = 11, U0RXD = 14, U0CTS = 15, U0DSR = 16, U1RXD = 17, U1CTS = 18, U1DSR = 21, I2S0O_BCK = 23, I2S0O_WS = 25, I2S0I_BCK = 27, I2S0I_WS = 28, I2CEXT0_SCL = 29, I2CEXT0_SDA = 30, PCNT0_SIG_CH0 = 39, PCNT0_SIG_CH1 = 40, PCNT0_CTRL_CH0 = 41, PCNT0_CTRL_CH1 = 42, PCNT1_SIG_CH0 = 43, PCNT1_SIG_CH1 = 44, PCNT1_CTRL_CH0 = 45, PCNT1_CTRL_CH1 = 46, PCNT2_SIG_CH0 = 47, PCNT2_SIG_CH1 = 48, PCNT2_CTRL_CH0 = 49, PCNT2_CTRL_CH1 = 50, PCNT3_SIG_CH0 = 51, PCNT3_SIG_CH1 = 52, PCNT3_CTRL_CH0 = 53, PCNT3_CTRL_CH1 = 54, USB_OTG_IDDIG = 64, USB_OTG_AVALID = 65, USB_SRP_BVALID = 66, USB_OTG_VBUSVALID = 67, USB_SRP_SESSEND = 68, SPI3_CLK = 72, SPI3_Q = 73, SPI3_D = 74, SPI3_HD = 75, SPI3_CS0 = 76, RMT_SIG_0 = 83, RMT_SIG_1 = 84, RMT_SIG_2 = 85, RMT_SIG_3 = 86, I2CEXT1_SCL = 95, I2CEXT1_SDA = 96, FSPICLK = 108, FSPIQ = 109, FSPID = 110, FSPIHD = 111, FSPIWP = 112, FSPIIO4 = 113, FSPIIO5 = 114, FSPIIO6 = 115, FSPIIO7 = 116, FSPICS0 = 117, SUBSPIQ = 127, SUBSPID = 128, SUBSPIHD = 129, SUBSPIWP = 130, I2S0I_DATA_IN15 = 158, SUBSPID4 = 167, SUBSPID5 = 168, SUBSPID6 = 169, SUBSPID7 = 170, SUBSPIDQS = 171, PCMFSYNC = 203, PCMCLK = 204, } /// Peripheral output signals for the GPIO mux #[allow(non_camel_case_types)] #[derive(PartialEq, Copy, Clone)] pub enum OutputSignal { SPIQ = 0, SPID = 1, SPIHD = 2, SPIWP = 3, SPICLK = 4, SPICS0 = 5, SPICS1 = 6, SPID4 = 7, SPID5 = 8, SPID6 = 9, SPID7 = 10, SPIDQS = 11, U0TXD = 14, U0RTS = 15, U0DTR = 16, U1TXD = 17, U1RTS = 18, U1DTR = 21, I2S0O_BCK = 23, I2S0O_WS = 25, I2S0I_BCK = 27, I2S0I_WS = 28, I2CEXT0_SCL = 29, I2CEXT0_SDA = 30, SDIO_TOHOST_INT = 31, SPI3_CLK = 72, SPI3_Q = 73, SPI3_D = 74, SPI3_HD = 75, SPI3_CS0 = 76, SPI3_CS1 = 77, SPI3_CS2 = 78, LEDC_LS_SIG0 = 79, LEDC_LS_SIG1 = 80, LEDC_LS_SIG2 = 81, LEDC_LS_SIG3 = 82, LEDC_LS_SIG4 = 83, LEDC_LS_SIG5 = 84, LEDC_LS_SIG6 = 85, LEDC_LS_SIG7 = 86, RMT_SIG_0 = 87, RMT_SIG_1 = 88, RMT_SIG_2 = 89, RMT_SIG_3 = 90, I2CEXT1_SCL = 95, I2CEXT1_SDA = 96, GPIO_SD0 = 100, GPIO_SD1 = 101, GPIO_SD2 = 102, GPIO_SD3 = 103, GPIO_SD4 = 104, GPIO_SD5 = 105, GPIO_SD6 = 106, GPIO_SD7 = 107, FSPICLK = 108, FSPIQ = 109, FSPID = 110, FSPIHD = 111, FSPIWP = 112, FSPIIO4 = 113, FSPIIO5 = 114, FSPIIO6 = 115, FSPIIO7 = 116, FSPICS0 = 117, FSPICS1 = 118, FSPICS2 = 119, FSPICS3 = 120, FSPICS4 = 121, FSPICS5 = 122, SUBSPICLK = 126, SUBSPIQ = 127, SUBSPID = 128, SUBSPIHD = 129, SUBSPIWP = 130, SUBSPICS0 = 131, SUBSPICS1 = 132, FSPIDQS = 133, FSPI_HSYNC = 134, FSPI_VSYNC = 135, FSPI_DE = 136, FSPICD = 137, SPI3_CD = 139, SPI3_DQS = 140, I2S0O_DATA_OUT23 = 166, SUBSPID4 = 167, SUBSPID5 = 168, SUBSPID6 = 169, SUBSPID7 = 170, SUBSPIDQS = 171, PCMFSYNC = 209, PCMCLK = 210, CLK_I2S = 251, GPIO = 256, } crate::gpio::gpio! { (0, 0, InputOutputAnalog) (1, 0, InputOutputAnalog) (2, 0, InputOutputAnalog) (3, 0, InputOutputAnalog) (4, 0, InputOutputAnalog) (5, 0, InputOutputAnalog) (6, 0, InputOutputAnalog) (7, 0, InputOutputAnalog) (8, 0, InputOutputAnalog) (9, 0, InputOutputAnalog) (10, 0, InputOutputAnalog) (11, 0, InputOutputAnalog) (12, 0, InputOutputAnalog) (13, 0, InputOutputAnalog) (14, 0, InputOutputAnalog) (15, 0, InputOutputAnalog) (16, 0, InputOutputAnalog) (17, 0, InputOutputAnalog) (18, 0, InputOutputAnalog) (19, 0, InputOutputAnalog) (20, 0, InputOutputAnalog) (21, 0, InputOutputAnalog) (26, 0, InputOutput) (27, 0, InputOutput) (28, 0, InputOutput) (29, 0, InputOutput) (30, 0, InputOutput) (31, 0, InputOutput) (32, 1, InputOutput) (33, 1, InputOutput) (34, 1, InputOutput) (35, 1, InputOutput) (36, 1, InputOutput) (37, 1, InputOutput) (38, 1, InputOutput) (39, 1, InputOutput) (40, 1, InputOutput) (41, 1, InputOutput) (42, 1, InputOutput) (43, 1, InputOutput) (44, 1, InputOutput) (45, 1, InputOutput) (46, 1, InputOutput) } crate::gpio::analog! { ( 0, 0, touch_pad[0], mux_sel, fun_sel, fun_ie, rue, rde) ( 1, 1, touch_pad[1], mux_sel, fun_sel, fun_ie, rue, rde) ( 2, 2, touch_pad[2], mux_sel, fun_sel, fun_ie, rue, rde) ( 3, 3, touch_pad[3], mux_sel, fun_sel, fun_ie, rue, rde) ( 4, 4, touch_pad[4], mux_sel, fun_sel, fun_ie, rue, rde) ( 5, 5, touch_pad[5], mux_sel, fun_sel, fun_ie, rue, rde) ( 6, 6, touch_pad[6], mux_sel, fun_sel, fun_ie, rue, rde) ( 7, 7, touch_pad[7], mux_sel, fun_sel, fun_ie, rue, rde) ( 8, 8, touch_pad[8], mux_sel, fun_sel, fun_ie, rue, rde) ( 9, 9, touch_pad[9], mux_sel, fun_sel, fun_ie, rue, rde) (10, 10, touch_pad[10], mux_sel, fun_sel, fun_ie, rue, rde) (11, 11, touch_pad[11], mux_sel, fun_sel, fun_ie, rue, rde) (12, 12, touch_pad[12], mux_sel, fun_sel, fun_ie, rue, rde) (13, 13, touch_pad[13], mux_sel, fun_sel, fun_ie, rue, rde) (14, 14, touch_pad[14], mux_sel, fun_sel, fun_ie, rue, rde) (15, 15, xtal_32p_pad, x32p_mux_sel, x32p_fun_sel, x32p_fun_ie, x32p_rue, x32p_rde) (16, 16, xtal_32n_pad, x32n_mux_sel, x32n_fun_sel, x32n_fun_ie, x32n_rue, x32n_rde) (17, 17, pad_dac1, pdac1_mux_sel, pdac1_fun_sel, pdac1_fun_ie, pdac1_rue, pdac1_rde) (18, 18, pad_dac2, pdac2_mux_sel, pdac2_fun_sel, pdac2_fun_ie, pdac2_rue, pdac2_rde) (19, 19, rtc_pad19, mux_sel, fun_sel, fun_ie, rue, rde) (20, 20, rtc_pad20, mux_sel, fun_sel, fun_ie, rue, rde) (21, 21, rtc_pad21, mux_sel, fun_sel, fun_ie, rue, rde) } crate::gpio::rtc_pins! { ( 0, 0, touch_pad[0], "", touch_pad0_hold, rue, rde) ( 1, 1, touch_pad[1], "", touch_pad1_hold, rue, rde) ( 2, 2, touch_pad[2], "", touch_pad2_hold, rue, rde) ( 3, 3, touch_pad[3], "", touch_pad3_hold, rue, rde) ( 4, 4, touch_pad[4], "", touch_pad4_hold, rue, rde) ( 5, 5, touch_pad[5], "", touch_pad5_hold, rue, rde) ( 6, 6, touch_pad[6], "", touch_pad6_hold, rue, rde) ( 7, 7, touch_pad[7], "", touch_pad7_hold, rue, rde) ( 8, 8, touch_pad[8], "", touch_pad8_hold, rue, rde) ( 9, 9, touch_pad[9], "", touch_pad9_hold, rue, rde) (10, 10, touch_pad[10], "", touch_pad10_hold, rue, rde) (11, 11, touch_pad[11], "", touch_pad11_hold, rue, rde) (12, 12, touch_pad[12], "", touch_pad12_hold, rue, rde) (13, 13, touch_pad[13], "", touch_pad13_hold, rue, rde) (14, 14, touch_pad[14], "", touch_pad14_hold, rue, rde) (15, 15, xtal_32p_pad, x32p_, x32p_hold, x32p_rue, x32p_rde) (16, 16, xtal_32n_pad, x32n_, x32n_hold, x32n_rue, x32n_rde) (17, 17, pad_dac1, pdac1_, pdac1_hold, pdac1_rue, pdac1_rde) (18, 18, pad_dac2, pdac2_, pdac2_hold, pdac2_rue, pdac2_rde) (19, 19, rtc_pad19, "", pad19_hold, rue, rde) (20, 20, rtc_pad20, "", pad20_hold, rue, rde) (21, 21, rtc_pad21, "", pad21_hold, rue, rde) } impl InterruptStatusRegisterAccess for InterruptStatusRegisterAccessBank0 { fn pro_cpu_interrupt_status_read() -> u32 { unsafe { &*GPIO::PTR }.pcpu_int.read().bits() } fn pro_cpu_nmi_status_read() -> u32 { unsafe { &*GPIO::PTR }.pcpu_nmi_int.read().bits() } } impl InterruptStatusRegisterAccess for InterruptStatusRegisterAccessBank1 { fn pro_cpu_interrupt_status_read() -> u32 { unsafe { &*GPIO::PTR }.pcpu_int1.read().bits() } fn pro_cpu_nmi_status_read() -> u32 { unsafe { &*GPIO::PTR }.pcpu_nmi_int1.read().bits() } } // implement marker traits on USB pins impl crate::otg_fs::UsbSel for Gpio18 {} impl crate::otg_fs::UsbDp for Gpio19 {} impl crate::otg_fs::UsbDm for Gpio20 {}