mirror of
https://github.com/espressif/esp-idf
synced 2025-03-10 01:29:21 -04:00
Merge branch 'bugfix/clear_lp_sw_trigger_int_before_sleep' into 'master'
fix(ulp): add api to get lp_cpu wakeup cause and clear wakeup source at startup Closes IDFGH-11526 See merge request espressif/esp-idf!27747
This commit is contained in:
commit
8d165aa767
@ -11,6 +11,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "hal/assert.h"
|
#include "hal/assert.h"
|
||||||
#include "hal/misc.h"
|
#include "hal/misc.h"
|
||||||
|
#include "hal/lp_aon_ll.h"
|
||||||
#include "soc/soc_etm_struct.h"
|
#include "soc/soc_etm_struct.h"
|
||||||
#include "soc/pcr_struct.h"
|
#include "soc/pcr_struct.h"
|
||||||
|
|
||||||
@ -112,6 +113,10 @@ static inline void etm_ll_channel_set_task(soc_etm_dev_t *hw, uint32_t chan, uin
|
|||||||
hw->channel[chan].task_id.task_id = task;
|
hw->channel[chan].task_id.task_id = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define etm_ll_is_lpcore_wakeup_triggered() lp_aon_ll_get_lpcore_etm_wakeup_flag()
|
||||||
|
|
||||||
|
#define etm_ll_clear_lpcore_wakeup_status() lp_aon_ll_clear_lpcore_etm_wakeup_flag()
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -85,6 +85,24 @@ static inline void lp_aon_ll_inform_wakeup_type(bool dslp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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_aon_ll_get_lpcore_etm_wakeup_flag(void)
|
||||||
|
{
|
||||||
|
return REG_GET_BIT(LP_AON_LPCORE_REG, LP_AON_LPCORE_ETM_WAKEUP_FLAG);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the flag that marks whether LP CPU is awakened by soc_etm
|
||||||
|
*/
|
||||||
|
static inline void lp_aon_ll_clear_lpcore_etm_wakeup_flag(void)
|
||||||
|
{
|
||||||
|
REG_SET_BIT(LP_AON_LPCORE_REG, LP_AON_LPCORE_ETM_WAKEUP_FLAG_CLR);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -109,6 +109,14 @@ static inline void lp_core_ll_set_wakeup_source(uint32_t flags)
|
|||||||
PMU.lp_ext.pwr1.wakeup_en = flags;
|
PMU.lp_ext.pwr1.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.pwr1.wakeup_en;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/lp_timer_struct.h"
|
#include "soc/lp_timer_struct.h"
|
||||||
|
#include "soc/lp_timer_reg.h"
|
||||||
#include "soc/lp_aon_reg.h"
|
#include "soc/lp_aon_reg.h"
|
||||||
#include "hal/lp_timer_types.h"
|
#include "hal/lp_timer_types.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
@ -61,6 +62,16 @@ FORCE_INLINE_ATTR void lp_timer_ll_clear_lp_alarm_intr_status(lp_timer_dev_t *de
|
|||||||
dev->lp_int_clr.alarm = 1;
|
dev->lp_int_clr.alarm = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_lp_intr_raw(lp_timer_dev_t *dev)
|
||||||
|
{
|
||||||
|
return dev->lp_int_raw.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void lp_timer_ll_clear_lp_intsts_mask(lp_timer_dev_t *dev, uint32_t mask)
|
||||||
|
{
|
||||||
|
dev->lp_int_clr.val = mask;
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us)
|
FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us)
|
||||||
{
|
{
|
||||||
uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG);
|
uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG);
|
||||||
|
@ -531,6 +531,16 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_reject_cause(pmu_dev_t *hw)
|
|||||||
return hw->wakeup.status1;
|
return hw->wakeup.status1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_interrupt_raw(pmu_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->lp_ext.int_raw.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void pmu_ll_lp_clear_intsts_mask(pmu_dev_t *hw, uint32_t mask)
|
||||||
|
{
|
||||||
|
hw->lp_ext.int_clr.val = mask;
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
FORCE_INLINE_ATTR void pmu_ll_lp_set_min_sleep_cycle(pmu_dev_t *hw, uint32_t slow_clk_cycle)
|
||||||
{
|
{
|
||||||
hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle;
|
hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle;
|
||||||
|
@ -121,6 +121,24 @@ static inline void etm_ll_channel_set_task(soc_etm_dev_t *hw, uint32_t chan, uin
|
|||||||
hw->channel[chan].task_id.task_id = task;
|
hw->channel[chan].task_id.task_id = task;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the flag that marks whether LP CPU is awakened by ETM
|
||||||
|
*
|
||||||
|
* @return Return true if lpcore is woken up by soc etm flag
|
||||||
|
*/
|
||||||
|
static inline bool etm_ll_is_lpcore_wakeup_triggered(void)
|
||||||
|
{
|
||||||
|
return SOC_ETM.task_st5.ulp_task_wakeup_cpu_st;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clear the flag that marks whether LP CPU is awakened by ETM
|
||||||
|
*/
|
||||||
|
static inline void etm_ll_clear_lpcore_wakeup_status(void)
|
||||||
|
{
|
||||||
|
SOC_ETM.task_st5_clr.ulp_task_wakeup_cpu_st_clr = 1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -111,6 +111,13 @@ static inline void lp_core_ll_set_wakeup_source(uint32_t flags)
|
|||||||
PMU.lp_cpu_pwr2.lp_cpu_wakeup_en = flags;
|
PMU.lp_cpu_pwr2.lp_cpu_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_cpu_pwr2.lp_cpu_wakeup_en;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Set boot address for lp core
|
* @brief Set boot address for lp core
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/rtc.h"
|
#include "soc/rtc.h"
|
||||||
#include "soc/lp_timer_struct.h"
|
#include "soc/lp_timer_struct.h"
|
||||||
|
#include "soc/lp_timer_reg.h"
|
||||||
#include "soc/lp_system_reg.h"
|
#include "soc/lp_system_reg.h"
|
||||||
#include "hal/lp_timer_types.h"
|
#include "hal/lp_timer_types.h"
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
@ -61,6 +62,16 @@ FORCE_INLINE_ATTR void lp_timer_ll_clear_lp_alarm_intr_status(lp_timer_dev_t *de
|
|||||||
dev->lp_int_clr.main_timer_lp_int_clr = 1;
|
dev->lp_int_clr.main_timer_lp_int_clr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR uint32_t lp_timer_ll_get_lp_intr_raw(lp_timer_dev_t *dev)
|
||||||
|
{
|
||||||
|
return dev->lp_int_raw.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void lp_timer_ll_clear_lp_intsts_mask(lp_timer_dev_t *dev, uint32_t mask)
|
||||||
|
{
|
||||||
|
dev->lp_int_clr.val = mask;
|
||||||
|
}
|
||||||
|
|
||||||
FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us)
|
FORCE_INLINE_ATTR uint64_t lp_timer_ll_time_to_count(uint64_t time_in_us)
|
||||||
{
|
{
|
||||||
uint32_t slow_clk_value = REG_READ(LP_SYSTEM_REG_LP_STORE1_REG);
|
uint32_t slow_clk_value = REG_READ(LP_SYSTEM_REG_LP_STORE1_REG);
|
||||||
|
35
components/hal/esp32p4/include/hal/pmu_ll.h
Normal file
35
components/hal/esp32p4/include/hal/pmu_ll.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
// The LL layer for ESP32-C6 PMU register operations
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "soc/soc.h"
|
||||||
|
#include "esp_attr.h"
|
||||||
|
#include "hal/assert.h"
|
||||||
|
#include "soc/pmu_struct.h"
|
||||||
|
#include "hal/pmu_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR uint32_t pmu_ll_lp_get_interrupt_raw(pmu_dev_t *hw)
|
||||||
|
{
|
||||||
|
return hw->lp_int_raw.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
FORCE_INLINE_ATTR void pmu_ll_lp_clear_intsts_mask(pmu_dev_t *hw, uint32_t mask)
|
||||||
|
{
|
||||||
|
hw->lp_int_raw.val = mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -13,6 +13,19 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Traverse all possible wake-up sources and update the wake-up cause so that
|
||||||
|
* ulp_lp_core_get_wakeup_cause can obtain the bitmap of the wake-up reasons.
|
||||||
|
*/
|
||||||
|
void ulp_lp_core_update_wakeup_cause(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the wakeup source which caused LP_CPU to wakeup from sleep
|
||||||
|
*
|
||||||
|
* @return Wakeup cause in bit map, for the meaning of each bit, refer
|
||||||
|
* to the definition of wakeup source in lp_core_ll.h
|
||||||
|
*/
|
||||||
|
uint32_t ulp_lp_core_get_wakeup_cause(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wakeup main CPU from sleep or deep sleep.
|
* @brief Wakeup main CPU from sleep or deep sleep.
|
||||||
|
@ -14,6 +14,8 @@ extern void main();
|
|||||||
/* Initialize lp core related system functions before calling user's main*/
|
/* Initialize lp core related system functions before calling user's main*/
|
||||||
void lp_core_startup()
|
void lp_core_startup()
|
||||||
{
|
{
|
||||||
|
ulp_lp_core_update_wakeup_cause();
|
||||||
|
|
||||||
main();
|
main();
|
||||||
|
|
||||||
ulp_lp_core_memory_shared_cfg_t* shared_mem = ulp_lp_core_memory_shared_cfg_get();
|
ulp_lp_core_memory_shared_cfg_t* shared_mem = ulp_lp_core_memory_shared_cfg_get();
|
||||||
|
@ -9,6 +9,13 @@
|
|||||||
#include "riscv/csr.h"
|
#include "riscv/csr.h"
|
||||||
#include "soc/soc.h"
|
#include "soc/soc.h"
|
||||||
#include "soc/pmu_reg.h"
|
#include "soc/pmu_reg.h"
|
||||||
|
#include "hal/misc.h"
|
||||||
|
#include "hal/lp_core_ll.h"
|
||||||
|
#include "hal/etm_ll.h"
|
||||||
|
#include "hal/lp_timer_ll.h"
|
||||||
|
#include "hal/pmu_ll.h"
|
||||||
|
#include "hal/uart_ll.h"
|
||||||
|
#include "hal/rtc_io_ll.h"
|
||||||
|
|
||||||
/* LP_FAST_CLK is not very accurate, for now use a rough estimate */
|
/* LP_FAST_CLK is not very accurate, for now use a rough estimate */
|
||||||
#if CONFIG_IDF_TARGET_ESP32C6
|
#if CONFIG_IDF_TARGET_ESP32C6
|
||||||
@ -17,6 +24,46 @@
|
|||||||
#define LP_CORE_CPU_FREQUENCY_HZ 20000000
|
#define LP_CORE_CPU_FREQUENCY_HZ 20000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint32_t lp_wakeup_cause = 0;
|
||||||
|
|
||||||
|
void ulp_lp_core_update_wakeup_cause(void)
|
||||||
|
{
|
||||||
|
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_HP_CPU) \
|
||||||
|
&& (pmu_ll_lp_get_interrupt_raw(&PMU) & PMU_HP_SW_TRIGGER_INT_RAW)) {
|
||||||
|
lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_HP_CPU;
|
||||||
|
pmu_ll_lp_clear_intsts_mask(&PMU, PMU_HP_SW_TRIGGER_INT_CLR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_UART) \
|
||||||
|
&& (uart_ll_get_intraw_mask(&LP_UART) & LP_UART_WAKEUP_INT_RAW)) {
|
||||||
|
lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_UART;
|
||||||
|
uart_ll_clr_intsts_mask(&LP_UART, LP_UART_WAKEUP_INT_CLR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_IO) \
|
||||||
|
&& rtcio_ll_get_interrupt_status()) {
|
||||||
|
lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_IO;
|
||||||
|
rtcio_ll_clear_interrupt_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_ETM) \
|
||||||
|
&& etm_ll_is_lpcore_wakeup_triggered()) {
|
||||||
|
lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_ETM;
|
||||||
|
etm_ll_clear_lpcore_wakeup_status();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((lp_core_ll_get_wakeup_source() & LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER) \
|
||||||
|
&& (lp_timer_ll_get_lp_intr_raw(&LP_TIMER) & LP_TIMER_MAIN_TIMER_LP_INT_RAW)) {
|
||||||
|
lp_wakeup_cause |= LP_CORE_LL_WAKEUP_SOURCE_LP_TIMER;
|
||||||
|
lp_timer_ll_clear_lp_intsts_mask(&LP_TIMER, LP_TIMER_MAIN_TIMER_LP_INT_CLR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ulp_lp_core_get_wakeup_cause()
|
||||||
|
{
|
||||||
|
return lp_wakeup_cause;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Wakeup main CPU from sleep or deep sleep.
|
* @brief Wakeup main CPU from sleep or deep sleep.
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user