diff --git a/components/esp_driver_gpio/src/dedic_gpio.c b/components/esp_driver_gpio/src/dedic_gpio.c index 3faf0d9de7..410f60e79b 100644 --- a/components/esp_driver_gpio/src/dedic_gpio.c +++ b/components/esp_driver_gpio/src/dedic_gpio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,6 +32,8 @@ #include "hal/dedic_gpio_ll.h" #endif +#define DEDIC_GPIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT + static const char *TAG = "dedic_gpio"; typedef struct dedic_gpio_platform_t dedic_gpio_platform_t; @@ -74,7 +76,7 @@ static esp_err_t dedic_gpio_build_platform(int core_id) // prevent building platform concurrently _lock_acquire(&s_platform_mutexlock[core_id]); if (!s_platform[core_id]) { - s_platform[core_id] = calloc(1, sizeof(dedic_gpio_platform_t)); + s_platform[core_id] = (dedic_gpio_platform_t *)heap_caps_calloc(1, sizeof(dedic_gpio_platform_t), DEDIC_GPIO_MEM_ALLOC_CAPS); if (s_platform[core_id]) { // initialize platform members s_platform[core_id]->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; @@ -212,7 +214,7 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ ESP_GOTO_ON_ERROR(dedic_gpio_build_platform(core_id), err, TAG, "build platform %d failed", core_id); size_t bundle_size = sizeof(dedic_gpio_bundle_t) + config->array_size * sizeof(config->gpio_array[0]); - bundle = calloc(1, bundle_size); + bundle = (dedic_gpio_bundle_t *)heap_caps_calloc(1, bundle_size, DEDIC_GPIO_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(bundle, ESP_ERR_NO_MEM, err, TAG, "no mem for bundle"); // for performance reasons, we only search for continuous channels diff --git a/components/esp_driver_gpio/test_apps/gpio/main/CMakeLists.txt b/components/esp_driver_gpio/test_apps/gpio/main/CMakeLists.txt index 54bda14eae..5d076f931d 100644 --- a/components/esp_driver_gpio/test_apps/gpio/main/CMakeLists.txt +++ b/components/esp_driver_gpio/test_apps/gpio/main/CMakeLists.txt @@ -8,5 +8,5 @@ endif() # 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} - PRIV_REQUIRES unity esp_driver_gpio spi_flash + PRIV_REQUIRES unity esp_driver_gpio spi_flash esp_psram WHOLE_ARCHIVE) diff --git a/components/esp_driver_gpio/test_apps/gpio/sdkconfig.defaults.esp32p4 b/components/esp_driver_gpio/test_apps/gpio/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..d2699b2221 --- /dev/null +++ b/components/esp_driver_gpio/test_apps/gpio/sdkconfig.defaults.esp32p4 @@ -0,0 +1,3 @@ +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/main/CMakeLists.txt b/components/esp_driver_gpio/test_apps/gpio_extensions/main/CMakeLists.txt index ac737d0ac3..2b6b748106 100644 --- a/components/esp_driver_gpio/test_apps/gpio_extensions/main/CMakeLists.txt +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/main/CMakeLists.txt @@ -19,7 +19,7 @@ endif() # 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} - PRIV_REQUIRES unity esp_driver_gpio + PRIV_REQUIRES unity esp_driver_gpio esp_psram WHOLE_ARCHIVE) message(STATUS "Checking gpio_ext registers are not read-write by half-word") diff --git a/components/esp_driver_gpio/test_apps/gpio_extensions/sdkconfig.defaults.esp32p4 b/components/esp_driver_gpio/test_apps/gpio_extensions/sdkconfig.defaults.esp32p4 new file mode 100644 index 0000000000..d2699b2221 --- /dev/null +++ b/components/esp_driver_gpio/test_apps/gpio_extensions/sdkconfig.defaults.esp32p4 @@ -0,0 +1,3 @@ +CONFIG_SPIRAM=y +CONFIG_SPIRAM_MODE_HEX=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index c7096c62cb..ab418ccb16 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -33,6 +33,9 @@ #include "driver/rtc_io.h" #include "soc/rtc_io_channel.h" #include "driver/lp_io.h" +#if SOC_LP_GPIO_MATRIX_SUPPORTED +#include "soc/lp_gpio_pins.h" +#endif #endif #if I2C_USE_RETENTION_LINK #include "esp_private/sleep_retention.h" @@ -428,8 +431,8 @@ esp_err_t i2c_common_deinit_pins(i2c_bus_handle_t handle) ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->sda_num), TAG, "deinit rtc gpio failed"); ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->scl_num), TAG, "deinit rtc gpio failed"); #if SOC_LP_GPIO_MATRIX_SUPPORTED - lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0); - lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0); + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0); + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0); #endif } #endif diff --git a/components/esp_driver_ppa/test_apps/pytest_ppa.py b/components/esp_driver_ppa/test_apps/pytest_ppa.py index 5622c6be44..ed18219927 100644 --- a/components/esp_driver_ppa/test_apps/pytest_ppa.py +++ b/components/esp_driver_ppa/test_apps/pytest_ppa.py @@ -3,6 +3,7 @@ import pytest from pytest_embedded import Dut from pytest_embedded_idf.utils import idf_parametrize +from pytest_embedded_idf.utils import soc_filtered_targets @pytest.mark.generic @@ -13,6 +14,6 @@ from pytest_embedded_idf.utils import idf_parametrize ], indirect=True, ) -@idf_parametrize('target', ['esp32p4'], indirect=['target']) +@idf_parametrize('target', soc_filtered_targets('SOC_PPA_SUPPORTED == 1'), indirect=['target']) def test_ppa(dut: Dut) -> None: dut.run_all_single_board_cases() diff --git a/components/esp_driver_ppa/test_apps/sdkconfig.defaults.esp32p4 b/components/esp_driver_ppa/test_apps/sdkconfig.defaults.esp32p4 index 702fac3342..729de73952 100644 --- a/components/esp_driver_ppa/test_apps/sdkconfig.defaults.esp32p4 +++ b/components/esp_driver_ppa/test_apps/sdkconfig.defaults.esp32p4 @@ -1,3 +1,4 @@ CONFIG_SPIRAM=y CONFIG_SPIRAM_MODE_HEX=y CONFIG_SPIRAM_SPEED_200M=y +CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=0 diff --git a/components/esp_driver_uart/include/driver/uart_wakeup.h b/components/esp_driver_uart/include/driver/uart_wakeup.h index 7e735d7d29..4ac3665da0 100644 --- a/components/esp_driver_uart/include/driver/uart_wakeup.h +++ b/components/esp_driver_uart/include/driver/uart_wakeup.h @@ -74,8 +74,11 @@ esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg); * * @param uart_num The UART port to initialize for wakeup (e.g., UART_NUM_0, UART_NUM_1, etc.). * @param wakeup_mode The UART wakeup mode set in `uart_wakeup_setup`. + * + * @return + * - `ESP_OK` Clear wakeup configuration successfully. */ -void uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode); +esp_err_t uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode); #ifdef __cplusplus } diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 9656a3ff06..12733ec167 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -35,6 +35,9 @@ #include "driver/rtc_io.h" #include "hal/rtc_io_ll.h" #include "driver/lp_io.h" +#if SOC_LP_GPIO_MATRIX_SUPPORTED +#include "soc/lp_gpio_pins.h" +#endif #endif #include "clk_ctrl_os.h" #include "esp_pm.h" @@ -108,6 +111,11 @@ static const char *UART_TAG = "uart"; .hal.dev = UART_LL_GET_HW(uart_num), \ INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) \ .hw_enabled = false, \ + .tx_io_num = -1, \ + .rx_io_num = -1, \ + .rts_io_num = -1, \ + .cts_io_num = -1, \ + .io_reserved_mask = 0, \ } typedef struct { @@ -169,6 +177,11 @@ typedef struct uart_context_t { uart_hal_context_t hal; /*!< UART hal context*/ DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) bool hw_enabled; + int tx_io_num; + int rx_io_num; + int rts_io_num; + int cts_io_num; + uint64_t io_reserved_mask; } uart_context_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; @@ -707,8 +720,72 @@ static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t id return true; } -//internal signal can be output to multiple GPIO pads -//only one GPIO pad can connect with input signal +static void uart_release_pin(uart_port_t uart_num) +{ + if (uart_num >= UART_NUM_MAX) { + return; + } + if (uart_context[uart_num].tx_io_num >= 0) { + gpio_output_disable(uart_context[uart_num].tx_io_num); +#if (SOC_UART_LP_NUM >= 1) + if (!(uart_num < SOC_UART_HP_NUM)) { + rtc_gpio_deinit(uart_context[uart_num].tx_io_num); + } +#endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + gpio_sleep_sel_en(uart_context[uart_num].tx_io_num); // re-enable the switch to the sleep configuration to save power consumption +#endif + } + + if (uart_context[uart_num].rx_io_num >= 0) { + if (uart_num < SOC_UART_HP_NUM) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); + } +#if (SOC_UART_LP_NUM >= 1) + else { +#if SOC_LP_GPIO_MATRIX_SUPPORTED + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); +#endif + rtc_gpio_deinit(uart_context[uart_num].rx_io_num); + } +#endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + gpio_sleep_sel_en(uart_context[uart_num].rx_io_num); // re-enable the switch to the sleep configuration to save power consumption +#endif + } + + if (uart_context[uart_num].rts_io_num >= 0) { + gpio_output_disable(uart_context[uart_num].rts_io_num); +#if (SOC_UART_LP_NUM >= 1) + if (!(uart_num < SOC_UART_HP_NUM)) { + rtc_gpio_deinit(uart_context[uart_num].rts_io_num); + } +#endif + } + + if (uart_context[uart_num].cts_io_num >= 0) { + if (uart_num < SOC_UART_HP_NUM) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false); + } +#if (SOC_UART_LP_NUM >= 1) + else { +#if SOC_LP_GPIO_MATRIX_SUPPORTED + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false); +#endif + rtc_gpio_deinit(uart_context[uart_num].cts_io_num); + } +#endif + } + + esp_gpio_revoke(uart_context[uart_num].io_reserved_mask); + + uart_context[uart_num].tx_io_num = -1; + uart_context[uart_num].rx_io_num = -1; + uart_context[uart_num].rts_io_num = -1; + uart_context[uart_num].cts_io_num = -1; + uart_context[uart_num].io_reserved_mask = 0; +} + esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { ESP_RETURN_ON_FALSE((uart_num >= 0), ESP_FAIL, UART_TAG, "uart_num error"); @@ -740,6 +817,9 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #endif + // First, release previously configured IOs if there is + uart_release_pin(uart_num); + // Potential IO reserved mask uint64_t io_reserve_mask = 0; io_reserve_mask |= (tx_io_num > 0 ? BIT64(tx_io_num) : 0); @@ -752,42 +832,60 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r bool tx_rx_same_io = (tx_io_num == rx_io_num); /* In the following statements, if the io_num is negative, no need to configure anything. */ - if (tx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX))) { - if (uart_num < SOC_UART_HP_NUM) { - gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); - esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); - // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected - // (output enabled too early may cause unnecessary level change at the pad) - } -#if SOC_LP_GPIO_MATRIX_SUPPORTED - else { - rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin - lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); - // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected - } + if (tx_io_num >= 0) { + uart_context[uart_num].tx_io_num = tx_io_num; +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason + // But TX IO in isolate state could write garbled data to the other end + // Therefore, we should disable the switch of the TX pin to sleep configuration + gpio_sleep_sel_dis(tx_io_num); #endif - } - - if (rx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX))) { - io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved - if (uart_num < SOC_UART_HP_NUM) { - gpio_input_enable(rx_io_num); - esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); - } -#if SOC_LP_GPIO_MATRIX_SUPPORTED - else { - rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); - rtc_gpio_set_direction(rx_io_num, mode); - if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip - rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin + if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) { + if (uart_num < SOC_UART_HP_NUM) { + gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected + // (output enabled too early may cause unnecessary level change at the pad) + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin + lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected } - - lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); - } #endif + } } - if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) { + if (rx_io_num >= 0) { + uart_context[uart_num].rx_io_num = rx_io_num; +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason + // But RX IO in isolate state could receive garbled data into FIFO, which is not desired + // Therefore, we should disable the switch of the RX pin to sleep configuration + gpio_sleep_sel_dis(rx_io_num); +#endif + if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { + io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved + if (uart_num < SOC_UART_HP_NUM) { + gpio_input_enable(rx_io_num); + esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_set_direction(rx_io_num, mode); + if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip + rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin + } + + lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#endif + } + } + + if (rts_io_num >= 0 && (uart_context[uart_num].rts_io_num = rts_io_num, !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX))) { if (uart_num < SOC_UART_HP_NUM) { gpio_func_sel(rts_io_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); @@ -802,7 +900,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r #endif } - if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) { + if (cts_io_num >= 0 && (uart_context[uart_num].cts_io_num = cts_io_num, !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX))) { io_reserve_mask &= ~BIT64(cts_io_num); // input IO via GPIO matrix does not need to be reserved if (uart_num < SOC_UART_HP_NUM) { gpio_pullup_en(cts_io_num); @@ -819,6 +917,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } // IO reserve + uart_context[uart_num].io_reserved_mask = io_reserve_mask; uint64_t old_busy_mask = esp_gpio_reserve(io_reserve_mask); uint64_t conflict_mask = old_busy_mask & io_reserve_mask; while (conflict_mask > 0) { @@ -1801,6 +1900,9 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) ESP_LOGI(UART_TAG, "ALREADY NULL"); return ESP_OK; } + + uart_release_pin(uart_num); + esp_intr_free(p_uart_obj[uart_num]->intr_handle); uart_disable_rx_intr(uart_num); uart_disable_tx_intr(uart_num); @@ -2077,7 +2179,7 @@ esp_err_t uart_detect_bitrate_stop(uart_port_t uart_num, bool deinit, uart_bitra } if (deinit) { // release the port - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + uart_release_pin(uart_num); #if SOC_UART_SUPPORT_RTC_CLK if (src_clk == (soc_module_clk_t)UART_SCLK_RTC) { periph_rtc_dig_clk8m_disable(); diff --git a/components/esp_driver_uart/src/uart_wakeup.c b/components/esp_driver_uart/src/uart_wakeup.c index 174dedf14c..8412487a1e 100644 --- a/components/esp_driver_uart/src/uart_wakeup.c +++ b/components/esp_driver_uart/src/uart_wakeup.c @@ -11,6 +11,7 @@ * Updates to this file should be made carefully and should not include FreeRTOS APIs or other IDF-specific functionalities, such as the interrupt allocator. */ +#include "esp_check.h" #include "driver/uart_wakeup.h" #include "hal/uart_hal.h" #include "esp_private/esp_sleep_internal.h" @@ -54,29 +55,26 @@ static esp_err_t uart_char_seq_wk_configure(uart_dev_t *hw, const char* phrase) esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg) { - - if (cfg == NULL) { - return ESP_ERR_INVALID_ARG; - } + ESP_RETURN_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, TAG, "cfg is NULL"); uart_dev_t *hw = UART_LL_GET_HW(uart_num); + uart_hal_context_t hal = { + .dev = hw, + }; + soc_module_clk_t src_clk; + uart_hal_get_sclk(&hal, &src_clk); + if (uart_num < SOC_UART_HP_NUM && cfg->wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) { + // For wakeup modes except ACTIVE_THRESH, the function clock needs to be exist to trigger wakeup + ESP_RETURN_ON_FALSE(src_clk == SOC_MOD_CLK_XTAL, ESP_ERR_NOT_SUPPORTED, TAG, "failed to setup uart wakeup due to the clock source is not XTAL!"); + } + + esp_err_t ret = ESP_OK; // This should be mocked at ll level if the selection of the UART wakeup mode is not supported by this SOC. uart_ll_set_wakeup_mode(hw, cfg->wakeup_mode); #if SOC_PM_SUPPORT_PMU_CLK_ICG // When hp uarts are utilized, the main XTAL need to be PU and UARTx & IOMX ICG need to be ungate - bool __attribute__((unused)) is_hp_uart = (uart_num < SOC_UART_HP_NUM); - uart_hal_context_t hal = { - .dev = hw, - }; - soc_module_clk_t src_clk; - uart_hal_get_sclk(&hal, &src_clk); - - if (is_hp_uart && cfg->wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) { - if (src_clk != SOC_MOD_CLK_XTAL) { - ESP_LOGE(TAG, "Failed to setup uart wakeup due to the clock source is not XTAL!"); - return ESP_ERR_NOT_SUPPORTED; - } + if (uart_num < SOC_UART_HP_NUM && cfg->wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) { esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON); esp_sleep_clock_config(UART_LL_SLEEP_CLOCK(uart_num), ESP_SLEEP_CLOCK_OPTION_UNGATE); esp_sleep_clock_config(ESP_SLEEP_CLOCK_IOMUX, ESP_SLEEP_CLOCK_OPTION_UNGATE); @@ -86,45 +84,48 @@ esp_err_t uart_wakeup_setup(uart_port_t uart_num, const uart_wakeup_cfg_t *cfg) switch (cfg->wakeup_mode) { #if SOC_UART_WAKEUP_SUPPORT_ACTIVE_THRESH_MODE case UART_WK_MODE_ACTIVE_THRESH: - // UART_ACTIVE_THRESHOLD register has only 10 bits, and the min value is 3. if (cfg->rx_edge_threshold < UART_LL_WAKEUP_EDGE_THRED_MIN || cfg->rx_edge_threshold > UART_LL_WAKEUP_EDGE_THRED_MAX(hw)) { - return ESP_ERR_INVALID_ARG; + ret = ESP_ERR_INVALID_ARG; + } else { + uart_ll_set_wakeup_edge_thrd(hw, cfg->rx_edge_threshold); } - uart_ll_set_wakeup_edge_thrd(hw, cfg->rx_edge_threshold); - return ESP_OK; + break; #endif #if SOC_UART_WAKEUP_SUPPORT_FIFO_THRESH_MODE case UART_WK_MODE_FIFO_THRESH: if (cfg->rx_fifo_threshold > UART_LL_WAKEUP_FIFO_THRED_MAX(hw)) { - return ESP_ERR_INVALID_ARG; + ret = ESP_ERR_INVALID_ARG; + } else { + uart_ll_set_wakeup_fifo_thrd(hw, cfg->rx_fifo_threshold); } - uart_ll_set_wakeup_fifo_thrd(hw, cfg->rx_fifo_threshold); - return ESP_OK; + break; #endif #if SOC_UART_WAKEUP_SUPPORT_START_BIT_MODE case UART_WK_MODE_START_BIT: - return ESP_OK; + break; #endif #if SOC_UART_WAKEUP_SUPPORT_CHAR_SEQ_MODE case UART_WK_MODE_CHAR_SEQ: - return uart_char_seq_wk_configure(hw, cfg->wake_chars_seq); + ret = uart_char_seq_wk_configure(hw, cfg->wake_chars_seq); + break; #endif + default: + ret = ESP_ERR_INVALID_ARG; + break; } - return ESP_ERR_INVALID_ARG; + return ret; } -void uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode) +esp_err_t uart_wakeup_clear(uart_port_t uart_num, uart_wakeup_mode_t wakeup_mode) { #if SOC_PM_SUPPORT_PMU_CLK_ICG // When hp uarts are utilized, the main XTAL need to be PU and UARTx & IOMX ICG need to be ungate - bool __attribute__((unused)) is_hp_uart = (uart_num < SOC_UART_HP_NUM); - - if (is_hp_uart && wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) { + if (uart_num < SOC_UART_HP_NUM && wakeup_mode != UART_WK_MODE_ACTIVE_THRESH) { esp_sleep_clock_config(UART_LL_SLEEP_CLOCK(uart_num), ESP_SLEEP_CLOCK_OPTION_GATE); esp_sleep_clock_config(ESP_SLEEP_CLOCK_IOMUX, ESP_SLEEP_CLOCK_OPTION_GATE); esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF); } #endif - + return ESP_OK; } diff --git a/components/esp_driver_uart/test_apps/uart/main/test_hp_uart_wakeup.c b/components/esp_driver_uart/test_apps/uart/main/test_hp_uart_wakeup.c index fefe3b907c..704e8c60af 100644 --- a/components/esp_driver_uart/test_apps/uart/main/test_hp_uart_wakeup.c +++ b/components/esp_driver_uart/test_apps/uart/main/test_hp_uart_wakeup.c @@ -5,26 +5,14 @@ */ #include #include -#include -#include #include "unity.h" #include "test_utils.h" #include "driver/uart.h" #include "driver/uart_wakeup.h" -#include "esp_log.h" -#include "esp_rom_gpio.h" -#include "esp_private/gpio.h" #include "esp_sleep.h" #include "esp_timer.h" -#if SOC_LP_GPIO_MATRIX_SUPPORTED -#include "driver/lp_io.h" -#include "driver/rtc_io.h" -#include "hal/rtc_io_ll.h" -#endif -#include "soc/uart_periph.h" #include "soc/uart_pins.h" #include "soc/soc_caps.h" -#include "soc/clk_tree_defs.h" #include "test_common.h" #if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32P4 @@ -84,9 +72,9 @@ static esp_err_t uart_initialization(uart_port_param_t *port_param) }; const int uart_tx = port_param->tx_pin_num; const int uart_rx = port_param->rx_pin_num; + TEST_ESP_OK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0)); TEST_ESP_OK(uart_param_config(uart_num, &uart_config)); TEST_ESP_OK(uart_set_pin(uart_num, uart_tx, uart_rx, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); - TEST_ESP_OK(uart_driver_install(uart_num, BUF_SIZE * 2, BUF_SIZE * 2, 20, NULL, 0)); return ESP_OK; } @@ -100,9 +88,6 @@ static esp_err_t uart_wakeup_config(uart_port_param_t *port_param, uart_wakeup_c * of the SOC to ensure proper operation. Besides, the Rx pin need extra configuration to enable it can work during light sleep */ uart_port_t uart_num = port_param->port_num; - int rx_io_num = port_param->rx_pin_num; - // Keep configure of rx_io - TEST_ESP_OK(gpio_sleep_sel_dis(rx_io_num)); // Initializes the UART wakeup functionality. TEST_ESP_OK(uart_wakeup_setup(uart_num, uart_wakeup_cfg)); TEST_ESP_OK(esp_sleep_enable_uart_wakeup(uart_num)); diff --git a/examples/system/light_sleep/main/uart_wakeup.c b/examples/system/light_sleep/main/uart_wakeup.c index 6bba8e2798..d5f8d7bf1b 100644 --- a/examples/system/light_sleep/main/uart_wakeup.c +++ b/examples/system/light_sleep/main/uart_wakeup.c @@ -12,7 +12,6 @@ #include "soc/uart_pins.h" #include "driver/uart.h" #include "driver/uart_wakeup.h" -#include "driver/gpio.h" #include "sdkconfig.h" #define EXAMPLE_UART_NUM 0 @@ -42,6 +41,7 @@ static void uart_wakeup_task(void *arg) } uint8_t* dtmp = (uint8_t*) malloc(EXAMPLE_READ_BUF_SIZE); + assert(dtmp); while(1) { // Waiting for UART event. @@ -100,7 +100,7 @@ static void uart_wakeup_task(void *arg) vTaskDelete(NULL); } -static esp_err_t uart_initialization(void) +static void uart_initialization(void) { uart_config_t uart_cfg = { .baud_rate = CONFIG_ESP_CONSOLE_UART_BAUDRATE, @@ -115,19 +115,16 @@ static esp_err_t uart_initialization(void) #endif }; //Install UART driver, and get the queue. - ESP_RETURN_ON_ERROR(uart_driver_install(EXAMPLE_UART_NUM, EXAMPLE_UART_BUF_SIZE, EXAMPLE_UART_BUF_SIZE, 20, &uart_evt_que, 0), - TAG, "Install uart failed"); + ESP_ERROR_CHECK(uart_driver_install(EXAMPLE_UART_NUM, EXAMPLE_UART_BUF_SIZE, EXAMPLE_UART_BUF_SIZE, 20, &uart_evt_que, 0)); if (EXAMPLE_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM) { /* temp fix for uart garbled output, can be removed when IDF-5683 done */ - ESP_RETURN_ON_ERROR(uart_wait_tx_idle_polling(EXAMPLE_UART_NUM), TAG, "Wait uart tx done failed"); + ESP_ERROR_CHECK(uart_wait_tx_idle_polling(EXAMPLE_UART_NUM)); } - ESP_RETURN_ON_ERROR(uart_param_config(EXAMPLE_UART_NUM, &uart_cfg), TAG, "Configure uart param failed"); - ESP_RETURN_ON_ERROR(uart_set_pin(EXAMPLE_UART_NUM, EXAMPLE_UART_TX_IO_NUM, EXAMPLE_UART_RX_IO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE), - TAG, "Configure uart gpio pins failed"); - return ESP_OK; + ESP_ERROR_CHECK(uart_param_config(EXAMPLE_UART_NUM, &uart_cfg)); + ESP_ERROR_CHECK(uart_set_pin(EXAMPLE_UART_NUM, EXAMPLE_UART_TX_IO_NUM, EXAMPLE_UART_RX_IO_NUM, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); } -static esp_err_t uart_wakeup_config(void) +static void uart_wakeup_config(void) { uart_wakeup_cfg_t uart_wakeup_cfg = {}; uint8_t wakeup_mode = CONFIG_EXAMPLE_UART_WAKEUP_MODE_SELCTED; @@ -162,23 +159,23 @@ static esp_err_t uart_wakeup_config(void) #endif default: ESP_LOGE(TAG, "Unknown UART wakeup mode"); - return ESP_FAIL; + ESP_ERROR_CHECK(ESP_FAIL); break; } ESP_ERROR_CHECK(uart_wakeup_setup(EXAMPLE_UART_NUM, &uart_wakeup_cfg)); ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(EXAMPLE_UART_NUM)); - return ESP_OK; } esp_err_t example_register_uart_wakeup(void) { - /* Initialize uart1 */ - ESP_RETURN_ON_ERROR(uart_initialization(), TAG, "Initialize uart%d failed", EXAMPLE_UART_NUM); + /* Initialize console uart */ + uart_initialization(); /* Enable wakeup from uart */ - ESP_RETURN_ON_ERROR(uart_wakeup_config(), TAG, "Configure uart as wakeup source failed"); + uart_wakeup_config(); xTaskCreate(uart_wakeup_task, "uart_wakeup_task", 4096, NULL, 5, NULL); ESP_LOGI(TAG, "uart wakeup source is ready"); + return ESP_OK; }