From 0cdaf0008d826a8eb8051559c24bb506b5d11490 Mon Sep 17 00:00:00 2001 From: Lou Tianhao Date: Fri, 5 Jan 2024 17:21:13 +0800 Subject: [PATCH] feat(pm): add test_io_wakeup --- .../test_apps/.build-test-rules.yml | 4 + .../test_apps/wakeup_tests/CMakeLists.txt | 13 + .../test_apps/wakeup_tests/README.md | 2 + .../wakeup_tests/main/CMakeLists.txt | 12 + .../wakeup_tests/main/include/io_wakeup_cmd.h | 17 + .../wakeup_tests/main/src/io_wakeup_cmd.c | 358 ++++++++++++++++++ .../wakeup_tests/main/test_app_main.c | 52 +++ .../wakeup_tests/pytest_wakeup_tests.py | 174 +++++++++ .../wakeup_tests/sdkconfig.ci.default | 3 + .../test_apps/wakeup_tests/sdkconfig.defaults | 2 + components/esp_pm/pm_impl.c | 2 +- .../esp_system_unity_tests/main/test_sleep.c | 94 +---- 12 files changed, 639 insertions(+), 94 deletions(-) create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/CMakeLists.txt create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/README.md create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/main/CMakeLists.txt create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/main/include/io_wakeup_cmd.h create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/main/test_app_main.c create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.ci.default create mode 100644 components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.defaults diff --git a/components/esp_hw_support/test_apps/.build-test-rules.yml b/components/esp_hw_support/test_apps/.build-test-rules.yml index dcb1f22d88..206557ba4d 100644 --- a/components/esp_hw_support/test_apps/.build-test-rules.yml +++ b/components/esp_hw_support/test_apps/.build-test-rules.yml @@ -41,3 +41,7 @@ components/esp_hw_support/test_apps/rtc_power_modes: - if: IDF_TARGET in ["esp32s2", "esp32s3", "esp32c2", "esp32c3"] temporary: true reason: the other targets are not tested yet + +components/esp_hw_support/test_apps/wakeup_tests: + disable: + - if: IDF_TARGET in ["esp32c5", "esp32p4", "linux"] diff --git a/components/esp_hw_support/test_apps/wakeup_tests/CMakeLists.txt b/components/esp_hw_support/test_apps/wakeup_tests/CMakeLists.txt new file mode 100644 index 0000000000..703608f645 --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/CMakeLists.txt @@ -0,0 +1,13 @@ +# The following lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) + +list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" "sdkconfig.defaults") + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) +set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components") + +project(wakeup_tests) diff --git a/components/esp_hw_support/test_apps/wakeup_tests/README.md b/components/esp_hw_support/test_apps/wakeup_tests/README.md new file mode 100644 index 0000000000..a8b7833fa3 --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/README.md @@ -0,0 +1,2 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | diff --git a/components/esp_hw_support/test_apps/wakeup_tests/main/CMakeLists.txt b/components/esp_hw_support/test_apps/wakeup_tests/main/CMakeLists.txt new file mode 100644 index 0000000000..dc2dfd74e7 --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/main/CMakeLists.txt @@ -0,0 +1,12 @@ +set(srcs "test_app_main.c" + "src/io_wakeup_cmd.c") + +set(include "." + "include") + +# In order for the cases defined by `TEST_CASE` to be linked into the final elf, +# the component can be registered as WHOLE_ARCHIVE +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS include + REQUIRES unity esp_driver_gpio console test_utils efuse + WHOLE_ARCHIVE) diff --git a/components/esp_hw_support/test_apps/wakeup_tests/main/include/io_wakeup_cmd.h b/components/esp_hw_support/test_apps/wakeup_tests/main/include/io_wakeup_cmd.h new file mode 100644 index 0000000000..5f6e0966b1 --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/main/include/io_wakeup_cmd.h @@ -0,0 +1,17 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void register_io_wakeup_cmd(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c b/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c new file mode 100644 index 0000000000..c327f00011 --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/main/src/io_wakeup_cmd.c @@ -0,0 +1,358 @@ +/* + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ + +#include "unity.h" +#include "unity_test_utils.h" +#include "test_utils.h" +#include "esp_sleep.h" +#include "driver/rtc_io.h" +#include "driver/gpio.h" +#include "esp_console.h" +#include "linenoise/linenoise.h" +#include "argtable3/argtable3.h" +#include "esp_log.h" + +static const char* TAG = "io_wakeup_test"; + +typedef enum { + IO_WAKEUP_LEVEL_LOW = 0, + IO_WAKEUP_LEVEL_HIGH, + IO_WAKEUP_LEVEL_MAX, +} io_wakeup_level_t; + +static struct { + struct arg_int *mode; + struct arg_end *end; +} sleep_args; + +static int process_sleep(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &sleep_args); + if (nerrors != 0) { + arg_print_errors(stderr, sleep_args.end, argv[0]); + return 1; + } + + if (sleep_args.mode->count == 1) { + if (sleep_args.mode->ival[0] == 0) { + esp_light_sleep_start(); + ESP_LOGI(TAG, "esp_light_sleep_start"); + } else if (sleep_args.mode->ival[0] == 1) { + esp_deep_sleep_start(); + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + return 0; +} + +static void register_sleep(void) +{ + sleep_args.mode = + arg_int0("m", "mode", "", "configure the sleep mode, 0: light; 1: deep"); + sleep_args.end = arg_end(2); + + const esp_console_cmd_t cmd = { + .command = "sleep", + .help = "select the sleep mode", + .hint = NULL, + .func = &process_sleep, + .argtable = &sleep_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} + +#if SOC_PM_SUPPORT_EXT1_WAKEUP +static struct { + struct arg_int *pin; + struct arg_int *mode; + struct arg_lit *disable; + struct arg_end *end; +} ext1_wakeup_args; + +static int process_ext1_wakeup(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &ext1_wakeup_args); + int io_wakeup_num = 0, io_wakeup_level = 0; + if (nerrors != 0) { + arg_print_errors(stderr, ext1_wakeup_args.end, argv[0]); + return 1; + } + + if (ext1_wakeup_args.pin->count == 1) { + io_wakeup_num = ext1_wakeup_args.pin->ival[0]; + ESP_LOGI(TAG, "io_wakeup_num = %d\n", io_wakeup_num); + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + + if (ext1_wakeup_args.mode->count) { + if (ext1_wakeup_args.mode->count == 1) { + io_wakeup_level = ext1_wakeup_args.mode->ival[0]; + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + } + ESP_LOGI(TAG, "io_wakeup_level = %d\n", io_wakeup_level); + + if (ext1_wakeup_args.disable->count) { + ESP_ERROR_CHECK(esp_sleep_disable_ext1_wakeup_io(1ULL << io_wakeup_num)); + } else { +#if CONFIG_IDF_TARGET_ESP32 + ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup_io(1ULL << io_wakeup_num, io_wakeup_level == 0 ? ESP_EXT1_WAKEUP_ALL_LOW : ESP_EXT1_WAKEUP_ANY_HIGH)); +#else + ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup_io(1ULL << io_wakeup_num, io_wakeup_level == 0 ? ESP_EXT1_WAKEUP_ANY_LOW : ESP_EXT1_WAKEUP_ANY_HIGH)); +#endif + } + return 0; +} + +static void register_ext1_wakeup(void) +{ + ext1_wakeup_args.pin = + arg_int0("p", "pin", "", "configure the ext1 wakeup pin num"); + ext1_wakeup_args.mode = + arg_int0("m", "mode", "", "configure the ext1 wakeup mode"); + ext1_wakeup_args.disable = + arg_lit0("d", "disable", "disable the ext1 wakeup on certain pin"); + ext1_wakeup_args.end = arg_end(4); + + const esp_console_cmd_t cmd = { + .command = "ext1", + .help = "configue ext1 wakeup", + .hint = NULL, + .func = &process_ext1_wakeup, + .argtable = &ext1_wakeup_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} +#endif + +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP +static struct { + struct arg_int *pin; + struct arg_int *level; + struct arg_lit *disable; + struct arg_end *end; +} rtcio_wakeup_args; +static int process_rtcio_wakeup(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &rtcio_wakeup_args); + int io_wakeup_num = 0, io_wakeup_level = 0; + if (nerrors != 0) { + arg_print_errors(stderr, rtcio_wakeup_args.end, argv[0]); + return 1; + } + + if (rtcio_wakeup_args.pin->count == 1) { + io_wakeup_num = rtcio_wakeup_args.pin->ival[0]; + ESP_LOGI(TAG, "io_wakeup_num = %d\n", io_wakeup_num); + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + + if (rtcio_wakeup_args.level->count) { + if (rtcio_wakeup_args.level->count == 1) { + io_wakeup_level = rtcio_wakeup_args.level->ival[0]; + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + } + ESP_LOGI(TAG, "io_wakeup_level = %d\n", io_wakeup_level); + + if (rtcio_wakeup_args.disable->count) { + ESP_ERROR_CHECK(gpio_deep_sleep_wakeup_disable(io_wakeup_num)); + } else { + gpio_config_t config = { + .pin_bit_mask = BIT64(io_wakeup_num), + .mode = GPIO_MODE_INPUT, + .pull_down_en = false, + .pull_up_en = false, + .intr_type = GPIO_INTR_DISABLE + }; + ESP_ERROR_CHECK(gpio_config(&config)); + + /* Enable wake up from GPIO */ + ESP_ERROR_CHECK(esp_deep_sleep_enable_gpio_wakeup(BIT64(io_wakeup_num), io_wakeup_level)); + } + + return 0; +} + +static void register_rtcio_wakeup(void) +{ + rtcio_wakeup_args.pin = + arg_int0("p", "pin", "", "configure the rtcio wakeup pin num"); + rtcio_wakeup_args.level = + arg_int0("l", "level", "", "configure the rtcio wakeup level"); + rtcio_wakeup_args.disable = + arg_lit0("d", "disable", "disable the rtcio wakeup on certain pin"); + rtcio_wakeup_args.end = arg_end(4); + + const esp_console_cmd_t cmd = { + .command = "rtcio", + .help = "configue rtcio wakeup", + .hint = NULL, + .func = &process_rtcio_wakeup, + .argtable = &rtcio_wakeup_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} +#endif + +static struct { + struct arg_int *pin; + struct arg_int *level; + struct arg_lit *disable; + struct arg_end *end; +} gpio_wakeup_args; + +static int process_gpio_wakeup(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &gpio_wakeup_args); + int io_wakeup_num = 0, io_wakeup_level = 0; + if (nerrors != 0) { + arg_print_errors(stderr, gpio_wakeup_args.end, argv[0]); + return 1; + } + + if (gpio_wakeup_args.pin->count == 1) { + io_wakeup_num = gpio_wakeup_args.pin->ival[0]; + ESP_LOGI(TAG, "io_wakeup_num = %d\n", io_wakeup_num); + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + + if (gpio_wakeup_args.level->count) { + if (gpio_wakeup_args.level->count == 1) { + io_wakeup_level = gpio_wakeup_args.level->ival[0]; + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + } + ESP_LOGI(TAG, "io_wakeup_level = %d\n", io_wakeup_level); + + if (gpio_wakeup_args.disable->count) { + ESP_ERROR_CHECK(gpio_wakeup_disable(io_wakeup_num)); + } else { + gpio_config_t config = { + .pin_bit_mask = BIT64(io_wakeup_num), + .mode = GPIO_MODE_INPUT, + .pull_down_en = false, + .pull_up_en = false, + .intr_type = GPIO_INTR_DISABLE + }; + ESP_ERROR_CHECK(gpio_config(&config)); + + /* Enable wake up from GPIO */ + ESP_ERROR_CHECK(gpio_wakeup_enable(io_wakeup_num, io_wakeup_level == 0 ? GPIO_INTR_LOW_LEVEL : GPIO_INTR_HIGH_LEVEL)); + ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup()); + } + + return 0; +} + +static void register_gpio_wakeup(void) +{ + gpio_wakeup_args.pin = + arg_int0("p", "pin", "", "configure the gpio wakeup pin num"); + gpio_wakeup_args.level = + arg_int0("l", "level", "", "configure the gpio wakeup level"); + gpio_wakeup_args.disable = + arg_lit0("d", "disable", "disable the gpio wakeup on certain pin"); + gpio_wakeup_args.end = arg_end(4); + + const esp_console_cmd_t cmd = { + .command = "gpio", + .help = "configue gpio wakeup", + .hint = NULL, + .func = &process_gpio_wakeup, + .argtable = &gpio_wakeup_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} + +static struct { + struct arg_int *pin; + struct arg_int *level; + struct arg_end *end; +} gpio_control_args; + +static int process_gpio_control(int argc, char **argv) +{ + int nerrors = arg_parse(argc, argv, (void **) &gpio_control_args); + int io_num = 0, io_level = 0; + if (nerrors != 0) { + arg_print_errors(stderr, gpio_control_args.end, argv[0]); + return 1; + } + + if (gpio_control_args.pin->count == 1) { + io_num = gpio_control_args.pin->ival[0]; + ESP_LOGI(TAG, "io_num = %d\n", io_num); + } else { + ESP_LOGE(TAG, "no valid arguments"); + return 1; + } + + gpio_config_t io_conf = { + .mode = GPIO_MODE_OUTPUT, + .pin_bit_mask = (1ULL << io_num) + }; + ESP_ERROR_CHECK(gpio_config(&io_conf)); + if (gpio_control_args.level->count == 1) { + io_level = gpio_control_args.level->ival[0]; + ESP_LOGI(TAG, "io_level = %d\n", io_level); + } else { + ESP_LOGI(TAG, "io_num = %d\n", io_num); + ESP_LOGE(TAG, "no valid io_level argument"); + } + + ESP_ERROR_CHECK(gpio_set_level(io_num, io_level == 0 ? 0 : 1)); + + return 0; +} + +static void register_gpio_control(void) +{ + gpio_control_args.pin = + arg_int0("p", "pin", "", "configure the gpio control pin num"); + gpio_control_args.level = + arg_int0("l", "level", "", "configure the gpio control pin level"); + gpio_control_args.end = arg_end(3); + + const esp_console_cmd_t cmd = { + .command = "gpio_control", + .help = "configue gpio control", + .hint = NULL, + .func = &process_gpio_control, + .argtable = &gpio_control_args + }; + ESP_ERROR_CHECK(esp_console_cmd_register(&cmd)); +} + +void register_io_wakeup_cmd(void) +{ + register_sleep(); +#if SOC_PM_SUPPORT_EXT1_WAKEUP + register_ext1_wakeup(); +#endif + register_gpio_control(); + register_gpio_wakeup(); +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP + register_rtcio_wakeup(); +#endif +} diff --git a/components/esp_hw_support/test_apps/wakeup_tests/main/test_app_main.c b/components/esp_hw_support/test_apps/wakeup_tests/main/test_app_main.c new file mode 100644 index 0000000000..7317c4d401 --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/main/test_app_main.c @@ -0,0 +1,52 @@ +/* + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "unity.h" +#include "unity_test_runner.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "unity_test_utils_memory.h" +#include "esp_console.h" +#include "linenoise/linenoise.h" +#include "argtable3/argtable3.h" +#include "io_wakeup_cmd.h" + +static const char* TAG = "esp_hw_support_test_app"; +#define PROMPT_STR "io_wakeup_test" + +#define LEAKS (100) + +void setUp(void) +{ + unity_utils_record_free_mem(); +} + +void tearDown(void) +{ + unity_utils_evaluate_leaks_direct(LEAKS); +} + +void app_main(void) +{ + ESP_LOGI(TAG, "Running esp-hw-support test app"); + esp_console_repl_t *repl = NULL; + esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT(); + /* Prompt to be printed before each line. + * This can be customized, made dynamic, etc. + */ + repl_config.prompt = PROMPT_STR ">"; + repl_config.max_cmdline_length = 256; + /* Register commands */ + esp_console_register_help_command(); + register_io_wakeup_cmd(); + + esp_console_dev_uart_config_t hw_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_console_new_repl_uart(&hw_config, &repl_config, &repl)); + + ESP_ERROR_CHECK(esp_console_start_repl(repl)); +} diff --git a/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py b/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py new file mode 100644 index 0000000000..4cf4f5400a --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/pytest_wakeup_tests.py @@ -0,0 +1,174 @@ +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: CC0-1.0 + +from time import sleep +from typing import Tuple + +import pytest +from pytest_embedded_idf.dut import IdfDut + +TEST_CONFIGS = [ + pytest.param('default'), +] + +# TODO: PM-66 +# ESP32: need to fix GPIO16 and GPIO17 bug +# ESP32S2: need to fix GPIO43 bug +# ESP32S3: need to fix GPIO33, GPIO34 and GPIO43 bug +available_gpio_nums = { + 'esp32': [0, 2, 4, 5, 12, 13, 14, 15, 18, 19, 21, 22, 23, 27], + 'esp32s2': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 21, 33, 34, 35, 36, 37, 38, 39, 40, 42, 45], + 'esp32s3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 35, 36, 37, 39, 40, 42, 45, 46], + 'esp32c2': [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 18], + 'esp32c3': [0, 1, 2, 3, 4, 5, 6, 7, 9, 10, 18, 19], + 'esp32c6': [0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 15, 18, 19, 20, 21, 22, 23], + 'esp32h2': [0, 1, 2, 3, 4, 5, 9, 10, 11, 12, 22, 25, 26, 27], +} + +available_rtcio_nums = { + 'esp32': [36, 37, 38, 39, 34, 35, 4, 0, 2, 15, 13, 12, 14, 27], + 'esp32s2': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], + 'esp32s3': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21], + 'esp32c2': [0, 1, 2, 3, 4, 5], + 'esp32c3': [0, 1, 2, 3, 4, 5], + 'esp32c6': [0, 1, 2, 3, 4, 5, 6, 7], + 'esp32h2': [7, 8, 9, 10, 11, 12, 13, 14], +} + + +@pytest.mark.esp32 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.generic_multi_device +@pytest.mark.parametrize('count', [2], indirect=True) +@pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +def test_ext1_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: + wakee = dut[0] + waker = dut[1] + + chip_type = wakee.app.target + gpio_nums = available_gpio_nums.get(chip_type, []) + rtcio_nums = available_rtcio_nums.get(chip_type, []) + + for wakeup_level in [0, 1]: + for gpio_num in rtcio_nums: + if gpio_num not in gpio_nums: + continue + + wakee.write('\r\n') + sleep(0.1) + wakee.expect('io_wakeup_test>', timeout=10) + wakee.write(f'ext1 -p {gpio_num} -m {wakeup_level}') + wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) + wakee.expect(f'io_wakeup_level = {wakeup_level}', timeout=10) + + waker.expect('io_wakeup_test>', timeout=10) + sleep_level = 1 - wakeup_level + waker.write(f'gpio_control -p {gpio_num} -l {sleep_level}') + waker.expect(f'io_num = {gpio_num}', timeout=10) + waker.expect(f'io_level = {sleep_level}', timeout=10) + + wakee.write('sleep -m 1') + + waker.write(f'gpio_control -p {gpio_num} -l {wakeup_level}') + waker.expect(f'io_num = {gpio_num}', timeout=10) + waker.expect(f'io_level = {wakeup_level}', timeout=10) + + wakee.expect('io_wakeup_test>', timeout=10) + + sleep(2) + + wakee.write(f'ext1 -p {gpio_num} -d') + wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) + + +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.esp32c6 +@pytest.mark.generic_multi_device +@pytest.mark.parametrize('count', [2], indirect=True) +@pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +def test_rtcio_deepsleep(dut: Tuple[IdfDut, IdfDut]) -> None: + wakee = dut[0] + waker = dut[1] + + chip_type = wakee.app.target + gpio_nums = available_gpio_nums.get(chip_type, []) + rtcio_nums = available_rtcio_nums.get(chip_type, []) + + for wakeup_level in [0, 1]: + for gpio_num in rtcio_nums: + if gpio_num not in gpio_nums: + continue + + wakee.write('\r\n') + sleep(0.1) + wakee.expect('io_wakeup_test>', timeout=10) + wakee.write(f'rtcio -p {gpio_num} -l {wakeup_level}') + wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) + wakee.expect(f'io_wakeup_level = {wakeup_level}', timeout=10) + + waker.expect('io_wakeup_test>', timeout=10) + sleep_level = 1 - wakeup_level + waker.write(f'gpio_control -p {gpio_num} -l {sleep_level}') + waker.expect(f'io_num = {gpio_num}', timeout=10) + waker.expect(f'io_level = {sleep_level}', timeout=10) + + wakee.write('sleep -m 1') + + waker.write(f'gpio_control -p {gpio_num} -l {wakeup_level}') + waker.expect(f'io_num = {gpio_num}', timeout=10) + waker.expect(f'io_level = {wakeup_level}', timeout=10) + + wakee.expect('io_wakeup_test>', timeout=10) + + sleep(2) + + wakee.write(f'rtcio -p {gpio_num} -d') + wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) + + +@pytest.mark.esp32 +@pytest.mark.esp32c2 +@pytest.mark.esp32c3 +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32c6 +@pytest.mark.esp32h2 +@pytest.mark.generic_multi_device +@pytest.mark.parametrize('count', [2], indirect=True) +@pytest.mark.parametrize('config', TEST_CONFIGS, indirect=True) +def test_gpio_wakeup_enable_lightsleep(dut: Tuple[IdfDut, IdfDut]) -> None: + wakee = dut[0] + waker = dut[1] + + chip_type = wakee.app.target + gpio_nums = available_gpio_nums.get(chip_type, []) + + for wakeup_level in [1, 0]: + for gpio_num in gpio_nums: + + wakee.write('\r\n') + wakee.expect('io_wakeup_test>', timeout=10) + wakee.write(f'gpio -p {gpio_num} -l {wakeup_level}') + wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) + wakee.expect(f'io_wakeup_level = {wakeup_level}', timeout=10) + + waker.expect('io_wakeup_test>', timeout=10) + sleep_level = 1 - wakeup_level + waker.write(f'gpio_control -p {gpio_num} -l {sleep_level}') + waker.expect(f'io_num = {gpio_num}', timeout=10) + waker.expect(f'io_level = {sleep_level}', timeout=10) + + wakee.write('sleep -m 0') + + waker.write(f'gpio_control -p {gpio_num} -l {wakeup_level}') + waker.expect(f'io_num = {gpio_num}', timeout=10) + waker.expect(f'io_level = {wakeup_level}', timeout=10) + + wakee.expect('esp_light_sleep_start', timeout=10) + + wakee.write(f'gpio -p {gpio_num} -d') + wakee.expect(f'io_wakeup_num = {gpio_num}', timeout=10) diff --git a/components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.ci.default b/components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.ci.default new file mode 100644 index 0000000000..7a9bc9908a --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.ci.default @@ -0,0 +1,3 @@ +# Default configuration +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=n +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=n diff --git a/components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.defaults b/components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.defaults new file mode 100644 index 0000000000..fb76bc2e1b --- /dev/null +++ b/components/esp_hw_support/test_apps/wakeup_tests/sdkconfig.defaults @@ -0,0 +1,2 @@ +CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND=n +CONFIG_ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS=n diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 62210faa6a..93e2a421a6 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2016-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2016-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index e5cb5a3176..29d0ea2ccb 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2019-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2019-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -41,7 +41,6 @@ #define ESP_EXT0_WAKEUP_LEVEL_LOW 0 #define ESP_EXT0_WAKEUP_LEVEL_HIGH 1 - __attribute__((unused)) static struct timeval tv_start, tv_stop; @@ -391,72 +390,6 @@ TEST_CASE_MULTIPLE_STAGES("can set sleep wake stub from stack in RTC RAM", "[dee #if SOC_RTCIO_INPUT_OUTPUT_SUPPORTED -#if SOC_PM_SUPPORT_EXT0_WAKEUP -TEST_CASE("wake up using ext0 (13 high)", "[deepsleep][ignore]") -{ - ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_HIGH)); - esp_deep_sleep_start(); -} - -TEST_CASE("wake up using ext0 (13 low)", "[deepsleep][ignore]") -{ - ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_enable_ext0_wakeup(GPIO_NUM_13, ESP_EXT0_WAKEUP_LEVEL_LOW)); - esp_deep_sleep_start(); -} -#endif // SOC_PM_SUPPORT_EXT0_WAKEUP - -#if SOC_PM_SUPPORT_EXT1_WAKEUP -TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 high)", "[deepsleep][ignore]") -{ - // This test needs external pulldown - ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH)); - esp_deep_sleep_start(); -} - -TEST_CASE("wake up using ext1 when RTC_PERIPH is off (13 low)", "[deepsleep][ignore]") -{ - // This test needs external pullup - ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); -#if CONFIG_IDF_TARGET_ESP32 - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); -#else - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_LOW)); -#endif - esp_deep_sleep_start(); -} - -TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 high)", "[deepsleep][ignore]") -{ - ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pullup_dis(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pulldown_en(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_HIGH)); - esp_deep_sleep_start(); -} - -TEST_CASE("wake up using ext1 when RTC_PERIPH is on (13 low)", "[deepsleep][ignore]") -{ - ESP_ERROR_CHECK(rtc_gpio_init(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pullup_en(GPIO_NUM_13)); - ESP_ERROR_CHECK(gpio_pulldown_dis(GPIO_NUM_13)); - ESP_ERROR_CHECK(esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON)); -#if CONFIG_IDF_TARGET_ESP32 - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ALL_LOW)); -#else - ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(BIT(GPIO_NUM_13), ESP_EXT1_WAKEUP_ANY_LOW)); -#endif - esp_deep_sleep_start(); -} -#endif // SOC_PM_SUPPORT_EXT1_WAKEUP - __attribute__((unused)) static float get_time_ms(void) { gettimeofday(&tv_stop, NULL); @@ -647,29 +580,4 @@ static void check_time_deepsleep(void) TEST_CASE_MULTIPLE_STAGES("check a time after wakeup from deep sleep", "[deepsleep][reset=DEEPSLEEP_RESET]", trigger_deepsleep, check_time_deepsleep); -#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP -static void gpio_deepsleep_wakeup_config(void) -{ - gpio_config_t io_conf = { - .mode = GPIO_MODE_INPUT, - .pin_bit_mask = ((1ULL << 2) | (1ULL << 4)) - }; - ESP_ERROR_CHECK(gpio_config(&io_conf)); -} - -TEST_CASE("wake up using GPIO (2 or 4 high)", "[deepsleep][ignore]") -{ - gpio_deepsleep_wakeup_config(); - ESP_ERROR_CHECK(esp_deep_sleep_enable_gpio_wakeup(((1ULL << 2) | (1ULL << 4)) , ESP_GPIO_WAKEUP_GPIO_HIGH)); - esp_deep_sleep_start(); -} - -TEST_CASE("wake up using GPIO (2 or 4 low)", "[deepsleep][ignore]") -{ - gpio_deepsleep_wakeup_config(); - ESP_ERROR_CHECK(esp_deep_sleep_enable_gpio_wakeup(((1ULL << 2) | (1ULL << 4)) , ESP_GPIO_WAKEUP_GPIO_LOW)); - esp_deep_sleep_start(); -} -#endif // SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP - #endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4)