diff --git a/components/esp_hw_support/sleep_system_peripheral.c b/components/esp_hw_support/sleep_system_peripheral.c index 8f472d84d875..f706a736479d 100644 --- a/components/esp_hw_support/sleep_system_peripheral.c +++ b/components/esp_hw_support/sleep_system_peripheral.c @@ -79,10 +79,10 @@ esp_err_t sleep_sys_periph_tee_apm_retention_init(void) esp_err_t sleep_sys_periph_uart0_retention_init(void) { - #define N_REGS_UART() (((UART_ID_REG(0) - REG_UART_BASE(0)) / 4) + 1) + #define N_REGS_UART() (((UART_ID_REG(0) - UART_INT_RAW_REG(0)) / 4) + 1) const static sleep_retention_entries_config_t uart_regs_retention[] = { - [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), REG_UART_BASE(0), REG_UART_BASE(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */ + [0] = { .config = REGDMA_LINK_CONTINUOUS_INIT(REGDMA_UART_LINK(0x00), UART_INT_RAW_REG(0), UART_INT_RAW_REG(0), N_REGS_UART(), 0, 0), .owner = ENTRY(0) | ENTRY(2) }, /* uart */ /* Note: uart register should set update reg to make the configuration take effect */ [1] = { .config = REGDMA_LINK_WRITE_INIT (REGDMA_UART_LINK(0x01), UART_REG_UPDATE_REG(0), UART_REG_UPDATE, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) }, [2] = { .config = REGDMA_LINK_WAIT_INIT (REGDMA_UART_LINK(0x02), UART_REG_UPDATE_REG(0), 0x0, UART_REG_UPDATE_M, 1, 0), .owner = ENTRY(0) | ENTRY(2) } diff --git a/examples/wifi/.build-test-rules.yml b/examples/wifi/.build-test-rules.yml index 0dc1197282cd..87d7c105f01c 100644 --- a/examples/wifi/.build-test-rules.yml +++ b/examples/wifi/.build-test-rules.yml @@ -29,6 +29,10 @@ examples/wifi/itwt: disable: - if: SOC_WIFI_HE_SUPPORT != 1 +examples/wifi/power_save: + disable: + - if: SOC_WIFI_SUPPORTED != 1 + examples/wifi/wifi_aware: disable: - if: SOC_WIFI_NAN_SUPPORT != 1 diff --git a/examples/wifi/power_save/README.md b/examples/wifi/power_save/README.md index 0e0583412240..95e01f1acdb9 100644 --- a/examples/wifi/power_save/README.md +++ b/examples/wifi/power_save/README.md @@ -23,4 +23,4 @@ Power save mode only works in station mode. If the modem sleep mode is enabled, ![current consumption with CONFIG_PM_ENABLE disabled](image/power_save_graph_PM_disabled.png) -Note that current consumption and average current are higher when disabled. \ No newline at end of file +Note that current consumption and average current are higher when disabled. diff --git a/examples/wifi/power_save/main/CMakeLists.txt b/examples/wifi/power_save/main/CMakeLists.txt index ff5ba16ba554..8a184368d389 100644 --- a/examples/wifi/power_save/main/CMakeLists.txt +++ b/examples/wifi/power_save/main/CMakeLists.txt @@ -1,2 +1,3 @@ idf_component_register(SRCS "power_save.c" + "get_ap_info.c" INCLUDE_DIRS ".") diff --git a/examples/wifi/power_save/main/Kconfig.projbuild b/examples/wifi/power_save/main/Kconfig.projbuild index 3b468d17bd5e..21a9f4c49ce3 100644 --- a/examples/wifi/power_save/main/Kconfig.projbuild +++ b/examples/wifi/power_save/main/Kconfig.projbuild @@ -1,14 +1,23 @@ menu "Example Configuration" + config EXAMPLE_GET_AP_INFO_FROM_STDIN + bool "Get AP info from console" + default n + help + If enabled, the example will prompt the user to enter the SSID and Password of the AP to be connected + via the console. + config EXAMPLE_WIFI_SSID string "WiFi SSID" default "myssid" + depends on !EXAMPLE_GET_AP_INFO_FROM_STDIN help SSID (network name) for the example to connect to. config EXAMPLE_WIFI_PASSWORD string "WiFi Password" default "mypassword" + depends on !EXAMPLE_GET_AP_INFO_FROM_STDIN help WiFi password (WPA or WPA2) for the example to use. diff --git a/examples/wifi/power_save/main/get_ap_info.c b/examples/wifi/power_save/main/get_ap_info.c new file mode 100644 index 000000000000..00c9558464de --- /dev/null +++ b/examples/wifi/power_save/main/get_ap_info.c @@ -0,0 +1,68 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_vfs_dev.h" +#include "driver/uart.h" + +#if CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN +static const char *TAG = "power_save"; +static char stdin_ssid[32]; +static char stdin_password[64]; + +void get_ap_info_from_stdin(void) +{ + // Initialize VFS & UART so we can use std::cout/cin + setvbuf(stdin, NULL, _IONBF, 0); + /* Install UART driver for interrupt-driven reads and writes */ + ESP_ERROR_CHECK( uart_driver_install( (uart_port_t)CONFIG_ESP_CONSOLE_UART_NUM, + 256, 0, 0, NULL, 0) ); + + /* Tell VFS to use UART driver */ + esp_vfs_dev_uart_use_driver(CONFIG_ESP_CONSOLE_UART_NUM); + esp_vfs_dev_uart_port_set_rx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CR); + /* Move the caret to the beginning of the next line on '\n' */ + esp_vfs_dev_uart_port_set_tx_line_endings(CONFIG_ESP_CONSOLE_UART_NUM, ESP_LINE_ENDINGS_CRLF); + + ESP_LOGI(TAG, "Input SSID:"); + + if (fgets(stdin_ssid, 32, stdin) == NULL) { + ESP_LOGE(TAG, "Failed to get SSID"); + } else { + stdin_ssid[strcspn(stdin_ssid, "\n")] = '\0'; + } + + ESP_LOGI(TAG, "Input Password:"); + if (fgets(stdin_password, 64, stdin) == NULL) { + ESP_LOGE(TAG, "Failed to get password"); + } else { + stdin_password[strcspn(stdin_password, "\n")] = '\0'; + } + + /* Back to use non-blocking vfs console*/ + esp_vfs_dev_uart_use_nonblocking(CONFIG_ESP_CONSOLE_UART_NUM); + uart_driver_delete(CONFIG_ESP_CONSOLE_UART_NUM); +} +#endif + +char *get_ap_ssid(void) +{ +#if CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN + return stdin_ssid; +#else + return CONFIG_EXAMPLE_WIFI_SSID; +#endif +} + +char *get_ap_password(void) +{ +#if CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN + return stdin_password; +#else + return CONFIG_EXAMPLE_WIFI_PASSWORD; +#endif +} diff --git a/examples/wifi/power_save/main/get_ap_info.h b/examples/wifi/power_save/main/get_ap_info.h new file mode 100644 index 000000000000..e41c83db4f54 --- /dev/null +++ b/examples/wifi/power_save/main/get_ap_info.h @@ -0,0 +1,34 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + + +#if CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN +/** + * Initialize vfs console and prompt user input the AP info + */ +void get_ap_info_from_stdin(void); +#endif + +/** + * Get the AP ssid from user input or configure + * @return The string of SSID + */ +char *get_ap_ssid(void); + +/** + * Get the AP password from user input or configure + * @return The string of password + */ +char *get_ap_password(void); + +#ifdef __cplusplus +} +#endif diff --git a/examples/wifi/power_save/main/power_save.c b/examples/wifi/power_save/main/power_save.c index 5bd256b78841..d804974d6510 100644 --- a/examples/wifi/power_save/main/power_save.c +++ b/examples/wifi/power_save/main/power_save.c @@ -12,6 +12,8 @@ set a router or a AP using the same SSID&PASSWORD as configuration of this example. start esp32 and when it connected to AP it will enter power save mode */ +#include +#include "sdkconfig.h" #include "freertos/FreeRTOS.h" #include "freertos/event_groups.h" #include "esp_wifi.h" @@ -19,10 +21,7 @@ #include "esp_event.h" #include "esp_pm.h" #include "nvs_flash.h" - -/*set the ssid and password via "idf.py menuconfig"*/ -#define DEFAULT_SSID CONFIG_EXAMPLE_WIFI_SSID -#define DEFAULT_PWD CONFIG_EXAMPLE_WIFI_PASSWORD +#include "get_ap_info.h" #define DEFAULT_LISTEN_INTERVAL CONFIG_EXAMPLE_WIFI_LISTEN_INTERVAL #define DEFAULT_BEACON_TIMEOUT CONFIG_EXAMPLE_WIFI_BEACON_TIMEOUT @@ -69,11 +68,15 @@ static void wifi_power_save(void) wifi_config_t wifi_config = { .sta = { - .ssid = DEFAULT_SSID, - .password = DEFAULT_PWD, .listen_interval = DEFAULT_LISTEN_INTERVAL, }, }; + + strcpy((char *)wifi_config.sta.ssid, get_ap_ssid()); + strcpy((char *)wifi_config.sta.password, get_ap_password()); + + ESP_LOGI(TAG, "Connecting AP: %s with password: %s", wifi_config.sta.ssid, wifi_config.sta.password); + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config)); ESP_ERROR_CHECK(esp_wifi_start()); @@ -93,6 +96,10 @@ void app_main(void) } ESP_ERROR_CHECK( ret ); +#if CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN + get_ap_info_from_stdin(); +#endif + #if CONFIG_PM_ENABLE // Configure dynamic frequency scaling: // maximum and minimum frequencies are set in sdkconfig, diff --git a/examples/wifi/power_save/pytest_wifi_power_save.py b/examples/wifi/power_save/pytest_wifi_power_save.py new file mode 100644 index 000000000000..265e76439959 --- /dev/null +++ b/examples/wifi/power_save/pytest_wifi_power_save.py @@ -0,0 +1,77 @@ +# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import logging + +import pexpect +import pytest +from common_test_methods import get_env_config_variable +from pytest_embedded import Dut + +bad_event_str = [ + 'bcn_timout', + 'm f probe req l', + 'abort() was called', + 'Guru Meditation Error', +] + + +def _run_test(dut: Dut) -> None: + if dut.app.sdkconfig.get('EXAMPLE_GET_AP_INFO_FROM_STDIN') is True: + env_name = 'wifi_ap' + ap_ssid = get_env_config_variable(env_name, 'ap_ssid') + ap_password = get_env_config_variable(env_name, 'ap_password') + tag = 'power_save' + dut.expect(f'{tag}: Input SSID:', timeout=5) + dut.write(f'{ap_ssid}') + dut.expect(f'{tag}: Input Password:', timeout=5) + dut.write(f'{ap_password}') + else: + # for local test may config ssid/password from menuconfig + pass + + try: + dut.expect(r'got ip: (\d+\.\d+\.\d+\.\d+)[^\d]', timeout=20) + log_after_got_ip = dut.expect(pexpect.TIMEOUT, timeout=10).decode() + if any(s in log_after_got_ip for s in bad_event_str): + logging.info('Abnormal connection log:') + logging.info('\n' + log_after_got_ip) + raise RuntimeError('Something abnormal happened after got ip') + except pexpect.exceptions.TIMEOUT: + raise RuntimeError('Failed to get ip in power save mode') + + +@pytest.mark.esp32 +@pytest.mark.esp32c2 +@pytest.mark.esp32s2 +@pytest.mark.esp32c3 +@pytest.mark.esp32s3 +@pytest.mark.esp32c6 +@pytest.mark.wifi_ap +def test_wifi_power_save(dut: Dut) -> None: + _run_test(dut) + + +@pytest.mark.esp32c6 +@pytest.mark.wifi_ap +@pytest.mark.parametrize( + 'config', + [ + 'pd_top', + ], + indirect=True, +) +def test_wifi_power_save_pd_top(dut: Dut) -> None: + _run_test(dut) + + +@pytest.mark.esp32c2 +@pytest.mark.wifi_ap +@pytest.mark.xtal_26mhz +@pytest.mark.parametrize( + 'config, baud', [ + ('c2_xtal26m', '74880'), + ], indirect=True +) +def test_wifi_power_save_esp32c2_26mhz(dut: Dut) -> None: + _run_test(dut) diff --git a/examples/wifi/power_save/sdkconfig.ci.c2_xtal26m b/examples/wifi/power_save/sdkconfig.ci.c2_xtal26m new file mode 100644 index 000000000000..065020b06fb2 --- /dev/null +++ b/examples/wifi/power_save/sdkconfig.ci.c2_xtal26m @@ -0,0 +1,3 @@ +CONFIG_IDF_TARGET="esp32c2" +CONFIG_XTAL_FREQ_26=y +CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN=y diff --git a/examples/wifi/power_save/sdkconfig.ci.default b/examples/wifi/power_save/sdkconfig.ci.default new file mode 100644 index 000000000000..4054e1490a98 --- /dev/null +++ b/examples/wifi/power_save/sdkconfig.ci.default @@ -0,0 +1 @@ +CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN=y diff --git a/examples/wifi/power_save/sdkconfig.ci.pd_top b/examples/wifi/power_save/sdkconfig.ci.pd_top new file mode 100644 index 000000000000..d4eb06e13ff7 --- /dev/null +++ b/examples/wifi/power_save/sdkconfig.ci.pd_top @@ -0,0 +1,4 @@ +CONFIG_EXAMPLE_GET_AP_INFO_FROM_STDIN=y +CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y +CONFIG_ESP_PHY_MAC_BB_PD=y +CONFIG_MBEDTLS_HARDWARE_AES=n