diff --git a/esp-hal/src/gpio/interconnect.rs b/esp-hal/src/gpio/interconnect.rs index 4acf6f75471..ef863c1bd42 100644 --- a/esp-hal/src/gpio/interconnect.rs +++ b/esp-hal/src/gpio/interconnect.rs @@ -88,7 +88,7 @@ impl InputSignal { /// - invert: Configures whether or not to invert the input value /// - input: The GPIO number to connect to the input signal fn connect(&self, signal: usize, invert: bool, input: u8) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .func_in_sel_cfg(signal - FUNC_IN_SEL_OFFSET) .modify(|_, w| unsafe { w.sel() @@ -122,10 +122,9 @@ impl PeripheralInput for InputSignal { GPIO_FUNCTION } else { self.input_signals(private::Internal) - .into_iter() - .position(|s| s == Some(signal)) - .ok_or(()) - .and_then(AlternateFunction::try_from) + .iter() + .find(|(_af, s)| *s == signal) + .map(|(af, _)| *af) .unwrap_or(GPIO_FUNCTION) }; @@ -153,12 +152,12 @@ impl PeripheralInput for InputSignal { self.pin .set_alternate_function(GPIO_FUNCTION, private::Internal); - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) .modify(|_, w| w.sel().clear_bit()); } - fn input_signals(&self, _: private::Internal) -> [Option; 6] { + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, gpio::InputSignal)] { PeripheralInput::input_signals(&self.pin, private::Internal) } @@ -239,7 +238,7 @@ impl OutputSignal { enable_from_gpio: bool, output: u8, ) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .func_out_sel_cfg(output as usize) .modify(|_, w| unsafe { w.out_sel() @@ -269,10 +268,9 @@ impl PeripheralOutput for OutputSignal { GPIO_FUNCTION } else { self.output_signals(private::Internal) - .into_iter() - .position(|s| s == Some(signal)) - .ok_or(()) - .and_then(AlternateFunction::try_from) + .iter() + .find(|(_af, s)| *s == signal) + .map(|(af, _)| *af) .unwrap_or(GPIO_FUNCTION) }; @@ -306,12 +304,12 @@ impl PeripheralOutput for OutputSignal { self.pin .set_alternate_function(GPIO_FUNCTION, private::Internal); - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) .modify(|_, w| w.sel().clear_bit()); } - fn output_signals(&self, _: private::Internal) -> [Option; 6] { + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, gpio::OutputSignal)] { PeripheralOutput::output_signals(&self.pin, private::Internal) } @@ -405,7 +403,7 @@ impl PeripheralInput for AnyInputSignal { } { fn init_input(&self, pull: Pull, _internal: private::Internal); fn is_input_high(&self, _internal: private::Internal) -> bool; - fn input_signals(&self, _internal: private::Internal) -> [Option; 6]; + fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, gpio::InputSignal)]; } to match &mut self.0 { diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 064b82c311b..ca1741d70a8 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -208,6 +208,8 @@ pub enum Pull { } /// Drive strength (values are approximates) +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum DriveStrength { /// Drive strength of approximately 5mA. I5mA = 0, @@ -226,7 +228,8 @@ pub enum DriveStrength { /// The `AlternateFunction` enum allows to select one of several functions that /// a pin can perform, rather than using it as a general-purpose input or /// output. -#[derive(PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum AlternateFunction { /// Alternate function 0. Function0 = 0, @@ -259,7 +262,8 @@ impl TryFrom for AlternateFunction { } /// RTC function -#[derive(PartialEq)] +#[derive(Debug, Eq, PartialEq, Copy, Clone)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] pub enum RtcFunction { /// RTC mode. Rtc = 0, @@ -342,10 +346,10 @@ pub trait Pin: Sealed { } #[doc(hidden)] - fn output_signals(&self, _: private::Internal) -> [Option; 6]; + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)]; #[doc(hidden)] - fn input_signals(&self, _: private::Internal) -> [Option; 6]; + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, InputSignal)]; #[doc(hidden)] fn gpio_bank(&self, _: private::Internal) -> GpioRegisterAccess; @@ -380,7 +384,7 @@ pub trait PeripheralInput: PeripheralSignal { /// Returns the list of input signals that can be connected to this pin /// using IO_MUX. #[doc(hidden)] - fn input_signals(&self, _: private::Internal) -> [Option; 6]; + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, InputSignal)]; /// Connect the pin to a peripheral. #[doc(hidden)] @@ -436,7 +440,7 @@ pub trait PeripheralOutput: PeripheralSignal { /// Returns the list of output signals that can be connected to this pin /// using IO_MUX. #[doc(hidden)] - fn output_signals(&self, _: private::Internal) -> [Option; 6]; + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)]; /// Connect the pin to a peripheral. #[doc(hidden)] @@ -557,43 +561,43 @@ struct Bank0GpioRegisterAccess; impl Bank0GpioRegisterAccess { fn write_out_en_clear(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .enable_w1tc() .write(|w| unsafe { w.bits(word) }); } fn write_out_en_set(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .enable_w1ts() .write(|w| unsafe { w.bits(word) }); } fn read_input() -> u32 { - unsafe { &*GPIO::PTR }.in_().read().bits() + unsafe { GPIO::steal() }.in_().read().bits() } fn read_output() -> u32 { - unsafe { &*GPIO::PTR }.out().read().bits() + unsafe { GPIO::steal() }.out().read().bits() } fn read_interrupt_status() -> u32 { - unsafe { &*GPIO::PTR }.status().read().bits() + unsafe { GPIO::steal() }.status().read().bits() } fn write_interrupt_status_clear(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .status_w1tc() .write(|w| unsafe { w.bits(word) }); } fn write_output_set(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .out_w1ts() .write(|w| unsafe { w.bits(word) }); } fn write_output_clear(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .out_w1tc() .write(|w| unsafe { w.bits(word) }); } @@ -605,43 +609,43 @@ struct Bank1GpioRegisterAccess; #[cfg(any(esp32, esp32s2, esp32s3))] impl Bank1GpioRegisterAccess { fn write_out_en_clear(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .enable1_w1tc() .write(|w| unsafe { w.bits(word) }); } fn write_out_en_set(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .enable1_w1ts() .write(|w| unsafe { w.bits(word) }); } fn read_input() -> u32 { - unsafe { &*GPIO::PTR }.in1().read().bits() + unsafe { GPIO::steal() }.in1().read().bits() } fn read_output() -> u32 { - unsafe { &*GPIO::PTR }.out1().read().bits() + unsafe { GPIO::steal() }.out1().read().bits() } fn read_interrupt_status() -> u32 { - unsafe { &*GPIO::PTR }.status1().read().bits() + unsafe { GPIO::steal() }.status1().read().bits() } fn write_interrupt_status_clear(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .status1_w1tc() .write(|w| unsafe { w.bits(word) }); } fn write_output_set(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .out1_w1ts() .write(|w| unsafe { w.bits(word) }); } fn write_output_clear(word: u32) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .out1_w1tc() .write(|w| unsafe { w.bits(word) }); } @@ -692,7 +696,7 @@ fn disable_usb_pads(gpionum: u8) { } if pins.contains(&gpionum) { - unsafe { &*crate::peripherals::USB_DEVICE::PTR } + unsafe { crate::peripherals::USB_DEVICE::steal() } .conf0() .modify(|_, w| { w.usb_pad_enable().clear_bit(); @@ -764,7 +768,7 @@ where self.gpio_bank(private::Internal).read_input() & (1 << (GPIONUM % 32)) != 0 } - fn input_signals(&self, _: private::Internal) -> [Option; 6] { + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, InputSignal)] { ::input_signals(self, private::Internal) } @@ -810,7 +814,7 @@ where } fn enable_open_drain(&mut self, on: bool, _: private::Internal) { - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .pin(GPIONUM as usize) .modify(|_, w| w.pad_driver().bit(on)); } @@ -831,7 +835,7 @@ where self.gpio_bank(private::Internal).read_output() & (1 << (GPIONUM % 32)) != 0 } - fn output_signals(&self, _: private::Internal) -> [Option; 6] { + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)] { ::output_signals(self, private::Internal) } @@ -853,7 +857,7 @@ where fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { self.output_enable(true, private::Internal); - let gpio = unsafe { &*GPIO::PTR }; + let gpio = unsafe { GPIO::steal() }; gpio.pin(GPIONUM as usize) .modify(|_, w| w.pad_driver().bit(open_drain)); @@ -1045,29 +1049,24 @@ macro_rules! gpio { $crate::gpio::GpioRegisterAccess::[] } - fn output_signals(&self, _: $crate::private::Internal) -> [Option; 6]{ - #[allow(unused_mut)] - let mut output_signals = [None; 6]; - - $( + fn output_signals(&self, _: $crate::private::Internal) -> &[(AlternateFunction, OutputSignal)] { + &[ $( - output_signals[ $af_output_num ] = Some( OutputSignal::$af_output_signal ); - )* - )? - - output_signals + $( + (AlternateFunction::[< Function $af_output_num >], OutputSignal::$af_output_signal ), + )* + )? + ] } - fn input_signals(&self, _: $crate::private::Internal) -> [Option; 6] { - #[allow(unused_mut)] - let mut input_signals = [None; 6]; - $( + fn input_signals(&self, _: $crate::private::Internal) -> &[(AlternateFunction, InputSignal)] { + &[ $( - input_signals[ $af_input_num ] = Some( InputSignal::$af_input_signal ); - )* - )? - - input_signals + $( + (AlternateFunction::[< Function $af_input_num >], InputSignal::$af_input_signal ), + )* + )? + ] } } @@ -1171,7 +1170,7 @@ macro_rules! rtc_pins { } fn rtcio_pad_hold(&mut self, enable: bool) { - let rtc_ctrl = unsafe { &*$crate::peripherals::LPWR::PTR }; + let rtc_ctrl = unsafe { $crate::peripherals::LPWR::steal() }; cfg_if::cfg_if! { if #[cfg(esp32)] { @@ -1191,7 +1190,7 @@ macro_rules! rtc_pins { impl $crate::gpio::RtcPinWithResistors for GpioPin<$pin_num> { fn rtcio_pullup(&mut self, enable: bool) { - let rtcio = unsafe { &*$crate::peripherals::RTC_IO::PTR }; + let rtcio = unsafe { $crate::peripherals::RTC_IO::steal() }; paste::paste! { rtcio.$pin_reg.modify(|_, w| w.[< $prefix rue >]().bit(enable)); @@ -1199,7 +1198,7 @@ macro_rules! rtc_pins { } fn rtcio_pulldown(&mut self, enable: bool) { - let rtcio = unsafe { &*$crate::peripherals::RTC_IO::PTR }; + let rtcio = unsafe { $crate::peripherals::RTC_IO::steal() }; paste::paste! { rtcio.$pin_reg.modify(|_, w| w.[< $prefix rde >]().bit(enable)); @@ -1439,7 +1438,7 @@ macro_rules! analog { w.fun_wpd().clear_bit() }); - unsafe{ &*GPIO::PTR }.enable_w1tc().write(|w| unsafe { w.bits(1 << $pin_num) }); + unsafe{ GPIO::steal() }.enable_w1tc().write(|w| unsafe { w.bits(1 << $pin_num) }); } } )+ @@ -2147,13 +2146,13 @@ pub(crate) mod internal { }) } - fn output_signals(&self, _: private::Internal) -> [Option; 6] { + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)] { handle_gpio_input!(&self.0, target, { Pin::output_signals(target, private::Internal) }) } - fn input_signals(&self, _: private::Internal) -> [Option; 6] { + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, InputSignal)] { handle_gpio_input!(&self.0, target, { Pin::input_signals(target, private::Internal) }) @@ -2199,7 +2198,7 @@ pub(crate) mod internal { }) } - fn input_signals(&self, _: private::Internal) -> [Option; 6] { + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, InputSignal)] { handle_gpio_input!(&self.0, target, { PeripheralInput::input_signals(target, private::Internal) }) @@ -2279,7 +2278,7 @@ pub(crate) mod internal { }) } - fn output_signals(&self, _: private::Internal) -> [Option; 6] { + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)] { handle_gpio_output!(&self.0, target, { PeripheralOutput::output_signals(target, private::Internal) }) @@ -2348,7 +2347,7 @@ pub(crate) mod internal { } fn is_listening(pin_num: u8) -> bool { - let bits = unsafe { &*GPIO::PTR } + let bits = unsafe { GPIO::steal() } .pin(pin_num as usize) .read() .int_ena() @@ -2357,7 +2356,7 @@ fn is_listening(pin_num: u8) -> bool { } fn set_int_enable(gpio_num: u8, int_ena: u8, int_type: u8, wake_up_from_light_sleep: bool) { - let gpio = unsafe { &*GPIO::PTR }; + let gpio = unsafe { GPIO::steal() }; gpio.pin(gpio_num as usize).modify(|_, w| unsafe { w.int_ena().bits(int_ena); w.int_type().bits(int_type); diff --git a/esp-hal/src/gpio/placeholder.rs b/esp-hal/src/gpio/placeholder.rs index 5e604324b61..e5034a55891 100644 --- a/esp-hal/src/gpio/placeholder.rs +++ b/esp-hal/src/gpio/placeholder.rs @@ -20,8 +20,8 @@ impl PeripheralSignal for Level { } impl PeripheralInput for Level { - fn input_signals(&self, _: private::Internal) -> [Option; 6] { - [None; 6] + fn input_signals(&self, _: private::Internal) -> &[(AlternateFunction, InputSignal)] { + &[] } fn init_input(&self, _pull: Pull, _: private::Internal) {} @@ -40,7 +40,7 @@ impl PeripheralInput for Level { Level::Low => ZERO_INPUT, }; - unsafe { &*GPIO::PTR } + unsafe { GPIO::steal() } .func_in_sel_cfg(signal as usize - FUNC_IN_SEL_OFFSET) .modify(|_, w| unsafe { w.sel() @@ -78,8 +78,8 @@ impl PeripheralOutput for Level { false } - fn output_signals(&self, _: private::Internal) -> [Option; 6] { - [None; 6] + fn output_signals(&self, _: private::Internal) -> &[(AlternateFunction, OutputSignal)] { + &[] } fn connect_peripheral_to_output(&mut self, _signal: OutputSignal, _: private::Internal) {} @@ -116,7 +116,7 @@ impl PeripheralInput for NoPin { fn is_input_high(&self, _internal: private::Internal) -> bool; fn connect_input_to_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal); fn disconnect_input_from_peripheral(&mut self, _signal: InputSignal, _internal: private::Internal); - fn input_signals(&self, _internal: private::Internal) -> [Option; 6]; + fn input_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, InputSignal)]; } } } @@ -134,7 +134,7 @@ impl PeripheralOutput for NoPin { fn internal_pull_up_in_sleep_mode(&mut self, _on: bool, _internal: private::Internal); fn internal_pull_down_in_sleep_mode(&mut self, _on: bool, _internal: private::Internal); fn is_set_high(&self, _internal: private::Internal) -> bool; - fn output_signals(&self, _internal: private::Internal) -> [Option; 6]; + fn output_signals(&self, _internal: private::Internal) -> &[(AlternateFunction, OutputSignal)]; fn connect_peripheral_to_output(&mut self, _signal: OutputSignal, _internal: private::Internal); fn disconnect_from_peripheral_output(&mut self, _signal: OutputSignal, _internal: private::Internal); } diff --git a/esp-hal/src/gpio/rtc_io.rs b/esp-hal/src/gpio/rtc_io.rs index db3ed328829..2eb87a1714e 100644 --- a/esp-hal/src/gpio/rtc_io.rs +++ b/esp-hal/src/gpio/rtc_io.rs @@ -32,10 +32,13 @@ use core::marker::PhantomData; -#[cfg(esp32c6)] -use super::OpenDrain; -use super::RtcPin; -use crate::into_ref; +use super::{InputPin, OutputPin, RtcPin}; +use crate::{ + gpio::RtcFunction, + into_ref, + peripheral::Peripheral, + peripherals::{GPIO, RTC_IO}, +}; /// A GPIO output pin configured for low power operation pub struct LowPowerOutput<'d, const PIN: u8> { @@ -44,12 +47,12 @@ pub struct LowPowerOutput<'d, const PIN: u8> { impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> { /// Create a new output pin for use by the low-power core - pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + pub fn new

(pin: impl Peripheral

+ 'd) -> Self where - P: super::OutputPin + RtcPin, + P: OutputPin + RtcPin, { into_ref!(pin); - pin.rtc_set_config(false, true, crate::gpio::RtcFunction::Rtc); + pin.rtc_set_config(false, true, RtcFunction::Rtc); let this = Self { phantom: PhantomData, @@ -60,7 +63,7 @@ impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> { } fn output_enable(&self, enable: bool) { - let rtc_io = unsafe { crate::peripherals::RTC_IO::steal() }; + let rtc_io = unsafe { RTC_IO::steal() }; if enable { rtc_io @@ -81,12 +84,12 @@ pub struct LowPowerInput<'d, const PIN: u8> { impl<'d, const PIN: u8> LowPowerInput<'d, PIN> { /// Create a new input pin for use by the low-power core - pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + pub fn new

(pin: impl Peripheral

+ 'd) -> Self where - P: super::InputPin + RtcPin, + P: InputPin + RtcPin, { into_ref!(pin); - pin.rtc_set_config(true, true, crate::gpio::RtcFunction::Rtc); + pin.rtc_set_config(true, true, RtcFunction::Rtc); let this = Self { phantom: PhantomData, @@ -99,17 +102,23 @@ impl<'d, const PIN: u8> LowPowerInput<'d, PIN> { } fn input_enable(&self, enable: bool) { - get_pin_reg(PIN).modify(|_, w| w.fun_ie().bit(enable)); + unsafe { RTC_IO::steal() } + .touch_pad(PIN as usize) + .modify(|_, w| w.fun_ie().bit(enable)); } /// Sets pull-up enable for the pin pub fn pullup_enable(&self, enable: bool) { - get_pin_reg(PIN).modify(|_, w| w.rue().bit(enable)); + unsafe { RTC_IO::steal() } + .touch_pad(PIN as usize) + .modify(|_, w| w.rue().bit(enable)); } /// Sets pull-down enable for the pin pub fn pulldown_enable(&self, enable: bool) { - get_pin_reg(PIN).modify(|_, w| w.rde().bit(enable)); + unsafe { RTC_IO::steal() } + .touch_pad(PIN as usize) + .modify(|_, w| w.rde().bit(enable)); } } @@ -120,12 +129,12 @@ pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> { impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> { /// Create a new output pin for use by the low-power core - pub fn new

(pin: impl crate::peripheral::Peripheral

+ 'd) -> Self + pub fn new

(pin: impl Peripheral

+ 'd) -> Self where - P: super::InputPin + super::OutputPin + RtcPin, + P: InputPin + OutputPin + RtcPin, { into_ref!(pin); - pin.rtc_set_config(true, true, crate::gpio::RtcFunction::Rtc); + pin.rtc_set_config(true, true, RtcFunction::Rtc); let this = Self { phantom: PhantomData, @@ -141,7 +150,7 @@ impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> { } fn output_enable(&self, enable: bool) { - let rtc_io = unsafe { crate::peripherals::RTC_IO::steal() }; + let rtc_io = unsafe { RTC_IO::steal() }; if enable { rtc_io @@ -155,35 +164,28 @@ impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> { } fn input_enable(&self, enable: bool) { - get_pin_reg(PIN).modify(|_, w| w.fun_ie().bit(enable)); + unsafe { RTC_IO::steal() } + .touch_pad(PIN as usize) + .modify(|_, w| w.fun_ie().bit(enable)); } /// Sets pull-up enable for the pin pub fn pullup_enable(&self, enable: bool) { - get_pin_reg(PIN).modify(|_, w| w.rue().bit(enable)); + unsafe { RTC_IO::steal() } + .touch_pad(PIN as usize) + .modify(|_, w| w.rue().bit(enable)); } /// Sets pull-down enable for the pin pub fn pulldown_enable(&self, enable: bool) { - get_pin_reg(PIN).modify(|_, w| w.rde().bit(enable)); + unsafe { RTC_IO::steal() } + .touch_pad(PIN as usize) + .modify(|_, w| w.rde().bit(enable)); } fn set_open_drain_output(&self, enable: bool) { - use crate::peripherals::GPIO; - let gpio = unsafe { &*GPIO::PTR }; - - gpio.pin(PIN as usize) + unsafe { GPIO::steal() } + .pin(PIN as usize) .modify(|_, w| w.pad_driver().bit(enable)); } } - -#[cfg(any(esp32s2, esp32s3))] -#[inline(always)] -fn get_pin_reg(pin: u8) -> &'static crate::peripherals::rtc_io::TOUCH_PAD { - unsafe { - let rtc_io = &*crate::peripherals::RTC_IO::PTR; - let pin_ptr = (rtc_io.touch_pad(0).as_ptr()).add(pin as usize); - - &*(pin_ptr as *const crate::peripherals::rtc_io::TOUCH_PAD) - } -}