1
//! Wake the chip through a pad.
2
//!
3
//! A pin declares that it can wake the chip, and its interrupt trigger sets the condition. Sleep
4
//! entry then assigns all the listening pins to the hardware paths of the chip. It assigns them
5
//! together, so the result does not depend on the order in which the user configured the pins.
6
//!
7
//! The chip has two kinds of path. The digital path reads the pad through the high-performance GPIO
8
//! peripheral. It works on every pad, but it needs that peripheral powered. Every listening pin has
9
//! this path, because the driver writes the interrupt-enable bit and the wakeup-enable bit of a pin
10
//! together. The low-power paths are `ext0`, `ext1` and the per-pin low-power path. These paths
11
//! continue to work when the peripheral is powered down. Deep sleep always powers the peripheral
12
//! down, and light sleep powers it down on request, so such a sleep needs a low-power path. Only
13
//! low-power pads have one, and a pin must request it with [`WakeupConfig`].
14
//!
15
//! The [`path`] module holds the low-power paths of the chip, and divides the pins between them.
16
//! This module collects the pins and requests the power domains that they need.
17
//!
18
//! This module also isolates the digital pads before a deep sleep, because it holds the pad tables.
19
//! That step is part of sleep entry, and it is not a wakeup source.
20
//!
21
//! All of this code runs with the flash accessible. Sleep entry calls the entry hook before it
22
//! writes the sleep configuration to hardware, and calls the exit hook after the wake sequence
23
//! restores it. The hooks still use the [`ram`][crate::ram] attribute, to keep the flash out of the
24
//! sleep path.
25

            
26
// Each generation of the low-power paths needs its own allocation.
27
#[cfg_attr(sleep_ext1_version = "1", path = "ext1_v1.rs")]
28
#[cfg_attr(sleep_ext1_version = "2", path = "ext1_v2.rs")]
29
#[cfg_attr(sleep_ext1_version = "3", path = "ext1_v3.rs")]
30
#[cfg_attr(not(sleep_ext1_version_is_set), path = "per_pin.rs")]
31
mod path;
32

            
33
use portable_atomic::Ordering;
34

            
35
// The pad function is selected only on the chips that have a low-power IO MUX.
36
#[cfg(sleep_ext1_version_is_set)]
37
use crate::gpio::lp_io::LpFunction;
38
use crate::{
39
    gpio::{
40
        AnyPin,
41
        Event,
42
        GpioBank,
43
        Level,
44
        Pin,
45
        WakeConfigError,
46
        low_level::PadMask,
47
        lp_io::low_level,
48
    },
49
    peripherals::GPIO,
50
    rtc_cntl::{
51
        WakeupSource,
52
        sleep::{SleepResource, WrappedSleepConfig},
53
    },
54
};
55

            
56
/// Configures whether a pin can wake the chip from sleep.
57
///
58
/// The wake condition is the interrupt trigger of the pin, which
59
/// [`listen`][crate::gpio::Input::listen] and the `wait_for` family set. **A pin that does not
60
/// listen is not a wakeup source.** A pin that listens wakes the chip from light sleep through the
61
/// digital path, and needs no configuration for that.
62
///
63
/// # Hold the pad at the level that does not wake the chip
64
///
65
/// A pad that is already at its wake level when the sleep starts ends the sleep immediately. The
66
/// configuration of the pin must hold the pad at the other level. Sleep keeps the pull resistors
67
/// that the pin is configured with, and adds no resistor of its own. A pin with
68
/// [`Pull::None`][crate::gpio::Pull::None] and no external resistor therefore floats during the
69
/// sleep, and a floating pad wakes the chip immediately and every time.
70
///
71
/// A level-triggered wake pin needs a pull against the level that wakes the chip, or an external
72
/// resistor. For a pin that wakes the chip on a low level, use an external pull-up.
73
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, procmacros::BuilderLite)]
74
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
75
#[non_exhaustive]
76
#[instability::unstable]
77
pub struct WakeupConfig {
78
    /// Lets the pin wake the chip while the high-performance GPIO peripheral is powered down.
79
    ///
80
    /// Deep sleep needs this path, and so does a light sleep that powers the peripheral down. Only
81
    /// low-power pads have such a path.
82
    ///
83
    /// Sleep entry configures the pad as the low-power path requires, and keeps the pull resistors
84
    /// of the pin in both cases. Before a deep sleep it also holds the pad, because deep sleep
85
    /// powers down the circuit that drives it. A light sleep returns the pad to the digital GPIO
86
    /// peripheral when it ends. After a deep sleep, the boot releases the hold.
87
    low_power_path: bool,
88
}
89

            
90
/// The pads that can wake the chip through a low-power path.
91
///
92
/// Hardware records the digital path, in the wakeup-enable bit of the pad. No low-power register
93
/// records the request alone, because every such register also arms a level, and esp32h2 has no
94
/// per-pin low-power register. This record is therefore in software. It does not have to survive a
95
/// deep sleep, because that wake resets the chip, and a program starts with no wakeup sources.
96
static LOW_POWER_PADS: PadMask = PadMask::new();
97

            
98
/// The pads that sleep entry prepared, and that the exit hook must return to their driver.
99
///
100
/// A sleep that ends without a reset has to undo the preparation. A light sleep is such a sleep,
101
/// and so is a deep sleep that the hardware rejects.
102
static PREPARED_PADS: PadMask = PadMask::new();
103

            
104
/// The pads that ended the last sleep.
105
///
106
/// Each path reports through a status that other code clears or overwrites later. The digital path
107
/// has no status of its own, only the interrupt of the pin, which the interrupt handler of the pin
108
/// clears. A low-power path keeps its status until the next sleep arms the path again.
109
/// [`record_wakeup`] therefore reads all the statuses when the sleep ends, and [`caused_wakeup`]
110
/// reads only this record.
111
static WOKEN_PADS: PadMask = PadMask::new();
112

            
113
for_each_gpio! {
114
    (all $( ($n:literal, $gpio:ident $_ins:tt $_outs:tt $_attrs:tt) ),*) => {
115
        /// The highest pin number plus one, which is the length of the pad tables.
116
        const PAD_COUNT: usize = {
117
            let mut highest = 0;
118
            $( if $n > highest { highest = $n; } )*
119
            highest + 1
120
        };
121
    };
122
}
123

            
124
/// Marks a pad that the low-power registers do not reach, in [`LP_NUMBERS`].
125
const NO_LP_NUMBER: u8 = u8::MAX;
126

            
127
for_each_lp_function! {
128
    (LP_GPIOn $( (($_sig:ident, LP_GPIOn, $lp:literal), $gpio:ident, $_af:ident, $_in:tt $_out:tt) ),*) => {
129
        /// The number that the low-power registers use for each pad that they reach.
130
        ///
131
        /// The two domains number the pads separately, and only some chips give a pad the same
132
        /// number in both domains. A low-power register therefore takes the number from this table,
133
        /// and never the pin number.
134
        const LP_NUMBERS: [u8; PAD_COUNT] = {
135
            let mut numbers = [NO_LP_NUMBER; PAD_COUNT];
136
            $( numbers[crate::peripherals::$gpio::NUMBER as usize] = $lp; )*
137
            numbers
138
        };
139
    };
140
}
141

            
142
/// The number of low-power pads. Every one of them can be armed at the same time.
143
const MAX_ARMED: usize = {
144
    let mut count = 0;
145
    let mut pad = 0;
146
    while pad < PAD_COUNT {
147
        if LP_NUMBERS[pad] != NO_LP_NUMBER {
148
            count += 1;
149
        }
150
        pad += 1;
151
    }
152
    count
153
};
154

            
155
/// A listening pin, and the level that wakes the chip.
156
#[derive(Debug, Clone, Copy)]
157
struct Armed {
158
    /// The digital pin number.
159
    gpio: u8,
160
    /// The number that the low-power registers use for the pad.
161
    lp: u8,
162
    level: Level,
163
}
164

            
165
impl Armed {
166
    const NONE: Self = Self {
167
        gpio: 0,
168
        lp: 0,
169
        level: Level::Low,
170
    };
171
}
172

            
173
/// Applies a pin's wakeup configuration.
174
pub(crate) fn apply_config(pin: &AnyPin<'_>, config: &WakeupConfig) -> Result<(), WakeConfigError> {
175
    if config.low_power_path {
176
        if lp_number(pin.number()).is_none() {
177
            return Err(WakeConfigError::NoLowPowerPath);
178
        }
179

            
180
        LOW_POWER_PADS.set(pin.number(), true);
181
        enable();
182
    } else {
183
        LOW_POWER_PADS.set(pin.number(), false);
184
    }
185

            
186
    Ok(())
187
}
188

            
189
/// Returns whether this pad ended the last sleep.
190
pub(crate) fn caused_wakeup(pin: &AnyPin<'_>) -> bool {
191
    WOKEN_PADS.contains(pin.number())
192
}
193

            
194
/// Copies the pads that ended the sleep from the path statuses into [`WOKEN_PADS`].
195
///
196
/// A sleep ends in one of two places: at the end of a light sleep, and in the sleep initialization
197
/// of a boot after a deep sleep. Both places call this function, and they call it after every
198
/// sleep, so that the record does not describe an earlier sleep. The boot calls it before it
199
/// releases the pads that the previous run armed, because that release also clears the `ext1`
200
/// selection.
201
#[crate::ram]
202
325
pub(crate) fn record_wakeup() {
203
    let cause = crate::rtc_cntl::wakeup_cause();
204

            
205
    for bank in GpioBank::ALL {
206
        // The digital path reports only through the interrupt of the pin. The interrupt status is
207
        // still set here, unless an interrupt handler ran first. A handler can only run first if
208
        // interrupts were enabled during the light sleep.
209
        let digital = if cause.contains(WakeupSource::Gpio) {
210
            bank.read_interrupt_status() & bank.listening().load(Ordering::Relaxed)
211
        } else {
212
            0
213
        };
214

            
215
        WOKEN_PADS.word(bank).store(digital, Ordering::Relaxed);
216
    }
217

            
218
    for (gpio, &lp) in LP_NUMBERS.iter().enumerate() {
219
        if lp != NO_LP_NUMBER && path::caused_wakeup(gpio as u8, cause) {
220
            WOKEN_PADS.set(gpio as u8, true);
221
        }
222
    }
223
325
}
224

            
225
/// Records that a pad can wake the chip, and registers the hooks that allocate the paths.
226
///
227
/// The mask bit alone does not wake the chip. A wake also needs the per-pin digital bit that
228
/// `listen` writes, or a low-power path that the entry hook assigns. If no pin can wake the chip,
229
/// the entry hook clears the mask bit again. A sleep with no other wakeup source is then refused,
230
/// instead of never ending.
231
pub(crate) fn enable() {
232
    WakeupSource::Gpio.enable_with_hooks(Some(entry_hook), Some(exit_hook));
233
}
234

            
235
fn disable() {
236
    WakeupSource::Gpio.disable();
237

            
238
    // Without this, a bit that a path of this chip still holds outlives the hook that clears it,
239
    // and the chip keeps a wakeup source that nobody requested.
240
    path::disable();
241
}
242

            
243
/// Returns the number that the low-power registers use for `gpio`, or `None` if they do not reach
244
/// the pad.
245
fn lp_number(gpio: u8) -> Option<u8> {
246
    match LP_NUMBERS[gpio as usize] {
247
        NO_LP_NUMBER => None,
248
        lp => Some(lp),
249
    }
250
}
251

            
252
/// Returns every pad that the low-power registers reach, as a pin number and a low-power number.
253
fn low_power_pads() -> impl Iterator<Item = (u8, u8)> {
254
    LP_NUMBERS
255
        .iter()
256
        .copied()
257
        .enumerate()
258
        .filter(|&(_, lp)| lp != NO_LP_NUMBER)
259
        .map(|(gpio, lp)| (gpio as u8, lp))
260
}
261

            
262
/// Returns the low-power number of every pad that the low-power registers reach.
263
#[cfg(not(sleep_ext1_version = "3"))]
264
fn low_power_numbers() -> impl Iterator<Item = u8> {
265
    low_power_pads().map(|(_, lp)| lp)
266
}
267

            
268
/// Returns whether a wakeup source that configures pads is enabled.
269
///
270
/// Call this before the initialization clears the mask. The result tells the initialization whether
271
/// it must release the pads that the previous run armed. ESP-IDF uses the same condition for
272
/// `esp_deep_sleep_wakeup_io_reset`.
273
pub(crate) fn wake_enabled() -> bool {
274
    let sources = crate::rtc_cntl::sleep::enabled_sources();
275

            
276
    #[allow(unused_mut)]
277
    let mut enabled = sources.contains(WakeupSource::Gpio);
278

            
279
    #[cfg(sleep_has_wakeup_source_ext0)]
280
    {
281
        enabled |= sources.contains(WakeupSource::Ext0);
282
    }
283
    #[cfg(sleep_has_wakeup_source_ext1)]
284
    {
285
        enabled |= sources.contains(WakeupSource::Ext1);
286
    }
287

            
288
    enabled
289
}
290

            
291
/// Releases the pads that the previous run armed for a deep sleep.
292
///
293
/// A deep sleep holds its wake pads, because it powers down the circuit that drives them. The wake
294
/// resets the chip, but it does not release the hold: the hold register is in the always-on domain.
295
/// A held pad would ignore its driver for the rest of the program, so the boot releases it.
296
///
297
/// The function releases the hold, and changes nothing else. A change of a pad function can take a
298
/// pad from a low-power core, which keeps its pads while it runs.
299
pub(crate) fn wake_io_reset() {
300
    path::wake_io_reset();
301
}
302

            
303
/// Records that sleep entry took the hold of a pad, so that the exit hook releases it.
304
#[cfg(not(sleep_ext1_version_is_set))]
305
fn hold_taken(gpio: u8) {
306
    PREPARED_PADS.set(gpio, true);
307
}
308

            
309
/// Assigns the listening pins to the hardware paths, and requests the power domains that they need.
310
#[crate::ram]
311
fn entry_hook(config: &mut WrappedSleepConfig<'_>) {
312
    let mut buffer = [Armed::NONE; MAX_ARMED];
313
    let (armed, mut digital) = collect(&mut buffer);
314

            
315
    // Deep sleep powers the high-performance GPIO peripheral down. The digital path then cannot
316
    // wake the chip, whatever number of pins listen.
317
    digital &= !config.is_deep_sleep();
318

            
319
    if armed.is_empty() && !digital {
320
        // No pad can wake the chip, so the record must go. A mask that still claims a GPIO wakeup
321
        // source lets a sleep start that no other source can end.
322
        disable();
323
        return;
324
    }
325

            
326
    if digital {
327
        // The digital path reads the pad through the high-performance GPIO peripheral.
328
        config.keep_alive(SleepResource::HpPeripherals);
329
    }
330

            
331
    path::allocate(armed, config);
332
}
333

            
334
/// Returns the pads to the digital GPIO peripheral after a sleep that did not reset the chip.
335
///
336
/// A light sleep is such a sleep, and so is a deep sleep that the hardware rejects. The hooks of a
337
/// rejected deep sleep run in the same place, because sleep entry prepared the same pads.
338
#[crate::ram]
339
fn exit_hook() {
340
    for bank in GpioBank::ALL {
341
        let mut prepared = PREPARED_PADS.word(bank).swap(0, Ordering::Relaxed);
342

            
343
        while prepared != 0 {
344
            let pin = prepared.trailing_zeros();
345
            prepared &= !(1 << pin);
346

            
347
            let Some(lp) = lp_number(bank.offset() + pin as u8) else {
348
                continue;
349
            };
350

            
351
            low_level::pad_hold(lp, false);
352

            
353
            // Only a chip with a low-power IO MUX moved the pad, so only such a chip has to move it
354
            // back. esp32c2 and esp32c3 keep the pad on the digital IO MUX.
355
            #[cfg(sleep_ext1_version_is_set)]
356
            low_level::set_config(lp, true, false, LpFunction::LP_GPIO);
357
        }
358
    }
359
}
360

            
361
/// Collects the listening pins that requested a low-power path, and returns whether any pin
362
/// listens.
363
///
364
/// Every listening pin can end a light sleep, so the record of the listening pins gives both
365
/// results. Neither result needs a read of the pin registers.
366
fn collect(buffer: &mut [Armed; MAX_ARMED]) -> (&[Armed], bool) {
367
    let mut count = 0;
368
    let mut digital = false;
369

            
370
    for bank in GpioBank::ALL {
371
        let listening = bank.listening().load(Ordering::Relaxed);
372
        digital |= listening != 0;
373

            
374
        let mut participants = listening & LOW_POWER_PADS.word(bank).load(Ordering::Relaxed);
375
        while participants != 0 {
376
            let pin = participants.trailing_zeros();
377
            participants &= !(1 << pin);
378

            
379
            // Only a pad that the low-power registers reach enters the mask, so it has a number.
380
            let gpio = bank.offset() + pin as u8;
381
            let Some(lp) = lp_number(gpio) else { continue };
382

            
383
            if let Some(level) = armed_level(gpio) {
384
                buffer[count] = Armed { gpio, lp, level };
385
                count += 1;
386
            }
387
        }
388
    }
389

            
390
    (&buffer[..count], digital)
391
}
392

            
393
/// Returns the level that wakes the chip through this pad, or `None` if the trigger sets no level.
394
///
395
/// The wake paths accept a level only, so an edge trigger becomes the level at the end of the edge.
396
/// This keeps the configured request. `AnyEdge` ends at the level that the pin is not at now,
397
/// which is the meaning of "wake when the pin changes". This read of the pin can race with the pin,
398
/// but the result is safe. If the pin changes before the sleep starts, the path arms a level that
399
/// is already present, and the sleep is rejected or ends immediately.
400
fn armed_level(gpio: u8) -> Option<Level> {
401
    let trigger = GPIO::regs().pin(gpio as usize).read().int_type().bits();
402
    Some(
403
        if trigger == Event::HighLevel as u8 || trigger == Event::RisingEdge as u8 {
404
            Level::High
405
        } else if trigger == Event::LowLevel as u8 || trigger == Event::FallingEdge as u8 {
406
            Level::Low
407
        } else if trigger == Event::AnyEdge as u8 {
408
            !Level::from(unsafe { AnyPin::steal(gpio) }.is_input_high())
409
        } else {
410
            return None;
411
        },
412
    )
413
}
414

            
415
/// Moves the pad to the low-power IO MUX, which makes it readable while the high-performance GPIO
416
/// peripheral is powered down.
417
///
418
/// Before a deep sleep this function also holds the pad, because deep sleep powers down the circuit
419
/// that drives it. A light sleep does not hold the pad. A light sleep powers down no circuit that
420
/// drives the pad, and a hold would freeze an output.
421
#[cfg(sleep_ext1_version_is_set)]
422
fn prepare_pad(pin: &Armed, deep: bool) {
423
    // The low-power IO MUX has its own pull resistors, and the digital ones stop to work as soon as
424
    // the low-power IO MUX takes the pad. Copy the resistors, or an undriven pad floats away from
425
    // the level that the user selected, and wakes the chip immediately.
426
    #[cfg(not(esp32h2))]
427
    {
428
        let digital = crate::gpio::io_mux_reg(pin.gpio).read();
429
        low_level::pullup_enable(pin.lp, digital.fun_wpu().bit());
430
        low_level::pulldown_enable(pin.lp, digital.fun_wpd().bit());
431
    }
432

            
433
    // esp32h2 reaches the pad through the digital IO MUX, so it has no low-power MUX to select.
434
    low_level::set_config(pin.lp, true, !cfg!(esp32h2), LpFunction::LP_GPIO);
435
    low_level::pad_hold(pin.lp, deep);
436

            
437
    PREPARED_PADS.set(pin.gpio, true);
438
}
439

            
440
/// Disconnects the pads that no hold keeps, so that a powered-down output driver does not increase
441
/// the deep-sleep current.
442
///
443
/// No wakeup source controls this step, so every deep sleep does it, like
444
/// `esp_sleep_isolate_digital_gpio` in ESP-IDF. The step is destructive, because a pad loses the
445
/// peripheral function that drove it. It therefore runs at sleep entry, on the chips that cannot
446
/// hold a single pad through a deep sleep, and after the wakeup sources take the holds that they
447
/// need.
448
#[cfg(all(sleep_deep_sleep_needs_gpio_isolation, feature = "rt"))]
449
pub(crate) fn isolate_pads_for_deep_sleep() {
450
    use crate::{
451
        gpio::{AlternateFunction, OutputSignal, io_mux_reg},
452
        peripherals::LPWR,
453
    };
454

            
455
    // If the hold is disabled, no pad keeps its level through the sleep. ESP-IDF also skips the
456
    // isolation in that case.
457
    let dig_iso = LPWR::regs().dig_iso().read();
458
    let hold_enabled = !dig_iso.dg_pad_force_unhold().bit() && dig_iso.dg_pad_autohold_en().bit();
459
    if !hold_enabled {
460
        return;
461
    }
462
    for gpio in 0..PAD_COUNT as u8 {
463
        // Only the pads that the digital supply feeds leak current, and those are the pads with no
464
        // low-power number. The low-power pads have their own supply, which stays powered, and a
465
        // wake pad is always a low-power pad.
466
        if lp_number(gpio).is_some() {
467
            continue;
468
        }
469

            
470
        // A pad that the user holds keeps its level, which is the purpose of the hold. Isolation
471
        // would cancel that request.
472
        if crate::gpio::lp_io::low_level::is_digital_pad_held(gpio) {
473
            continue;
474
        }
475

            
476
        GPIO::regs()
477
            .func_out_sel_cfg(gpio as usize)
478
            .modify(|_, w| unsafe { w.bits(OutputSignal::GPIO as u32) });
479

            
480
        io_mux_reg(gpio).modify(|_, w| unsafe {
481
            w.fun_wpu().clear_bit();
482
            w.fun_wpd().clear_bit();
483
            w.fun_ie().clear_bit();
484
            // A pad that keeps a peripheral function increases the deep-sleep current.
485
            w.mcu_sel().bits(AlternateFunction::GPIO as u8)
486
        });
487
    }
488
}
489

            
490
/// Isolates digital pads when a power domain that feeds them is powered down.
491
///
492
/// ESP-IDF does this when `SOC_GPIO_NEED_SOFT_ISOLATE_DURING_PD` is set. The chip can still hold a
493
/// single pad, so a held pad is left alone. The pad list comes from `for_each_gpio_soft_isolate`,
494
/// which already omits low-power pads and the flash or PSRAM interface.
495
#[cfg(gpio_need_soft_isolate_during_pd)]
496
pub(crate) fn isolate_pads_for_deep_sleep() {
497
    for_each_gpio_soft_isolate! {
498
        ($n:literal) => {
499
            isolate_soft_isolate_pad($n);
500
        };
501
    }
502
}
503

            
504
/// Disconnects one digital pad so that a powered-down driver does not increase the sleep current.
505
#[cfg(gpio_need_soft_isolate_during_pd)]
506
fn isolate_soft_isolate_pad(gpio: u8) {
507
    use crate::gpio::{AlternateFunction, io_mux_reg, low_level};
508

            
509
    if crate::gpio::lp_io::low_level::is_digital_pad_held(gpio) {
510
        return;
511
    }
512

            
513
    io_mux_reg(gpio).modify(|_, w| unsafe {
514
        w.fun_wpu().clear_bit();
515
        w.fun_wpd().clear_bit();
516
        w.fun_ie().clear_bit();
517
        w.mcu_sel().bits(AlternateFunction::GPIO as u8)
518
    });
519

            
520
    let bank = low_level::bank(gpio);
521
    bank.write_out_en_clear(1 << (gpio - bank.offset()));
522
}