Skip to content

Commit c17644a

Browse files
committed
feat(gpio): add IO hold support for Deep-sleep for ESP32-P4 ECO5
1 parent 8948bf6 commit c17644a

File tree

37 files changed

+117
-147
lines changed

37 files changed

+117
-147
lines changed

components/esp_driver_gpio/include/driver/gpio.h

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -419,23 +419,25 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t *stren
419419
* signal or the IO MUX/GPIO configuration is modified (including input enable, output enable, output value,
420420
* function, and drive strength values). This function can be used to retain the state of GPIOs when the power
421421
* domain of where GPIO/IOMUX belongs to becomes off. For example, chip or system is reset (e.g. watchdog
422-
* time-out, deep-sleep events are triggered), or peripheral power-down in light-sleep.
422+
* time-out, Deep-sleep events are triggered), or peripheral power-down in Light-sleep.
423423
*
424424
* This function works in both input and output modes, and only applicable to output-capable GPIOs.
425425
* If this function is enabled:
426426
* in output mode: the output level of the GPIO will be locked and can not be changed.
427427
* in input mode: the input read value can still reflect the changes of the input signal.
428428
*
429+
* Power down or call `gpio_hold_dis` will disable this function.
430+
*
429431
* Please be aware that,
430432
*
431-
* On ESP32P4, the states of IOs can not be hold after waking up from Deep-sleep.
433+
* 1. USB pads cannot hold at low level after waking up from Deep-sleep. The USB related registers are reset, so the USB pull-up is back.
434+
*
435+
* 2. For ESP32-P4 rev < 3.0, the states of IOs can not be hold after waking up from Deep-sleep.
432436
*
433-
* Additionally, on ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep.
437+
* 3. For ESP32/S2/C3/S3/C2, this function cannot be used to hold the state of a digital GPIO during Deep-sleep.
434438
* Even if this function is enabled, the digital GPIO will be reset to its default state when the chip wakes up from
435439
* Deep-sleep. If you want to hold the state of a digital GPIO during Deep-sleep, please call `gpio_deep_sleep_hold_en`.
436440
*
437-
* Power down or call `gpio_hold_dis` will disable this function.
438-
*
439441
* @param gpio_num GPIO number, only support output-capable GPIOs
440442
*
441443
* @return
@@ -463,7 +465,7 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num);
463465
*/
464466
esp_err_t gpio_hold_dis(gpio_num_t gpio_num);
465467

466-
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
468+
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
467469
/**
468470
* @brief Enable all digital gpio pads hold function during Deep-sleep.
469471
*
@@ -487,7 +489,7 @@ void gpio_deep_sleep_hold_en(void);
487489
* @brief Disable all digital gpio pads hold function during Deep-sleep.
488490
*/
489491
void gpio_deep_sleep_hold_dis(void);
490-
#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
492+
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
491493

492494
#if SOC_GPIO_SUPPORT_FORCE_HOLD
493495
/**

components/esp_driver_gpio/src/gpio.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@
88
#include "esp_err.h"
99
#include "freertos/FreeRTOS.h"
1010
#include "esp_heap_caps.h"
11+
#include "sdkconfig.h"
1112
#include "driver/gpio.h"
1213
#include "driver/rtc_io.h"
1314
#include "soc/interrupts.h"
1415
#if !CONFIG_FREERTOS_UNICORE
1516
#include "esp_ipc.h"
1617
#endif
17-
1818
#include "soc/soc_caps.h"
1919
#include "soc/gpio_periph.h"
2020
#include "esp_log.h"
@@ -775,7 +775,7 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num)
775775
return ret;
776776
}
777777

778-
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
778+
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
779779
void gpio_deep_sleep_hold_en(void)
780780
{
781781
portENTER_CRITICAL(&gpio_context.gpio_spinlock);
@@ -789,7 +789,7 @@ void gpio_deep_sleep_hold_dis(void)
789789
gpio_hal_deep_sleep_hold_dis(gpio_context.gpio_hal);
790790
portEXIT_CRITICAL(&gpio_context.gpio_spinlock);
791791
}
792-
#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
792+
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
793793

794794
#if SOC_GPIO_SUPPORT_FORCE_HOLD
795795
esp_err_t IRAM_ATTR gpio_force_hold_all()

components/esp_driver_gpio/test_apps/gpio/main/test_gpio.c

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,7 @@ TEST_CASE("GPIO_light_sleep_wake_up_test", "[gpio][ignore]")
884884
}
885885
#endif
886886

887-
#if SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP
887+
#if SOC_DEEP_SLEEP_SUPPORTED
888888
// Pick one digital IO for each target to test is enough
889889
static void gpio_deep_sleep_hold_test_first_stage(void)
890890
{
@@ -902,7 +902,9 @@ static void gpio_deep_sleep_hold_test_first_stage(void)
902902
.pull_up_en = GPIO_PULLUP_DISABLE,
903903
};
904904
TEST_ESP_OK(gpio_config(&io_conf));
905-
TEST_ESP_OK(gpio_set_level(io_num, 0));
905+
906+
const bool initial_level = gpio_get_level(io_num);
907+
TEST_ESP_OK(gpio_set_level(io_num, !initial_level));
906908

907909
// Enable global persistence
908910
TEST_ESP_OK(gpio_hold_en(io_num));
@@ -911,6 +913,10 @@ static void gpio_deep_sleep_hold_test_first_stage(void)
911913
// Extra step is required, so that all digital IOs can automatically get held when entering Deep-sleep
912914
gpio_deep_sleep_hold_en();
913915
#endif
916+
vTaskDelay(pdMS_TO_TICKS(200));
917+
TEST_ESP_OK(gpio_set_level(io_num, initial_level));
918+
TEST_ASSERT_EQUAL_INT(!initial_level, gpio_get_level(io_num));
919+
vTaskDelay(pdMS_TO_TICKS(200));
914920

915921
esp_deep_sleep_start();
916922
}
@@ -921,16 +927,31 @@ static void gpio_deep_sleep_hold_test_second_stage(void)
921927
// Check reset reason is waking up from deepsleep
922928
TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
923929

924-
// Pin should stay at low level after the deep sleep
925-
TEST_ASSERT_EQUAL_INT(0, gpio_get_level(io_num));
930+
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399
931+
bool level = gpio_get_level(io_num);
926932
// Set level should not take effect since hold is still active (and the INPUT_OUTPUT mode should still be held)
927-
TEST_ESP_OK(gpio_set_level(io_num, 1));
928-
TEST_ASSERT_EQUAL_INT(0, gpio_get_level(io_num));
933+
TEST_ESP_OK(gpio_set_level(io_num, !level));
934+
TEST_ASSERT_EQUAL_INT(level, gpio_get_level(io_num));
935+
#endif
929936

930937
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
931938
gpio_deep_sleep_hold_dis();
932939
#endif
933940
TEST_ESP_OK(gpio_hold_dis(io_num));
941+
942+
gpio_config_t io_conf = {
943+
.intr_type = GPIO_INTR_DISABLE,
944+
.mode = GPIO_MODE_INPUT_OUTPUT,
945+
.pin_bit_mask = (1ULL << io_num),
946+
.pull_down_en = GPIO_PULLDOWN_DISABLE,
947+
.pull_up_en = GPIO_PULLUP_DISABLE,
948+
};
949+
TEST_ESP_OK(gpio_config(&io_conf));
950+
951+
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399
952+
// Check that the hold level after wakeup is the level before entering deep sleep
953+
TEST_ASSERT_EQUAL_INT(!level, gpio_get_level(io_num));
954+
#endif
934955
}
935956

936957
/*
@@ -942,4 +963,4 @@ static void gpio_deep_sleep_hold_test_second_stage(void)
942963
TEST_CASE_MULTIPLE_STAGES("GPIO_deep_sleep_output_hold_test", "[gpio]",
943964
gpio_deep_sleep_hold_test_first_stage,
944965
gpio_deep_sleep_hold_test_second_stage)
945-
#endif // SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP
966+
#endif // SOC_DEEP_SLEEP_SUPPORTED

components/esp_driver_gpio/test_apps/gpio/main/test_gpio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ extern "C" {
3939
#define TEST_GPIO_EXT_IN_IO (3)
4040
#define TEST_GPIO_INPUT_LEVEL_LOW_PIN (1)
4141
#define TEST_GPIO_SIGNAL_IDX (SIG_IN_FUNC250_IDX)
42+
#define TEST_GPIO_DEEP_SLEEP_HOLD_PIN (28)
4243
#elif CONFIG_IDF_TARGET_ESP32H2
4344
#define TEST_GPIO_EXT_OUT_IO (2)
4445
#define TEST_GPIO_EXT_IN_IO (3)

components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ TEST_CASE("RTCIO_interrupt_test", "[rtcio]")
278278
#endif //SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP && (SOC_RTCIO_PIN_COUNT > 0)
279279
#endif //SOC_RTCIO_INPUT_OUTPUT_SUPPORTED
280280

281-
#if SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP
281+
#if SOC_DEEP_SLEEP_SUPPORTED
282282
// It is not necessary to test every rtcio pin, it will take too much ci testing time for deep sleep
283283
// Only tests on s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX] pin
284284
// The default configuration of these pads is low level
@@ -311,8 +311,10 @@ static void rtcio_deep_sleep_hold_test_second_stage(void)
311311
int io_num = s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX];
312312
// Check reset reason is waking up from deepsleep
313313
TEST_ASSERT_EQUAL(ESP_RST_DEEPSLEEP, esp_reset_reason());
314+
#if !CONFIG_ESP32P4_SELECTS_REV_LESS_V3 // DIG-399
314315
// Pin should stay at high level after the deep sleep
315316
TEST_ASSERT_EQUAL_INT(1, gpio_get_level(io_num));
317+
#endif
316318

317319
gpio_hold_dis(io_num);
318320
}
@@ -326,4 +328,4 @@ static void rtcio_deep_sleep_hold_test_second_stage(void)
326328
TEST_CASE_MULTIPLE_STAGES("RTCIO_deep_sleep_output_hold_test", "[rtcio]",
327329
rtcio_deep_sleep_hold_test_first_stage,
328330
rtcio_deep_sleep_hold_test_second_stage)
329-
#endif // SOC_DEEP_SLEEP_SUPPORTED && SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP
331+
#endif // SOC_DEEP_SLEEP_SUPPORTED

components/esp_driver_gpio/test_apps/gpio/main/test_rtcio.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = {
162162
GPIO_NUM_15, //GPIO15
163163
};
164164
#define TEST_RTCIO_INTR_PIN_INDEX 2 // IO2
165+
#define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5 // IO5
165166
#elif CONFIG_IDF_TARGET_ESP32C61 || CONFIG_IDF_TARGET_ESP32C5
166167
// Has no input-only rtcio pins, all pins support pull-up/down
167168
#define RTCIO_SUPPORT_PU_PD(num) 1

components/esp_hw_support/include/esp_private/esp_sleep_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ esp_err_t esp_sleep_acquire_lp_use_xtal(void);
9797
esp_err_t esp_sleep_release_lp_use_xtal(void);
9898
#endif
9999

100-
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
100+
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
101101
/**
102102
* @brief Isolate all digital IOs except those that are held during deep sleep
103103
*

components/esp_hw_support/port/esp32p4/private_include/pmu_param.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <esp_types.h>
1212
#include "soc/pmu_struct.h"
1313
#include "hal/pmu_hal.h"
14+
#include "sdkconfig.h"
1415

1516
#ifdef __cplusplus
1617
extern "C" {
@@ -330,6 +331,7 @@ typedef struct {
330331
} pmu_sleep_digital_config_t;
331332

332333

334+
#if CONFIG_ESP32P4_SELECTS_REV_LESS_V3
333335
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
334336
.syscntl = { \
335337
.dig_pad_slp_sel = 0, \
@@ -343,6 +345,19 @@ typedef struct {
343345
.lp_pad_hold_all = (sleep_flags & PMU_SLEEP_PD_LP_PERIPH) ? 1 : 0, \
344346
} \
345347
}
348+
#else // !CONFIG_ESP32P4_SELECTS_REV_LESS_V3
349+
#define PMU_SLEEP_DIGITAL_DSLP_CONFIG_DEFAULT(sleep_flags) { \
350+
.syscntl = { \
351+
.dig_pad_slp_sel = 0, \
352+
} \
353+
}
354+
355+
#define PMU_SLEEP_DIGITAL_LSLP_CONFIG_DEFAULT(sleep_flags) { \
356+
.syscntl = { \
357+
.dig_pad_slp_sel = 0, \
358+
} \
359+
}
360+
#endif
346361

347362
typedef struct {
348363
struct {

components/esp_hw_support/sleep_gpio.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ void esp_sleep_enable_gpio_switch(bool enable)
170170
}
171171
}
172172

173-
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
173+
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
174174
IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
175175
{
176176
gpio_hal_context_t gpio_hal = {
@@ -225,7 +225,7 @@ IRAM_ATTR void esp_sleep_isolate_digital_gpio(void)
225225
}
226226
}
227227
}
228-
#endif //SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
228+
#endif //!SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
229229

230230
#if SOC_DEEP_SLEEP_SUPPORTED
231231
void esp_deep_sleep_wakeup_io_reset(void)

components/esp_hw_support/sleep_modes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,7 @@ static esp_err_t FORCE_IRAM_ATTR esp_sleep_start_safe(uint32_t sleep_flags, uint
907907
}
908908
#endif
909909
if (deep_sleep) {
910-
#if SOC_GPIO_SUPPORT_HOLD_IO_IN_DSLP && !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
910+
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
911911
esp_sleep_isolate_digital_gpio();
912912
#endif
913913

0 commit comments

Comments
 (0)