Skip to content

Commit

Permalink
Merge branch 'bugfix/clear_lp_sw_trigger_int_before_sleep_v5.1' into …
Browse files Browse the repository at this point in the history
…'release/v5.1'

feat(ulp): add api to get lp_cpu wakeup cause and clear wakeup source at startup(v5.1)

See merge request espressif/esp-idf!28147
  • Loading branch information
jack0c committed Dec 29, 2023
2 parents 82bfc1d + 53afab3 commit 2c7d68d
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 0 deletions.
5 changes: 5 additions & 0 deletions components/hal/esp32c6/include/hal/etm_ll.h
Expand Up @@ -11,6 +11,7 @@
#include <stdbool.h>
#include "hal/assert.h"
#include "hal/misc.h"
#include "hal/lp_aon_ll.h"
#include "soc/soc_etm_struct.h"

#ifdef __cplusplus
Expand Down Expand Up @@ -98,6 +99,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;
}

#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
}
#endif
18 changes: 18 additions & 0 deletions components/hal/esp32c6/include/hal/lp_aon_ll.h
Expand Up @@ -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
}
#endif
11 changes: 11 additions & 0 deletions components/hal/esp32c6/include/hal/lp_timer_ll.h
Expand Up @@ -12,6 +12,7 @@
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/lp_timer_struct.h"
#include "soc/lp_timer_reg.h"
#include "soc/lp_aon_reg.h"
#include "hal/lp_timer_types.h"
#include "esp_attr.h"
Expand Down Expand Up @@ -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;
}

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)
{
uint32_t slow_clk_value = REG_READ(LP_AON_STORE1_REG);
Expand Down
10 changes: 10 additions & 0 deletions components/hal/esp32c6/include/hal/pmu_ll.h
Expand Up @@ -531,6 +531,16 @@ FORCE_INLINE_ATTR uint32_t pmu_ll_hp_get_reject_cause(pmu_dev_t *hw)
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)
{
hw->wakeup.cntl3.lp_min_slp_val = slow_clk_cycle;
Expand Down
13 changes: 13 additions & 0 deletions components/ulp/lp_core/lp_core/include/ulp_lp_core_utils.h
Expand Up @@ -12,6 +12,19 @@ extern "C" {

#include <stdint.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.
Expand Down
2 changes: 2 additions & 0 deletions components/ulp/lp_core/lp_core/lp_core_startup.c
Expand Up @@ -14,6 +14,8 @@ extern void main();
/* Initialize lp core related system functions before calling user's main*/
void lp_core_startup()
{
ulp_lp_core_update_wakeup_cause();

main();

ulp_lp_core_memory_shared_cfg_t* shared_mem = ulp_lp_core_memory_shared_cfg_get();
Expand Down
47 changes: 47 additions & 0 deletions components/ulp/lp_core/lp_core/lp_core_utils.c
Expand Up @@ -9,10 +9,57 @@
#include "riscv/csr.h"
#include "soc/soc.h"
#include "soc/pmu_reg.h"
#include "hal/misc.h"
#include "ulp_lp_core.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 */
#define LP_CORE_CPU_FREQUENCY_HZ 16000000

static uint32_t lp_wakeup_cause = 0;

void ulp_lp_core_update_wakeup_cause(void)
{
if ((REG_GET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN) & ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU) \
&& (pmu_ll_lp_get_interrupt_raw(&PMU) & PMU_HP_SW_TRIGGER_INT_RAW)) {
lp_wakeup_cause |= ULP_LP_CORE_WAKEUP_SOURCE_HP_CPU;
pmu_ll_lp_clear_intsts_mask(&PMU, PMU_HP_SW_TRIGGER_INT_CLR);
}

if ((REG_GET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN) & ULP_LP_CORE_WAKEUP_SOURCE_LP_UART) \
&& REG_GET_BIT(LP_UART_INT_RAW_REG, LP_UART_WAKEUP_INT_RAW)) {
lp_wakeup_cause |= ULP_LP_CORE_WAKEUP_SOURCE_LP_UART;
REG_SET_BIT(LP_UART_INT_CLR_REG, LP_UART_WAKEUP_INT_CLR);
}

if ((REG_GET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN) & ULP_LP_CORE_WAKEUP_SOURCE_LP_IO) \
&& rtcio_ll_get_interrupt_status()) {
lp_wakeup_cause |= ULP_LP_CORE_WAKEUP_SOURCE_LP_IO;
rtcio_ll_clear_interrupt_status();
}

if ((REG_GET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN) & ULP_LP_CORE_WAKEUP_SOURCE_ETM) \
&& etm_ll_is_lpcore_wakeup_triggered()) {
lp_wakeup_cause |= ULP_LP_CORE_WAKEUP_SOURCE_ETM;
etm_ll_clear_lpcore_wakeup_status();
}

if ((REG_GET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN) & ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER) \
&& (lp_timer_ll_get_lp_intr_raw(&LP_TIMER) & LP_TIMER_MAIN_TIMER_LP_INT_RAW)) {
lp_wakeup_cause |= ULP_LP_CORE_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.
*
Expand Down

0 comments on commit 2c7d68d

Please sign in to comment.