From 0bac17405855a52b4adf99421e98275408ac7763 Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Thu, 9 Mar 2023 14:14:09 +0800 Subject: [PATCH] ulp: added sleep support for lp core Added support for running LP core while hp core sleeps, as well as waking up the hp core. --- .../include/esp_private/esp_pmu.h | 6 ++ .../esp_hw_support/port/esp32c6/pmu_sleep.c | 1 + components/esp_hw_support/sleep_modes.c | 15 ++-- components/hal/adc_hal_common.c | 4 +- components/hal/esp32c6/include/hal/pmu_ll.h | 5 ++ .../soc/esp32/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32/include/soc/soc_caps.h | 3 + .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../esp32s2/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s2/include/soc/soc_caps.h | 2 + .../esp32s3/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32s3/include/soc/soc_caps.h | 3 + components/ulp/.build-test-rules.yml | 2 +- components/ulp/CMakeLists.txt | 2 +- components/ulp/cmake/CMakeLists.txt | 4 +- .../ulp/cmake/toolchain-lp-core-riscv.cmake | 2 +- .../ulp/lp_core/include/ulp_lp_core_utils.h | 36 +++++++++ components/ulp/lp_core/lp_core.c | 16 +++- .../ulp/lp_core/lp_core/lp_core_utils.c | 43 ++++++++++ components/ulp/lp_core/lp_core/vector.S | 24 ++++++ .../ulp/test_apps/lp_core/main/CMakeLists.txt | 2 +- .../lp_core/main/lp_core/test_main.c | 44 ++++++++++- .../lp_core/main/lp_core/test_shared.h | 3 + .../ulp/test_apps/lp_core/main/test_lp_core.c | 78 +++++++++++++++++++ .../test_apps/ulp_riscv/main/test_ulp_riscv.c | 2 +- .../ulp_core/include/ulp_riscv_utils.h | 2 +- docs/conf_common.py | 8 +- docs/en/api-reference/peripherals/gpio.rst | 2 +- docs/en/api-reference/system/index.rst | 2 +- docs/zh_CN/api-reference/peripherals/gpio.rst | 2 +- docs/zh_CN/api-reference/system/index.rst | 2 +- examples/system/.build-test-rules.yml | 2 +- 33 files changed, 307 insertions(+), 27 deletions(-) create mode 100644 components/ulp/lp_core/include/ulp_lp_core_utils.h create mode 100644 components/ulp/lp_core/lp_core/lp_core_utils.c create mode 100644 components/ulp/lp_core/lp_core/vector.S diff --git a/components/esp_hw_support/include/esp_private/esp_pmu.h b/components/esp_hw_support/include/esp_private/esp_pmu.h index a97cbd7053..fe3021a830 100644 --- a/components/esp_hw_support/include/esp_private/esp_pmu.h +++ b/components/esp_hw_support/include/esp_private/esp_pmu.h @@ -51,6 +51,9 @@ extern "C" { #define RTC_UART1_TRIG_EN PMU_UART1_WAKEUP_EN //!< UART1 wakeup (light sleep only) #define RTC_BT_TRIG_EN PMU_BLE_SOC_WAKEUP_EN //!< BT wakeup (light sleep only) #define RTC_USB_TRIG_EN PMU_USB_WAKEUP_EN +#if SOC_LP_CORE_SUPPORTED +#define RTC_LP_CORE_TRIG_EN PMU_LP_CORE_WAKEUP_EN //!< LP core wakeup +#endif //SOC_LP_CORE_SUPPORTED #define RTC_XTAL32K_DEAD_TRIG_EN 0 // TODO #define RTC_BROWNOUT_DET_TRIG_EN 0 // TODO @@ -82,6 +85,9 @@ extern "C" { #define PMU_UART1_WAKEUP_EN BIT(7) #define PMU_SDIO_WAKEUP_EN BIT(8) #define PMU_BLE_SOC_WAKEUP_EN BIT(10) +#if SOC_LP_CORE_SUPPORTED +#define PMU_LP_CORE_WAKEUP_EN BIT(11) +#endif //SOC_LP_CORE_SUPPORTED #define PMU_USB_WAKEUP_EN BIT(14) diff --git a/components/esp_hw_support/port/esp32c6/pmu_sleep.c b/components/esp_hw_support/port/esp32c6/pmu_sleep.c index 213858f7a4..f990464c80 100644 --- a/components/esp_hw_support/port/esp32c6/pmu_sleep.c +++ b/components/esp_hw_support/port/esp32c6/pmu_sleep.c @@ -273,6 +273,7 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp pmu_ll_hp_clear_wakeup_intr_status(PMU_instance()->hal->dev); pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev); pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev); + pmu_ll_hp_clear_sw_intr_status(PMU_instance()->hal->dev); /* Start entry into sleep mode */ pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev); diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index d5c545fef4..ca088feb69 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -533,8 +533,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo } #endif -#if !CONFIG_IDF_TARGET_ESP32C6 // TODO IDF-7012 Add sleep support for lp core -#if CONFIG_ULP_COPROC_ENABLED +#if CONFIG_ULP_COPROC_TYPE_FSM // Enable ULP wakeup if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) { #ifdef CONFIG_IDF_TARGET_ESP32 @@ -544,7 +543,6 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t mo #endif } #endif -#endif //!CONFIG_IDF_TARGET_ESP32C6 misc_modules_sleep_prepare(deep_sleep); @@ -1075,7 +1073,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) { s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN); } -#if CONFIG_ULP_COPROC_ENABLED && !CONFIG_IDF_TARGET_ESP32C6 // TODO IDF-7012 Add sleep support for lp core +#if CONFIG_ULP_COPROC_TYPE_FSM else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN; } @@ -1109,6 +1107,9 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void) #elif CONFIG_ULP_COPROC_TYPE_RISCV s_config.wakeup_triggers |= (RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN); return ESP_OK; +#elif CONFIG_ULP_COPROC_TYPE_LP_CORE + s_config.wakeup_triggers |= RTC_LP_CORE_TRIG_EN; + return ESP_OK; #else return ESP_ERR_NOT_SUPPORTED; #endif //CONFIG_ULP_COPROC_TYPE_FSM @@ -1494,7 +1495,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) } else if (wakeup_cause & RTC_TOUCH_TRIG_EN) { return ESP_SLEEP_WAKEUP_TOUCHPAD; #endif -#if SOC_ULP_SUPPORTED +#if SOC_ULP_FSM_SUPPORTED } else if (wakeup_cause & RTC_ULP_TRIG_EN) { return ESP_SLEEP_WAKEUP_ULP; #endif @@ -1511,6 +1512,10 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) return ESP_SLEEP_WAKEUP_ULP; } else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) { return ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG; +#endif +#if SOC_LP_CORE_SUPPORTED + } else if (wakeup_cause & RTC_LP_CORE_TRIG_EN) { + return ESP_SLEEP_WAKEUP_ULP; #endif } else { return ESP_SLEEP_WAKEUP_UNDEFINED; diff --git a/components/hal/adc_hal_common.c b/components/hal/adc_hal_common.c index ee530e6a7e..7d39ca139c 100644 --- a/components/hal/adc_hal_common.c +++ b/components/hal/adc_hal_common.c @@ -18,7 +18,7 @@ static adc_ll_controller_t get_controller(adc_unit_t unit, adc_hal_work_mode_t w { if (unit == ADC_UNIT_1) { switch (work_mode) { -#if SOC_ULP_SUPPORTED +#if SOC_ULP_HAS_ADC case ADC_HAL_ULP_FSM_MODE: return ADC_LL_CTRL_ULP; #endif @@ -35,7 +35,7 @@ static adc_ll_controller_t get_controller(adc_unit_t unit, adc_hal_work_mode_t w } } else { switch (work_mode) { -#if SOC_ULP_SUPPORTED +#if SOC_ULP_HAS_ADC case ADC_HAL_ULP_FSM_MODE: return ADC_LL_CTRL_ULP; #endif diff --git a/components/hal/esp32c6/include/hal/pmu_ll.h b/components/hal/esp32c6/include/hal/pmu_ll.h index b5cc2b3193..32f399b39b 100644 --- a/components/hal/esp32c6/include/hal/pmu_ll.h +++ b/components/hal/esp32c6/include/hal/pmu_ll.h @@ -506,6 +506,11 @@ FORCE_INLINE_ATTR bool pmu_ll_hp_is_sleep_reject(pmu_dev_t *hw) return (hw->hp_ext.int_raw.reject == 1); } +FORCE_INLINE_ATTR void pmu_ll_hp_clear_sw_intr_status(pmu_dev_t *hw) +{ + hw->hp_ext.int_clr.sw = 1; +} + FORCE_INLINE_ATTR void pmu_ll_hp_clear_wakeup_intr_status(pmu_dev_t *hw) { hw->hp_ext.int_clr.wakeup = 1; diff --git a/components/soc/esp32/include/soc/Kconfig.soc_caps.in b/components/soc/esp32/include/soc/Kconfig.soc_caps.in index 7f67f83b1b..102b32340d 100644 --- a/components/soc/esp32/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32/include/soc/Kconfig.soc_caps.in @@ -842,3 +842,7 @@ config SOC_BT_CLASSIC_SUPPORTED config SOC_BLE_DEVICE_PRIVACY_SUPPORTED bool default n + +config SOC_ULP_HAS_ADC + bool + default y diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index 61bfb4c17e..c6aba6fec9 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -413,3 +413,6 @@ #define SOC_BLE_MESH_SUPPORTED (1) /*!< Support BLE MESH */ #define SOC_BT_CLASSIC_SUPPORTED (1) /*!< Support Bluetooth Classic hardware */ #define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (0) /*!< Support BLE device privacy mode */ + +/*-------------------------- ULP CAPS ----------------------------------------*/ +#define SOC_ULP_HAS_ADC (1) /* ADC can be accessed from ULP */ diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index 70aef4c549..ad0b96bd11 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -71,6 +71,10 @@ config SOC_SUPPORTS_SECURE_DL_MODE bool default y +config SOC_ULP_SUPPORTED + bool + default y + config SOC_LP_CORE_SUPPORTED bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 0a15699693..e029d3f26e 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -42,6 +42,7 @@ #define SOC_TEMP_SENSOR_SUPPORTED 1 #define SOC_WIFI_SUPPORTED 1 #define SOC_SUPPORTS_SECURE_DL_MODE 1 +#define SOC_ULP_SUPPORTED 1 #define SOC_LP_CORE_SUPPORTED 1 #define SOC_EFUSE_KEY_PURPOSE_FIELD 1 #define SOC_RTC_FAST_MEM_SUPPORTED 1 diff --git a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in index 0a756e0f60..5749bc4223 100644 --- a/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s2/include/soc/Kconfig.soc_caps.in @@ -1074,3 +1074,7 @@ config SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW config SOC_WIFI_NAN_SUPPORT bool default y + +config SOC_ULP_HAS_ADC + bool + default y diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index 94e210a282..4a2cd91381 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -460,3 +460,5 @@ #define SOC_WIFI_MESH_SUPPORT (1) /*!< Support WIFI MESH */ #define SOC_WIFI_SUPPORT_VARIABLE_BEACON_WINDOW (1) /*!< Support delta early time for rf phy on/off */ #define SOC_WIFI_NAN_SUPPORT (1) /*!< Support WIFI Aware (NAN) */ +/*-------------------------- ULP CAPS ----------------------------------------*/ +#define SOC_ULP_HAS_ADC (1) /* ADC can be accessed from ULP */ diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 98ca8a4ce8..bc2d6f1044 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -1250,3 +1250,7 @@ config SOC_BLE_50_SUPPORTED config SOC_BLE_DEVICE_PRIVACY_SUPPORTED bool default y + +config SOC_ULP_HAS_ADC + bool + default y diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 2d954d0bae..9da2c4af85 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -506,3 +506,6 @@ #define SOC_BLE_MESH_SUPPORTED (1) /*!< Support BLE MESH */ #define SOC_BLE_50_SUPPORTED (1) /*!< Support Bluetooth 5.0 */ #define SOC_BLE_DEVICE_PRIVACY_SUPPORTED (1) /*!< Support BLE device privacy mode */ + +/*-------------------------- ULP CAPS ----------------------------------------*/ +#define SOC_ULP_HAS_ADC (1) /* ADC can be accessed from ULP */ diff --git a/components/ulp/.build-test-rules.yml b/components/ulp/.build-test-rules.yml index 9bb58bc05d..1d2feb9226 100644 --- a/components/ulp/.build-test-rules.yml +++ b/components/ulp/.build-test-rules.yml @@ -5,7 +5,7 @@ components/ulp/test_apps/lp_core: - if: SOC_LP_CORE_SUPPORTED != 1 components/ulp/test_apps/ulp_fsm: enable: - - if: SOC_ULP_SUPPORTED == 1 + - if: SOC_ULP_FSM_SUPPORTED == 1 components/ulp/test_apps/ulp_riscv: disable: diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index b410482744..6b3f590bed 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -3,7 +3,7 @@ idf_build_get_property(target IDF_TARGET) set(srcs "") set(includes "") -if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED) +if(CONFIG_ULP_COPROC_TYPE_FSM OR CONFIG_SOC_RISCV_COPROC_SUPPORTED) list(APPEND srcs "ulp_common/ulp_common.c" diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index 5a945563cf..74fe03c6d0 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -79,7 +79,9 @@ if(ULP_COCPU_IS_RISCV) elseif(ULP_COCPU_IS_LP_CORE) list(APPEND ULP_S_SOURCES "${IDF_PATH}/components/ulp/lp_core/lp_core/start.S" - "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_startup.c") + "${IDF_PATH}/components/ulp/lp_core/lp_core/vector.S" + "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_startup.c" + "${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_utils.c") target_link_options(${ULP_APP_NAME} PRIVATE "-nostartfiles") target_link_options(${ULP_APP_NAME} PRIVATE "-Wl,--no-warn-rwx-segments") diff --git a/components/ulp/cmake/toolchain-lp-core-riscv.cmake b/components/ulp/cmake/toolchain-lp-core-riscv.cmake index 3f4d5d4e68..9b9ce09e8b 100644 --- a/components/ulp/cmake/toolchain-lp-core-riscv.cmake +++ b/components/ulp/cmake/toolchain-lp-core-riscv.cmake @@ -9,7 +9,7 @@ set(CMAKE_C_FLAGS "-Os -march=rv32imac_zicsr_zifencei -mdiv -fdata-sections -ffu CACHE STRING "C Compiler Base Flags") set(CMAKE_CXX_FLAGS "-Os -march=rv32imac_zicsr_zifencei -mdiv -fdata-sections -ffunction-sections" CACHE STRING "C++ Compiler Base Flags") -set(CMAKE_ASM_FLAGS "-march=rv32imac -x assembler-with-cpp" +set(CMAKE_ASM_FLAGS "-march=rv32imac_zicsr_zifencei -x assembler-with-cpp" CACHE STRING "Assembler Base Flags") set(CMAKE_EXE_LINKER_FLAGS "-march=rv32imac_zicsr_zifencei --specs=nano.specs --specs=nosys.specs" CACHE STRING "Linker Base Flags") diff --git a/components/ulp/lp_core/include/ulp_lp_core_utils.h b/components/ulp/lp_core/include/ulp_lp_core_utils.h new file mode 100644 index 0000000000..e1ba5c6f2a --- /dev/null +++ b/components/ulp/lp_core/include/ulp_lp_core_utils.h @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + + +/** + * @brief Wakeup main CPU from sleep or deep sleep. + * + * This raises a software interrupt signal, if the + * main CPU has configured the ULP as a wakeup source + * calling this function will make the main CPU to + * exit from sleep or deep sleep. + */ +void ulp_lp_core_wakeup_main_processor(void); + + +/** + * @brief Makes the co-processor busy wait for a certain number of microseconds + * + * @param us Number of microseconds to busy-wait for + */ +void ulp_lp_core_delay_us(uint32_t us); + +#ifdef __cplusplus +} +#endif diff --git a/components/ulp/lp_core/lp_core.c b/components/ulp/lp_core/lp_core.c index 47b9822d40..38f7a1339a 100644 --- a/components/ulp/lp_core/lp_core.c +++ b/components/ulp/lp_core/lp_core.c @@ -7,20 +7,28 @@ #include "sdkconfig.h" #include "esp_log.h" #include "soc/pmu_reg.h" +#include "soc/lp_aon_reg.h" #include "soc/lpperi_reg.h" #include "hal/misc.h" #include "ulp_common.h" #include "ulp_lp_core.h" - const static char* TAG = "ulp-lp-core"; - esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg) { + /* Enable LP-Core */ + REG_CLR_BIT(LP_AON_LPCORE_REG, LP_AON_LPCORE_DISABLE); + + /* Allow LP core to access LP memory during sleep */ + REG_CLR_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL); + REG_SET_BIT(LP_AON_LPBUS_REG, LP_AON_FAST_MEM_MUX_SEL_UPDATE); REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN, 1); + /* Enable JTAG debugging */ + REG_CLR_BIT(LPPERI_CPU_REG, LPPERI_LPCORE_DBGM_UNAVALIABLE); + switch(cfg->wakeup_source) { case ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU: REG_SET_FIELD(PMU_HP_LP_CPU_COMM_REG, PMU_HP_TRIGGER_LP, 1); @@ -41,6 +49,10 @@ esp_err_t ulp_lp_core_load_binary(const uint8_t* program_binary, size_t program_ return ESP_ERR_INVALID_SIZE; } + /* Turn off LP CPU before loading binary */ + REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN, 0); + REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_SLEEP_REQ, 1); + uint8_t* base = (uint8_t*) RTC_SLOW_MEM; //Start by clearing memory reserved with zeros, this will also will initialize the bss: diff --git a/components/ulp/lp_core/lp_core/lp_core_utils.c b/components/ulp/lp_core/lp_core/lp_core_utils.c new file mode 100644 index 0000000000..c5d753bdc6 --- /dev/null +++ b/components/ulp/lp_core/lp_core/lp_core_utils.c @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include +#include "riscv/csr.h" +#include "soc/soc.h" +#include "soc/pmu_reg.h" + +/* LP_FAST_CLK is not very accurate, for now use a rough estimate */ +#define LP_CORE_CPU_FREQUENCY_HZ 16000000 + +/** + * @brief Wakeup main CPU from sleep or deep sleep. + * + * This raises a software interrupt signal, if the + * main CPU has configured the ULP as a wakeup source + * calling this function will make the main CPU to + * exit from sleep or deep sleep. + */ +void ulp_lp_core_wakeup_main_processor(void) +{ + REG_SET_FIELD(PMU_HP_LP_CPU_COMM_REG, PMU_LP_TRIGGER_HP, 1); +} + + +/** + * @brief Makes the co-processor busy wait for a certain number of microseconds + * + * @param us Number of microseconds to busy-wait for + */ +void ulp_lp_core_delay_us(uint32_t us) +{ + uint32_t start = RV_READ_CSR(mcycle); + uint32_t end = us * (LP_CORE_CPU_FREQUENCY_HZ / 1000000); + + while ((RV_READ_CSR(mcycle) - start) < end) { + /* nothing to do */ + } +} diff --git a/components/ulp/lp_core/lp_core/vector.S b/components/ulp/lp_core/lp_core/vector.S new file mode 100644 index 0000000000..76c41a81b1 --- /dev/null +++ b/components/ulp/lp_core/lp_core/vector.S @@ -0,0 +1,24 @@ +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + .section .init.vector,"ax" + /* This is the vector table. It is currently empty, but will be populated + * with exception and interrupt handlers when this is supported + */ + + .align 0x4, 0xff + .global _vector_table + .type _vector_table, @function +_vector_table: + .option push + .option norvc + + .rept 32 + nop + .endr + + .option pop + .size _vector_table, .-_vector_table diff --git a/components/ulp/test_apps/lp_core/main/CMakeLists.txt b/components/ulp/test_apps/lp_core/main/CMakeLists.txt index f9003f5147..177c57e546 100644 --- a/components/ulp/test_apps/lp_core/main/CMakeLists.txt +++ b/components/ulp/test_apps/lp_core/main/CMakeLists.txt @@ -3,7 +3,7 @@ set(lp_core_sources "lp_core/test_main.c") idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "lp_core" - REQUIRES ulp unity + REQUIRES ulp unity esp_timer WHOLE_ARCHIVE) set(lp_core_app_name lp_core_test_app) diff --git a/components/ulp/test_apps/lp_core/main/lp_core/test_main.c b/components/ulp/test_apps/lp_core/main/lp_core/test_main.c index 91d8818764..16f869e56e 100644 --- a/components/ulp/test_apps/lp_core/main/lp_core/test_main.c +++ b/components/ulp/test_apps/lp_core/main/lp_core/test_main.c @@ -8,6 +8,8 @@ #include #include #include "test_shared.h" +#include "ulp_lp_core_utils.h" + volatile lp_core_test_commands_t main_cpu_command = LP_CORE_NO_COMMAND; @@ -33,10 +35,48 @@ void handle_commands(lp_core_test_commands_t cmd) /* Set the command reply status */ main_cpu_reply = LP_CORE_COMMAND_OK; + main_cpu_command = LP_CORE_NO_COMMAND; + + break; + + case LP_CORE_DELAY_TEST: + counter++; + /* Echo the command ID back to the main CPU */ + command_resp = LP_CORE_DELAY_TEST; + + ulp_lp_core_delay_us(test_data_in); + main_cpu_reply = LP_CORE_COMMAND_OK; + main_cpu_command = LP_CORE_NO_COMMAND; + break; + + case LP_CORE_DEEP_SLEEP_WAKEUP_SHORT_DELAY_TEST: + /* Echo the command ID back to the main CPU */ + command_resp = LP_CORE_DEEP_SLEEP_WAKEUP_SHORT_DELAY_TEST; + + /* Set the command reply status */ + main_cpu_reply = LP_CORE_COMMAND_OK; + main_cpu_command = LP_CORE_NO_COMMAND; + + ulp_lp_core_delay_us(1000*1000); + ulp_lp_core_wakeup_main_processor(); + + break; + + case LP_CORE_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST: + /* Echo the command ID back to the main CPU */ + command_resp = LP_CORE_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST; + + /* Set the command reply status */ + main_cpu_reply = LP_CORE_COMMAND_OK; + main_cpu_command = LP_CORE_NO_COMMAND; + + ulp_lp_core_delay_us(10000*1000); + ulp_lp_core_wakeup_main_processor(); + break; case LP_CORE_NO_COMMAND: - main_cpu_reply = LP_CORE_COMMAND_OK; + main_cpu_reply = LP_CORE_COMMAND_NOK; break; default: @@ -49,7 +89,7 @@ int main (void) { while (1) { handle_commands(main_cpu_command); - } + } return 0; } diff --git a/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h b/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h index 384b0b1656..fa61107ca5 100644 --- a/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h +++ b/components/ulp/test_apps/lp_core/main/lp_core/test_shared.h @@ -9,6 +9,9 @@ typedef enum{ LP_CORE_READ_WRITE_TEST = 1, + LP_CORE_DELAY_TEST, + LP_CORE_DEEP_SLEEP_WAKEUP_SHORT_DELAY_TEST, + LP_CORE_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST, LP_CORE_NO_COMMAND, } lp_core_test_commands_t; diff --git a/components/ulp/test_apps/lp_core/main/test_lp_core.c b/components/ulp/test_apps/lp_core/main/test_lp_core.c index c2bd74e5d5..88b6b004b2 100644 --- a/components/ulp/test_apps/lp_core/main/test_lp_core.c +++ b/components/ulp/test_apps/lp_core/main/test_lp_core.c @@ -10,6 +10,8 @@ #include "ulp_lp_core.h" #include "test_shared.h" #include "unity.h" +#include "esp_sleep.h" +#include "esp_timer.h" extern const uint8_t lp_core_main_bin_start[] asm("_binary_lp_core_test_app_bin_start"); extern const uint8_t lp_core_main_bin_end[] asm("_binary_lp_core_test_app_bin_end"); @@ -59,4 +61,80 @@ TEST_CASE("LP core and main CPU are able to exchange data", "[lp_core]") /* Clear test data */ ulp_main_cpu_command = LP_CORE_NO_COMMAND; + ulp_command_resp = LP_CORE_NO_COMMAND; } + +TEST_CASE("Test LP core delay", "[lp_core]") +{ + int64_t start, diff; + const uint32_t delay_period_us = 5000000; + const uint32_t delta_us = 500000; // RTC FAST is not very accurate + + /* Load ULP RISC-V firmware and start the coprocessor */ + load_and_start_lp_core_firmware(); + + /* Setup test data */ + ulp_test_data_in = delay_period_us; + ulp_main_cpu_command = LP_CORE_DELAY_TEST; + + /* Wait till we receive the correct command response */ + while (ulp_command_resp != LP_CORE_DELAY_TEST) { + } + + start = esp_timer_get_time(); + + /* Wait till we receive COMMAND_OK reply */ + while (ulp_main_cpu_reply != LP_CORE_COMMAND_OK) { + } + + diff = esp_timer_get_time() - start; + + printf("Waited for %" PRIi64 "us, expected: %" PRIi32 "us\n", diff, delay_period_us); + TEST_ASSERT_INT_WITHIN(delta_us, delay_period_us, diff); + + /* Clear test data */ + ulp_main_cpu_command = LP_CORE_NO_COMMAND; + ulp_command_resp = LP_CORE_NO_COMMAND; +} + + +static void do_ulp_wakeup_deepsleep(lp_core_test_commands_t ulp_cmd) +{ + /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */ + load_and_start_lp_core_firmware(); + + /* Setup wakeup triggers */ + TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK); + + /* Setup test data */ + ulp_main_cpu_command = ulp_cmd; + + /* Enter Deep Sleep */ + esp_deep_sleep_start(); + UNITY_TEST_FAIL(__LINE__, "Should not get here!"); +} + + +static void check_reset_reason_ulp_wakeup(void) +{ + TEST_ASSERT_EQUAL(ESP_SLEEP_WAKEUP_ULP, esp_sleep_get_wakeup_cause()); +} + +static void do_ulp_wakeup_after_short_delay_deepsleep(void) +{ + do_ulp_wakeup_deepsleep(LP_CORE_DEEP_SLEEP_WAKEUP_SHORT_DELAY_TEST); +} + +static void do_ulp_wakeup_after_long_delay_deepsleep(void) +{ + do_ulp_wakeup_deepsleep(LP_CORE_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST); +} + +TEST_CASE_MULTIPLE_STAGES("LP-core is able to wakeup main CPU from deep sleep after a short delay", "[ulp]", + do_ulp_wakeup_after_short_delay_deepsleep, + check_reset_reason_ulp_wakeup); + +/* Certain erroneous wake-up triggers happen only after sleeping for a few seconds */ +TEST_CASE_MULTIPLE_STAGES("LP-core is able to wakeup main CPU from deep sleep after a long delay", "[ulp]", + do_ulp_wakeup_after_long_delay_deepsleep, + check_reset_reason_ulp_wakeup); diff --git a/components/ulp/test_apps/ulp_riscv/main/test_ulp_riscv.c b/components/ulp/test_apps/ulp_riscv/main/test_ulp_riscv.c index 8336fb5d3c..88209775ee 100644 --- a/components/ulp/test_apps/ulp_riscv/main/test_ulp_riscv.c +++ b/components/ulp/test_apps/ulp_riscv/main/test_ulp_riscv.c @@ -321,7 +321,7 @@ static void do_ulp_wakeup_after_long_delay_deepsleep(void) do_ulp_wakeup_deepsleep(RISCV_DEEP_SLEEP_WAKEUP_LONG_DELAY_TEST, true); } -/* Certain erroneous wake-up triggers happen only after a sleeping for a few seconds */ +/* Certain erroneous wake-up triggers happen only after sleeping for a few seconds */ TEST_CASE_MULTIPLE_STAGES("ULP-RISC-V is able to wakeup main CPU from deep sleep after a long delay", "[ulp]", do_ulp_wakeup_after_long_delay_deepsleep, check_reset_reason_ulp_wakeup); diff --git a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h index 20eebb6282..d73bb5ca1b 100644 --- a/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h +++ b/components/ulp/ulp_riscv/ulp_core/include/ulp_riscv_utils.h @@ -18,7 +18,7 @@ extern "C" { * @brief Wakeup main CPU from sleep or deep sleep. * * This raises a software interrupt signal, if the - * main CPU is configured the ULP as a wakeup source + * main CPU has configured the ULP as a wakeup source * calling this function will make the main CPU to * exit from sleep or deep sleep. */ diff --git a/docs/conf_common.py b/docs/conf_common.py index 1b6120bacb..032488d9ff 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -104,9 +104,9 @@ FTDI_JTAG_DOCS = ['api-guides/jtag-debugging/configure-ft2232h-jtag.rst'] USB_SERIAL_JTAG_DOCS = ['api-guides/jtag-debugging/configure-builtin-jtag.rst', 'api-guides/usb-serial-jtag-console.rst'] -ULP_DOCS = ['api-reference/system/ulp.rst', - 'api-reference/system/ulp_macros.rst', - 'api-reference/system/ulp_instruction_set.rst'] +ULP_FSM_DOCS = ['api-reference/system/ulp.rst', + 'api-reference/system/ulp_macros.rst', + 'api-reference/system/ulp_instruction_set.rst'] RISCV_COPROC_DOCS = ['api-reference/system/ulp-risc-v.rst',] @@ -183,7 +183,7 @@ conditional_include_dict = {'SOC_BT_SUPPORTED':BT_DOCS, 'SOC_DAC_SUPPORTED':DAC_DOCS, 'SOC_ETM_SUPPORTED':ETM_DOCS, 'SOC_TOUCH_SENSOR_SUPPORTED':TOUCH_SENSOR_DOCS, - 'SOC_ULP_SUPPORTED':ULP_DOCS, + 'SOC_ULP_FSM_SUPPORTED':ULP_FSM_DOCS, 'SOC_RISCV_COPROC_SUPPORTED':RISCV_COPROC_DOCS, 'SOC_DIG_SIGN_SUPPORTED':['api-reference/peripherals/ds.rst'], 'SOC_HMAC_SUPPORTED':['api-reference/peripherals/hmac.rst'], diff --git a/docs/en/api-reference/peripherals/gpio.rst b/docs/en/api-reference/peripherals/gpio.rst index 3f2b060344..c2cb49e67f 100644 --- a/docs/en/api-reference/peripherals/gpio.rst +++ b/docs/en/api-reference/peripherals/gpio.rst @@ -18,7 +18,7 @@ GPIO Summary .. list:: - In Deep-sleep mode - :SOC_ULP_SUPPORTED: - The :doc:`Ultra Low Power co-processor <../../api-reference/system/ulp>` is running + :SOC_ULP_SUPPORTED and not esp32c6: - The :doc:`Ultra Low Power co-processor <../../api-reference/system/ulp>` is running - Analog functions such as ADC/DAC/etc are in use. diff --git a/docs/en/api-reference/system/index.rst b/docs/en/api-reference/system/index.rst index b3b90e9e56..9fadf2b1a7 100644 --- a/docs/en/api-reference/system/index.rst +++ b/docs/en/api-reference/system/index.rst @@ -37,7 +37,7 @@ System API system_time :SOC_ASYNC_MEMCPY_SUPPORTED: async_memcpy :esp32: himem - :SOC_ULP_SUPPORTED: ulp + :SOC_ULP_FSM_SUPPORTED: ulp :SOC_RISCV_COPROC_SUPPORTED: ulp-risc-v wdts diff --git a/docs/zh_CN/api-reference/peripherals/gpio.rst b/docs/zh_CN/api-reference/peripherals/gpio.rst index 36ae6094f8..cc1f66111b 100644 --- a/docs/zh_CN/api-reference/peripherals/gpio.rst +++ b/docs/zh_CN/api-reference/peripherals/gpio.rst @@ -18,7 +18,7 @@ GPIO 汇总 .. list:: - 处于 Deep-sleep 模式时 - :SOC_ULP_SUPPORTED: - :doc:`超低功耗协处理器 (ULP) <../../api-reference/system/ulp>` 运行时 + :SOC_ULP_SUPPORTED and not esp32c6: - :doc:`超低功耗协处理器 (ULP) <../../api-reference/system/ulp>` 运行时 - 使用 ADC/DAC 等模拟功能时 diff --git a/docs/zh_CN/api-reference/system/index.rst b/docs/zh_CN/api-reference/system/index.rst index bad02e4143..2ab39f8a31 100644 --- a/docs/zh_CN/api-reference/system/index.rst +++ b/docs/zh_CN/api-reference/system/index.rst @@ -37,7 +37,7 @@ System API system_time :SOC_ASYNC_MEMCPY_SUPPORTED: async_memcpy :esp32: himem - :SOC_ULP_SUPPORTED: ulp + :SOC_ULP_FSM_SUPPORTED: ulp :SOC_RISCV_COPROC_SUPPORTED: ulp-risc-v wdts diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 8e67000c32..14846111f3 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -187,7 +187,7 @@ examples/system/task_watchdog: examples/system/ulp_fsm/ulp: disable: - - if: SOC_ULP_SUPPORTED != 1 + - if: SOC_ULP_FSM_SUPPORTED != 1 examples/system/ulp_fsm/ulp_adc: enable: