diff --git a/esp-hal/CHANGELOG.md b/esp-hal/CHANGELOG.md index 6ce6ee451..a186ea25e 100644 --- a/esp-hal/CHANGELOG.md +++ b/esp-hal/CHANGELOG.md @@ -102,6 +102,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `ClockSource` enums are now `#[non_exhaustive]` (#2912) +- `gpio::{Input, Flex}::wakeup_enable` now returns an error instead of panicking. (#2916) + ### Fixed - Xtensa devices now correctly enable the `esp-hal-procmacros/rtc-slow` feature (#2594) diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 0886c2de3..277e98039 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -52,6 +52,8 @@ //! [embedded-hal-async]: https://docs.rs/embedded-hal-async/latest/embedded_hal_async/index.html //! [Inverting TX and RX Pins]: crate::uart#inverting-rx-and-tx-pins +use core::fmt::Display; + use portable_atomic::{AtomicPtr, AtomicU32, Ordering}; use procmacros::ram; use strum::EnumCount; @@ -203,6 +205,30 @@ impl From for bool { } } +/// Errors that can occur when configuring a pin to be a wakeup source. +#[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum WakeConfigError { + /// Returned when trying to configure a pin to wake up from light sleep on + /// an edge trigger, which is not supported. + EdgeTriggeringNotSupported, +} + +impl Display for WakeConfigError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + WakeConfigError::EdgeTriggeringNotSupported => { + write!( + f, + "Edge triggering is not supported for wake-up from light sleep" + ) + } + } + } +} + +impl core::error::Error for WakeConfigError {} + /// Pull setting for an input. #[derive(Debug, Eq, PartialEq, Copy, Clone, Hash)] #[cfg_attr(feature = "defmt", derive(defmt::Format))] @@ -1531,8 +1557,8 @@ impl<'d> Input<'d> { /// This will unlisten for interrupts #[instability::unstable] #[inline] - pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) { - self.pin.wakeup_enable(enable, event); + pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) -> Result<(), WakeConfigError> { + self.pin.wakeup_enable(enable, event) } /// Split the pin into an input and output signal. @@ -1805,11 +1831,11 @@ impl<'d> Flex<'d> { int_enable: bool, nmi_enable: bool, wake_up_from_light_sleep: bool, - ) { + ) -> Result<(), WakeConfigError> { if wake_up_from_light_sleep { match event { Event::AnyEdge | Event::RisingEdge | Event::FallingEdge => { - panic!("Edge triggering is not supported for wake-up from light sleep"); + return Err(WakeConfigError::EdgeTriggeringNotSupported); } _ => {} } @@ -1820,7 +1846,9 @@ impl<'d> Flex<'d> { Some(gpio_intr_enable(int_enable, nmi_enable)), event as u8, wake_up_from_light_sleep, - ) + ); + + Ok(()) } /// Listen for interrupts. @@ -1828,7 +1856,9 @@ impl<'d> Flex<'d> { /// See [`Input::listen`] for more information and an example. #[inline] pub fn listen(&mut self, event: Event) { - self.listen_with_options(event, true, false, false) + // Unwrap can't fail currently as listen_with_options is only supposed to return + // an error if wake_up_from_light_sleep is true. + unwrap!(self.listen_with_options(event, true, false, false)); } /// Stop listening for interrupts. @@ -1863,8 +1893,8 @@ impl<'d> Flex<'d> { /// This will unlisten for interrupts #[instability::unstable] #[inline] - pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) { - self.listen_with_options(event.into(), false, false, enable); + pub fn wakeup_enable(&mut self, enable: bool, event: WakeEvent) -> Result<(), WakeConfigError> { + self.listen_with_options(event.into(), false, false, enable) } /// Set the GPIO to output mode.