From 26fd843376247a80e4eb585619c6ad8b0422738e Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Mon, 11 Mar 2024 09:57:53 +0100 Subject: [PATCH 1/2] feat(lp_core): Added support for LP UART on LP core for esp32p4 This commit enables LP UART support for the LP core on the esp32p4. --- .../esp32p4/include/soc/Kconfig.soc_caps.in | 4 ++ components/soc/esp32p4/include/soc/soc_caps.h | 2 +- components/ulp/lp_core/include/lp_core_uart.h | 29 +++++++-- components/ulp/lp_core/lp_core_uart.c | 64 +++++++++++++++---- examples/system/.build-test-rules.yml | 4 +- 5 files changed, 80 insertions(+), 23 deletions(-) diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 0efc00d996..d959c78d01 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -179,6 +179,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 2adb7e1c05..8043bc04c5 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/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_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/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 From b90a2795879159f832521b77976fa061a68b3254 Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Mon, 11 Mar 2024 12:15:09 +0100 Subject: [PATCH 2/2] feat(lp-core): Added ability to print from LP ROM on the LP core This commit adds the ability to use LP ROM functions from the LP core. This allows the LP core code to utilize standard functions such as those for printing from the LP ROM and therefore help reduce the code size on the LP core. --- components/ulp/Kconfig | 12 +++++++++++ components/ulp/cmake/CMakeLists.txt | 1 + .../lp_core/include/ulp_lp_core_print.h | 20 ++++++++++++++++++- .../ulp/lp_core/lp_core/lp_core_print.c | 4 ++++ components/ulp/project_include.cmake | 4 ++++ 5 files changed, 40 insertions(+), 1 deletion(-) 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/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/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}