diff --git a/arch/risc-v/src/common/espressif/Kconfig b/arch/risc-v/src/common/espressif/Kconfig index e62ffab54bb..22990f6eaad 100644 --- a/arch/risc-v/src/common/espressif/Kconfig +++ b/arch/risc-v/src/common/espressif/Kconfig @@ -643,6 +643,271 @@ config ESPRESSIF_ULP_ENABLE_UBSAN But note that it will increase code size significantly and it can happen that application will not fit into RTC RAM +choice ESPRESSIF_ULP_WAKEUP_SOURCE + prompt "LP Coprocessor wakeup source" + default ESPRESSIF_ULP_WAKEUP_HP_CPU + +config ESPRESSIF_ULP_WAKEUP_HP_CPU + bool "Wakeup by HP core" + +config ESPRESSIF_ULP_WAKEUP_LP_UART + depends on ESPRESSIF_LP_UART + bool "Wakeup by LP UART RX" + +config ESPRESSIF_ULP_WAKEUP_LP_IO + bool "Wakeup by LP IO interrupt" + +config ESPRESSIF_ULP_WAKEUP_LP_TIMER + bool "Wakeup by LP timer" + +endchoice # ESPRESSIF_ULP_WAKEUP_SOURCE + +menu "ULP Wakeup LP IO Sources" + depends on ESPRESSIF_ULP_WAKEUP_LP_IO + +menu "GPIOs to wakeup ULP when low" + +config ESPRESSIF_ULP_WAKEUP_LP_IO0_LOW + bool "LP_IO0" + default n + ---help--- + Wakeup ULP when LP_GPIO0 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO1_LOW + bool "LP_IO1" + default n + ---help--- + Wakeup ULP when LP_GPIO1 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO2_LOW + bool "LP_IO2" + default n + ---help--- + Wakeup ULP when LP_GPIO2 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO3_LOW + bool "LP_IO3" + default n + ---help--- + Wakeup ULP when LP_GPIO3 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO4_LOW + bool "LP_IO4" + default n + ---help--- + Wakeup ULP when LP_GPIO4 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO5_LOW + bool "LP_IO5" + default n + ---help--- + Wakeup ULP when LP_GPIO5 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO6_LOW + bool "LP_IO6" + default n + ---help--- + Wakeup ULP when LP_GPIO6 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO7_LOW + bool "LP_IO7" + default n + ---help--- + Wakeup ULP when LP_GPIO7 is low. + +config ESPRESSIF_ULP_WAKEUP_LP_IO8_LOW + bool "LP_IO8" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO8 is low + +config ESPRESSIF_ULP_WAKEUP_LP_IO9_LOW + bool "LP_IO9" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO9 is low + +config ESPRESSIF_ULP_WAKEUP_LP_IO10_LOW + bool "LP_IO10" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO10 is low + +config ESPRESSIF_ULP_WAKEUP_LP_IO11_LOW + bool "LP_IO11" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO11 is low + +config ESPRESSIF_ULP_WAKEUP_LP_IO12_LOW + bool "LP_IO12" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO12 is low + +config ESPRESSIF_ULP_WAKEUP_LP_IO13_LOW + bool "LP_IO13" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO13 is low + +config ESPRESSIF_ULP_WAKEUP_LP_IO14_LOW + bool "LP_IO14" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO14 is low + +endmenu # GPIOs to wakeup ULP when low + +menu "GPIOs to wakeup ULP when high" + +config ESPRESSIF_ULP_WAKEUP_LP_IO0_HIGH + bool "LP_IO0" + default n + ---help--- + Wakeup ULP when LP_GPIO0 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO1_HIGH + bool "LP_IO1" + default n + ---help--- + Wakeup ULP when LP_GPIO1 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO2_HIGH + bool "LP_IO2" + default n + ---help--- + Wakeup ULP when LP_GPIO2 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO3_HIGH + bool "LP_IO3" + default n + ---help--- + Wakeup ULP when LP_GPIO3 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO4_HIGH + bool "LP_IO4" + default n + ---help--- + Wakeup ULP when LP_GPIO4 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO5_HIGH + bool "LP_IO5" + default n + ---help--- + Wakeup ULP when LP_GPIO5 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO6_HIGH + bool "LP_IO6" + default n + ---help--- + Wakeup ULP when LP_GPIO6 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO7_HIGH + bool "LP_IO7" + default n + ---help--- + Wakeup ULP when LP_GPIO7 is high. + +config ESPRESSIF_ULP_WAKEUP_LP_IO8_HIGH + bool "LP_IO8" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO8 is high + +config ESPRESSIF_ULP_WAKEUP_LP_IO9_HIGH + bool "LP_IO9" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO9 is high + +config ESPRESSIF_ULP_WAKEUP_LP_IO10_HIGH + bool "LP_IO10" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO10 is high + +config ESPRESSIF_ULP_WAKEUP_LP_IO11_HIGH + bool "LP_IO11" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO11 is high + +config ESPRESSIF_ULP_WAKEUP_LP_IO12_HIGH + bool "LP_IO12" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO12 is high + +config ESPRESSIF_ULP_WAKEUP_LP_IO13_HIGH + bool "LP_IO13" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO13 is high + +config ESPRESSIF_ULP_WAKEUP_LP_IO14_HIGH + bool "LP_IO14" + default n + depends on ARCH_CHIP_ESP32P4 + ---help--- + Wakeup ULP when LP_GPIO14 is high + +endmenu # GPIOs to wakeup ULP when high + +endmenu # ULP Wakeup LP IO Sources + +config ESPRESSIF_ULP_WAKEUP_SLEEP_DURATION_US + int "Sleep duration of LP Coprocessor in us" + depends on ESPRESSIF_ULP_WAKEUP_LP_TIMER + default 1000000 + +choice ESPRESSIF_ULP_WAKEUP_LPUART_MODE + prompt "LP Coprocessor UART Wakeup Mode" + depends on ESPRESSIF_ULP_WAKEUP_LP_UART + default ESPRESSIF_ULP_WAKEUP_LPUART_START_BIT_MODE + +config ESPRESSIF_ULP_WAKEUP_LPUART_ACTIVE_EDGE_THRESHOLD_MODE + bool "Wake-up triggered by active edge threshold" + +config ESPRESSIF_ULP_WAKEUP_LPUART_FIFO_THRESHOLD_MODE + bool "Wake-up triggered by the number of bytes received in the RX FIFO" + +config ESPRESSIF_ULP_WAKEUP_LPUART_START_BIT_MODE + bool "Wake-up triggered by the detection of a start bit" + +config ESPRESSIF_ULP_WAKEUP_LPUART_CHAR_SEQ_MODE + bool "Wake-up triggered by detecting a specific character sequence" + +endchoice # ESPRESSIF_ULP_WAKEUP_LPUART_MODE + +config ESPRESSIF_ULP_WAKEUP_LPUART_ACTIVE_EDGE_THRESHOLD + int "Number of RXD edge changes to to trigger wake-up" + depends on ESPRESSIF_ULP_WAKEUP_LPUART_ACTIVE_EDGE_THRESHOLD_MODE + default 3 + +config ESPRESSIF_ULP_WAKEUP_LPUART_FIFO_THRESHOLD + int "Number of bytes needed to receive in the RX FIFO to trigger wake-up" + depends on ESPRESSIF_ULP_WAKEUP_LPUART_FIFO_THRESHOLD_MODE + default 8 + +config ESPRESSIF_ULP_WAKEUP_LPUART_CHAR_SEQ + string "Character sequence to trigger wake-up" + depends on ESPRESSIF_ULP_WAKEUP_LPUART_CHAR_SEQ_MODE + default "esp" + endmenu # LP Core (Low-power core) Coprocessor Configuration menu "PM Configuration" diff --git a/arch/risc-v/src/common/espressif/esp_ulp.c b/arch/risc-v/src/common/espressif/esp_ulp.c index 4f5ad69648e..69c8a01d1f0 100644 --- a/arch/risc-v/src/common/espressif/esp_ulp.c +++ b/arch/risc-v/src/common/espressif/esp_ulp.c @@ -32,6 +32,11 @@ #include "ulp_lp_core.h" #include "ulp/ulp_var_map.h" +#include "esp_ulp.h" +#include "driver/rtc_io.h" + +#include "ulp_lp_core_lp_uart_shared.h" +#include "hal/uart_ll.h" /**************************************************************************** * Pre-processor Definitions @@ -65,7 +70,20 @@ static const struct file_operations g_esp_ulp_fops = ulp_lp_core_cfg_t cfg = { +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_HP_CPU .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_TIMER + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER, + .lp_timer_sleep_duration_us = + CONFIG_ESPRESSIF_ULP_WAKEUP_SLEEP_DURATION_US, +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_IO, +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_UART + .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_UART, +#endif }; /**************************************************************************** @@ -76,6 +94,231 @@ ulp_lp_core_cfg_t cfg = * Private Functions ****************************************************************************/ +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_UART +/**************************************************************************** + * Name: esp_ulp_wakeup_lpuart_init + * + * Description: + * Configure LPUART to use as ULP wakeup source. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success, or -1 (ERROR) in case of failure. + * + ****************************************************************************/ + +static int esp_ulp_wakeup_lpuart_init(void) +{ + uart_wakeup_cfg_t wake_up_cfg = + { +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_ACTIVE_EDGE_THRESHOLD_MODE + .wakeup_mode = UART_WK_MODE_ACTIVE_THRESH, + .rx_edge_threshold = + CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_ACTIVE_EDGE_THRESHOLD +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_FIFO_THRESHOLD_MODE + .wakeup_mode = UART_WK_MODE_FIFO_THRESH, + .rx_fifo_threshold = CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_FIFO_THRESHOLD +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_START_BIT_MODE + .wakeup_mode = UART_WK_MODE_START_BIT, +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_CHAR_SEQ_MODE + .wakeup_mode = UART_WK_MODE_CHAR_SEQ, + .wake_chars_seq = CONFIG_ESPRESSIF_ULP_WAKEUP_LPUART_CHAR_SEQ +#endif + }; + + return uart_wakeup_setup(LP_UART_NUM_0, &wake_up_cfg); +} +#endif + +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO +/**************************************************************************** + * Name: esp_ulp_get_high_io_mask + * + * Description: + * Get ULP wakeup high IO mask value from configured wakeup pins. + * + * Input Parameters: + * None + * + * Returned Value: + * A 64-bit unsigned integer where each bit corresponds to an RTC GPIO pin + * that has been configured high as an ULP wakeup source. + * + ****************************************************************************/ + +static uint64_t esp_ulp_get_high_io_mask(void) +{ + uint64_t io_mask = 0; +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO0_HIGH + io_mask |= BIT(0); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO1_HIGH + io_mask |= BIT(1); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO2_HIGH + io_mask |= BIT(2); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO3_HIGH + io_mask |= BIT(3); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO4_HIGH + io_mask |= BIT(4); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO5_HIGH + io_mask |= BIT(5); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO6_HIGH + io_mask |= BIT(6); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO7_HIGH + io_mask |= BIT(7); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO8_HIGH + io_mask |= BIT(8); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO9_HIGH + io_mask |= BIT(9); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO10_HIGH + io_mask |= BIT(10); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO11_HIGH + io_mask |= BIT(11); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO12_HIGH + io_mask |= BIT(12); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO13_HIGH + io_mask |= BIT(13); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO14_HIGH + io_mask |= BIT(14); +#endif + + return io_mask; +} + +/**************************************************************************** + * Name: esp_ulp_get_low_io_mask + * + * Description: + * Get ULP wakeup low IO mask value from configured wakeup pins. + * + * Input Parameters: + * None + * + * Returned Value: + * A 64-bit unsigned integer where each bit corresponds to an RTC GPIO pin + * that has been configured low as an ULP wakeup source. + * + ****************************************************************************/ + +static uint64_t esp_ulp_get_low_io_mask(void) +{ + uint64_t io_mask = 0; +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO0_LOW + io_mask |= BIT(0); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO1_LOW + io_mask |= BIT(1); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO2_LOW + io_mask |= BIT(2); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO3_LOW + io_mask |= BIT(3); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO4_LOW + io_mask |= BIT(4); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO5_LOW + io_mask |= BIT(5); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO6_LOW + io_mask |= BIT(6); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO7_LOW + io_mask |= BIT(7); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO8_LOW + io_mask |= BIT(8); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO9_LOW + io_mask |= BIT(9); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO10_LOW + io_mask |= BIT(10); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO11_LOW + io_mask |= BIT(11); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO12_LOW + io_mask |= BIT(12); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO13_LOW + io_mask |= BIT(13); +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO14_LOW + io_mask |= BIT(14); +#endif + + return io_mask; +} + +/**************************************************************************** + * Name: esp_ulp_wakeup_io_init + * + * Description: + * Configure GPIO to use as ULP wakeup source. + * + * Input Parameters: + * None + * + * Returned Value: + * Zero (OK) on success, or -1 (ERROR) in case of failure. + * + ****************************************************************************/ + +static int esp_ulp_wakeup_io_init(void) +{ + int ret = OK; + int pin_mask; + gpio_int_type_t wake_up_type; + uint64_t io_mask_low = esp_ulp_get_low_io_mask(); + uint64_t io_mask_high = esp_ulp_get_high_io_mask(); + + for (int i = 0; i < CONFIG_SOC_RTCIO_PIN_COUNT; i++) + { + pin_mask = BIT(i); + if ((io_mask_low & pin_mask) != 0 || + (io_mask_high & pin_mask) != 0) + { + ret = esp_rtcio_config_gpio(i, ESP_RTC_GPIO_MODE_INPUT_OUTPUT); + if (ret != OK) + { + ferr("Failed to configure pin: %d\n", i); + return ret; + } + + wake_up_type = GPIO_INTR_HIGH_LEVEL; + if ((io_mask_low & pin_mask) != 0) + { + wake_up_type = GPIO_INTR_LOW_LEVEL; + } + + rtc_gpio_wakeup_enable(i, wake_up_type); + } + } + + return OK; +} +#endif + /**************************************************************************** * Name: esp_ulp_ioctl * @@ -220,11 +463,30 @@ int esp_ulp_load_bin(const char *buffer, size_t buflen) * None * * Returned Value: - * None + * Returns OK on success; a negated errno value on failure * ****************************************************************************/ -void esp_ulp_init(void) +int esp_ulp_init(void) { + int ret = OK; +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_IO + ret = esp_ulp_wakeup_io_init(); + if (ret != OK) + { + return ret; + } + +#endif +#ifdef CONFIG_ESPRESSIF_ULP_WAKEUP_LP_UART + esp_ulp_wakeup_lpuart_init(); + if (ret != OK) + { + ferr("Failed to LP UART wakeup\n"); + return ret; + } + +#endif esp_ulp_register(); + return ret; } diff --git a/arch/risc-v/src/common/espressif/esp_ulp.h b/arch/risc-v/src/common/espressif/esp_ulp.h index 9371bee6ad3..d71af22dd36 100644 --- a/arch/risc-v/src/common/espressif/esp_ulp.h +++ b/arch/risc-v/src/common/espressif/esp_ulp.h @@ -30,6 +30,8 @@ #include #include +#include "espressif/esp_rtc_gpio.h" + #ifndef __ASSEMBLY__ #undef EXTERN @@ -72,11 +74,11 @@ int esp_ulp_load_bin(const char *buffer, size_t buflen); * None * * Returned Value: - * None + * Returns OK on success; a negated errno value on failure * ****************************************************************************/ -void esp_ulp_init(void); +int esp_ulp_init(void); #ifdef __cplusplus }