Merge branch 'feature/lp_core_lp_uart_support' into 'master'

feat(lp_core): Added support for LP UART on LP core for esp32p4

Closes IDF-7533

See merge request espressif/esp-idf!29555
This commit is contained in:
Sudeep Mohanty 2024-03-15 17:57:50 +08:00
commit 05db166e5d
10 changed files with 120 additions and 24 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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() \

View File

@ -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 */

View File

@ -6,6 +6,8 @@
#include <stdarg.h>
#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 */

View File

@ -6,15 +6,21 @@
#include <stdint.h>
#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;
}

View File

@ -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}

View File

@ -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