From 5f51dcc686f6b7940fcdb33d6c72a6f825574e15 Mon Sep 17 00:00:00 2001 From: Xu Si Yu Date: Tue, 11 Jul 2023 21:25:47 +0800 Subject: [PATCH 1/2] ci(openthread): Add a test case for openthread sleepy device --- .gitlab/ci/target-test.yml | 9 ++ conftest.py | 1 + examples/openthread/.build-test-rules.yml | 33 +++---- examples/openthread/ot_ci_function.py | 58 ++++++++++-- .../ot_sleepy_device/sdkconfig.ci.sleepy_c6 | 4 + .../ot_sleepy_device/sdkconfig.ci.sleepy_h2 | 4 + examples/openthread/pytest_otbr.py | 89 ++++++++++++++++++- 7 files changed, 166 insertions(+), 32 deletions(-) create mode 100644 examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 create mode 100644 examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 diff --git a/.gitlab/ci/target-test.yml b/.gitlab/ci/target-test.yml index 2cc9b39d90..01cb606842 100644 --- a/.gitlab/ci/target-test.yml +++ b/.gitlab/ci/target-test.yml @@ -1069,6 +1069,15 @@ pytest_examples_openthread_br: - esp32c6 - openthread_br +pytest_examples_openthread_sleep: + extends: + - .pytest_examples_dir_template + - .rules:test:example_test-esp32h2 + needs: + - build_pytest_examples_esp32c6 + - build_pytest_examples_esp32h2 + tags: [ esp32c6, openthread_sleep ] + pytest_examples_zigbee: extends: - .pytest_examples_dir_template diff --git a/conftest.py b/conftest.py index 608fae5d43..ca0f0d3795 100644 --- a/conftest.py +++ b/conftest.py @@ -132,6 +132,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.', 'zigbee_multi_dut': 'zigbee runner which have multiple duts.', '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.', diff --git a/examples/openthread/.build-test-rules.yml b/examples/openthread/.build-test-rules.yml index 708b984373..eb59f014aa 100644 --- a/examples/openthread/.build-test-rules.yml +++ b/examples/openthread/.build-test-rules.yml @@ -3,24 +3,23 @@ # TODO: Modify the configuration after the files matching rules are changed # Or delete TODO without modifying the configuration if it is sure that current rules are correct. .openthread_dependencies: &openthread_dependencies + depends_components: + - esp_coex + - esp_netif + - esp_phy + - ieee802154 + - lwip + - openthread depends_filepatterns: - - components/esp_coex/* - - components/esp_coex/**/* - - components/esp_netif/* - - components/esp_netif/**/* - - components/esp_phy/* - - components/esp_phy/**/* - - components/ieee802154/* - - components/ieee802154/**/* - - components/lwip/* - - components/lwip/**/* - - components/openthread/* - - components/openthread/**/* - examples/common_components/iperf/* - examples/common_components/iperf/**/* - examples/openthread/* - examples/openthread/**/* +.openthread_sleep_dependencies: &openthread_sleep_dependencies + depends_components: + - esp_hw_support + examples/openthread/ot_br: disable: - if: IDF_TARGET in ["esp32h2"] @@ -35,10 +34,6 @@ examples/openthread/ot_br: examples/openthread/ot_cli: enable: - if: IDF_TARGET in ["esp32h2", "esp32c6"] - disable_test: - - if: IDF_TARGET == "esp32c6" - temporary: true - reason: only test on esp32h2 <<: *openthread_dependencies examples/openthread/ot_rcp: @@ -53,8 +48,4 @@ examples/openthread/ot_rcp: examples/openthread/ot_sleepy_device: enable: - if: IDF_TARGET in ["esp32h2", "esp32c6"] - disable_test: - - if: IDF_TARGET in ["esp32h2", "esp32c6"] - temporary: true - reason: No support # TO-DO: TZ-134 - <<: *openthread_dependencies + <<: [*openthread_dependencies, *openthread_sleep_dependencies] diff --git a/examples/openthread/ot_ci_function.py b/examples/openthread/ot_ci_function.py index 6cd68793d1..48db7e60e5 100644 --- a/examples/openthread/ot_ci_function.py +++ b/examples/openthread/ot_ci_function.py @@ -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/sdkconfig.ci.sleepy_c6 b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 new file mode 100644 index 0000000000..e61c1118f2 --- /dev/null +++ b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32c6" +CONFIG_IDF_TARGET_ESP32C6=y +CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 +CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" diff --git a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 new file mode 100644 index 0000000000..fbc855ee78 --- /dev/null +++ b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 @@ -0,0 +1,4 @@ +CONFIG_IDF_TARGET="esp32h2" +CONFIG_IDF_TARGET_ESP32H2=y +CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 +CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index b90ed95e42..87334b4264 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -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,84 @@ 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")}', + '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")}', + 'esp32c6|esp32h2'), + ], + indirect=True, +) +def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: + leader = dut[0] + sleepy_device = dut[1] + 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.clean_buffer(sleepy_device) + ocf.joinThreadNetwork(leader, leader_para) + ocf.clean_buffer(sleepy_device) + sleepy_device.serial.hard_reset() + sleepy_device.expect('detached -> child', timeout=20) + ocf.clean_buffer(sleepy_device) + output = sleepy_device.expect(pexpect.TIMEOUT, timeout=5) + assert 'rst:' not in str(output) and 'boot:' not in 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) From 753f74cb99b6747cfa125528f22b896586940cde Mon Sep 17 00:00:00 2001 From: Xu Si Yu Date: Fri, 21 Jul 2023 14:49:50 +0800 Subject: [PATCH 2/2] feat(openthread): add sleep debug message --- components/esp_hw_support/Kconfig | 6 ++++++ components/esp_hw_support/sleep_modes.c | 8 ++++++++ .../openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 | 2 ++ .../openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 | 2 ++ examples/openthread/pytest_otbr.py | 2 ++ 5 files changed, 20 insertions(+) diff --git a/components/esp_hw_support/Kconfig b/components/esp_hw_support/Kconfig index 759cc09bf6..4a9b2d226b 100644 --- a/components/esp_hw_support/Kconfig +++ b/components/esp_hw_support/Kconfig @@ -164,6 +164,12 @@ menu "Hardware Settings" only for code quality inspection. Enabling it will increase the time overhead of entering and exiting sleep. It is not recommended to enable it in the release version. + config ESP_SLEEP_DEBUG + bool "esp sleep debug" + default n + help + Enable esp sleep debug. + endmenu menu "ESP_SLEEP_WORKAROUND" diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index 3835c113aa..4175ae3d06 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -579,6 +579,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m bool deep_sleep = (mode == ESP_SLEEP_MODE_DEEP_SLEEP); bool should_skip_sleep = false; +#if CONFIG_ESP_SLEEP_DEBUG + // The following three logs are used to confirm whether the digital domain and modem are powered off. + // Some CI tests depend on these three logs and it is best not to modify them. + ESP_EARLY_LOGD(TAG, "pd_lags %lu", pd_flags); + ESP_EARLY_LOGD(TAG, "PMU_SLEEP_PD_TOP: %s", (pd_flags & PMU_SLEEP_PD_TOP) ? "True":"False"); + ESP_EARLY_LOGD(TAG, "PMU_SLEEP_PD_MODEM: %s", (pd_flags & PMU_SLEEP_PD_MODEM) ? "True":"False"); +#endif + int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment; #if SOC_RTC_SLOW_CLK_SUPPORT_RC_FAST_D256 diff --git a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 index e61c1118f2..80eea90801 100644 --- a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 +++ b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_c6 @@ -2,3 +2,5 @@ CONFIG_IDF_TARGET="esp32c6" CONFIG_IDF_TARGET_ESP32C6=y CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" +CONFIG_ESP_SLEEP_DEBUG=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y diff --git a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 index fbc855ee78..43b8d650b8 100644 --- a/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 +++ b/examples/openthread/ot_sleepy_device/sdkconfig.ci.sleepy_h2 @@ -2,3 +2,5 @@ CONFIG_IDF_TARGET="esp32h2" CONFIG_IDF_TARGET_ESP32H2=y CONFIG_OPENTHREAD_NETWORK_CHANNEL=12 CONFIG_OPENTHREAD_NETWORK_MASTERKEY="aabbccddeeff00112233445566778899" +CONFIG_ESP_SLEEP_DEBUG=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG=y diff --git a/examples/openthread/pytest_otbr.py b/examples/openthread/pytest_otbr.py index 87334b4264..2ae516518b 100644 --- a/examples/openthread/pytest_otbr.py +++ b/examples/openthread/pytest_otbr.py @@ -576,6 +576,8 @@ def test_ot_sleepy_device(dut: Tuple[IdfDut, IdfDut]) -> None: ocf.clean_buffer(sleepy_device) sleepy_device.serial.hard_reset() sleepy_device.expect('detached -> child', timeout=20) + sleepy_device.expect('PMU_SLEEP_PD_TOP: True', timeout=10) + sleepy_device.expect('PMU_SLEEP_PD_MODEM: True', timeout=20) ocf.clean_buffer(sleepy_device) output = sleepy_device.expect(pexpect.TIMEOUT, timeout=5) assert 'rst:' not in str(output) and 'boot:' not in str(output)