From aae3aa5e5f0f064c5dfcb2f9a56915d102cd557a Mon Sep 17 00:00:00 2001 From: Marius Vikhammer Date: Fri, 14 Jun 2024 17:39:57 +0800 Subject: [PATCH] feat(lp-core): bringup lp-core for C5 MP LP-Core is now able to boot and run on C5 MP chip. --- .../hal/esp32c5/include/hal/lp_core_ll.h | 10 +++++++++ components/hal/esp32c5/include/hal/pmu_ll.h | 10 +++++++++ .../hal/esp32c5/include/hal/rtc_io_ll.h | 21 ++++++++++++++++++ .../esp32c5/include/soc/Kconfig.soc_caps.in | 12 ++++++++++ .../soc/esp32c5/include/soc/pmu_struct.h | 16 ++++++++++---- components/soc/esp32c5/include/soc/soc_caps.h | 6 ++++- components/ulp/cmake/CMakeLists.txt | 6 +---- .../lp_core/include/ulp_lp_core_interrupts.h | 5 +++-- .../ulp/lp_core/lp_core/lp_core_interrupt.c | 7 +++--- .../lp_core/port/esp32c5/vector_table.S | 22 +++++++++++++++++++ components/ulp/test_apps/lp_core/README.md | 4 ++-- .../ulp/test_apps/lp_core/main/test_lp_core.c | 11 +++++----- docs/doxygen/Doxyfile_esp32c5 | 1 + examples/system/.build-test-rules.yml | 5 +++-- .../system/ulp/lp_core/interrupt/README.md | 4 ++-- 15 files changed, 113 insertions(+), 27 deletions(-) create mode 100644 components/ulp/lp_core/lp_core/port/esp32c5/vector_table.S diff --git a/components/hal/esp32c5/include/hal/lp_core_ll.h b/components/hal/esp32c5/include/hal/lp_core_ll.h index c1e5baeae6..59cb13c441 100644 --- a/components/hal/esp32c5/include/hal/lp_core_ll.h +++ b/components/hal/esp32c5/include/hal/lp_core_ll.h @@ -120,6 +120,16 @@ static inline void lp_core_ll_request_sleep(void) PMU.lp_ext.pwr1.sleep_req = 1; } +/** + * @brief Get which interrupts have triggered on the LP core + * + * @return uint8_t bit mask of triggered LP interrupt sources + */ +static inline uint8_t lp_core_ll_get_triggered_interrupt_srcs(void) +{ + return LPPERI.interrupt_source.lp_interrupt_source; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/pmu_ll.h b/components/hal/esp32c5/include/hal/pmu_ll.h index 83793ed62d..97a15793da 100644 --- a/components/hal/esp32c5/include/hal/pmu_ll.h +++ b/components/hal/esp32c5/include/hal/pmu_ll.h @@ -683,6 +683,16 @@ FORCE_INLINE_ATTR void pmu_ll_lp_clear_intsts_mask(pmu_dev_t *hw, uint32_t mask) hw->lp_ext.int_clr.val = mask; } +FORCE_INLINE_ATTR void pmu_ll_lp_clear_sw_intr_status(pmu_dev_t *hw) +{ + hw->lp_ext.int_clr.sw_trigger = 1; +} + +FORCE_INLINE_ATTR void pmu_ll_lp_enable_sw_intr(pmu_dev_t *hw, bool enable) +{ + hw->lp_ext.int_ena.sw_trigger = enable; +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c5/include/hal/rtc_io_ll.h b/components/hal/esp32c5/include/hal/rtc_io_ll.h index 89c8c9a37c..ef2eb7bcf6 100644 --- a/components/hal/esp32c5/include/hal/rtc_io_ll.h +++ b/components/hal/esp32c5/include/hal/rtc_io_ll.h @@ -44,6 +44,15 @@ typedef enum { RTCIO_LL_OUTPUT_OD = 0x1, /*!< RTCIO output mode is open-drain. */ } rtcio_ll_out_mode_t; +typedef enum { + RTCIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */ + RTCIO_INTR_POSEDGE = 1, /*!< GPIO interrupt type : rising edge */ + RTCIO_INTR_NEGEDGE = 2, /*!< GPIO interrupt type : falling edge */ + RTCIO_INTR_ANYEDGE = 3, /*!< GPIO interrupt type : both rising and falling edge */ + RTCIO_INTR_LOW_LEVEL = 4, /*!< GPIO interrupt type : input low level trigger */ + RTCIO_INTR_HIGH_LEVEL = 5, /*!< GPIO interrupt type : input high level trigger */ +} rtcio_ll_intr_type_t; + /** * @brief Select a RTC IOMUX function for the RTC IO * @@ -451,6 +460,18 @@ static inline void rtcio_ll_clear_interrupt_status(void) abort(); } +/** + * Enable interrupt function and set interrupt type + * + * @param rtcio_num The index of rtcio. 0 ~ MAX(rtcio). + * @param type Interrupt type on high level or low level. + */ +static inline void rtcio_ll_intr_enable(int rtcio_num, rtcio_ll_intr_type_t type) +{ + // TODO: [ESP32C5] IDF-8719 + //LP_GPIO.pin[rtcio_num].int_type = type; +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index e36ec0f749..7ba1e43a20 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -35,6 +35,14 @@ config SOC_SUPPORTS_SECURE_DL_MODE bool default y +config SOC_LP_CORE_SUPPORTED + bool + default y + +config SOC_ULP_SUPPORTED + bool + default y + config SOC_EFUSE_KEY_PURPOSE_FIELD bool default y @@ -774,3 +782,7 @@ config SOC_CLK_RC32K_SUPPORTED config SOC_RCC_IS_INDEPENDENT bool default y + +config SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR + bool + default y diff --git a/components/soc/esp32c5/include/soc/pmu_struct.h b/components/soc/esp32c5/include/soc/pmu_struct.h index bdb33425cf..ef9f62e81b 100644 --- a/components/soc/esp32c5/include/soc/pmu_struct.h +++ b/components/soc/esp32c5/include/soc/pmu_struct.h @@ -376,6 +376,16 @@ typedef union { uint32_t val; } pmu_power_wait_timer1_reg_t; +typedef union { + struct { + uint32_t reserved0 : 9; + uint32_t powerdown_timer: 7; + uint32_t powerup_timer : 7; + uint32_t wait_timer : 9; + }; + uint32_t val; +} pmu_power_wait_timer2_reg_t; + typedef union { struct { uint32_t force_reset : 1; @@ -445,6 +455,7 @@ typedef union { typedef struct pmu_power_hw_regmap_t{ pmu_power_wait_timer0_reg_t wait_timer0; pmu_power_wait_timer1_reg_t wait_timer1; + pmu_power_wait_timer2_reg_t wait_timer2; pmu_power_domain_cntl_reg_t hp_pd[5]; pmu_power_domain_cntl_reg_t lp_peri; pmu_power_memory_cntl_reg_t mem_cntl; @@ -731,8 +742,6 @@ typedef struct pmu_dev_t{ volatile uint32_t val; } vdd_spi_status; - uint32_t reserved[150]; - union { struct { volatile uint32_t pmu_date: 31; @@ -745,9 +754,8 @@ typedef struct pmu_dev_t{ extern pmu_dev_t PMU; #ifndef __cplusplus -_Static_assert(sizeof(pmu_dev_t) == 0x400, "Invalid size of pmu_dev_t structure"); -//_Static_assert(offsetof(pmu_dev_t, reserved) == (PMU_VDD_SPI_STATUS_REG - DR_REG_PMU_BASE) + 4, "Invalid size of pmu_dev_t structure"); +//_Static_assert(offsetof(pmu_dev_t, reserved) == (PMU_VDD_SPI_STATUS_REG - DR_REG_PMU_BASE) + 4, "Invalid size of pmu_dev_t structure"); TODO IDF-8643 #endif diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index 9f2762b069..923ba7c3d9 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -33,7 +33,8 @@ // #define SOC_TEMP_SENSOR_SUPPORTED 1 // TODO: [ESP32C5] IDF-8727 // #define SOC_WIFI_SUPPORTED 1 // TODO: [ESP32C5] IDF-8851 #define SOC_SUPPORTS_SECURE_DL_MODE 1 -// #define SOC_LP_CORE_SUPPORTED 1 // TODO: [ESP32C5] IDF-8637 +#define SOC_LP_CORE_SUPPORTED 1 +#define SOC_ULP_SUPPORTED 1 #define SOC_EFUSE_KEY_PURPOSE_FIELD 1 #define SOC_EFUSE_SUPPORTED 1 #define SOC_RTC_FAST_MEM_SUPPORTED 1 @@ -579,3 +580,6 @@ /*------------------------------------- PHY CAPS -------------------------------------*/ // #define SOC_PHY_COMBO_MODULE (1) /*!< Support Wi-Fi, BLE and 15.4*/ + +/*------------------------------------- ULP CAPS -------------------------------------*/ +#define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */ diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index 05bddaa68d..f08c3ab0a0 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -121,11 +121,7 @@ elseif(ULP_COCPU_IS_LP_CORE) target_link_options(${ULP_APP_NAME} PRIVATE -Wl,--gc-sections) target_link_options(${ULP_APP_NAME} PRIVATE -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}.map) - if(${IDF_TARGET} STREQUAL "esp32c5") - set(target_folder "esp32c5/mp") - else() - set(target_folder ${IDF_TARGET}) - endif() + set(target_folder ${IDF_TARGET}) target_link_options(${ULP_APP_NAME} PRIVATE SHELL:-T ${IDF_PATH}/components/soc/${target_folder}/ld/${IDF_TARGET}.peripherals.ld) diff --git a/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h b/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h index f757711974..8d20d1f43c 100644 --- a/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h +++ b/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h @@ -7,13 +7,14 @@ #pragma once #include "sdkconfig.h" +#include "soc/soc_caps.h" #ifdef __cplusplus extern "C" { #endif -#if CONFIG_IDF_TARGET_ESP32C6 -#define LP_CORE_ISR_ATTR // On C6 registers are saved by us before calling the ISR +#if SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR +#define LP_CORE_ISR_ATTR // On chips with just a single interrupt entry point registers are saved by us before calling the ISR #else #define LP_CORE_ISR_ATTR __attribute__((interrupt)) #endif diff --git a/components/ulp/lp_core/lp_core/lp_core_interrupt.c b/components/ulp/lp_core/lp_core/lp_core_interrupt.c index a24b7953e1..63de987f52 100644 --- a/components/ulp/lp_core/lp_core/lp_core_interrupt.c +++ b/components/ulp/lp_core/lp_core/lp_core_interrupt.c @@ -7,11 +7,12 @@ #include #include "sdkconfig.h" +#include "soc/soc_caps.h" #include "hal/lp_core_ll.h" #include "riscv/rv_utils.h" #include "riscv/rvruntime-frames.h" -#if CONFIG_IDF_TARGET_ESP32C6 +#if SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR /* Enable interrupt 30, which all external interrupts are routed to*/ #define MIE_ALL_INTS_MASK (1 << 30) #else @@ -66,7 +67,7 @@ void __attribute__((weak, alias("ulp_lp_core_default_intr_handler"))) ulp_lp_cor void __attribute__((weak, alias("ulp_lp_core_default_intr_handler"))) ulp_lp_core_lp_rtc_intr_handler(void); void __attribute__((weak, alias("ulp_lp_core_default_intr_handler"))) ulp_lp_core_sw_intr_handler(void); -#if CONFIG_IDF_TARGET_ESP32C6 +#if SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR static void* s_intr_handlers[] = { ulp_lp_core_lp_io_intr_handler, @@ -90,4 +91,4 @@ void __attribute__((weak)) ulp_lp_core_intr_handler(void) } } -#endif +#endif //SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR diff --git a/components/ulp/lp_core/lp_core/port/esp32c5/vector_table.S b/components/ulp/lp_core/lp_core/port/esp32c5/vector_table.S new file mode 100644 index 0000000000..a1309e3cf8 --- /dev/null +++ b/components/ulp/lp_core/lp_core/port/esp32c5/vector_table.S @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + + .section .init.vector,"ax" + + .global _vector_table + .type _vector_table, @function +_vector_table: + .option push + .option norvc + + .rept 30 + j _panic_handler + .endr + j _interrupt_handler // All interrupts are routed to mtvec + 4*30, i.e. the 31st entry + j _panic_handler + + .option pop + .size _vector_table, .-_vector_table diff --git a/components/ulp/test_apps/lp_core/README.md b/components/ulp/test_apps/lp_core/README.md index b386444355..59db987a22 100644 --- a/components/ulp/test_apps/lp_core/README.md +++ b/components/ulp/test_apps/lp_core/README.md @@ -1,3 +1,3 @@ -| Supported Targets | ESP32-C6 | ESP32-P4 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | 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 2545d4a3ac..bc1102c75f 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 @@ -8,7 +8,6 @@ #include #include #include "soc/soc_caps.h" -#include "soc/gpio_num.h" #include "esp_rom_caps.h" #include "lp_core_test_app.h" #include "lp_core_test_app_counter.h" @@ -321,6 +320,7 @@ TEST_CASE("LP core can schedule next wake-up time by itself", "[ulp]") TEST_ASSERT_INT_WITHIN_MESSAGE(5, expected_run_count, ulp_set_timer_wakeup_counter, "LP Core did not wake up the expected number of times"); } +#if SOC_RTCIO_PIN_COUNT > 0 TEST_CASE("LP core gpio tests", "[ulp]") { /* Load ULP firmware and start the coprocessor */ @@ -337,19 +337,15 @@ TEST_CASE("LP core gpio tests", "[ulp]") TEST_ASSERT_TRUE(ulp_gpio_test_succeeded); } +#endif //SOC_RTCIO_PIN_COUNT > 0 #endif //SOC_LP_TIMER_SUPPORTED #define ISR_TEST_ITERATIONS 100 #define IO_TEST_PIN 0 -#include "lp_core_uart.h" TEST_CASE("LP core ISR tests", "[ulp]") { - lp_core_uart_cfg_t ucfg = LP_CORE_UART_DEFAULT_CONFIG(); - - ESP_ERROR_CHECK(lp_core_uart_init(&ucfg)); - /* Load ULP firmware and start the coprocessor */ ulp_lp_core_cfg_t cfg = { .wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU, @@ -368,6 +364,7 @@ TEST_CASE("LP core ISR tests", "[ulp]") printf("ULP PMU ISR triggered %"PRIu32" times\n", ulp_pmu_isr_counter); TEST_ASSERT_EQUAL(ISR_TEST_ITERATIONS, ulp_pmu_isr_counter); +#if SOC_RTCIO_PIN_COUNT > 0 /* Test LP IO interrupt */ rtc_gpio_init(IO_TEST_PIN); rtc_gpio_set_direction(IO_TEST_PIN, RTC_GPIO_MODE_INPUT_ONLY); @@ -384,4 +381,6 @@ TEST_CASE("LP core ISR tests", "[ulp]") printf("ULP LP IO ISR triggered %"PRIu32" times\n", ulp_io_isr_counter); TEST_ASSERT_EQUAL(ISR_TEST_ITERATIONS, ulp_io_isr_counter); +#endif //SOC_RTCIO_PIN_COUNT > 0 + } diff --git a/docs/doxygen/Doxyfile_esp32c5 b/docs/doxygen/Doxyfile_esp32c5 index c97591d32c..234f39a672 100644 --- a/docs/doxygen/Doxyfile_esp32c5 +++ b/docs/doxygen/Doxyfile_esp32c5 @@ -7,4 +7,5 @@ INPUT += \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_print.h \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_uart.h \ $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h \ + $(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_interrupts.h \ $(PROJECT_PATH)/components/ulp/ulp_common/include/ulp_common.h \ diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index b8668629a8..526fc7ad43 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -259,13 +259,14 @@ examples/system/task_watchdog: examples/system/ulp/lp_core/gpio: enable: - - if: SOC_LP_CORE_SUPPORTED == 1 + - if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) + depends_components: - ulp examples/system/ulp/lp_core/gpio_intr_pulse_counter: enable: - - if: SOC_LP_CORE_SUPPORTED == 1 + - if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_ULP_LP_UART_SUPPORTED == 1) depends_components: - ulp diff --git a/examples/system/ulp/lp_core/interrupt/README.md b/examples/system/ulp/lp_core/interrupt/README.md index b508bd913d..082a827ba4 100644 --- a/examples/system/ulp/lp_core/interrupt/README.md +++ b/examples/system/ulp/lp_core/interrupt/README.md @@ -1,5 +1,5 @@ -| Supported Targets | ESP32-C6 | ESP32-P4 | -| ----------------- | -------- | -------- | +| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | +| ----------------- | -------- | -------- | -------- | # LP-Core example with interrupt triggered from HP-Core: