diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index fb9cb95fa2..113e6e91d8 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -183,6 +183,10 @@ config SOC_LP_TIMER_SUPPORTED bool default y +config SOC_ULP_LP_UART_SUPPORTED + bool + default y + config SOC_LP_GPIO_MATRIX_SUPPORTED bool default y diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index cbcfba0c9d..dc4d629791 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -72,7 +72,7 @@ #define SOC_DCDC_SUPPORTED 1 // #define SOC_PAU_SUPPORTED 1 //TODO: IDF-7531 #define SOC_LP_TIMER_SUPPORTED 1 -// #define SOC_ULP_LP_UART_SUPPORTED 1 //TODO: IDF-7533 +#define SOC_ULP_LP_UART_SUPPORTED 1 #define SOC_LP_GPIO_MATRIX_SUPPORTED 1 #define SOC_LP_PERIPHERALS_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 diff --git a/components/ulp/Kconfig b/components/ulp/Kconfig index 5b8a7c5ce1..29b1e5ff00 100644 --- a/components/ulp/Kconfig +++ b/components/ulp/Kconfig @@ -80,4 +80,16 @@ menu "Ultra Low Power (ULP) Co-processor" Size of the shared memory defined in ulp_lp_core_memory_shared.c. Size should be kept in-sync with the size of the struct defined there. + config ULP_ROM_PRINT_ENABLE + depends on ULP_COPROC_TYPE_LP_CORE && ESP_ROM_HAS_LP_ROM + bool + prompt "Enable print utilities from LP ROM" + default "y" + help + Set this option to enable printf functionality from LP ROM. This option + can help reduce the LP core binary size by not linking printf functionality + from RAM code. + Note: For LP ROM prints to work properly, make sure that the LP core boots + from the LP ROM. + endmenu # Ultra Low Power (ULP) Co-processor diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index e396502853..d35f517966 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -54,6 +54,7 @@ target_link_options(${ULP_APP_NAME} PRIVATE SHELL:-T ${CMAKE_CURRENT_BINARY_DIR} # To avoid warning "Manually-specified variables were not used by the project" set(bypassWarning "${IDF_TARGET}") +set(bypassWarning "${CONFIG_ESP_ROM_HAS_LP_ROM}") if(ULP_COCPU_IS_RISCV) #risc-v ulp uses extra files for building: list(APPEND ULP_S_SOURCES diff --git a/components/ulp/lp_core/include/lp_core_uart.h b/components/ulp/lp_core/include/lp_core_uart.h index dfb2b5bd3a..3b367a548d 100644 --- a/components/ulp/lp_core/include/lp_core_uart.h +++ b/components/ulp/lp_core/include/lp_core_uart.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,23 @@ extern "C" { #include "hal/uart_types.h" #include "hal/gpio_types.h" +/** + * Default LP_IO Mux pins for LP UART + */ +#if CONFIG_IDF_TARGET_ESP32P4 +#define LP_UART_DEFAULT_TX_GPIO_NUM GPIO_NUM_14 +#define LP_UART_DEFAULT_RX_GPIO_NUM GPIO_NUM_15 +#define LP_UART_DEFAULT_RTS_GPIO_NUM (-1) +#define LP_UART_DEFAULT_CTS_GPIO_NUM (-1) +#elif CONFIG_IDF_TARGET_ESP32C6 +#define LP_UART_DEFAULT_TX_GPIO_NUM GPIO_NUM_5 +#define LP_UART_DEFAULT_RX_GPIO_NUM GPIO_NUM_4 +#define LP_UART_DEFAULT_RTS_GPIO_NUM GPIO_NUM_2 +#define LP_UART_DEFAULT_CTS_GPIO_NUM GPIO_NUM_3 +#else +#error "LP IO Mux pins undefined for LP UART" +#endif /* CONFIG_IDF_TARGET_ESP32P4 */ + /** * @brief LP UART IO pins configuration */ @@ -47,11 +64,11 @@ typedef struct { } lp_core_uart_cfg_t; /* Default LP UART GPIO settings */ -#define LP_UART_DEFAULT_GPIO_CONFIG() \ - .uart_pin_cfg.tx_io_num = GPIO_NUM_5, \ - .uart_pin_cfg.rx_io_num = GPIO_NUM_4, \ - .uart_pin_cfg.rts_io_num = GPIO_NUM_2, \ - .uart_pin_cfg.cts_io_num = GPIO_NUM_3, \ +#define LP_UART_DEFAULT_GPIO_CONFIG() \ + .uart_pin_cfg.tx_io_num = LP_UART_DEFAULT_TX_GPIO_NUM, \ + .uart_pin_cfg.rx_io_num = LP_UART_DEFAULT_RX_GPIO_NUM, \ + .uart_pin_cfg.rts_io_num = LP_UART_DEFAULT_RTS_GPIO_NUM, \ + .uart_pin_cfg.cts_io_num = LP_UART_DEFAULT_CTS_GPIO_NUM, \ /* Default LP UART protocol config */ #define LP_UART_DEFAULT_PROTO_CONFIG() \ diff --git a/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h b/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h index 43a956b9be..4c0b214528 100644 --- a/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h +++ b/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h @@ -1,8 +1,9 @@ /* - * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ +#include "sdkconfig.h" /** * @brief Print from the LP core @@ -14,4 +15,21 @@ * @param ... variable argument list * */ +#if CONFIG_ULP_ROM_PRINT_ENABLE +extern int ets_printf(const char* format, ...); +int (*lp_core_printf)(const char* format, ...) = ets_printf; +#else +//TODO: Change return type from void to int in IDF 6.0 void lp_core_printf(const char* format, ...); +#endif /* CONFIG_ULP_ROM_PRINT_ENABLE */ + +#if CONFIG_ULP_ROM_PRINT_ENABLE +/** + * @brief Install LP ROM UART printf function as standard putc handler to enable prints + * + * @note This function must be called before printing anything when the LP core boots from LP ROM but does not install + * putc handler. This is possible when the LP ROM is instructed so by setting bit#1 in the LP_SYSTEM_REG_LP_STORE9_REG register. + */ +extern void ets_install_uart_printf(void); +void (*lp_core_install_uart_printf)(void) = ets_install_uart_printf; +#endif /* CONFIG_ULP_ROM_PRINT_ENABLE */ diff --git a/components/ulp/lp_core/lp_core/lp_core_print.c b/components/ulp/lp_core/lp_core/lp_core_print.c index d010f68328..785d59e6c4 100644 --- a/components/ulp/lp_core/lp_core/lp_core_print.c +++ b/components/ulp/lp_core/lp_core/lp_core_print.c @@ -6,6 +6,8 @@ #include #include "ulp_lp_core_uart.h" +#if !CONFIG_ULP_ROM_PRINT_ENABLE + #define LP_UART_PORT_NUM LP_UART_NUM_0 #define BINARY_SUPPORT 1 @@ -271,3 +273,5 @@ int lp_core_printf(const char* format, ...) return ret; } + +#endif /* !CONFIG_ULP_ROM_PRINT_ENABLE */ diff --git a/components/ulp/lp_core/lp_core_uart.c b/components/ulp/lp_core/lp_core_uart.c index 7ab414ec16..21c8ad4ee2 100644 --- a/components/ulp/lp_core/lp_core_uart.c +++ b/components/ulp/lp_core/lp_core_uart.c @@ -6,15 +6,21 @@ #include #include "esp_err.h" +#include "esp_check.h" #include "lp_core_uart.h" #include "driver/rtc_io.h" +#include "driver/lp_io.h" +#include "soc/uart_periph.h" #include "soc/lp_uart_struct.h" #include "hal/uart_hal.h" +#include "hal/rtc_io_hal.h" #include "hal/rtc_io_types.h" #include "esp_clk_tree.h" #include "esp_private/periph_ctrl.h" #include "esp_private/uart_share_hw_ctrl.h" +static const char *LP_UART_TAG = "lp_uart"; + #define LP_UART_PORT_NUM LP_UART_NUM_0 #define LP_UART_TX_IDLE_NUM_DEFAULT (0U) @@ -67,8 +73,13 @@ static esp_err_t lp_core_uart_param_config(const lp_core_uart_cfg_t *cfg) return ret; } -static esp_err_t lp_uart_config_io(gpio_num_t pin, rtc_gpio_mode_t direction) +static esp_err_t lp_uart_config_io(gpio_num_t pin, rtc_gpio_mode_t direction, uint32_t idx) { + /* Skip configuration if the LP_IO is -1 */ + if (pin < 0) { + return ESP_OK; + } + /* Initialize LP_IO */ esp_err_t ret = rtc_gpio_init(pin); if (ret != ESP_OK) { @@ -81,8 +92,26 @@ static esp_err_t lp_uart_config_io(gpio_num_t pin, rtc_gpio_mode_t direction) return ESP_FAIL; } - /* Set LP_IO function */ - ret = rtc_gpio_iomux_func_sel(pin, 1); + /* Connect pins */ + const uart_periph_sig_t *upin = &uart_periph_signal[LP_UART_PORT_NUM].pins[idx]; +#if !SOC_LP_GPIO_MATRIX_SUPPORTED + /* When LP_IO Matrix is not support, LP_IO Mux must be connected to the pins */ + ret = rtc_gpio_iomux_func_sel(pin, upin->iomux_func); +#else + /* If the configured pin is the default LP_IO Mux pin for LP UART, then set the LP_IO MUX function */ + if (upin->default_gpio == pin) { + ret = rtc_gpio_iomux_func_sel(pin, upin->iomux_func); + } else { + /* Select FUNC1 for LP_IO Matrix */ + ret = rtc_gpio_iomux_func_sel(pin, 1); + /* Connect the LP_IO to the LP UART peripheral signal */ + if (direction == RTC_GPIO_MODE_OUTPUT_ONLY) { + ret = lp_gpio_connect_out_signal(pin, UART_PERIPH_SIGNAL(LP_UART_PORT_NUM, idx), 0, 0); + } else { + ret = lp_gpio_connect_in_signal(pin, UART_PERIPH_SIGNAL(LP_UART_PORT_NUM, idx), 0); + } + } +#endif /* SOC_LP_GPIO_MATRIX_SUPPORTED */ return ret; } @@ -92,22 +121,29 @@ static esp_err_t lp_core_uart_set_pin(const lp_core_uart_cfg_t *cfg) esp_err_t ret = ESP_OK; /* Argument sanity check */ - if ((cfg->uart_pin_cfg.tx_io_num != GPIO_NUM_5) || - (cfg->uart_pin_cfg.rx_io_num != GPIO_NUM_4) || - (cfg->uart_pin_cfg.rts_io_num != GPIO_NUM_2) || - (cfg->uart_pin_cfg.cts_io_num != GPIO_NUM_3)) { - // Invalid IO config - return ESP_ERR_INVALID_ARG; - } +#if !SOC_LP_GPIO_MATRIX_SUPPORTED + const uart_periph_sig_t *pins = uart_periph_signal[LP_UART_PORT_NUM].pins; + // LP_UART has its fixed IOs + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.tx_io_num < 0 || (cfg->uart_pin_cfg.tx_io_num == pins[SOC_UART_TX_PIN_IDX].default_gpio)), ESP_FAIL, LP_UART_TAG, "tx_io_num error"); + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.rx_io_num < 0 || (cfg->uart_pin_cfg.rx_io_num == pins[SOC_UART_RX_PIN_IDX].default_gpio)), ESP_FAIL, LP_UART_TAG, "rx_io_num error"); + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.rts_io_num < 0 || (cfg->uart_pin_cfg.rts_io_num == pins[SOC_UART_RTS_PIN_IDX].default_gpio)), ESP_FAIL, LP_UART_TAG, "rts_io_num error"); + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.cts_io_num < 0 || (cfg->uart_pin_cfg.cts_io_num == pins[SOC_UART_CTS_PIN_IDX].default_gpio)), ESP_FAIL, LP_UART_TAG, "cts_io_num error"); +#else + // LP_UART signals can be routed to any LP_IOs + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.tx_io_num < 0 || rtc_gpio_is_valid_gpio(cfg->uart_pin_cfg.tx_io_num)), ESP_FAIL, LP_UART_TAG, "tx_io_num error"); + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.rx_io_num < 0 || rtc_gpio_is_valid_gpio(cfg->uart_pin_cfg.rx_io_num)), ESP_FAIL, LP_UART_TAG, "rx_io_num error"); + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.rts_io_num < 0 || rtc_gpio_is_valid_gpio(cfg->uart_pin_cfg.rts_io_num)), ESP_FAIL, LP_UART_TAG, "rts_io_num error"); + ESP_RETURN_ON_FALSE((cfg->uart_pin_cfg.cts_io_num < 0 || rtc_gpio_is_valid_gpio(cfg->uart_pin_cfg.cts_io_num)), ESP_FAIL, LP_UART_TAG, "cts_io_num error"); +#endif /* SOC_LP_GPIO_MATRIX_SUPPORTED */ /* Configure Tx Pin */ - ret = lp_uart_config_io(cfg->uart_pin_cfg.tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); + ret = lp_uart_config_io(cfg->uart_pin_cfg.tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_TX_PIN_IDX); /* Configure Rx Pin */ - ret = lp_uart_config_io(cfg->uart_pin_cfg.rx_io_num, RTC_GPIO_MODE_INPUT_ONLY); + ret = lp_uart_config_io(cfg->uart_pin_cfg.rx_io_num, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_RX_PIN_IDX); /* Configure RTS Pin */ - ret = lp_uart_config_io(cfg->uart_pin_cfg.rts_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); + ret = lp_uart_config_io(cfg->uart_pin_cfg.rts_io_num, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_RTS_PIN_IDX); /* Configure CTS Pin */ - ret = lp_uart_config_io(cfg->uart_pin_cfg.cts_io_num, RTC_GPIO_MODE_INPUT_ONLY); + ret = lp_uart_config_io(cfg->uart_pin_cfg.cts_io_num, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_CTS_PIN_IDX); return ret; } diff --git a/components/ulp/project_include.cmake b/components/ulp/project_include.cmake index 47df252e01..b3e35dca96 100644 --- a/components/ulp/project_include.cmake +++ b/components/ulp/project_include.cmake @@ -49,6 +49,9 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs) elseif(CONFIG_ULP_COPROC_TYPE_LP_CORE) set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-lp-core-riscv.cmake) set(ULP_IS_LP_CORE_RISCV ON) + if(CONFIG_ESP_ROM_HAS_LP_ROM) + set(CONFIG_ESP_ROM_HAS_LP_ROM ON) + endif() endif() externalproject_add(${app_name} @@ -67,6 +70,7 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs) -DPYTHON=${python} -DULP_COCPU_IS_RISCV=${ULP_IS_RISCV} -DULP_COCPU_IS_LP_CORE=${ULP_IS_LP_CORE_RISCV} + -DCONFIG_ESP_ROM_HAS_LP_ROM=${CONFIG_ESP_ROM_HAS_LP_ROM} ${extra_cmake_args} BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/${app_name} --target build BUILD_BYPRODUCTS ${ulp_artifacts} ${ulp_artifacts_extras} ${ulp_ps_sources} diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 96215c3c3a..5113c2c41e 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -285,7 +285,7 @@ examples/system/ulp/lp_core/lp_uart/lp_uart_echo: - if: SOC_ULP_LP_UART_SUPPORTED != 1 - if: IDF_TARGET == "esp32p4" temporary: true - reason: target esp32p4 is not supported yet TODO IDF-7533 + reason: target esp32p4 is not supported yet TODO IDF-9407 depends_components: - ulp @@ -294,7 +294,7 @@ examples/system/ulp/lp_core/lp_uart/lp_uart_print: - if: SOC_ULP_LP_UART_SUPPORTED != 1 - if: IDF_TARGET == "esp32p4" temporary: true - reason: target esp32p4 is not supported yet TODO IDF-7533 + reason: target esp32p4 is not supported yet TODO IDF-9407 depends_components: - ulp