mirror of
https://github.com/espressif/esp-idf.git
synced 2026-10-02 03:00:34 +03:00
feat(ulp): add support for ulp on esp32s31
This commit is contained in:
@@ -13,6 +13,11 @@
|
||||
#include "esp_cpu.h"
|
||||
|
||||
#include "hal/apm_hal.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S31
|
||||
#include "soc/hp_peri0_pms_reg.h"
|
||||
#include "soc/hp_peri1_pms_reg.h"
|
||||
#include "soc/lp_peri_pms_reg.h"
|
||||
#endif
|
||||
|
||||
void bootloader_init_mem(void)
|
||||
{
|
||||
@@ -37,6 +42,22 @@ void bootloader_init_mem(void)
|
||||
#endif // SOC_APM_CTRL_FILTER_SUPPORTED
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S31
|
||||
/* TODO: [ESP32S31] IDF-14620
|
||||
As a temp. fix to allow ULP access to all peripherals during bringup.
|
||||
Open all LP/HP peripheral PMS control registers for all security modes.
|
||||
*/
|
||||
for (uint32_t reg = LP_PERI_PMS_LP_SYSREG_CTRL_REG; reg <= LP_PERI_PMS_LP_DAC_CTRL_REG; reg += 4) {
|
||||
REG_WRITE(reg, 0xFF);
|
||||
}
|
||||
for (uint32_t reg = HP_PERI0_PMS_TRACE0_CTRL_REG; reg <= HP_PERI0_PMS_AXI_PERF_MON_CTRL_REG; reg += 4) {
|
||||
REG_WRITE(reg, 0xFF);
|
||||
}
|
||||
for (uint32_t reg = HP_PERI1_PMS_HP_USBOTG_PHY_CTRL_REG; reg <= HP_PERI1_PMS_HP_PERI1_PMS_CTRL_REG; reg += 4) {
|
||||
REG_WRITE(reg, 0xFF);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
|
||||
// protect memory region
|
||||
esp_cpu_configure_region_protection();
|
||||
|
||||
@@ -20,6 +20,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Aliases used by LP core code (lp_core_utils.c) which references LP_TIMER naming convention
|
||||
#define LP_TIMER RTC_TIMER
|
||||
#define LP_TIMER_MAIN_TIMER_LP_INT_RAW RTC_TIMER_MAIN_TIMER_LP_INT_RAW
|
||||
|
||||
FORCE_INLINE_ATTR void rtc_timer_ll_set_alarm_target(rtc_timer_dev_t *dev, uint8_t timer_id, uint64_t value)
|
||||
{
|
||||
HAL_FORCE_MODIFY_U32_REG_FIELD(dev->target[timer_id].hi, target_hi, (value >> 32) & 0xFFFF);
|
||||
|
||||
@@ -32,3 +32,24 @@ config RTC_CLK_CAL_CYCLES
|
||||
- 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.
|
||||
In case more value will help improve the definition of the launch of the crystal.
|
||||
If the crystal could not start, it will be switched to internal RC.
|
||||
|
||||
choice RTC_FAST_CLK_SRC
|
||||
depends on SOC_CLK_LP_FAST_SUPPORT_XTAL
|
||||
prompt "RTC fast clock source"
|
||||
default RTC_FAST_CLK_SRC_RC_FAST
|
||||
help
|
||||
Choose which clock is used as RTC fast clock source.
|
||||
|
||||
Choosing the faster 40 MHz XTAL can allow modules which depend on RTC_FAST
|
||||
to work at a higher clock frequency. With this the ULP LP-Core will run with a
|
||||
CPU frequency of 40 Mhz instead of the default 20 Mhz.
|
||||
|
||||
The drawback is that the XTAL is usually powered down during sleep, as
|
||||
it draw a lot of power. Choosing this option will cause the XTAL to stay
|
||||
powered on, increasing sleep power consumption.
|
||||
|
||||
config RTC_FAST_CLK_SRC_RC_FAST
|
||||
bool "20 Mhz RC Fast Clock"
|
||||
config RTC_FAST_CLK_SRC_XTAL
|
||||
bool "40 Mhz crystal (increased power consumption during sleep)"
|
||||
endchoice
|
||||
|
||||
@@ -61,10 +61,14 @@ MEMORY
|
||||
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
|
||||
/**
|
||||
* lp ram memory (RWX). Persists over deep sleep. // TODO: IDF-5667
|
||||
* lp ram memory (RWX). Persists over deep sleep.
|
||||
*/
|
||||
/* TODO: ["ESP32S31"] IDF-14640 */
|
||||
lp_ram_seg(RW) : org = 0x2E000000, len = 0x8000 - RESERVE_RTC_MEM
|
||||
#if CONFIG_ULP_COPROC_ENABLED
|
||||
lp_ram_seg(RW) : org = 0x2E000000 + CONFIG_ULP_COPROC_RESERVE_MEM,
|
||||
len = 0x8000 - CONFIG_ULP_COPROC_RESERVE_MEM - RESERVE_RTC_MEM
|
||||
#else
|
||||
lp_ram_seg(RW) : org = 0x2E000000, len = 0x8000 - RESERVE_RTC_MEM
|
||||
#endif // CONFIG_ULP_COPROC_ENABLED
|
||||
|
||||
/* We reduced the size of lp_ram_seg by RESERVE_RTC_MEM value.
|
||||
It reserves the amount of LP memory that we use for this memory segment.
|
||||
@@ -72,10 +76,8 @@ MEMORY
|
||||
- (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files).
|
||||
- (higher addr) bootloader rtc data (s_bootloader_retain_mem, when a Kconfig option is on).
|
||||
The aim of this is to keep data that will not be moved around and have a fixed address.
|
||||
This segment is placed at the beginning of LP RAM, as the end of LP RAM is occupied by LP ROM stack/data
|
||||
*/
|
||||
/* TODO: ["ESP32S31"] IDF-14640 */
|
||||
lp_reserved_seg(RW) : org = 0x2E000000 + 0x8000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM
|
||||
lp_reserved_seg(RW) : org = 0x2E000000 + 0x8000 - RESERVE_RTC_MEM, len = RESERVE_RTC_MEM
|
||||
|
||||
/* PSRAM seg */
|
||||
extern_ram_seg(RWX) : org = 0x50000000, len = IDROM_SEG_SIZE
|
||||
@@ -92,14 +94,12 @@ REGION_ALIAS("dram_seg", sram_seg);
|
||||
* S31 has no distinguished LP(RTC) fast and slow memory sections, instead, there is a unified LP_RAM section
|
||||
* Thus, the following region segments are not configurable like on other targets
|
||||
*/
|
||||
|
||||
/* TODO: ["ESP32S31"] IDF-14640 */
|
||||
REGION_ALIAS("rtc_text_seg", lp_ram_seg);
|
||||
REGION_ALIAS("rtc_data_seg", lp_ram_seg);
|
||||
REGION_ALIAS("rtc_slow_seg", lp_ram_seg);
|
||||
REGION_ALIAS("rtc_force_fast_seg", lp_ram_seg);
|
||||
REGION_ALIAS("rtc_force_slow_seg", lp_ram_seg);
|
||||
REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg );
|
||||
REGION_ALIAS("rtc_reserved_seg", lp_reserved_seg);
|
||||
|
||||
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||
REGION_ALIAS("flash_text_seg", irom_seg);
|
||||
|
||||
@@ -9,9 +9,6 @@ ENTRY(call_start_cpu0);
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/**
|
||||
* RTC memory should be implemented here TODO: [ESP32S31] IDF-14640
|
||||
*/
|
||||
#include "ld.rtc.sections"
|
||||
|
||||
#include "ld.iram.sections"
|
||||
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/*******************************************************************************
|
||||
* NOTICE
|
||||
* The hal is not public api, don't use it in application code.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "soc/lp_peri_clkrst_struct.h"
|
||||
#include "soc/lp_system_struct.h"
|
||||
#include "soc/pmu_struct.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_HP_CPU BIT(1) // SW_WAKEUP_HP
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_LP_IO BIT(9) // LP_GPIO_WAKEUP
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_LP_UART BIT(10) // LP_UART_WAKEUP
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER_0 BIT(13) // LP_TMR_WAKEUP[0]
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_ETM BIT(17) // REG_ETM_LPCORE_WAKEUP
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER_1 BIT(18)
|
||||
|
||||
|
||||
/* Use lp timer 1 as the normal wakeup timer, timer 0 is used by deep sleep */
|
||||
#define LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER_1
|
||||
|
||||
/**
|
||||
* @brief Set the boot address of the LP-core
|
||||
*
|
||||
* @param boot_address Boot address
|
||||
*/
|
||||
static inline void lp_core_ll_set_boot_address(intptr_t boot_address)
|
||||
{
|
||||
LP_SYS.lp_core_boot_addr.lp_cpu_boot_addr = boot_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the bus clock for LP-core
|
||||
*
|
||||
* @param enable true to enable, false to disable
|
||||
*/
|
||||
static inline void _lp_core_ll_enable_bus_clock(bool enable)
|
||||
{
|
||||
LP_PERI_CLKRST.cpu_ctrl.lp_core_clk_force_on = enable;
|
||||
LP_PERI_CLKRST.intr_ctrl.lp_intr_clk_en = enable;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define lp_core_ll_enable_bus_clock(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
_lp_core_ll_enable_bus_clock(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Reset the LP-core module
|
||||
*/
|
||||
static inline void lp_core_ll_reset_register(void)
|
||||
{
|
||||
LP_PERI_CLKRST.cpu_ctrl.lp_core_rst_en = 1;
|
||||
LP_PERI_CLKRST.intr_ctrl.lp_intr_rst_en = 1;
|
||||
LP_PERI_CLKRST.cpu_ctrl.lp_core_rst_en = 0;
|
||||
LP_PERI_CLKRST.intr_ctrl.lp_intr_rst_en = 0;
|
||||
}
|
||||
|
||||
/// use a macro to wrap the function, force the caller to use it in a critical section
|
||||
/// the critical section needs to declare the __DECLARE_RCC_ATOMIC_ENV variable in advance
|
||||
#define lp_core_ll_reset_register(...) do { \
|
||||
(void)__DECLARE_RCC_ATOMIC_ENV; \
|
||||
lp_core_ll_reset_register(__VA_ARGS__); \
|
||||
} while(0)
|
||||
|
||||
/**
|
||||
* @brief Enable fast access of LP memory
|
||||
*
|
||||
* @note ESP32-S31 does not have a separate fast LP memory bus mux.
|
||||
* This function is a no-op kept for API compatibility.
|
||||
*
|
||||
* @param enable Enable if true, disable if false
|
||||
*/
|
||||
static inline void lp_core_ll_fast_lp_mem_enable(bool enable)
|
||||
{
|
||||
/* ESP32-S31 does not have a fast_mem_mux_sel equivalent */
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Trigger a LP_CORE_LL_WAKEUP_SOURCE_HP_CPU wake-up on the LP-core
|
||||
*/
|
||||
static inline void lp_core_ll_hp_wake_lp(void)
|
||||
{
|
||||
PMU.hp_lp_cpu_comm.hp_trigger_lp = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the debug module of LP-core, allowing JTAG to connect
|
||||
*
|
||||
* @param enable enable if true, disable if false
|
||||
*/
|
||||
static inline void lp_core_ll_debug_module_enable(bool enable)
|
||||
{
|
||||
LP_PERI_CLKRST.cpu.lpcore_dbgm_unavailable = !enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable CPU reset at sleep
|
||||
*
|
||||
* @param enable enable if true, disable if false
|
||||
*/
|
||||
static inline void lp_core_ll_rst_at_sleep_enable(bool enable)
|
||||
{
|
||||
PMU.lp_ext.pwr0.slp_reset_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stall LP-core at sleep requests
|
||||
*
|
||||
* @param enable enable if true, disable if false
|
||||
*/
|
||||
static inline void lp_core_ll_stall_at_sleep_request(bool enable)
|
||||
{
|
||||
PMU.lp_ext.pwr0.slp_stall_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set wake-up sources for the LP-core
|
||||
*
|
||||
* @param flags wake-up sources (see LP_CORE_LL_WAKEUP_SOURCE_* defines)
|
||||
*/
|
||||
static inline void lp_core_ll_set_wakeup_source(uint32_t flags)
|
||||
{
|
||||
PMU.lp_ext.pwr2.wakeup_en = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get wake-up sources for the LP-core
|
||||
*/
|
||||
static inline uint32_t lp_core_ll_get_wakeup_source(void)
|
||||
{
|
||||
return PMU.lp_ext.pwr2.wakeup_en;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request PMU to put LP-core to sleep
|
||||
*/
|
||||
static inline void lp_core_ll_request_sleep(void)
|
||||
{
|
||||
PMU.lp_ext.pwr1.sleep_req = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable wakeup from LP UART
|
||||
*
|
||||
* @param enable enable if true, disable if false
|
||||
*/
|
||||
static inline void lp_core_ll_enable_lp_uart_wakeup(bool enable)
|
||||
{
|
||||
LP_PERI_CLKRST.uart_misc_ctrl.lp_uart_wakeup_en = enable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the flag that marks whether LP CPU is awakened by ETM
|
||||
*
|
||||
* @return Return true if lpcore is woken up by soc_etm
|
||||
*/
|
||||
static inline bool lp_core_ll_get_etm_wakeup_flag(void)
|
||||
{
|
||||
return LP_SYS.sys_ctrl.lp_core_etm_wakeup_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear the flag that marks whether LP CPU is awakened by ETM
|
||||
*/
|
||||
static inline void lp_core_ll_clear_etm_wakeup_flag(void)
|
||||
{
|
||||
LP_SYS.sys_ctrl.lp_core_etm_wakeup_flag_clr = 0x01;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2025-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -103,6 +103,8 @@ SOC_RESERVE_MEMORY_REGION( SOC_EXTRAM_LOW, SOC_EXTRAM_HIGH, extram_region);
|
||||
|
||||
|
||||
#ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
|
||||
SOC_RESERVE_MEMORY_REGION(SOC_RTC_DRAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data);
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data);
|
||||
/* Reserve LP RAM from base up to end of .rtc.force_slow (includes ULP code/data area) */
|
||||
SOC_RESERVE_MEMORY_REGION(SOC_LP_RAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data);
|
||||
#endif
|
||||
|
||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data);
|
||||
|
||||
@@ -1610,3 +1610,7 @@ config SOC_LP_CORE_SUPPORT_ETM
|
||||
config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_CORE_SUPPORT_I2C
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -644,3 +644,4 @@
|
||||
#define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */
|
||||
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */
|
||||
#define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */
|
||||
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
|
||||
|
||||
@@ -1359,6 +1359,10 @@ config SOC_LP_CORE_SUPPORT_ETM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_CORE_SUPPORT_I2C
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_DEBUG_HAVE_OCD_STUB_BINS
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -552,6 +552,7 @@
|
||||
/*------------------------------------- ULP CAPS -------------------------------------*/
|
||||
#define SOC_LP_CORE_SINGLE_INTERRUPT_VECTOR (1) /*!< LP Core interrupts all map to a single entry in vector table */
|
||||
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */
|
||||
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
|
||||
|
||||
/*------------------------------------- DEBUG CAPS -------------------------------------*/
|
||||
#define SOC_DEBUG_HAVE_OCD_STUB_BINS (1)
|
||||
|
||||
@@ -1918,3 +1918,7 @@ config SOC_LP_CORE_SUPPORT_LP_ADC
|
||||
config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_CORE_SUPPORT_I2C
|
||||
bool
|
||||
default y
|
||||
|
||||
@@ -735,3 +735,4 @@
|
||||
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM */
|
||||
#define SOC_LP_CORE_SUPPORT_LP_ADC (1) /*!< LP ADC can be accessed from the LP-Core */
|
||||
#define SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS (1) /*!< LP Core will raise exceptions if accessing invalid addresses */
|
||||
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
|
||||
|
||||
@@ -59,6 +59,14 @@ config SOC_USB_OTG_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_ULP_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_CORE_SUPPORTED
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_EFUSE_KEY_PURPOSE_FIELD
|
||||
bool
|
||||
default y
|
||||
@@ -999,6 +1007,14 @@ config SOC_PM_RETENTION_MODULE_NUM
|
||||
int
|
||||
default 64
|
||||
|
||||
config SOC_LP_CORE_SUPPORT_ETM
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR
|
||||
bool
|
||||
default y
|
||||
|
||||
config SOC_LP_TIMER_BIT_WIDTH_LO
|
||||
int
|
||||
default 32
|
||||
|
||||
@@ -190,6 +190,9 @@ typedef enum {
|
||||
|
||||
extern const char * const esp_isr_names[ETS_MAX_INTR_SOURCE];
|
||||
|
||||
// ESP32-S31 names the PMU interrupt source ETS_PMT_INTR_SOURCE; alias for cross-chip compatibility
|
||||
#define ETS_PMU_INTR_SOURCE ETS_PMT_INTR_SOURCE
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -49,8 +49,8 @@
|
||||
// #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 // TODO: [ESP32S31] IDF-14788
|
||||
// #define SOC_TEMP_SENSOR_SUPPORTED 1 // TODO: [ESP32S31] IDF-14799
|
||||
// #define SOC_SUPPORTS_SECURE_DL_MODE 1 // TODO: [ESP32S31] IDF-14629
|
||||
// #define SOC_ULP_SUPPORTED 1 // TODO: [ESP32S31] IDF-14640
|
||||
// #define SOC_LP_CORE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14640
|
||||
#define SOC_ULP_SUPPORTED 1
|
||||
#define SOC_LP_CORE_SUPPORTED 1
|
||||
#define SOC_EFUSE_KEY_PURPOSE_FIELD 1 // TODO: [ESP32S31] IDF-14688
|
||||
#define SOC_EFUSE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14688
|
||||
#define SOC_RTC_FAST_MEM_SUPPORTED 1
|
||||
@@ -438,6 +438,12 @@
|
||||
|
||||
#define SOC_PM_RETENTION_MODULE_NUM (64)
|
||||
|
||||
/*-------------------------- LP_CORE CAPS ------------------------------------*/
|
||||
// #define SOC_LP_MAILBOX_SUPPORTED (1) // TODO: [ESP32S31] IDF-14637
|
||||
#define SOC_LP_CORE_SUPPORT_ETM (1) /*!< LP Core supports ETM wakeup */
|
||||
#define SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR (1) /*!< LP Core has no LP ROM; HP must write the reset_vector address (LP_RAM_BASE+0x80) to LP_SYS.lp_core_boot_addr before triggering LP wake */
|
||||
//#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */ TODO IDF-14635
|
||||
|
||||
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
|
||||
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
|
||||
#define SOC_LP_TIMER_BIT_WIDTH_HI 16 // Bit width of lp_timer high part
|
||||
|
||||
@@ -856,7 +856,6 @@ typedef struct {
|
||||
volatile mb_reg_clk_en_reg_t reg_clk_en;
|
||||
} mb_dev_t;
|
||||
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(mb_dev_t) == 0x64, "Invalid size of mb_dev_t structure");
|
||||
#endif
|
||||
|
||||
@@ -1019,6 +1019,8 @@ typedef struct {
|
||||
} lp_pwr_dev_t;
|
||||
|
||||
|
||||
extern lp_pwr_dev_t LP_PWR;
|
||||
|
||||
#ifndef __cplusplus
|
||||
_Static_assert(sizeof(lp_pwr_dev_t) == 0xa8, "Invalid size of lp_pwr_dev_t structure");
|
||||
#endif
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
#define DR_REG_INTERRUPT_CORE0_BASE DR_REG_INTR0_BASE
|
||||
#define DR_REG_INTERRUPT_CORE1_BASE (DR_REG_INTR0_BASE + 0x800)
|
||||
#define DR_REG_LPPERI_BASE DR_REG_LP_PERICLKRST_BASE
|
||||
#define DR_REG_LP_PWR_BASE DR_REG_LP_PWR_REG_BASE /* alias used by lp_pwr_reg.h */
|
||||
#define DR_REG_SDHOST_BASE DR_REG_SDMMC_BASE
|
||||
#define DR_REG_TRACE_BASE DR_REG_TRACE0_BASE
|
||||
#define DR_REG_MB_BASE DR_REG_LP_MAILBOX_BASE
|
||||
|
||||
@@ -62,11 +62,11 @@ if(CONFIG_ULP_COPROC_TYPE_LP_CORE)
|
||||
"lp_core/shared/ulp_lp_core_lp_uart_shared.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_LP_I2C_SUPPORTED)
|
||||
if(CONFIG_SOC_LP_CORE_SUPPORT_I2C)
|
||||
list(APPEND srcs "lp_core/lp_core_i2c.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_RTC_TIMER_V2)
|
||||
if(CONFIG_SOC_RTC_TIMER_V2 OR CONFIG_SOC_RTC_TIMER_V3)
|
||||
list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_timer_shared.c")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -168,26 +168,37 @@ function(ulp_apply_default_sources ulp_app_name)
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/vector.S"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/${IDF_TARGET}/vector_table.S"
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_memory_shared.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_uart_shared.c"
|
||||
"${IDF_PATH}/components/esp_driver_uart/src/uart_wakeup.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_timer_shared.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_startup.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_utils.c"
|
||||
|
||||
"${IDF_PATH}/components/esp_hal_uart/uart_hal_iram.c"
|
||||
"${IDF_PATH}/components/esp_hal_uart/uart_hal.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_uart.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_print.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_panic.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_interrupt.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_i2c.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_spi.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_ubsan.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_mailbox.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_adc_shared.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_vad_shared.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_critical_section_shared.c")
|
||||
|
||||
if(CONFIG_SOC_LP_CORE_SUPPORT_I2C)
|
||||
list(APPEND ULP_S_SOURCES
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_i2c.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_LP_SPI_SUPPORTED)
|
||||
list(APPEND ULP_S_SOURCES
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_spi.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_ULP_LP_UART_SUPPORTED)
|
||||
list(APPEND ULP_S_SOURCES
|
||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_lp_uart_shared.c"
|
||||
"${IDF_PATH}/components/esp_driver_uart/src/uart_wakeup.c"
|
||||
"${IDF_PATH}/components/esp_hal_uart/uart_hal_iram.c"
|
||||
"${IDF_PATH}/components/esp_hal_uart/uart_hal.c"
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_uart.c")
|
||||
endif()
|
||||
|
||||
if(CONFIG_SOC_LP_MAILBOX_SUPPORTED)
|
||||
list(APPEND ULP_S_SOURCES
|
||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/lp_core_mailbox_impl_hw.c")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -15,6 +15,9 @@ extern "C" {
|
||||
#include "hal/i2c_types.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "esp_err.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_LP_CORE_SUPPORT_I2C
|
||||
|
||||
/**
|
||||
* @brief LP Core I2C pin config parameters
|
||||
@@ -95,6 +98,8 @@ typedef struct {
|
||||
*/
|
||||
esp_err_t lp_core_i2c_master_init(i2c_port_t lp_i2c_num, const lp_core_i2c_cfg_t *cfg);
|
||||
|
||||
#endif /* SOC_LP_CORE_SUPPORT_I2C */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@@ -14,6 +14,9 @@ extern "C" {
|
||||
#include "esp_err.h"
|
||||
#include "hal/uart_types.h"
|
||||
#include "hal/gpio_types.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if SOC_ULP_LP_UART_SUPPORTED
|
||||
|
||||
/**
|
||||
* Default LP_IO Mux pins for LP UART
|
||||
@@ -101,6 +104,8 @@ typedef struct {
|
||||
*/
|
||||
esp_err_t lp_core_uart_init(const lp_core_uart_cfg_t *cfg);
|
||||
|
||||
#endif /* SOC_ULP_LP_UART_SUPPORTED */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_caps.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_assert.h"
|
||||
@@ -86,6 +87,14 @@ esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg)
|
||||
|
||||
#endif //ESP_ROM_HAS_LP_ROM
|
||||
|
||||
#if SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR
|
||||
/* Chips without LP ROM but with a SW-configurable boot address register
|
||||
* (e.g. ESP32-S31) must set the boot address explicitly. The hardware
|
||||
* default points to SOC_RTC_DRAM_LOW (the interrupt vector table base),
|
||||
* not to reset_vector which is placed 0x80 bytes into LP RAM. */
|
||||
lp_core_ll_set_boot_address((intptr_t)SOC_RTC_DRAM_LOW + 0x80);
|
||||
#endif // SOC_LP_CORE_CONFIGURABLE_BOOT_ADDR
|
||||
|
||||
PERIPH_RCC_ATOMIC() {
|
||||
#if CONFIG_ULP_NORESET_UNDER_DEBUG
|
||||
/* lp_core module reset causes loss of configured HW breakpoints and dcsr.ebreak* */
|
||||
|
||||
@@ -100,7 +100,7 @@ esp_err_t lp_core_i2c_master_write_read_device(i2c_port_t lp_i2c_num, uint16_t d
|
||||
*/
|
||||
void lp_core_i2c_master_set_ack_check_en(i2c_port_t lp_i2c_num, bool ack_check_en);
|
||||
|
||||
#if SOC_LP_I2C_SUPPORTED
|
||||
#if SOC_LP_CORE_SUPPORT_I2C
|
||||
/**
|
||||
* @brief Enable LP I2C master-related interrupts at the peripheral
|
||||
*
|
||||
@@ -126,7 +126,7 @@ static inline void ulp_lp_core_lp_i2c_intr_disable(i2c_port_t lp_i2c_num, uint32
|
||||
HAL_ASSERT(lp_i2c_num == LP_I2C_NUM_0);
|
||||
i2c_ll_disable_intr_mask(I2C_LL_GET_HW(lp_i2c_num), mask);
|
||||
}
|
||||
#endif /* SOC_LP_I2C_SUPPORTED */
|
||||
#endif /* SOC_LP_CORE_SUPPORT_I2C */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#include "soc/i2c_struct.h"
|
||||
#include "hal/i2c_ll.h"
|
||||
|
||||
#if SOC_LP_I2C_SUPPORTED
|
||||
#if SOC_LP_CORE_SUPPORT_I2C
|
||||
|
||||
#define LP_I2C_FIFO_LEN I2C_LL_GET(LP_FIFO_LEN)
|
||||
#define LP_I2C_READ_MODE I2C_MASTER_READ
|
||||
@@ -471,4 +471,4 @@ esp_err_t lp_core_i2c_master_write_read_device(i2c_port_t lp_i2c_num, uint16_t d
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* SOC_LP_I2C_SUPPORTED */
|
||||
#endif /* SOC_LP_CORE_SUPPORT_I2C */
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
#include "hal/uart_hal.h"
|
||||
#include "esp_rom_serial_output.h"
|
||||
|
||||
#define LP_UART_PORT_NUM LP_UART_NUM_0
|
||||
#define BINARY_SUPPORT 1
|
||||
|
||||
#define is_digit(c) ((c >= '0') && (c <= '9'))
|
||||
@@ -26,8 +25,9 @@ static void hp_uart_send_char(char t)
|
||||
}
|
||||
uart_ll_write_txfifo(uart, &t, 1);
|
||||
}
|
||||
#elif !CONFIG_ULP_ROM_PRINT_ENABLE
|
||||
#elif !CONFIG_ULP_ROM_PRINT_ENABLE && CONFIG_SOC_ULP_LP_UART_SUPPORTED
|
||||
void __attribute__((alias("lp_uart_send_char"))) lp_core_print_char(char c);
|
||||
#define LP_UART_PORT_NUM LP_UART_NUM_0
|
||||
static void lp_uart_send_char(char c)
|
||||
{
|
||||
int tx_len = 0;
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2026 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
|
||||
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j ulp_lp_core_sw_intr_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j ulp_lp_core_lp_uart_intr_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j ulp_lp_core_lp_spi_intr_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
j ulp_lp_core_trng_intr_handler
|
||||
j ulp_lp_core_lp_i2c_intr_handler
|
||||
j ulp_lp_core_lp_io_intr_handler
|
||||
j ulp_lp_core_lp_adc_intr_handler
|
||||
j ulp_lp_core_lp_touch_intr_handler
|
||||
j ulp_lp_core_tsens_intr_handler
|
||||
j ulp_lp_core_efuse_intr_handler
|
||||
j ulp_lp_core_lp_sysreg_intr_handler
|
||||
j ulp_lp_core_lp_ana_peri_intr_handler
|
||||
j ulp_lp_core_lp_pmu_intr_handler
|
||||
j ulp_lp_core_mailbox_intr_handler
|
||||
j ulp_lp_core_lp_timer_intr_handler
|
||||
j ulp_lp_core_lp_wdt_intr_handler
|
||||
j ulp_lp_core_lp_rtc_intr_handler
|
||||
j _panic_handler
|
||||
j _panic_handler
|
||||
|
||||
.option pop
|
||||
.size _vector_table, .-_vector_table
|
||||
@@ -4,6 +4,9 @@ components/ulp/test_apps/lp_core/lp_core_basic_tests:
|
||||
disable:
|
||||
- if: SOC_LP_CORE_SUPPORTED != 1
|
||||
- if: CONFIG_NAME == "xtal" and SOC_CLK_LP_FAST_SUPPORT_XTAL != 1
|
||||
- if: IDF_TARGET in ["esp32s31"] and CONFIG_NAME == "xtal"
|
||||
temporary: true
|
||||
reason: CONFIG_RTC_FAST_CLK_SRC_XTAL not supported yet # TODO: [ESP32S31] IDF-15576
|
||||
- if: CONFIG_NAME == "lp_vad" and SOC_LP_VAD_SUPPORTED != 1
|
||||
depends_components:
|
||||
- ulp
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(app_sources "test_app_main.c" "test_lp_core.c")
|
||||
|
||||
if(CONFIG_SOC_LP_I2C_SUPPORTED)
|
||||
if(CONFIG_SOC_LP_CORE_SUPPORT_I2C)
|
||||
list(APPEND app_sources "test_lp_core_i2c.c")
|
||||
endif()
|
||||
|
||||
@@ -37,7 +37,7 @@ endif()
|
||||
|
||||
set(lp_core_sources_gpio "lp_core/test_main_gpio.c")
|
||||
|
||||
if(CONFIG_SOC_LP_I2C_SUPPORTED)
|
||||
if(CONFIG_SOC_LP_CORE_SUPPORT_I2C)
|
||||
set(lp_core_sources_i2c "lp_core/test_main_i2c.c")
|
||||
endif()
|
||||
|
||||
@@ -79,7 +79,7 @@ endif()
|
||||
|
||||
ulp_embed_binary(lp_core_test_app_gpio "${lp_core_sources_gpio}" "${lp_core_exp_dep_srcs}")
|
||||
|
||||
if(CONFIG_SOC_LP_I2C_SUPPORTED)
|
||||
if(CONFIG_SOC_LP_CORE_SUPPORT_I2C)
|
||||
ulp_embed_binary(lp_core_test_app_i2c "${lp_core_sources_i2c}" "${lp_core_exp_dep_srcs}")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -79,6 +79,24 @@ static void clear_test_cmds(void)
|
||||
ulp_command_resp = LP_CORE_NO_COMMAND;
|
||||
}
|
||||
|
||||
TEST_CASE("LP core boots and executes code", "[lp_core]")
|
||||
{
|
||||
ulp_lp_core_cfg_t cfg = {
|
||||
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU,
|
||||
};
|
||||
|
||||
ulp_counter = 0;
|
||||
|
||||
load_and_start_lp_core_firmware(&cfg, lp_core_main_counter_bin_start, lp_core_main_counter_bin_end);
|
||||
|
||||
int timeout_ms = 1000;
|
||||
while (ulp_counter == 0 && timeout_ms-- > 0) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1));
|
||||
}
|
||||
|
||||
TEST_ASSERT_MESSAGE(ulp_counter > 0, "LP core did not execute: counter stayed at 0");
|
||||
}
|
||||
|
||||
TEST_CASE("LP core and main CPU are able to exchange data", "[lp_core]")
|
||||
{
|
||||
const uint32_t test_data = 0x12345678;
|
||||
@@ -539,7 +557,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
|
||||
#if SOC_RTCIO_PIN_COUNT > 0 && (SOC_RTCIO_INPUT_OUTPUT_SUPPORTED || SOC_LP_GPIO_MATRIX_SUPPORTED)
|
||||
TEST_CASE("LP core gpio tests", "[ulp]")
|
||||
{
|
||||
/* Load ULP firmware and start the coprocessor */
|
||||
@@ -583,7 +601,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
|
||||
#if SOC_RTCIO_PIN_COUNT > 0 && (SOC_RTCIO_INPUT_OUTPUT_SUPPORTED || SOC_LP_GPIO_MATRIX_SUPPORTED)
|
||||
/* Test LP IO interrupt */
|
||||
rtc_gpio_init(IO_TEST_PIN);
|
||||
rtc_gpio_set_direction(IO_TEST_PIN, RTC_GPIO_MODE_INPUT_ONLY);
|
||||
|
||||
@@ -52,6 +52,7 @@ def test_lp_vad(dut: Dut) -> None:
|
||||
|
||||
# TODO: Support LP I2C test for esp32p4 (IDF-9581)
|
||||
@pytest.mark.generic_multi_device
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='TODO IDF-15572 Enable ULP multi device tests for ESP32-S31')
|
||||
@pytest.mark.parametrize('count', [2], indirect=True)
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
@@ -66,6 +67,7 @@ def test_lp_core_multi_device(case_tester) -> None: # type: ignore
|
||||
|
||||
|
||||
@pytest.mark.generic_multi_device
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32s31'], reason='TODO IDF-15572 Enable ULP multi device tests for ESP32-S31')
|
||||
@pytest.mark.parametrize(
|
||||
'target',
|
||||
soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'),
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
||||
| ----------------- | -------- | -------- | -------- |
|
||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||
| ----------------- | -------- | -------- | -------- | --------- |
|
||||
|
||||
|
||||
@@ -17,6 +17,9 @@ def test_lp_core_hp_uart_print(dut: Dut) -> None:
|
||||
|
||||
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.temp_skip_ci(
|
||||
targets=['esp32s31'], reason='TODO IDF-15567 investigate esp32s31.default.test_lp_core_panic failure'
|
||||
)
|
||||
@idf_parametrize('target', soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'), indirect=['target'])
|
||||
def test_lp_core_panic(dut: Dut) -> None:
|
||||
dut.expect_exact('Press ENTER to see the list of tests')
|
||||
|
||||
Reference in New Issue
Block a user