From 9a246bcbf117301f4244cbb0a444abefed8d861b Mon Sep 17 00:00:00 2001 From: wuzhenghui Date: Sun, 8 Oct 2023 16:48:00 +0800 Subject: [PATCH 1/2] feat: support dump last time sleep context --- components/esp_hw_support/Kconfig | 6 ++ .../include/esp_private/esp_sleep_internal.h | 19 ++++- components/esp_hw_support/sleep_modes.c | 70 +++++++++++++++---- 3 files changed, 80 insertions(+), 15 deletions(-) diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 5aa11dc938..62ce1951dd 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -172,6 +172,12 @@ menu "Hardware Settings" For chips after esp32, the delay will be executed only in light sleep flow, the delay controlled by the EFUSE_FLASH_TPUW in ROM will be executed in deepsleep wake up flow.) + config ESP_SLEEP_DEBUG + bool "esp sleep debug" + default n + help + Enable esp sleep debug. + config ESP_SLEEP_GPIO_ENABLE_INTERNAL_RESISTORS bool "Allow to enable internal pull-up/downs for the Deep-Sleep wakeup IOs" default y diff --git a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h index 56a6b5fde1..83bbcc2509 100644 --- a/components/esp_hw_support/include/esp_private/esp_sleep_internal.h +++ b/components/esp_hw_support/include/esp_private/esp_sleep_internal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -13,6 +13,23 @@ extern "C" { #endif +#if CONFIG_ESP_SLEEP_DEBUG +typedef struct { + uint32_t lightsleep_cnt; + uint64_t sleep_in_rtc_time_stamp; + uint64_t sleep_out_rtc_time_stamp; + uint32_t wakeup_triggers; + uint32_t sleep_flags; + esp_err_t sleep_request_result; +} esp_sleep_context_t; + +/** + * @brief Set the context pointer of last sleep request + * @param sleep_ctx Structure where the context of the sleep information needs to be recorded in + */ +void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx); +#endif + /** * @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode * diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b6f30498b8..543c438c20 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -83,7 +83,6 @@ #include "esp32c2/rom/rtc.h" #elif CONFIG_IDF_TARGET_ESP32C6 #include "esp32c6/rom/rtc.h" -#include "hal/lp_timer_hal.h" #include "hal/gpio_ll.h" #elif CONFIG_IDF_TARGET_ESP32H2 #include "esp32h2/rom/rtc.h" @@ -196,8 +195,10 @@ typedef struct { uint32_t ext0_trigger_level : 1; uint32_t ext0_rtc_gpio_num : 5; #endif +#if SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP uint32_t gpio_wakeup_mask : 8; // 8 is the maximum RTCIO number in all chips that support GPIO wakeup uint32_t gpio_trigger_mode : 8; +#endif uint32_t sleep_time_adjustment; uint32_t ccount_ticks_record; uint32_t sleep_time_overhead_out; @@ -207,6 +208,17 @@ typedef struct { } sleep_config_t; +#if CONFIG_ESP_SLEEP_DEBUG +static esp_sleep_context_t *s_sleep_ctx = NULL; + +void esp_sleep_set_sleep_context(esp_sleep_context_t *sleep_ctx) +{ + s_sleep_ctx = sleep_ctx; +} +#endif + +static uint32_t s_lightsleep_cnt = 0; + _Static_assert(22 >= SOC_RTCIO_PIN_COUNT, "Chip has more RTCIOs than 22, should increase ext1_rtc_gpio_mask field size"); static sleep_config_t s_config = { @@ -715,11 +727,18 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m if (periph_using_8m) { sleep_flags |= RTC_SLEEP_DIG_USE_8M; } + +#if CONFIG_ESP_SLEEP_DEBUG + if (s_sleep_ctx != NULL) { + s_sleep_ctx->sleep_flags = sleep_flags; + } +#endif + // Enter sleep esp_err_t result; #if SOC_PMU_SUPPORTED pmu_sleep_config_t config; - pmu_sleep_init(pmu_sleep_config_default(&config, pd_flags, s_config.sleep_time_adjustment, + pmu_sleep_init(pmu_sleep_config_default(&config, sleep_flags, s_config.sleep_time_adjustment, s_config.rtc_clk_cal_period, s_config.fast_clk_cal_period, deep_sleep), deep_sleep); #else @@ -749,6 +768,11 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m if (should_skip_sleep) { result = ESP_ERR_SLEEP_REJECT; } else { +#if CONFIG_ESP_SLEEP_DEBUG + if (s_sleep_ctx != NULL) { + s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers; + } +#endif if (deep_sleep) { #if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP esp_sleep_isolate_digital_gpio(); @@ -792,8 +816,9 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0); if (pd_flags & PMU_SLEEP_PD_CPU) { result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); - } else { + } else #endif + { result = call_rtc_sleep_start(reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep); } esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_EXIT_SLEEP, (void *)0); @@ -1063,15 +1088,18 @@ esp_err_t esp_light_sleep_start(void) */ esp_clk_private_lock(); -#if SOC_LP_TIMER_SUPPORTED - s_config.rtc_ticks_at_sleep_start = lp_timer_hal_get_cycle_count(); -#else s_config.rtc_ticks_at_sleep_start = rtc_time_get(); -#endif uint32_t ccount_at_sleep_start = esp_cpu_get_cycle_count(); esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_TIME_START, (void *)0); uint64_t high_res_time_at_start = esp_timer_get_time(); uint32_t sleep_time_overhead_in = (ccount_at_sleep_start - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); + +#if CONFIG_ESP_SLEEP_DEBUG + if (s_sleep_ctx != NULL) { + s_sleep_ctx->sleep_in_rtc_time_stamp = s_config.rtc_ticks_at_sleep_start; + } +#endif + esp_ipc_isr_stall_other_cpu(); // Decide which power domains can be powered down @@ -1164,6 +1192,13 @@ esp_err_t esp_light_sleep_start(void) // reset light sleep wakeup flag before a new light sleep s_light_sleep_wakeup = false; + s_lightsleep_cnt++; +#if CONFIG_ESP_SLEEP_DEBUG + if (s_sleep_ctx != NULL) { + s_sleep_ctx->lightsleep_cnt = s_lightsleep_cnt; + } +#endif + // if rtc timer wakeup source is enabled, need to compare final sleep duration and min sleep duration to avoid late wakeup if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) && (final_sleep_duration_us <= min_sleep_duration_us)) { err = ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION; @@ -1176,13 +1211,15 @@ esp_err_t esp_light_sleep_start(void) s_light_sleep_wakeup = (err == ESP_OK); // System timer has been stopped for the duration of the sleep, correct for that. -#if SOC_LP_TIMER_SUPPORTED - uint64_t rtc_ticks_at_end = lp_timer_hal_get_cycle_count(); -#else uint64_t rtc_ticks_at_end = rtc_time_get(); -#endif uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start, s_config.rtc_clk_cal_period); +#if CONFIG_ESP_SLEEP_DEBUG + if (s_sleep_ctx != NULL) { + s_sleep_ctx->sleep_out_rtc_time_stamp = rtc_ticks_at_end; + } +#endif + /** * If sleep duration is too small(less than 1 rtc_slow_clk cycle), rtc_time_diff will be zero. * In this case, just ignore the time compensation and keep esp_timer monotonic. @@ -1211,6 +1248,12 @@ esp_err_t esp_light_sleep_start(void) esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_EXIT_SLEEP, (void *)0); s_config.sleep_time_overhead_out = (esp_cpu_get_cycle_count() - s_config.ccount_ticks_record) / (esp_clk_cpu_freq() / 1000000ULL); + +#if CONFIG_ESP_SLEEP_DEBUG + if (s_sleep_ctx != NULL) { + s_sleep_ctx->sleep_request_result = err; + } +#endif return err; } @@ -1307,7 +1350,7 @@ static esp_err_t timer_wakeup_prepare(int64_t sleep_duration) #if CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP // Last timer wake-up validity check if ((sleep_duration == 0) || \ - (target_wakeup_tick < lp_timer_hal_get_cycle_count() + SLEEP_TIMER_ALARM_TO_SLEEP_TICKS)) { + (target_wakeup_tick < rtc_time_get() + SLEEP_TIMER_ALARM_TO_SLEEP_TICKS)) { // Treat too short sleep duration setting as timer reject return ESP_ERR_SLEEP_REJECT; } @@ -1850,7 +1893,6 @@ static uint32_t get_power_down_flags(void) } #endif - #ifdef CONFIG_IDF_TARGET_ESP32 s_config.domain[ESP_PD_DOMAIN_XTAL].pd_option = ESP_PD_OPTION_OFF; #endif From abaa9f2bfe7a398a36a6fcd16b7b89ad990a8177 Mon Sep 17 00:00:00 2001 From: Xu Si Yu Date: Tue, 11 Jul 2023 21:25:47 +0800 Subject: [PATCH 2/2] ci(openthread): Add a test case for openthread sleepy device --- .gitlab/ci/dependencies/dependencies.yml | 14 +++ .gitlab/ci/rules.yml | 29 +++++ .gitlab/ci/target-test.yml | 11 ++ components/esp_hw_support/sleep_modes.c | 6 +- conftest.py | 1 + examples/openthread/.build-test-rules.yml | 8 -- examples/openthread/ot_ci_function.py | 60 +++++++++-- .../light_sleep/main/esp_ot_sleepy_device.c | 35 ++++++ examples/openthread/pytest_otbr.py | 102 +++++++++++++++++- 9 files changed, 242 insertions(+), 24 deletions(-) diff --git a/.gitlab/ci/dependencies/dependencies.yml b/.gitlab/ci/dependencies/dependencies.yml index 31f538a479..e687a6472d 100644 --- a/.gitlab/ci/dependencies/dependencies.yml +++ b/.gitlab/ci/dependencies/dependencies.yml @@ -172,6 +172,20 @@ - "build:example_test" - build:target_test +# For openthread sleepy +"test:example_test-otsleepy": + patterns: + - "example_test-otsleepy" + - "target_test-i154" + labels: + - target_test + - example_test + included_in: + - "build:example_test-esp32c6" + - "build:example_test-esp32h2" + - "build:example_test" + - build:target_test + "test:host_test": labels: - host_test diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index 2ab1ebfe3f..e45236c53d 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -93,6 +93,13 @@ - "examples/common_components/iperf/**/*" - "examples/openthread/**/*" +.patterns-example_test-otsleepy: &patterns-example_test-otsleepy + - "components/esp_hw_support/**/*" + - "components/esp_netif/**/*" + - "components/lwip/**/*" + - "components/openthread/**/*" + - "examples/openthread/**/*" + .patterns-target_test-wifi: &patterns-target_test-wifi - "components/esp_netif/**/*" - "components/lwip/**/*" @@ -1120,6 +1127,8 @@ changes: *patterns-example_test-ethernet - <<: *if-dev-push changes: *patterns-example_test-i154 + - <<: *if-dev-push + changes: *patterns-example_test-otsleepy - <<: *if-dev-push changes: *patterns-example_test-sdio - <<: *if-dev-push @@ -1290,6 +1299,8 @@ changes: *patterns-example_test-ethernet - <<: *if-dev-push changes: *patterns-example_test-i154 + - <<: *if-dev-push + changes: *patterns-example_test-otsleepy - <<: *if-dev-push changes: *patterns-example_test-sdio - <<: *if-dev-push @@ -1332,6 +1343,8 @@ changes: *patterns-example_test-ethernet - <<: *if-dev-push changes: *patterns-example_test-i154 + - <<: *if-dev-push + changes: *patterns-example_test-otsleepy - <<: *if-dev-push changes: *patterns-example_test-sdio - <<: *if-dev-push @@ -1512,6 +1525,8 @@ changes: *patterns-example_test-ethernet - <<: *if-dev-push changes: *patterns-example_test-i154 + - <<: *if-dev-push + changes: *patterns-example_test-otsleepy - <<: *if-dev-push changes: *patterns-example_test-sdio - <<: *if-dev-push @@ -2633,6 +2648,20 @@ - <<: *if-dev-push changes: *patterns-target_test-i154 +.rules:test:example_test-otsleepy: + rules: + - <<: *if-revert-branch + when: never + - <<: *if-protected + - <<: *if-label-build-only + when: never + - <<: *if-label-example_test + - <<: *if-label-target_test + - <<: *if-dev-push + changes: *patterns-example_test-otsleepy + - <<: *if-dev-push + changes: *patterns-target_test-i154 + .rules:test:host_test: rules: - <<: *if-revert-branch diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 2ccc054e23..ed46c8b98c 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -992,6 +992,17 @@ pytest_examples_openthread_br: - esp32c6 - openthread_br +pytest_examples_openthread_sleep: + extends: + - .pytest_examples_dir_template + - .rules:test:example_test-otsleepy + needs: + - build_pytest_examples_esp32c6 + - build_pytest_examples_esp32h2 + tags: + - esp32c6 + - openthread_sleep + pytest_components_esp32s3_usb_host: extends: - .pytest_components_dir_template diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 543c438c20..c43e3a6aa7 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -769,9 +769,9 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m result = ESP_ERR_SLEEP_REJECT; } else { #if CONFIG_ESP_SLEEP_DEBUG - if (s_sleep_ctx != NULL) { - s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers; - } + if (s_sleep_ctx != NULL) { + s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers; + } #endif if (deep_sleep) { #if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP diff --git a/conftest.py b/conftest.py index 145327b2b2..1d4c5a73aa 100644 --- a/conftest.py +++ b/conftest.py @@ -133,6 +133,7 @@ ENV_MARKERS = { # multi-dut markers 'ieee802154': 'ieee802154 related tests should run on ieee802154 runners.', 'openthread_br': 'tests should be used for openthread border router.', + 'openthread_sleep': 'tests should be used for openthread sleepy device.', 'wifi_two_dut': 'tests should be run on runners which has two wifi duts connected.', 'generic_multi_device': 'generic multiple devices whose corresponding gpio pins are connected to each other.', 'twai_network': 'multiple runners form a TWAI network.', diff --git a/examples/openthread/.build-test-rules.yml b/examples/openthread/.build-test-rules.yml index 7b8b09fe3b..49aa460e5c 100644 --- a/examples/openthread/.build-test-rules.yml +++ b/examples/openthread/.build-test-rules.yml @@ -13,10 +13,6 @@ examples/openthread/ot_br: examples/openthread/ot_cli: enable: - if: SOC_IEEE802154_SUPPORTED == 1 - disable_test: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: only test on esp32h2 examples/openthread/ot_rcp: enable: @@ -37,7 +33,3 @@ examples/openthread/ot_sleepy_device/deep_sleep: examples/openthread/ot_sleepy_device/light_sleep: enable: - if: SOC_IEEE802154_SUPPORTED == 1 - disable_test: - - if: SOC_IEEE802154_SUPPORTED == 1 - temporary: true - reason: Unsupport # TO-DO: TZ-134 diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index 6cd68793d1..346f991d42 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 # this file defines some functions for testing cli and br under pytest framework @@ -23,6 +23,26 @@ class thread_parameter: self.channel = channel self.exaddr = exaddr self.bbr = bbr + self.networkname = '' + self.panid = '' + self.extpanid = '' + self.networkkey = '' + self.pskc = '' + + def setnetworkname(self, networkname:str) -> None: + self.networkname = networkname + + def setpanid(self, panid:str) -> None: + self.panid = panid + + def setextpanid(self, extpanid:str) -> None: + self.extpanid = extpanid + + def setnetworkkey(self, networkkey:str) -> None: + self.networkkey = networkkey + + def setpskc(self, pskc:str) -> None: + self.pskc = pskc class wifi_parameter: @@ -34,23 +54,43 @@ class wifi_parameter: def joinThreadNetwork(dut:IdfDut, thread:thread_parameter) -> None: - if thread.dataset != '': + if thread.dataset: command = 'dataset set active ' + thread.dataset execute_command(dut, command) dut.expect('Done', timeout=5) else: execute_command(dut, 'dataset init new') dut.expect('Done', timeout=5) - execute_command(dut, 'dataset commit active') - dut.expect('Done', timeout=5) - if thread.channel != '': - command = 'channel ' + thread.channel + if thread.channel: + command = 'dataset channel ' + thread.channel execute_command(dut, command) dut.expect('Done', timeout=5) - if thread.exaddr != '': + if thread.exaddr: command = 'extaddr ' + thread.exaddr execute_command(dut, command) dut.expect('Done', timeout=5) + if thread.networkname: + command = 'dataset networkname ' + thread.networkname + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.panid: + command = 'dataset panid ' + thread.panid + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.extpanid: + command = 'dataset extpanid ' + thread.extpanid + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.networkkey: + command = 'dataset networkkey ' + thread.networkkey + execute_command(dut, command) + dut.expect('Done', timeout=5) + if thread.pskc: + command = 'dataset pskc ' + thread.pskc + execute_command(dut, command) + dut.expect('Done', timeout=5) + execute_command(dut, 'dataset commit active') + dut.expect('Done', timeout=5) if thread.bbr: execute_command(dut, 'bbr enable') dut.expect('Done', timeout=5) @@ -109,9 +149,13 @@ def getDataset(dut:IdfDut) -> str: return str(dut_data) -def reset_thread(dut:IdfDut) -> None: +def init_thread(dut:IdfDut) -> None: dut.expect('>', timeout=10) wait(dut, 3) + reset_thread(dut) + + +def reset_thread(dut:IdfDut) -> None: clean_buffer(dut) execute_command(dut, 'factoryreset') dut.expect('OpenThread attached to netif', timeout=20) diff --git a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c index 6d20b50ea5..95b5bc2e1d 100644 --- a/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c +++ b/examples/openthread/ot_sleepy_device/light_sleep/main/esp_ot_sleepy_device.c @@ -28,6 +28,13 @@ #include "openthread/logging.h" #include "openthread/thread.h" +#if CONFIG_ESP_SLEEP_DEBUG +#include "esp_timer.h" +#include "esp_sleep.h" +#include "esp_private/esp_pmu.h" +#include "esp_private/esp_sleep_internal.h" +#endif + #ifdef CONFIG_PM_ENABLE #include "esp_pm.h" #endif @@ -68,6 +75,17 @@ static esp_netif_t *init_openthread_netif(const esp_openthread_platform_config_t return netif; } +#if CONFIG_ESP_SLEEP_DEBUG +static esp_sleep_context_t s_sleep_ctx; + +static void print_sleep_flag(void *arg) +{ + ESP_LOGD(TAG, "sleep_flags %lu", s_sleep_ctx.sleep_flags); + ESP_LOGD(TAG, "PMU_SLEEP_PD_TOP: %s", (s_sleep_ctx.sleep_flags & PMU_SLEEP_PD_TOP) ? "True":"False"); + ESP_LOGD(TAG, "PMU_SLEEP_PD_MODEM: %s", (s_sleep_ctx.sleep_flags & PMU_SLEEP_PD_MODEM) ? "True":"False"); +} +#endif + static void ot_task_worker(void *aContext) { esp_openthread_platform_config_t config = { @@ -90,6 +108,23 @@ static void ot_task_worker(void *aContext) create_config_network(esp_openthread_get_instance()); +#if CONFIG_ESP_SLEEP_DEBUG + esp_sleep_set_sleep_context(&s_sleep_ctx); + esp_log_level_set(TAG, ESP_LOG_DEBUG); + + // create a timer to print the status of sleepy device + int periods = 2000; + const esp_timer_create_args_t timer_args = { + .name = "print_sleep_flag", + .arg = NULL, + .callback = &print_sleep_flag, + .skip_unhandled_events = true, + }; + esp_timer_handle_t periodic_timer; + ESP_ERROR_CHECK(esp_timer_create(&timer_args, &periodic_timer)); + ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, periods * 1000)); +#endif + // Run the main loop esp_openthread_launch_mainloop(); diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 06bb1bdcc0..95e146f7a9 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -1,4 +1,4 @@ -# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD # SPDX-License-Identifier: Unlicense OR CC0-1.0 # !/usr/bin/env python3 @@ -91,9 +91,9 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: cli_list = [cli_h2] router_extaddr_list = ['7766554433221101'] - ocf.reset_thread(br) + ocf.init_thread(br) for cli in cli_list: - ocf.reset_thread(cli) + ocf.init_thread(cli) br_ot_para = default_br_ot_para ocf.joinThreadNetwork(br, br_ot_para) cli_ot_para = default_cli_ot_para @@ -125,8 +125,8 @@ def test_thread_connect(dut:Tuple[IdfDut, IdfDut, IdfDut]) -> None: # / \ # Wi-FI_Host Thread_End_Device def formBasicWiFiThreadNetwork(br:IdfDut, cli:IdfDut) -> None: - ocf.reset_thread(br) - ocf.reset_thread(cli) + ocf.init_thread(br) + ocf.init_thread(cli) ocf.joinWiFiNetwork(br, default_br_wifi_para) ocf.joinThreadNetwork(br, default_br_ot_para) ot_para = default_cli_ot_para @@ -540,3 +540,95 @@ def test_TCP_NAT64(Init_interface:bool, dut: Tuple[IdfDut, IdfDut, IdfDut]) -> N ocf.execute_command(cli, 'factoryreset') time.sleep(3) assert b'hello' in mytcp.tcp_bytes + + +# Case 10: Sleepy device test +@pytest.mark.esp32h2 +@pytest.mark.esp32c6 +@pytest.mark.openthread_sleep +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('cli_h2|sleepy_c6', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device/light_sleep")}', + 'esp32h2|esp32c6'), + ('cli_c6|sleepy_h2', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_cli")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_sleepy_device/light_sleep")}', + 'esp32c6|esp32h2'), + ], + indirect=True, +) +def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: + leader = dut[0] + sleepy_device = dut[1] + fail_info = re.compile(r'Core\W*?\d\W*?register dump') + try: + ocf.init_thread(leader) + time.sleep(3) + leader_para = ocf.thread_parameter('leader', '', '12', '7766554433221100', False) + leader_para.setnetworkname('OpenThread-ESP') + leader_para.setpanid('0x1234') + leader_para.setextpanid('dead00beef00cafe') + leader_para.setnetworkkey('aabbccddeeff00112233445566778899') + leader_para.setpskc('104810e2315100afd6bc9215a6bfac53') + ocf.joinThreadNetwork(leader, leader_para) + ocf.wait(leader, 5) + output = sleepy_device.expect(pexpect.TIMEOUT, timeout=5) + assert not bool(fail_info.search(str(output))) + ocf.clean_buffer(sleepy_device) + sleepy_device.serial.hard_reset() + info = sleepy_device.expect(r'(.+)detached -> child', timeout=20)[1].decode(errors='replace') + assert not bool(fail_info.search(str(info))) + info = sleepy_device.expect(r'(.+)PMU_SLEEP_PD_TOP: True', timeout=10)[1].decode(errors='replace') + assert not bool(fail_info.search(str(info))) + info = sleepy_device.expect(r'(.+)PMU_SLEEP_PD_MODEM: True', timeout=20)[1].decode(errors='replace') + assert not bool(fail_info.search(str(info))) + output = sleepy_device.expect(pexpect.TIMEOUT, timeout=20) + assert not bool(fail_info.search(str(output))) + ocf.clean_buffer(sleepy_device) + ocf.execute_command(leader, 'factoryreset') + output = sleepy_device.expect(pexpect.TIMEOUT, timeout=5) + assert not bool(fail_info.search(str(output))) + finally: + ocf.execute_command(leader, 'factoryreset') + time.sleep(3) + + +# Case 11: Basic startup Test of BR +@pytest.mark.supported_targets +@pytest.mark.esp32h2 +@pytest.mark.esp32c6 +@pytest.mark.openthread_br +@pytest.mark.flaky(reruns=1, reruns_delay=1) +@pytest.mark.parametrize( + 'config, count, app_path, target', [ + ('rcp|br', 2, + f'{os.path.join(os.path.dirname(__file__), "ot_rcp")}' + f'|{os.path.join(os.path.dirname(__file__), "ot_br")}', + 'esp32c6|esp32s3'), + ], + indirect=True, +) +def test_basic_startup(dut: Tuple[IdfDut, IdfDut]) -> None: + br = dut[1] + dut[0].serial.stop_redirect_thread() + try: + ocf.init_thread(br) + time.sleep(3) + ocf.clean_buffer(br) + ocf.execute_command(br, 'ifconfig up') + br.expect('Done', timeout=5) + ocf.execute_command(br, 'thread start') + br.expect('Done', timeout=5) + assert ocf.wait_for_join(br, 'leader') + ocf.reset_thread(br) + ocf.joinWiFiNetwork(br, default_br_wifi_para) + ocf.execute_command(br, 'ifconfig up') + br.expect('Done', timeout=5) + ocf.execute_command(br, 'thread start') + br.expect('Done', timeout=5) + assert ocf.wait_for_join(br, 'leader') + finally: + ocf.execute_command(br, 'factoryreset') + time.sleep(3)