feat(lp-core): bringup lp-core for C5 MP

LP-Core is now able to boot and run on C5 MP chip.
This commit is contained in:
Marius Vikhammer 2024-06-14 17:39:57 +08:00
parent 0479494e7a
commit aae3aa5e5f
15 changed files with 113 additions and 27 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,11 +7,12 @@
#include <stdint.h>
#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

View File

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

View File

@ -1,3 +1,3 @@
| Supported Targets | ESP32-C6 | ESP32-P4 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
| ----------------- | -------- | -------- | -------- |

View File

@ -8,7 +8,6 @@
#include <inttypes.h>
#include <sys/time.h>
#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
}

View File

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

View File

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

View File

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