Allow pin drivers as wakeup sources (#2095)
Co-authored-by: Scott Mabin <scott@mabez.dev>
This commit is contained in:
parent
3ea95bd0d8
commit
be82a6521a
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- Added sleep and wakeup support for esp32c2 (#1922)
|
- Added sleep and wakeup support for esp32c2 (#1922)
|
||||||
- `Input`, `Output`, `OutputOpenDrain` and `Flex` now implement `Peripheral`. (#2094)
|
- `Input`, `Output`, `OutputOpenDrain` and `Flex` now implement `Peripheral`. (#2094)
|
||||||
- Previously unavailable memory is available via `.dram2_uninit` section (#2079)
|
- Previously unavailable memory is available via `.dram2_uninit` section (#2079)
|
||||||
|
- You can now use `Input`, `Output`, `OutputOpenDrain` and `Flex` pins as EXTI and RTCIO wakeup sources (#2095)
|
||||||
- Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883)
|
- Added `Rtc::set_current_time` to allow setting RTC time, and `Rtc::current_time` to getting RTC time while taking into account boot time (#1883)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@ -52,6 +52,28 @@ let pin = Input::new(io.gpio0); // pin will have the type `Input<'some>` (or `In
|
|||||||
let pin = Input::new_typed(io.gpio0); // pin will have the type `Input<'some, GpioPin<0>>`
|
let pin = Input::new_typed(io.gpio0); // pin will have the type `Input<'some, GpioPin<0>>`
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Wakeup using pin drivers
|
||||||
|
|
||||||
|
You can now use pin drivers as wakeup sources.
|
||||||
|
|
||||||
|
```rust
|
||||||
|
use esp_hal::peripheral::Peripheral; // needed for `into_ref`
|
||||||
|
|
||||||
|
let pin2 = Input::new(io.pins.gpio2, Pull::None);
|
||||||
|
let mut pin3 = Input::new(io.pins.gpio3, Pull::None);
|
||||||
|
// ... use pin2 as an input ..
|
||||||
|
|
||||||
|
// Ext0
|
||||||
|
let ext0 = Ext0WakeupSource::new(pin2, WakeupLevel::High);
|
||||||
|
|
||||||
|
// Ext1
|
||||||
|
let mut wakeup_pins: [&mut dyn RtcPin; 2] = [
|
||||||
|
&mut *pin_0.into_ref(),
|
||||||
|
&mut io.pins.gpio4, // unconfigured pins continue to work, too!
|
||||||
|
];
|
||||||
|
let ext1 = Ext1WakeupSource::new(&mut wakeup_pins, WakeupLevel::High);
|
||||||
|
```
|
||||||
|
|
||||||
## `esp_hal::time::current_time` rename
|
## `esp_hal::time::current_time` rename
|
||||||
|
|
||||||
To avoid confusion with the `Rtc::current_time` wall clock time APIs, we've renamed `esp_hal::time::current_time` to `esp_hal::time::now()`.
|
To avoid confusion with the `Rtc::current_time` wall clock time APIs, we've renamed `esp_hal::time::current_time` to `esp_hal::time::now()`.
|
||||||
|
|||||||
@ -257,6 +257,24 @@ macro_rules! lp_gpio {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! handle_rtcio {
|
||||||
|
($this:expr, $inner:ident, $code:tt) => {
|
||||||
|
match $this {
|
||||||
|
$(
|
||||||
|
ErasedPinInner::[<Gpio $gpionum >]($inner) => {
|
||||||
|
$code
|
||||||
|
},
|
||||||
|
)+
|
||||||
|
|
||||||
|
_ => panic!("Unsupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) use handle_rtcio;
|
||||||
|
pub(crate) use handle_rtcio as handle_rtcio_with_resistors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1411,6 +1411,45 @@ macro_rules! rtc_pins {
|
|||||||
$(
|
$(
|
||||||
$crate::gpio::rtc_pins!($pin_num, $rtc_pin, $pin_reg, $prefix, $hold $(, $rue, $rde)?);
|
$crate::gpio::rtc_pins!($pin_num, $rtc_pin, $pin_reg, $prefix, $hold $(, $rue, $rde)?);
|
||||||
)+
|
)+
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! handle_rtcio {
|
||||||
|
($this:expr, $inner:ident, $code:tt) => {
|
||||||
|
match $this {
|
||||||
|
$(
|
||||||
|
paste::paste! { ErasedPinInner::[<Gpio $pin_num >]($inner) } => {
|
||||||
|
$code
|
||||||
|
},
|
||||||
|
)+
|
||||||
|
|
||||||
|
_ => panic!("Unsupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! handle_rtcio_with_resistors {
|
||||||
|
(@ignore $a:ident, $b:ident) => {};
|
||||||
|
($this:expr, $inner:ident, $code:tt) => {
|
||||||
|
match $this {
|
||||||
|
$(
|
||||||
|
$(
|
||||||
|
paste::paste! { ErasedPinInner::[<Gpio $pin_num >]($inner) } => {
|
||||||
|
// FIXME: replace with $(ignore($rue)) once stable
|
||||||
|
handle_rtcio_with_resistors!(@ignore $rue, $rde);
|
||||||
|
$code
|
||||||
|
},
|
||||||
|
)?
|
||||||
|
)+
|
||||||
|
|
||||||
|
_ => panic!("Unsupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub(crate) use handle_rtcio;
|
||||||
|
pub(crate) use handle_rtcio_with_resistors;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1458,10 +1497,30 @@ macro_rules! rtc_pins {
|
|||||||
io_mux.gpio($pin_num).modify(|_, w| w.fun_wpd().bit(enable));
|
io_mux.gpio($pin_num).modify(|_, w| w.fun_wpd().bit(enable));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
( $( $pin_num:expr )+ ) => { $( $crate::gpio::rtc_pins!($pin_num); )+ };
|
( $( $pin_num:expr )+ ) => {
|
||||||
|
$( $crate::gpio::rtc_pins!($pin_num); )+
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! handle_rtcio {
|
||||||
|
($this:expr, $inner:ident, $code:tt) => {
|
||||||
|
match $this {
|
||||||
|
$(
|
||||||
|
paste::paste! { ErasedPinInner::[<Gpio $pin_num >]($inner) } => {
|
||||||
|
$code
|
||||||
|
},
|
||||||
|
)+
|
||||||
|
|
||||||
|
_ => panic!("Unsupported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use handle_rtcio;
|
||||||
|
pub(crate) use handle_rtcio as handle_rtcio_with_resistors;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
@ -2380,6 +2439,50 @@ pub(crate) mod internal {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(xtensa, esp32c2, esp32c3, esp32c6))]
|
||||||
|
impl RtcPin for ErasedPin {
|
||||||
|
#[cfg(xtensa)]
|
||||||
|
#[allow(unused_braces)] // False positive :/
|
||||||
|
fn rtc_number(&self) -> u8 {
|
||||||
|
handle_rtcio!(&self.0, target, { RtcPin::rtc_number(target) })
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(xtensa, esp32c6))]
|
||||||
|
fn rtc_set_config(&mut self, input_enable: bool, mux: bool, func: RtcFunction) {
|
||||||
|
handle_rtcio!(&mut self.0, target, {
|
||||||
|
RtcPin::rtc_set_config(target, input_enable, mux, func)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rtcio_pad_hold(&mut self, enable: bool) {
|
||||||
|
handle_rtcio!(&mut self.0, target, {
|
||||||
|
RtcPin::rtcio_pad_hold(target, enable)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(esp32c2, esp32c3, esp32c6))]
|
||||||
|
unsafe fn apply_wakeup(&mut self, wakeup: bool, level: u8) {
|
||||||
|
handle_rtcio!(&mut self.0, target, {
|
||||||
|
RtcPin::apply_wakeup(target, wakeup, level)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(esp32c2, esp32c3, esp32c6, xtensa))]
|
||||||
|
impl RtcPinWithResistors for ErasedPin {
|
||||||
|
fn rtcio_pullup(&mut self, enable: bool) {
|
||||||
|
handle_rtcio_with_resistors!(&mut self.0, target, {
|
||||||
|
RtcPinWithResistors::rtcio_pullup(target, enable)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rtcio_pulldown(&mut self, enable: bool) {
|
||||||
|
handle_rtcio_with_resistors!(&mut self.0, target, {
|
||||||
|
RtcPinWithResistors::rtcio_pulldown(target, enable)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_listening(pin_num: u8) -> bool {
|
fn is_listening(pin_num: u8) -> bool {
|
||||||
|
|||||||
@ -23,6 +23,11 @@ use crate::gpio::RtcPin as RtcIoWakeupPinType;
|
|||||||
#[cfg(any(esp32c3, esp32c6, esp32c2))]
|
#[cfg(any(esp32c3, esp32c6, esp32c2))]
|
||||||
use crate::gpio::RtcPinWithResistors as RtcIoWakeupPinType;
|
use crate::gpio::RtcPinWithResistors as RtcIoWakeupPinType;
|
||||||
use crate::rtc_cntl::Rtc;
|
use crate::rtc_cntl::Rtc;
|
||||||
|
#[cfg(any(esp32, esp32s3))]
|
||||||
|
use crate::{
|
||||||
|
into_ref,
|
||||||
|
peripheral::{Peripheral, PeripheralRef},
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg_attr(esp32, path = "esp32.rs")]
|
#[cfg_attr(esp32, path = "esp32.rs")]
|
||||||
#[cfg_attr(esp32s3, path = "esp32s3.rs")]
|
#[cfg_attr(esp32s3, path = "esp32s3.rs")]
|
||||||
@ -71,11 +76,10 @@ pub enum Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// External wake-up source (Ext0).
|
/// External wake-up source (Ext0).
|
||||||
#[derive(Debug)]
|
|
||||||
#[cfg(any(esp32, esp32s3))]
|
#[cfg(any(esp32, esp32s3))]
|
||||||
pub struct Ext0WakeupSource<'a, P: RtcIoWakeupPinType> {
|
pub struct Ext0WakeupSource<'a, P: RtcIoWakeupPinType> {
|
||||||
/// The pin used as the wake-up source.
|
/// The pin used as the wake-up source.
|
||||||
pin: RefCell<&'a mut P>,
|
pin: RefCell<PeripheralRef<'a, P>>,
|
||||||
/// The level at which the wake-up event is triggered.
|
/// The level at which the wake-up event is triggered.
|
||||||
level: WakeupLevel,
|
level: WakeupLevel,
|
||||||
}
|
}
|
||||||
@ -84,7 +88,8 @@ pub struct Ext0WakeupSource<'a, P: RtcIoWakeupPinType> {
|
|||||||
impl<'a, P: RtcIoWakeupPinType> Ext0WakeupSource<'a, P> {
|
impl<'a, P: RtcIoWakeupPinType> Ext0WakeupSource<'a, P> {
|
||||||
/// Creates a new external wake-up source (Ext0``) with the specified pin
|
/// Creates a new external wake-up source (Ext0``) with the specified pin
|
||||||
/// and wake-up level.
|
/// and wake-up level.
|
||||||
pub fn new(pin: &'a mut P, level: WakeupLevel) -> Self {
|
pub fn new(pin: impl Peripheral<P = P> + 'a, level: WakeupLevel) -> Self {
|
||||||
|
into_ref!(pin);
|
||||||
Self {
|
Self {
|
||||||
pin: RefCell::new(pin),
|
pin: RefCell::new(pin),
|
||||||
level,
|
level,
|
||||||
|
|||||||
@ -14,7 +14,7 @@ use esp_backtrace as _;
|
|||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
entry,
|
entry,
|
||||||
gpio::Io,
|
gpio::{Input, Io, Pull},
|
||||||
rtc_cntl::{
|
rtc_cntl::{
|
||||||
get_reset_reason,
|
get_reset_reason,
|
||||||
get_wakeup_cause,
|
get_wakeup_cause,
|
||||||
@ -33,7 +33,7 @@ fn main() -> ! {
|
|||||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||||
|
|
||||||
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
let mut ext0_pin = io.pins.gpio4;
|
let ext0_pin = Input::new(io.pins.gpio4, Pull::None);
|
||||||
|
|
||||||
println!("up and runnning!");
|
println!("up and runnning!");
|
||||||
let reason = get_reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn);
|
let reason = get_reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn);
|
||||||
@ -44,7 +44,7 @@ fn main() -> ! {
|
|||||||
let delay = Delay::new();
|
let delay = Delay::new();
|
||||||
|
|
||||||
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
||||||
let ext0 = Ext0WakeupSource::new(&mut ext0_pin, WakeupLevel::High);
|
let ext0 = Ext0WakeupSource::new(ext0_pin, WakeupLevel::High);
|
||||||
println!("sleeping!");
|
println!("sleeping!");
|
||||||
delay.delay_millis(100);
|
delay.delay_millis(100);
|
||||||
rtc.sleep_deep(&[&timer, &ext0]);
|
rtc.sleep_deep(&[&timer, &ext0]);
|
||||||
|
|||||||
@ -14,7 +14,8 @@ use esp_backtrace as _;
|
|||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
entry,
|
entry,
|
||||||
gpio::{Io, RtcPin},
|
gpio::{Input, Io, Pull, RtcPin},
|
||||||
|
peripheral::Peripheral,
|
||||||
rtc_cntl::{
|
rtc_cntl::{
|
||||||
get_reset_reason,
|
get_reset_reason,
|
||||||
get_wakeup_cause,
|
get_wakeup_cause,
|
||||||
@ -33,7 +34,7 @@ fn main() -> ! {
|
|||||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||||
|
|
||||||
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
let mut pin_0 = io.pins.gpio4;
|
let pin_0 = Input::new(io.pins.gpio4, Pull::None);
|
||||||
let mut pin_2 = io.pins.gpio2;
|
let mut pin_2 = io.pins.gpio2;
|
||||||
|
|
||||||
println!("up and runnning!");
|
println!("up and runnning!");
|
||||||
@ -45,7 +46,7 @@ fn main() -> ! {
|
|||||||
let delay = Delay::new();
|
let delay = Delay::new();
|
||||||
|
|
||||||
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
let timer = TimerWakeupSource::new(Duration::from_secs(30));
|
||||||
let mut wakeup_pins: [&mut dyn RtcPin; 2] = [&mut pin_0, &mut pin_2];
|
let mut wakeup_pins: [&mut dyn RtcPin; 2] = [&mut *pin_0.into_ref(), &mut pin_2];
|
||||||
let ext1 = Ext1WakeupSource::new(&mut wakeup_pins, WakeupLevel::High);
|
let ext1 = Ext1WakeupSource::new(&mut wakeup_pins, WakeupLevel::High);
|
||||||
println!("sleeping!");
|
println!("sleeping!");
|
||||||
delay.delay_millis(100);
|
delay.delay_millis(100);
|
||||||
|
|||||||
@ -15,7 +15,8 @@ use esp_backtrace as _;
|
|||||||
use esp_hal::{
|
use esp_hal::{
|
||||||
delay::Delay,
|
delay::Delay,
|
||||||
entry,
|
entry,
|
||||||
gpio::{Io, RtcPinWithResistors},
|
gpio::{Input, Io, Pull, RtcPinWithResistors},
|
||||||
|
peripheral::Peripheral,
|
||||||
rtc_cntl::{
|
rtc_cntl::{
|
||||||
get_reset_reason,
|
get_reset_reason,
|
||||||
get_wakeup_cause,
|
get_wakeup_cause,
|
||||||
@ -34,7 +35,7 @@ fn main() -> ! {
|
|||||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||||
|
|
||||||
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
let mut pin2 = io.pins.gpio2;
|
let pin2 = Input::new(io.pins.gpio2, Pull::None);
|
||||||
let mut pin3 = io.pins.gpio3;
|
let mut pin3 = io.pins.gpio3;
|
||||||
|
|
||||||
println!("up and runnning!");
|
println!("up and runnning!");
|
||||||
@ -47,7 +48,7 @@ fn main() -> ! {
|
|||||||
let timer = TimerWakeupSource::new(Duration::from_secs(10));
|
let timer = TimerWakeupSource::new(Duration::from_secs(10));
|
||||||
|
|
||||||
let wakeup_pins: &mut [(&mut dyn RtcPinWithResistors, WakeupLevel)] = &mut [
|
let wakeup_pins: &mut [(&mut dyn RtcPinWithResistors, WakeupLevel)] = &mut [
|
||||||
(&mut pin2, WakeupLevel::Low),
|
(&mut *pin2.into_ref(), WakeupLevel::Low),
|
||||||
(&mut pin3, WakeupLevel::High),
|
(&mut pin3, WakeupLevel::High),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@ use esp_hal::{
|
|||||||
delay::Delay,
|
delay::Delay,
|
||||||
entry,
|
entry,
|
||||||
gpio,
|
gpio,
|
||||||
gpio::Io,
|
gpio::{Input, Io, Pull},
|
||||||
|
peripheral::Peripheral,
|
||||||
rtc_cntl::{
|
rtc_cntl::{
|
||||||
get_reset_reason,
|
get_reset_reason,
|
||||||
get_wakeup_cause,
|
get_wakeup_cause,
|
||||||
@ -35,7 +36,7 @@ use esp_println::println;
|
|||||||
fn main() -> ! {
|
fn main() -> ! {
|
||||||
let peripherals = esp_hal::init(esp_hal::Config::default());
|
let peripherals = esp_hal::init(esp_hal::Config::default());
|
||||||
|
|
||||||
let mut io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
|
||||||
let mut rtc = Rtc::new(peripherals.LPWR);
|
let mut rtc = Rtc::new(peripherals.LPWR);
|
||||||
|
|
||||||
println!("up and runnning!");
|
println!("up and runnning!");
|
||||||
@ -49,13 +50,20 @@ fn main() -> ! {
|
|||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(any(feature = "esp32c3", feature = "esp32c2"))] {
|
if #[cfg(any(feature = "esp32c3", feature = "esp32c2"))] {
|
||||||
|
let pin2 = Input::new(io.pins.gpio2, Pull::None);
|
||||||
|
let mut pin3 = io.pins.gpio3;
|
||||||
|
|
||||||
let wakeup_pins: &mut [(&mut dyn gpio::RtcPinWithResistors, WakeupLevel)] = &mut [
|
let wakeup_pins: &mut [(&mut dyn gpio::RtcPinWithResistors, WakeupLevel)] = &mut [
|
||||||
(&mut io.pins.gpio2, WakeupLevel::Low),
|
(&mut *pin2.into_ref(), WakeupLevel::Low),
|
||||||
(&mut io.pins.gpio3, WakeupLevel::High),
|
(&mut pin3, WakeupLevel::High),
|
||||||
];
|
];
|
||||||
} else if #[cfg(feature = "esp32s3")] {
|
} else if #[cfg(feature = "esp32s3")] {
|
||||||
|
let pin17 = Input::new(io.pins.gpio17, Pull::None);
|
||||||
|
let mut pin18 = io.pins.gpio18;
|
||||||
|
|
||||||
let wakeup_pins: &mut [(&mut dyn gpio::RtcPin, WakeupLevel)] = &mut [
|
let wakeup_pins: &mut [(&mut dyn gpio::RtcPin, WakeupLevel)] = &mut [
|
||||||
(&mut io.pins.gpio18, WakeupLevel::Low)
|
(&mut *pin17.into_ref(), WakeupLevel::Low),
|
||||||
|
(&mut pin18, WakeupLevel::High),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user