mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
feat(ulp): add support for ulp on esp32s31
This commit is contained in:
@@ -13,6 +13,11 @@
|
|||||||
#include "esp_cpu.h"
|
#include "esp_cpu.h"
|
||||||
|
|
||||||
#include "hal/apm_hal.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)
|
void bootloader_init_mem(void)
|
||||||
{
|
{
|
||||||
@@ -37,6 +42,22 @@ void bootloader_init_mem(void)
|
|||||||
#endif // SOC_APM_CTRL_FILTER_SUPPORTED
|
#endif // SOC_APM_CTRL_FILTER_SUPPORTED
|
||||||
#endif
|
#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
|
#if CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
|
||||||
// protect memory region
|
// protect memory region
|
||||||
esp_cpu_configure_region_protection();
|
esp_cpu_configure_region_protection();
|
||||||
|
|||||||
@@ -20,6 +20,10 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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)
|
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);
|
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.
|
- 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.
|
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.
|
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
|
#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 */
|
#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
|
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.
|
/* 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.
|
It reserves the amount of LP memory that we use for this memory segment.
|
||||||
@@ -72,9 +76,7 @@ MEMORY
|
|||||||
- (lower addr) rtc timer data (s_rtc_timer_retain_mem, see esp_clk.c files).
|
- (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).
|
- (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.
|
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 */
|
/* PSRAM seg */
|
||||||
@@ -92,8 +94,6 @@ 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
|
* 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
|
* 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_text_seg", lp_ram_seg);
|
||||||
REGION_ALIAS("rtc_data_seg", lp_ram_seg);
|
REGION_ALIAS("rtc_data_seg", lp_ram_seg);
|
||||||
REGION_ALIAS("rtc_slow_seg", lp_ram_seg);
|
REGION_ALIAS("rtc_slow_seg", lp_ram_seg);
|
||||||
|
|||||||
@@ -9,9 +9,6 @@ ENTRY(call_start_cpu0);
|
|||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* RTC memory should be implemented here TODO: [ESP32S31] IDF-14640
|
|
||||||
*/
|
|
||||||
#include "ld.rtc.sections"
|
#include "ld.rtc.sections"
|
||||||
|
|
||||||
#include "ld.iram.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
|
* 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
|
#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);
|
/* Reserve LP RAM from base up to end of .rtc.force_slow (includes ULP code/data area) */
|
||||||
SOC_RESERVE_MEMORY_REGION((intptr_t)&_rtc_reserved_start, (intptr_t)&_rtc_reserved_end, rtc_reserved_data);
|
SOC_RESERVE_MEMORY_REGION(SOC_LP_RAM_LOW, (intptr_t)&_rtc_force_slow_end, rtcram_data);
|
||||||
#endif
|
#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
|
config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS
|
||||||
bool
|
bool
|
||||||
default y
|
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_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_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_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
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_LP_CORE_SUPPORT_I2C
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_DEBUG_HAVE_OCD_STUB_BINS
|
config SOC_DEBUG_HAVE_OCD_STUB_BINS
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
|
|||||||
@@ -552,6 +552,7 @@
|
|||||||
/*------------------------------------- ULP CAPS -------------------------------------*/
|
/*------------------------------------- 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_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_ETM (1) /*!< LP Core supports ETM */
|
||||||
|
#define SOC_LP_CORE_SUPPORT_I2C (1) /*!< LP Core supports I2C */
|
||||||
|
|
||||||
/*------------------------------------- DEBUG CAPS -------------------------------------*/
|
/*------------------------------------- DEBUG CAPS -------------------------------------*/
|
||||||
#define SOC_DEBUG_HAVE_OCD_STUB_BINS (1)
|
#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
|
config SOC_LP_CORE_SUPPORT_STORE_LOAD_EXCEPTIONS
|
||||||
bool
|
bool
|
||||||
default y
|
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_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_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_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
|
bool
|
||||||
default y
|
default y
|
||||||
|
|
||||||
|
config SOC_ULP_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
|
config SOC_LP_CORE_SUPPORTED
|
||||||
|
bool
|
||||||
|
default y
|
||||||
|
|
||||||
config SOC_EFUSE_KEY_PURPOSE_FIELD
|
config SOC_EFUSE_KEY_PURPOSE_FIELD
|
||||||
bool
|
bool
|
||||||
default y
|
default y
|
||||||
@@ -999,6 +1007,14 @@ config SOC_PM_RETENTION_MODULE_NUM
|
|||||||
int
|
int
|
||||||
default 64
|
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
|
config SOC_LP_TIMER_BIT_WIDTH_LO
|
||||||
int
|
int
|
||||||
default 32
|
default 32
|
||||||
|
|||||||
@@ -190,6 +190,9 @@ typedef enum {
|
|||||||
|
|
||||||
extern const char * const esp_isr_names[ETS_MAX_INTR_SOURCE];
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -49,8 +49,8 @@
|
|||||||
// #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 // TODO: [ESP32S31] IDF-14788
|
// #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 // TODO: [ESP32S31] IDF-14788
|
||||||
// #define SOC_TEMP_SENSOR_SUPPORTED 1 // TODO: [ESP32S31] IDF-14799
|
// #define SOC_TEMP_SENSOR_SUPPORTED 1 // TODO: [ESP32S31] IDF-14799
|
||||||
// #define SOC_SUPPORTS_SECURE_DL_MODE 1 // TODO: [ESP32S31] IDF-14629
|
// #define SOC_SUPPORTS_SECURE_DL_MODE 1 // TODO: [ESP32S31] IDF-14629
|
||||||
// #define SOC_ULP_SUPPORTED 1 // TODO: [ESP32S31] IDF-14640
|
#define SOC_ULP_SUPPORTED 1
|
||||||
// #define SOC_LP_CORE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14640
|
#define SOC_LP_CORE_SUPPORTED 1
|
||||||
#define SOC_EFUSE_KEY_PURPOSE_FIELD 1 // TODO: [ESP32S31] IDF-14688
|
#define SOC_EFUSE_KEY_PURPOSE_FIELD 1 // TODO: [ESP32S31] IDF-14688
|
||||||
#define SOC_EFUSE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14688
|
#define SOC_EFUSE_SUPPORTED 1 // TODO: [ESP32S31] IDF-14688
|
||||||
#define SOC_RTC_FAST_MEM_SUPPORTED 1
|
#define SOC_RTC_FAST_MEM_SUPPORTED 1
|
||||||
@@ -438,6 +438,12 @@
|
|||||||
|
|
||||||
#define SOC_PM_RETENTION_MODULE_NUM (64)
|
#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 ----------------------------------*/
|
/*-------------------------- LP_TIMER CAPS ----------------------------------*/
|
||||||
#define SOC_LP_TIMER_BIT_WIDTH_LO 32 // Bit width of lp_timer low part
|
#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
|
#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;
|
volatile mb_reg_clk_en_reg_t reg_clk_en;
|
||||||
} mb_dev_t;
|
} mb_dev_t;
|
||||||
|
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
_Static_assert(sizeof(mb_dev_t) == 0x64, "Invalid size of mb_dev_t structure");
|
_Static_assert(sizeof(mb_dev_t) == 0x64, "Invalid size of mb_dev_t structure");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1019,6 +1019,8 @@ typedef struct {
|
|||||||
} lp_pwr_dev_t;
|
} lp_pwr_dev_t;
|
||||||
|
|
||||||
|
|
||||||
|
extern lp_pwr_dev_t LP_PWR;
|
||||||
|
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
_Static_assert(sizeof(lp_pwr_dev_t) == 0xa8, "Invalid size of lp_pwr_dev_t structure");
|
_Static_assert(sizeof(lp_pwr_dev_t) == 0xa8, "Invalid size of lp_pwr_dev_t structure");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -137,6 +137,7 @@
|
|||||||
#define DR_REG_INTERRUPT_CORE0_BASE DR_REG_INTR0_BASE
|
#define DR_REG_INTERRUPT_CORE0_BASE DR_REG_INTR0_BASE
|
||||||
#define DR_REG_INTERRUPT_CORE1_BASE (DR_REG_INTR0_BASE + 0x800)
|
#define DR_REG_INTERRUPT_CORE1_BASE (DR_REG_INTR0_BASE + 0x800)
|
||||||
#define DR_REG_LPPERI_BASE DR_REG_LP_PERICLKRST_BASE
|
#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_SDHOST_BASE DR_REG_SDMMC_BASE
|
||||||
#define DR_REG_TRACE_BASE DR_REG_TRACE0_BASE
|
#define DR_REG_TRACE_BASE DR_REG_TRACE0_BASE
|
||||||
#define DR_REG_MB_BASE DR_REG_LP_MAILBOX_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")
|
"lp_core/shared/ulp_lp_core_lp_uart_shared.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CONFIG_SOC_LP_I2C_SUPPORTED)
|
if(CONFIG_SOC_LP_CORE_SUPPORT_I2C)
|
||||||
list(APPEND srcs "lp_core/lp_core_i2c.c")
|
list(APPEND srcs "lp_core/lp_core_i2c.c")
|
||||||
endif()
|
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")
|
list(APPEND srcs "lp_core/shared/ulp_lp_core_lp_timer_shared.c")
|
||||||
endif()
|
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/vector.S"
|
||||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/${IDF_TARGET}/vector_table.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_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/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_startup.c"
|
||||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_utils.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_print.c"
|
||||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_panic.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_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_ubsan.c"
|
||||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/lp_core_mailbox.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_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_lp_vad_shared.c"
|
||||||
"${IDF_PATH}/components/ulp/lp_core/shared/ulp_lp_core_critical_section_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)
|
if(CONFIG_SOC_LP_MAILBOX_SUPPORTED)
|
||||||
list(APPEND ULP_S_SOURCES
|
list(APPEND ULP_S_SOURCES
|
||||||
"${IDF_PATH}/components/ulp/lp_core/lp_core/port/lp_core_mailbox_impl_hw.c")
|
"${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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -15,6 +15,9 @@ extern "C" {
|
|||||||
#include "hal/i2c_types.h"
|
#include "hal/i2c_types.h"
|
||||||
#include "hal/gpio_types.h"
|
#include "hal/gpio_types.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
|
#include "soc/soc_caps.h"
|
||||||
|
|
||||||
|
#if SOC_LP_CORE_SUPPORT_I2C
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief LP Core I2C pin config parameters
|
* @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);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -14,6 +14,9 @@ extern "C" {
|
|||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "hal/uart_types.h"
|
#include "hal/uart_types.h"
|
||||||
#include "hal/gpio_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
|
* 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);
|
esp_err_t lp_core_uart_init(const lp_core_uart_cfg_t *cfg);
|
||||||
|
|
||||||
|
#endif /* SOC_ULP_LP_UART_SUPPORTED */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_rom_caps.h"
|
#include "esp_rom_caps.h"
|
||||||
|
#include "soc/soc.h"
|
||||||
#include "soc/soc_caps.h"
|
#include "soc/soc_caps.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_assert.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
|
#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() {
|
PERIPH_RCC_ATOMIC() {
|
||||||
#if CONFIG_ULP_NORESET_UNDER_DEBUG
|
#if CONFIG_ULP_NORESET_UNDER_DEBUG
|
||||||
/* lp_core module reset causes loss of configured HW breakpoints and dcsr.ebreak* */
|
/* 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);
|
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
|
* @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);
|
HAL_ASSERT(lp_i2c_num == LP_I2C_NUM_0);
|
||||||
i2c_ll_disable_intr_mask(I2C_LL_GET_HW(lp_i2c_num), mask);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "soc/i2c_struct.h"
|
#include "soc/i2c_struct.h"
|
||||||
#include "hal/i2c_ll.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_FIFO_LEN I2C_LL_GET(LP_FIFO_LEN)
|
||||||
#define LP_I2C_READ_MODE I2C_MASTER_READ
|
#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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* SOC_LP_I2C_SUPPORTED */
|
#endif /* SOC_LP_CORE_SUPPORT_I2C */
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include "hal/uart_hal.h"
|
#include "hal/uart_hal.h"
|
||||||
#include "esp_rom_serial_output.h"
|
#include "esp_rom_serial_output.h"
|
||||||
|
|
||||||
#define LP_UART_PORT_NUM LP_UART_NUM_0
|
|
||||||
#define BINARY_SUPPORT 1
|
#define BINARY_SUPPORT 1
|
||||||
|
|
||||||
#define is_digit(c) ((c >= '0') && (c <= '9'))
|
#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);
|
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);
|
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)
|
static void lp_uart_send_char(char c)
|
||||||
{
|
{
|
||||||
int tx_len = 0;
|
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:
|
disable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED != 1
|
- if: SOC_LP_CORE_SUPPORTED != 1
|
||||||
- if: CONFIG_NAME == "xtal" and SOC_CLK_LP_FAST_SUPPORT_XTAL != 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
|
- if: CONFIG_NAME == "lp_vad" and SOC_LP_VAD_SUPPORTED != 1
|
||||||
depends_components:
|
depends_components:
|
||||||
- ulp
|
- 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")
|
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")
|
list(APPEND app_sources "test_lp_core_i2c.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -37,7 +37,7 @@ endif()
|
|||||||
|
|
||||||
set(lp_core_sources_gpio "lp_core/test_main_gpio.c")
|
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")
|
set(lp_core_sources_i2c "lp_core/test_main_i2c.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ endif()
|
|||||||
|
|
||||||
ulp_embed_binary(lp_core_test_app_gpio "${lp_core_sources_gpio}" "${lp_core_exp_dep_srcs}")
|
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}")
|
ulp_embed_binary(lp_core_test_app_i2c "${lp_core_sources_i2c}" "${lp_core_exp_dep_srcs}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,24 @@ static void clear_test_cmds(void)
|
|||||||
ulp_command_resp = LP_CORE_NO_COMMAND;
|
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]")
|
TEST_CASE("LP core and main CPU are able to exchange data", "[lp_core]")
|
||||||
{
|
{
|
||||||
const uint32_t test_data = 0x12345678;
|
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");
|
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]")
|
TEST_CASE("LP core gpio tests", "[ulp]")
|
||||||
{
|
{
|
||||||
/* Load ULP firmware and start the coprocessor */
|
/* 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);
|
printf("ULP PMU ISR triggered %"PRIu32" times\n", ulp_pmu_isr_counter);
|
||||||
TEST_ASSERT_EQUAL(ISR_TEST_ITERATIONS, 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 */
|
/* Test LP IO interrupt */
|
||||||
rtc_gpio_init(IO_TEST_PIN);
|
rtc_gpio_init(IO_TEST_PIN);
|
||||||
rtc_gpio_set_direction(IO_TEST_PIN, RTC_GPIO_MODE_INPUT_ONLY);
|
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)
|
# TODO: Support LP I2C test for esp32p4 (IDF-9581)
|
||||||
@pytest.mark.generic_multi_device
|
@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('count', [2], indirect=True)
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
'config',
|
'config',
|
||||||
@@ -66,6 +67,7 @@ def test_lp_core_multi_device(case_tester) -> None: # type: ignore
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic_multi_device
|
@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(
|
@pytest.mark.parametrize(
|
||||||
'target',
|
'target',
|
||||||
soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'),
|
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.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'])
|
@idf_parametrize('target', soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'), indirect=['target'])
|
||||||
def test_lp_core_panic(dut: Dut) -> None:
|
def test_lp_core_panic(dut: Dut) -> None:
|
||||||
dut.expect_exact('Press ENTER to see the list of tests')
|
dut.expect_exact('Press ENTER to see the list of tests')
|
||||||
|
|||||||
@@ -7,4 +7,12 @@ INPUT += \
|
|||||||
$(PROJECT_PATH)/components/esp_driver_touch_sens/include/driver/touch_sens.h \
|
$(PROJECT_PATH)/components/esp_driver_touch_sens/include/driver/touch_sens.h \
|
||||||
$(PROJECT_PATH)/components/esp_driver_touch_sens/include/driver/touch_sens_types.h\
|
$(PROJECT_PATH)/components/esp_driver_touch_sens/include/driver/touch_sens_types.h\
|
||||||
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_init.h \
|
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_init.h \
|
||||||
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_cert_test.h
|
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_cert_test.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/lp_core/include/lp_core_etm.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/lp_core/include/ulp_lp_core.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/lp_core/shared/include/ulp_lp_core_lp_uart_shared.h \
|
||||||
|
$(PROJECT_PATH)/components/ulp/lp_core/lp_core/include/ulp_lp_core_gpio.h \
|
||||||
|
$(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_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 \
|
||||||
|
|||||||
@@ -234,8 +234,8 @@ To enhance the capabilities of the ULP LP core coprocessor, it has access to per
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
* LP IO
|
* LP IO
|
||||||
* LP I2C
|
:SOC_LP_CORE_SUPPORT_I2C: * LP I2C
|
||||||
* LP UART
|
:SOC_ULP_LP_UART_SUPPORTED: * LP UART
|
||||||
:SOC_LP_SPI_SUPPORTED: * LP SPI
|
:SOC_LP_SPI_SUPPORTED: * LP SPI
|
||||||
:SOC_LP_MAILBOX_SUPPORTED: * LP Mailbox
|
:SOC_LP_MAILBOX_SUPPORTED: * LP Mailbox
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ In addition to configuring the interrupt related registers for the interrupt sou
|
|||||||
ULP LP Core Clock Configuration
|
ULP LP Core Clock Configuration
|
||||||
-------------------------------
|
-------------------------------
|
||||||
|
|
||||||
{IDF_TARGET_XTAL_FREQ:default="Not updated", esp32c5="48 MHz", esp32p4="40 MHz"}
|
{IDF_TARGET_XTAL_FREQ:default="Not updated", esp32c5="48 MHz", esp32p4="40 MHz", esp32s31="40 MHz"}
|
||||||
|
|
||||||
The ULP LP Core clock source is based on the system clock ``LP_FAST_CLK``, see `TRM <{IDF_TARGET_TRM_EN_URL}>`__ > ``Reset and Clock`` for more details.
|
The ULP LP Core clock source is based on the system clock ``LP_FAST_CLK``, see `TRM <{IDF_TARGET_TRM_EN_URL}>`__ > ``Reset and Clock`` for more details.
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ The ULP LP Core clock source is based on the system clock ``LP_FAST_CLK``, see `
|
|||||||
|
|
||||||
On {IDF_TARGET_NAME}, ``LP_FAST_CLK`` supports using the external {IDF_TARGET_XTAL_FREQ} crystal (XTAL) as its clock source. This allows the ULP LP Core to run at a higher frequency than with the default ``RTC_FAST_CLOCK``, which runs at around 20 MHz. However, there is a trade-off: this clock is normally powered down during sleep to reduce power consumption, but if XTAL is selected as the source, it will remain powered up during sleep, which increases power consumption. If you only plan to use the LP Core as a coprocessor while the HP Core is active, then selecting XTAL can enhance both the performance and frequency stability of the LP Core.
|
On {IDF_TARGET_NAME}, ``LP_FAST_CLK`` supports using the external {IDF_TARGET_XTAL_FREQ} crystal (XTAL) as its clock source. This allows the ULP LP Core to run at a higher frequency than with the default ``RTC_FAST_CLOCK``, which runs at around 20 MHz. However, there is a trade-off: this clock is normally powered down during sleep to reduce power consumption, but if XTAL is selected as the source, it will remain powered up during sleep, which increases power consumption. If you only plan to use the LP Core as a coprocessor while the HP Core is active, then selecting XTAL can enhance both the performance and frequency stability of the LP Core.
|
||||||
|
|
||||||
To enable this feature, set :ref:`CONFIG_RTC_FAST_CLK_SRC` to ``CONFIG_RTC_FAST_CLK_SRC_XTAL``.
|
To enable this feature, set ``CONFIG_RTC_FAST_CLK_SRC`` to ``CONFIG_RTC_FAST_CLK_SRC_XTAL``.
|
||||||
|
|
||||||
|
|
||||||
Debugging ULP LP-Core Applications
|
Debugging ULP LP-Core Applications
|
||||||
@@ -293,12 +293,16 @@ Debugging ULP LP-Core Applications
|
|||||||
|
|
||||||
When programming the LP core, it can sometimes be challenging to figure out why the program is not behaving as expected. Here are some strategies to help you debug your LP core program:
|
When programming the LP core, it can sometimes be challenging to figure out why the program is not behaving as expected. Here are some strategies to help you debug your LP core program:
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
* Use the LP UART to print: the LP core has access to the LP UART peripheral, which can be used for printing information independently of the main CPU sleep state. See :example:`system/ulp/lp_core/lp_uart/lp_uart_print` for an example of how to use this driver.
|
* Use the LP UART to print: the LP core has access to the LP UART peripheral, which can be used for printing information independently of the main CPU sleep state. See :example:`system/ulp/lp_core/lp_uart/lp_uart_print` for an example of how to use this driver.
|
||||||
|
|
||||||
* Routing :cpp:func:`lp_core_printf` to the HP-Core console UART with :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`. This allows you to easily print LP core information to the already connected HP-Core console UART. The drawback of this approach is that it requires the main CPU to be awake and since there is no synchronization between the LP and HP cores, the output may be interleaved.
|
* Routing :cpp:func:`lp_core_printf` to the HP-Core console UART with :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`. This allows you to easily print LP core information to the already connected HP-Core console UART. The drawback of this approach is that it requires the main CPU to be awake and since there is no synchronization between the LP and HP cores, the output may be interleaved.
|
||||||
|
|
||||||
* Share program state through shared variables: as described in :ref:`ulp-lp-core-access-variables`, both the main CPU and the ULP core can easily access global variables in RTC memory. Writing state information to such a variable from the ULP and reading it from the main CPU can help you discern what is happening on the ULP core. The downside of this approach is that it requires the main CPU to be awake, which will not always be the case. Keeping the main CPU awake might even, in some cases, mask problems, as some issues may only occur when certain power domains are powered down.
|
* Share program state through shared variables: as described in :ref:`ulp-lp-core-access-variables`, both the main CPU and the ULP core can easily access global variables in RTC memory. Writing state information to such a variable from the ULP and reading it from the main CPU can help you discern what is happening on the ULP core. The downside of this approach is that it requires the main CPU to be awake, which will not always be the case. Keeping the main CPU awake might even, in some cases, mask problems, as some issues may only occur when certain power domains are powered down.
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
* Panic handler: the LP core has a panic handler that can dump the state of the LP core registers by the LP UART when an exception is detected. To enable the panic handler, set the :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` option to ``y``. This option can be kept disabled to reduce LP-RAM usage by the LP core application. To recover a backtrace from the panic dump, it is possible to use ``idf.py monitor``.
|
* Panic handler: the LP core has a panic handler that can dump the state of the LP core registers by the LP UART when an exception is detected. To enable the panic handler, set the :ref:`CONFIG_ULP_PANIC_OUTPUT_ENABLE` option to ``y``. This option can be kept disabled to reduce LP-RAM usage by the LP core application. To recover a backtrace from the panic dump, it is possible to use ``idf.py monitor``.
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
@@ -358,7 +362,7 @@ LP Core Debugging Specifics
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
#. For convenient debugging, you may need to add ``-O0`` compile option for ULP app in its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this.
|
#. For convenient debugging, you may need to add ``-O0`` compile option for ULP app in its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this.
|
||||||
:not esp32p4: #. LP core supports limited set of HW exceptions, so, for example, writing at address `0x0` will not cause a panic as it would be for the code running on HP core. This can be overcome to some extent by enabling undefined behavior sanitizer for LP core application, so `ubsan` can help to catch some errors. But note that it will increase code size significantly and it can happen that application won't fit into RTC RAM. To enable `ubsan` for ULP app, add ``-fsanitize=undefined -fno-sanitize=shift-base`` compile option to its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this.
|
:not esp32p4 and not esp32s31: #. LP core supports limited set of HW exceptions, so, for example, writing at address `0x0` will not cause a panic as it would be for the code running on HP core. This can be overcome to some extent by enabling undefined behavior sanitizer for LP core application, so `ubsan` can help to catch some errors. But note that it will increase code size significantly and it can happen that application won't fit into RTC RAM. To enable `ubsan` for ULP app, add ``-fsanitize=undefined -fno-sanitize=shift-base`` compile option to its ``CMakeLists.txt``. See :example:`system/ulp/lp_core/debugging/` on how to do this.
|
||||||
#. To be able to debug program running on LP core, debugging information and symbols need to be loaded to GDB. It can be done via GDB command line or in ``gdbinit`` file. See section above.
|
#. To be able to debug program running on LP core, debugging information and symbols need to be loaded to GDB. It can be done via GDB command line or in ``gdbinit`` file. See section above.
|
||||||
#. Upon startup, LP core application is loaded into RAM, so all SW breakpoints set before that moment will get overwritten. The best moment to set breakpoints for LP core application is to do this when LP core program reaches `main` function.
|
#. Upon startup, LP core application is loaded into RAM, so all SW breakpoints set before that moment will get overwritten. The best moment to set breakpoints for LP core application is to do this when LP core program reaches `main` function.
|
||||||
#. When using IDEs, it may lack support for configuring breakpoint actions or commands shown in ``gdbinit`` above. Consequently, you have to preset all breakpoints before debug session start and disable all of them except for ``main``. When program stops at ``main``, enable the remaining breakpoints and resume execution manually.
|
#. When using IDEs, it may lack support for configuring breakpoint actions or commands shown in ``gdbinit`` above. Consequently, you have to preset all breakpoints before debug session start and disable all of them except for ``main``. When program stops at ``main``, enable the remaining breakpoints and resume execution manually.
|
||||||
@@ -388,11 +392,11 @@ Application Examples
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
- :example:`system/ulp/lp_core/gpio` polls GPIO while main CPU is in Deep-sleep.
|
- :example:`system/ulp/lp_core/gpio` polls GPIO while main CPU is in Deep-sleep.
|
||||||
:esp32c6: - :example:`system/ulp/lp_core/lp_i2c` reads external I2C ambient light sensor (BH1750) while the main CPU is in Deep-sleep and wakes up the main CPU once a threshold is met.
|
:SOC_LP_CORE_SUPPORT_I2C: - :example:`system/ulp/lp_core/lp_i2c` reads external I2C ambient light sensor (BH1750) while the main CPU is in Deep-sleep and wakes up the main CPU once a threshold is met.
|
||||||
- :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core.
|
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` reads data written to a serial console and echoes it back. This example demonstrates the usage of the LP UART driver running on the LP core.
|
||||||
- :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core.
|
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` shows how to print various statements from a program running on the LP core.
|
||||||
- :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` shows how to trigger a wakeup using the LP UART specific character sequence wakeup mode.
|
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` shows how to trigger a wakeup using the LP UART specific character sequence wakeup mode.
|
||||||
- :example:`system/ulp/lp_core/lp_mailbox` shows how to use the mailbox for both synchronous and asynchronous communication between the HP and LP cores. Depending on the target, the implementation may use the hardware mailbox controller (if available) or a software-only implementation using interrupts.
|
:SOC_LP_MAILBOX_SUPPORTED: - :example:`system/ulp/lp_core/lp_mailbox` shows how to use the mailbox for both synchronous and asynchronous communication between the HP and LP cores. Depending on the target, the implementation may use the hardware mailbox controller (if available) or a software-only implementation using interrupts.
|
||||||
- :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU.
|
- :example:`system/ulp/lp_core/interrupt` shows how to register an interrupt handler on the LP core to receive an interrupt triggered by the main CPU.
|
||||||
- :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode.
|
- :example:`system/ulp/lp_core/gpio_intr_pulse_counter` shows how to use GPIO interrupts to count pulses while the main CPU is in Deep-sleep mode.
|
||||||
- :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app.
|
- :example:`system/ulp/lp_core/build_system/` demonstrates how to include custom ``CMakeLists.txt`` file for the ULP app.
|
||||||
@@ -405,7 +409,13 @@ Main CPU API Reference
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core.inc
|
.. include-build-file:: inc/ulp_lp_core.inc
|
||||||
|
|
||||||
|
.. only:: SOC_LP_CORE_SUPPORT_I2C
|
||||||
|
|
||||||
.. include-build-file:: inc/lp_core_i2c.inc
|
.. include-build-file:: inc/lp_core_i2c.inc
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
.. include-build-file:: inc/lp_core_uart.inc
|
.. include-build-file:: inc/lp_core_uart.inc
|
||||||
|
|
||||||
.. only:: SOC_LP_SPI_SUPPORTED
|
.. only:: SOC_LP_SPI_SUPPORTED
|
||||||
@@ -423,9 +433,19 @@ LP Core API Reference
|
|||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_utils.inc
|
.. include-build-file:: inc/ulp_lp_core_utils.inc
|
||||||
.. include-build-file:: inc/ulp_lp_core_gpio.inc
|
.. include-build-file:: inc/ulp_lp_core_gpio.inc
|
||||||
|
|
||||||
|
.. only:: SOC_LP_CORE_SUPPORT_I2C
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_i2c.inc
|
.. include-build-file:: inc/ulp_lp_core_i2c.inc
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_uart.inc
|
.. include-build-file:: inc/ulp_lp_core_uart.inc
|
||||||
|
|
||||||
|
.. only:: SOC_LP_MAILBOX_SUPPORTED
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_mailbox.inc
|
.. include-build-file:: inc/ulp_lp_core_mailbox.inc
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_print.inc
|
.. include-build-file:: inc/ulp_lp_core_print.inc
|
||||||
.. include-build-file:: inc/ulp_lp_core_interrupts.inc
|
.. include-build-file:: inc/ulp_lp_core_interrupts.inc
|
||||||
|
|
||||||
|
|||||||
@@ -234,8 +234,8 @@ ULP LP 内核支持的外设
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
* LP IO
|
* LP IO
|
||||||
* LP I2C
|
:SOC_LP_CORE_SUPPORT_I2C: * LP I2C
|
||||||
* LP UART
|
:SOC_ULP_LP_UART_SUPPORTED: * LP UART
|
||||||
:SOC_LP_SPI_SUPPORTED: * LP SPI
|
:SOC_LP_SPI_SUPPORTED: * LP SPI
|
||||||
:SOC_LP_MAILBOX_SUPPORTED: * LP 邮箱
|
:SOC_LP_MAILBOX_SUPPORTED: * LP 邮箱
|
||||||
|
|
||||||
@@ -277,7 +277,7 @@ ULP LP 内核中断
|
|||||||
ULP LP 内核时钟配置
|
ULP LP 内核时钟配置
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
{IDF_TARGET_XTAL_FREQ:default="未更新", esp32c5="48 MHz", esp32p4="40 MHz"}
|
{IDF_TARGET_XTAL_FREQ:default="未更新", esp32c5="48 MHz", esp32p4="40 MHz", esp32s31="40 MHz"}
|
||||||
|
|
||||||
ULP LP 内核的时钟源来自系统时钟 ``LP_FAST_CLK``,详情请参见 `技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`__ > ``复位和时钟``。
|
ULP LP 内核的时钟源来自系统时钟 ``LP_FAST_CLK``,详情请参见 `技术参考手册 <{IDF_TARGET_TRM_CN_URL}>`__ > ``复位和时钟``。
|
||||||
|
|
||||||
@@ -285,7 +285,7 @@ ULP LP 内核的时钟源来自系统时钟 ``LP_FAST_CLK``,详情请参见 `
|
|||||||
|
|
||||||
在 {IDF_TARGET_NAME} 上,``LP_FAST_CLK`` 支持使用外部 {IDF_TARGET_XTAL_FREQ} 晶振 (XTAL) 作为其时钟源。默认时钟源 ``RTC_FAST_CLOCK`` 的运行频率约为 20 MHz,使用外部晶振时钟后,ULP LP 内核将以更高的频率运行。缺点在于,``LP_FAST_CLK`` 在休眠期间通常会断电以减少功耗,而选择 XTAL 作为时钟源后,休眠期间时钟仍将保持通电,造成功耗增加。因此,如果仅希望在 HP 内核活动时将 LP 内核用作协处理器,则可以使用 XTAL 以提高 LP 内核的性能和频率稳定性。
|
在 {IDF_TARGET_NAME} 上,``LP_FAST_CLK`` 支持使用外部 {IDF_TARGET_XTAL_FREQ} 晶振 (XTAL) 作为其时钟源。默认时钟源 ``RTC_FAST_CLOCK`` 的运行频率约为 20 MHz,使用外部晶振时钟后,ULP LP 内核将以更高的频率运行。缺点在于,``LP_FAST_CLK`` 在休眠期间通常会断电以减少功耗,而选择 XTAL 作为时钟源后,休眠期间时钟仍将保持通电,造成功耗增加。因此,如果仅希望在 HP 内核活动时将 LP 内核用作协处理器,则可以使用 XTAL 以提高 LP 内核的性能和频率稳定性。
|
||||||
|
|
||||||
要启用此功能,请将 :ref:`CONFIG_RTC_FAST_CLK_SRC` 设置为 ``CONFIG_RTC_FAST_CLK_SRC_XTAL``。
|
要启用此功能,请将 ``CONFIG_RTC_FAST_CLK_SRC`` 设置为 ``CONFIG_RTC_FAST_CLK_SRC_XTAL``。
|
||||||
|
|
||||||
|
|
||||||
调试 ULP LP 内核应用程序
|
调试 ULP LP 内核应用程序
|
||||||
@@ -293,12 +293,16 @@ ULP LP 内核的时钟源来自系统时钟 ``LP_FAST_CLK``,详情请参见 `
|
|||||||
|
|
||||||
在编程 LP 内核时,有时很难弄清楚程序未按预期运行的原因。请参考以下策略,调试 LP 内核程序:
|
在编程 LP 内核时,有时很难弄清楚程序未按预期运行的原因。请参考以下策略,调试 LP 内核程序:
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
* 使用 LP UART 打印:LP 内核可以访问 LP UART 外设,在主 CPU 处于睡眠状态时独立打印信息。有关使用此驱动程序的示例,请参阅 :example:`system/ulp/lp_core/lp_uart/lp_uart_print`。
|
* 使用 LP UART 打印:LP 内核可以访问 LP UART 外设,在主 CPU 处于睡眠状态时独立打印信息。有关使用此驱动程序的示例,请参阅 :example:`system/ulp/lp_core/lp_uart/lp_uart_print`。
|
||||||
|
|
||||||
* 通过 :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`,将 :cpp:func:`lp_core_printf` 路由到 HP-Core 控制台 UART,可以轻松地将 LP 内核信息打印到已经连接的 HP-Core 控制台 UART。此方法的缺点是需要主 CPU 处于唤醒状态,并且由于 LP 内核与 HP 内未同步,输出可能会交错。
|
* 通过 :ref:`CONFIG_ULP_HP_UART_CONSOLE_PRINT`,将 :cpp:func:`lp_core_printf` 路由到 HP-Core 控制台 UART,可以轻松地将 LP 内核信息打印到已经连接的 HP-Core 控制台 UART。此方法的缺点是需要主 CPU 处于唤醒状态,并且由于 LP 内核与 HP 内未同步,输出可能会交错。
|
||||||
|
|
||||||
* 通过共享变量共享程序状态:如 :ref:`ulp-lp-core-access-variables` 所述,主 CPU 和 ULP 内核都可以轻松访问 RTC 内存中的全局变量。若想了解 ULP 内核的运行状态,可以将状态信息从 ULP 写入变量中,并通过主 CPU 读取信息。这种方法的缺点在于它需要主 CPU 一直处于唤醒状态,而这通常很难实现。另外,若主 CPU 一直处于唤醒状态,可能会掩盖某些问题,因为部分问题只会在特定电源域断电时发生。
|
* 通过共享变量共享程序状态:如 :ref:`ulp-lp-core-access-variables` 所述,主 CPU 和 ULP 内核都可以轻松访问 RTC 内存中的全局变量。若想了解 ULP 内核的运行状态,可以将状态信息从 ULP 写入变量中,并通过主 CPU 读取信息。这种方法的缺点在于它需要主 CPU 一直处于唤醒状态,而这通常很难实现。另外,若主 CPU 一直处于唤醒状态,可能会掩盖某些问题,因为部分问题只会在特定电源域断电时发生。
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
* 紧急处理程序:当检测到异常时,LP 内核的紧急处理程序会把 LP 内核寄存器的状态通过 LP UART 发送出去。将 ``CONFIG_ULP_PANIC_OUTPUT_ENABLE`` 选项设置为 ``y``,可以启用紧急处理程序。禁用此选项将减少 LP 内核应用程序的 LP-RAM 使用量。若想从紧急转储中解析栈回溯,可以使用 ``idf.py monitor``。
|
* 紧急处理程序:当检测到异常时,LP 内核的紧急处理程序会把 LP 内核寄存器的状态通过 LP UART 发送出去。将 ``CONFIG_ULP_PANIC_OUTPUT_ENABLE`` 选项设置为 ``y``,可以启用紧急处理程序。禁用此选项将减少 LP 内核应用程序的 LP-RAM 使用量。若想从紧急转储中解析栈回溯,可以使用 ``idf.py monitor``。
|
||||||
|
|
||||||
.. warning::
|
.. warning::
|
||||||
@@ -358,7 +362,7 @@ LP 内核调试特性
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
#. 为了方便调试,请在 ULP 应用的 ``CMakeLists.txt`` 文件中添加 ``-O0`` 编译选项。具体操作步骤请参见 :example:`system/ulp/lp_core/debugging/`。
|
#. 为了方便调试,请在 ULP 应用的 ``CMakeLists.txt`` 文件中添加 ``-O0`` 编译选项。具体操作步骤请参见 :example:`system/ulp/lp_core/debugging/`。
|
||||||
:not esp32p4: #. LP 内核支持的硬件异常类型有限,例如,写入地址 `0x0` 不会像在 HP 内核上一样造成系统崩溃。启用 LP 内核应用程序的未定义行为检测器 (`ubsan`) 可以捕捉一些错误,从而在一定程度上弥补这一限制。但请注意,这将显著增加代码量,可能会导致应用程序超出 RTC RAM 的容量限制。要启用 `ubsan`,请在 ``CMakeLists.txt`` 文件中添加 ``-fsanitize=undefined -fno-sanitize=shift-base`` 编译选项。具体操作步骤请参见 :example:`system/ulp/lp_core/debugging/`。
|
:not esp32p4 and not esp32s31: #. LP 内核支持的硬件异常类型有限,例如,写入地址 `0x0` 不会像在 HP 内核上一样造成系统崩溃。启用 LP 内核应用程序的未定义行为检测器 (`ubsan`) 可以捕捉一些错误,从而在一定程度上弥补这一限制。但请注意,这将显著增加代码量,可能会导致应用程序超出 RTC RAM 的容量限制。要启用 `ubsan`,请在 ``CMakeLists.txt`` 文件中添加 ``-fsanitize=undefined -fno-sanitize=shift-base`` 编译选项。具体操作步骤请参见 :example:`system/ulp/lp_core/debugging/`。
|
||||||
#. 为了调试运行在 LP 内核上的程序,需要先将调试信息和符号加载到 GDB 中。这可以通过 GDB 命令行或在 ``gdbinit`` 文件中完成。具体操作步骤请参见上文。
|
#. 为了调试运行在 LP 内核上的程序,需要先将调试信息和符号加载到 GDB 中。这可以通过 GDB 命令行或在 ``gdbinit`` 文件中完成。具体操作步骤请参见上文。
|
||||||
#. LP 内核应用程序会在启时会加载到 RAM 中,在此之前设置的所有软件断点都会被覆盖。设置 LP 内核应用断点的最佳时机是在 LP 内核程序运行至 ``main`` 函数之时。
|
#. LP 内核应用程序会在启时会加载到 RAM 中,在此之前设置的所有软件断点都会被覆盖。设置 LP 内核应用断点的最佳时机是在 LP 内核程序运行至 ``main`` 函数之时。
|
||||||
#. 使用 IDE 时,可能无法配置上述 ``gdbinit`` 文件中的断点操作或命令。因此,请在调试会话开始前预设并禁用所有断点,只保留 ``main`` 函数处的断点。当程序在 ``main`` 处停止时,手动启用其余断点并恢复执行。
|
#. 使用 IDE 时,可能无法配置上述 ``gdbinit`` 文件中的断点操作或命令。因此,请在调试会话开始前预设并禁用所有断点,只保留 ``main`` 函数处的断点。当程序在 ``main`` 处停止时,手动启用其余断点并恢复执行。
|
||||||
@@ -388,11 +392,11 @@ LP 内核调试特性
|
|||||||
.. list::
|
.. list::
|
||||||
|
|
||||||
- :example:`system/ulp/lp_core/gpio` 展示了 ULP LP 内核协处理器在主 CPU 深度睡眠时轮询 GPIO。
|
- :example:`system/ulp/lp_core/gpio` 展示了 ULP LP 内核协处理器在主 CPU 深度睡眠时轮询 GPIO。
|
||||||
:esp32c6: - :example:`system/ulp/lp_core/lp_i2c` 展示了 ULP LP 内核协处理器在主 CPU 深度睡眠时读取外部 I2C 环境光传感器 (BH1750),并在达到阈值时唤醒主 CPU。
|
:SOC_LP_CORE_SUPPORT_I2C: - :example:`system/ulp/lp_core/lp_i2c` 展示了 ULP LP 内核协处理器在主 CPU 深度睡眠时读取外部 I2C 环境光传感器 (BH1750),并在达到阈值时唤醒主 CPU。
|
||||||
- :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` 展示了低功耗内核上运行的 LP UART 驱动程序如何读取并回显写入串行控制台的数据。
|
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_echo` 展示了低功耗内核上运行的 LP UART 驱动程序如何读取并回显写入串行控制台的数据。
|
||||||
- :example:`system/ulp/lp_core/lp_uart/lp_uart_print` 展示了如何在低功耗内核上使用串口打印功能。
|
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_print` 展示了如何在低功耗内核上使用串口打印功能。
|
||||||
- :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` 展示了如何使用 LP UART 特定字符序列唤醒模式触发唤醒。
|
:SOC_ULP_LP_UART_SUPPORTED: - :example:`system/ulp/lp_core/lp_uart/lp_uart_char_seq_wakeup` 展示了如何使用 LP UART 特定字符序列唤醒模式触发唤醒。
|
||||||
- :example:`system/ulp/lp_core/lp_mailbox` 展示了如何在 HP 内核和 LP 内核之间使用邮箱进行同步和异步通信。根据目标设备的不同,示例实现可能会使用硬件邮箱控制器(如果可用),或者使用基于中断的纯软件实现。
|
:SOC_LP_MAILBOX_SUPPORTED: - :example:`system/ulp/lp_core/lp_mailbox` 展示了如何在 HP 内核和 LP 内核之间使用邮箱进行同步和异步通信。根据目标设备的不同,示例实现可能会使用硬件邮箱控制器(如果可用),或者使用基于中断的纯软件实现。
|
||||||
- :example:`system/ulp/lp_core/interrupt` 展示了如何在 LP 内核上注册中断处理程序,接收由主 CPU 触发的中断。
|
- :example:`system/ulp/lp_core/interrupt` 展示了如何在 LP 内核上注册中断处理程序,接收由主 CPU 触发的中断。
|
||||||
- :example:`system/ulp/lp_core/gpio_intr_pulse_counter` 展示了如何在主 CPU 处于 Deep-sleep 模式时,使用 GPIO 中断为脉冲计数。
|
- :example:`system/ulp/lp_core/gpio_intr_pulse_counter` 展示了如何在主 CPU 处于 Deep-sleep 模式时,使用 GPIO 中断为脉冲计数。
|
||||||
- :example:`system/ulp/lp_core/build_system/` 演示了如何为 ULP 应用程序添加自定义的 ``CMakeLists.txt`` 文件。
|
- :example:`system/ulp/lp_core/build_system/` 演示了如何为 ULP 应用程序添加自定义的 ``CMakeLists.txt`` 文件。
|
||||||
@@ -405,7 +409,13 @@ API 参考
|
|||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core.inc
|
.. include-build-file:: inc/ulp_lp_core.inc
|
||||||
|
|
||||||
|
.. only:: SOC_LP_CORE_SUPPORT_I2C
|
||||||
|
|
||||||
.. include-build-file:: inc/lp_core_i2c.inc
|
.. include-build-file:: inc/lp_core_i2c.inc
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
.. include-build-file:: inc/lp_core_uart.inc
|
.. include-build-file:: inc/lp_core_uart.inc
|
||||||
|
|
||||||
.. only:: SOC_LP_SPI_SUPPORTED
|
.. only:: SOC_LP_SPI_SUPPORTED
|
||||||
@@ -423,9 +433,19 @@ LP 内核 API 参考
|
|||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_utils.inc
|
.. include-build-file:: inc/ulp_lp_core_utils.inc
|
||||||
.. include-build-file:: inc/ulp_lp_core_gpio.inc
|
.. include-build-file:: inc/ulp_lp_core_gpio.inc
|
||||||
|
|
||||||
|
.. only:: SOC_LP_CORE_SUPPORT_I2C
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_i2c.inc
|
.. include-build-file:: inc/ulp_lp_core_i2c.inc
|
||||||
|
|
||||||
|
.. only:: SOC_ULP_LP_UART_SUPPORTED
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_uart.inc
|
.. include-build-file:: inc/ulp_lp_core_uart.inc
|
||||||
|
|
||||||
|
.. only:: SOC_LP_MAILBOX_SUPPORTED
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_mailbox.inc
|
.. include-build-file:: inc/ulp_lp_core_mailbox.inc
|
||||||
|
|
||||||
.. include-build-file:: inc/ulp_lp_core_print.inc
|
.. include-build-file:: inc/ulp_lp_core_print.inc
|
||||||
.. include-build-file:: inc/ulp_lp_core_interrupts.inc
|
.. include-build-file:: inc/ulp_lp_core_interrupts.inc
|
||||||
|
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ examples/system/ulp/lp_core/gpio_intr_pulse_counter:
|
|||||||
|
|
||||||
examples/system/ulp/lp_core/gpio_wakeup:
|
examples/system/ulp/lp_core/gpio_wakeup:
|
||||||
enable:
|
enable:
|
||||||
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0)
|
- if: (SOC_LP_CORE_SUPPORTED == 1) and (SOC_RTCIO_PIN_COUNT > 0) and (SOC_DEEP_SLEEP_SUPPORTED == 1)
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
depends_components+:
|
depends_components+:
|
||||||
- esp_driver_gpio
|
- esp_driver_gpio
|
||||||
@@ -61,14 +61,16 @@ examples/system/ulp/lp_core/lp_adc:
|
|||||||
|
|
||||||
examples/system/ulp/lp_core/lp_i2c:
|
examples/system/ulp/lp_core/lp_i2c:
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_I2C_SUPPORTED == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORT_I2C == 1 and SOC_DEEP_SLEEP_SUPPORTED == 1
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
depends_components+:
|
depends_components+:
|
||||||
- esp_hal_i2c
|
- esp_hal_i2c
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_mailbox:
|
examples/system/ulp/lp_core/lp_mailbox:
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1 and IDF_TARGET not in ["esp32s31"]
|
||||||
|
temporary: true
|
||||||
|
reason: ESP32-S31 not supported yet # TODO: [ESP32S31] IDF-14637
|
||||||
<<: *ulp_default_depends
|
<<: *ulp_default_depends
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_spi:
|
examples/system/ulp/lp_core/lp_spi:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- | -------- |
|
| ----------------- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# LP Core Build System Custom Modification Example:
|
# LP Core Build System Custom Modification Example:
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ from pytest_embedded_idf.utils import idf_parametrize
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target'])
|
@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4', 'esp32s31'], indirect=['target'])
|
||||||
def test_lp_core_build_sys(dut: IdfDut) -> None:
|
def test_lp_core_build_sys(dut: IdfDut) -> None:
|
||||||
dut.expect('Sum calculated by ULP using external library func: 11')
|
dut.expect('Sum calculated by ULP using external library func: 11')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- | -------- |
|
| ----------------- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# LP Core Debugging Example
|
# LP Core Debugging Example
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- | -------- |
|
| ----------------- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# LP Core simple example with inter-CPU critical section:
|
# LP Core simple example with inter-CPU critical section:
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ def test_lp_core_critical_section_main_1_task(dut: Dut) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@idf_parametrize('target', ['esp32p4'], indirect=['target'])
|
@idf_parametrize('target', ['esp32p4', 'esp32s31'], indirect=['target'])
|
||||||
def test_lp_core_critical_section_main_2_tasks(dut: Dut) -> None:
|
def test_lp_core_critical_section_main_2_tasks(dut: Dut) -> None:
|
||||||
dut.expect("LP CPU's increment starts, shared counter = 0")
|
dut.expect("LP CPU's increment starts, shared counter = 0")
|
||||||
dut.expect(r'core 0 started, cnt = \d+')
|
dut.expect(r'core 0 started, cnt = \d+')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- | -------- |
|
| ----------------- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# LP-Core example with interrupt triggered from HP-Core:
|
# LP-Core example with interrupt triggered from HP-Core:
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,6 @@ from pytest_embedded_idf.utils import idf_parametrize
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4'], indirect=['target'])
|
@idf_parametrize('target', ['esp32c5', 'esp32c6', 'esp32p4', 'esp32s31'], indirect=['target'])
|
||||||
def test_lp_core_intr(dut: Dut) -> None:
|
def test_lp_core_intr(dut: Dut) -> None:
|
||||||
dut.expect('Triggered 10 interrupts on the LP-Core, LP-Core received 10 interrupts')
|
dut.expect('Triggered 10 interrupts on the LP-Core, LP-Core received 10 interrupts')
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ from pytest_embedded_idf.utils import soc_filtered_targets
|
|||||||
|
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
@idf_parametrize('target', soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'), indirect=['target'])
|
@idf_parametrize('target', soc_filtered_targets('SOC_LP_CORE_SUPPORTED == 1'), indirect=['target'])
|
||||||
|
@pytest.mark.temp_skip_ci(
|
||||||
|
targets=['esp32s31'], reason='s31 bringup on this module is not done, TODO: [ESP32S31] IDF-14637'
|
||||||
|
)
|
||||||
def test_lp_mailbox(dut: Dut) -> None:
|
def test_lp_mailbox(dut: Dut) -> None:
|
||||||
# Wait for LP core to be loaded and running
|
# Wait for LP core to be loaded and running
|
||||||
dut.expect_exact('LP Mailbox initialized successfully')
|
dut.expect_exact('LP Mailbox initialized successfully')
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C5 | ESP32-C6 | ESP32-P4 |
|
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C5 | ESP32-C6 | ESP32-C61 | ESP32-H2 | ESP32-H21 | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 | ESP32-S31 |
|
||||||
| ----------------- | -------- | -------- | -------- |
|
| ----------------- | ----- | -------- | -------- | -------- | -------- | --------- | -------- | --------- | -------- | -------- | -------- | -------- | --------- |
|
||||||
|
|
||||||
# LP-Core example with interrupt triggered from LP Timer
|
# LP-Core example with interrupt triggered from LP Timer
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ ULP program periodically measures the input voltage on ADC_CHANNEL_6 (GPIO34 on
|
|||||||
|
|
||||||
By default, thresholds are set to 1.35V and 1.75V, approximately.
|
By default, thresholds are set to 1.35V and 1.75V, approximately.
|
||||||
|
|
||||||
GPIO15 is connected to ground to supress output from ROM bootloader.
|
GPIO15 is connected to ground to suppress output from ROM bootloader.
|
||||||
|
|
||||||
Average current drawn by the ESP32 in this example (with the default 4x averaging) depending on the measurement frequency is as follows:
|
Average current drawn by the ESP32 in this example (with the default 4x averaging) depending on the measurement frequency is as follows:
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Reading initial uncompensated temperature and pressure data ...
|
|||||||
Uncompensated Temperature = 22865
|
Uncompensated Temperature = 22865
|
||||||
Uncompensated Pressure = 41768
|
Uncompensated Pressure = 41768
|
||||||
|
|
||||||
Real Temperature = 24.900000 deg celcius
|
Real Temperature = 24.900000 deg celsius
|
||||||
Real Pressure = 990.640000 hPa
|
Real Pressure = 990.640000 hPa
|
||||||
|
|
||||||
Entering in deep sleep
|
Entering in deep sleep
|
||||||
@@ -85,7 +85,7 @@ mb = -32768
|
|||||||
mc = -11786
|
mc = -11786
|
||||||
md = 2746
|
md = 2746
|
||||||
|
|
||||||
New Real Temperature = 24.900000 deg celcius
|
New Real Temperature = 24.900000 deg celsius
|
||||||
New Real Pressure = 990.550000 hPa
|
New Real Pressure = 990.550000 hPa
|
||||||
Entering in deep sleep
|
Entering in deep sleep
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ This example demonstrates how the ULP-RISC-V coprocessor can register and handle
|
|||||||
- RTC IO triggered interrupts
|
- RTC IO triggered interrupts
|
||||||
|
|
||||||
The example keeps a count of the software interrupts triggered on the ULP RISC-V core and wakes up the main processor from deep sleep after a certain threshold.
|
The example keeps a count of the software interrupts triggered on the ULP RISC-V core and wakes up the main processor from deep sleep after a certain threshold.
|
||||||
Additionaly, it wakes up the main processor from deep sleep when a button is pressed and the GPIO interrupt is triggered.
|
Additionally, it wakes up the main processor from deep sleep when a button is pressed and the GPIO interrupt is triggered.
|
||||||
|
|
||||||
## How to use example
|
## How to use example
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user