forked from espressif/esp-idf
feat(lp_core): add support for lp timer and lp gpio on P4
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -117,6 +117,14 @@ static inline uint32_t lp_core_ll_get_wakeup_source(void)
|
|||||||
return PMU.lp_ext.pwr1.wakeup_en;
|
return PMU.lp_ext.pwr1.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;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -140,6 +140,14 @@ static inline void lp_core_ll_set_app_boot_address(intptr_t boot_address)
|
|||||||
LP_SYS.boot_addr_hp_lp_reg.boot_addr_hp_lp = boot_address;
|
LP_SYS.boot_addr_hp_lp_reg.boot_addr_hp_lp = boot_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@@ -8,8 +8,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "ulp_common.h"
|
#include "ulp_common.h"
|
||||||
|
#include "esp_rom_caps.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -28,6 +30,11 @@ extern "C" {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t wakeup_source; /*!< Wakeup source flags */
|
uint32_t wakeup_source; /*!< Wakeup source flags */
|
||||||
uint32_t lp_timer_sleep_duration_us; /*!< Sleep duration when ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER is specified. Measurement unit: us */
|
uint32_t lp_timer_sleep_duration_us; /*!< Sleep duration when ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER is specified. Measurement unit: us */
|
||||||
|
#if ESP_ROM_HAS_LP_ROM
|
||||||
|
bool skip_lp_rom_boot; /* !< Skips the LP rom code and boots directly into the app code placed in LP RAM,
|
||||||
|
this gives faster boot time for time sensitive use-cases at the cost of skipping
|
||||||
|
setup e.g. of UART */
|
||||||
|
#endif //ESP_ROM_HAS_LP_ROM
|
||||||
} ulp_lp_core_cfg_t;
|
} ulp_lp_core_cfg_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -59,7 +59,14 @@ esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg)
|
|||||||
|
|
||||||
#if ESP_ROM_HAS_LP_ROM
|
#if ESP_ROM_HAS_LP_ROM
|
||||||
/* If we have a LP ROM we boot from it, before jumping to the app code */
|
/* If we have a LP ROM we boot from it, before jumping to the app code */
|
||||||
lp_core_ll_set_boot_address(SOC_LP_ROM_LOW);
|
intptr_t boot_addr;
|
||||||
|
if (cfg->skip_lp_rom_boot) {
|
||||||
|
boot_addr = RTC_SLOW_MEM;
|
||||||
|
} else {
|
||||||
|
boot_addr = SOC_LP_ROM_LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
lp_core_ll_set_boot_address(boot_addr);
|
||||||
lp_core_ll_set_app_boot_address(RTC_SLOW_MEM);
|
lp_core_ll_set_app_boot_address(RTC_SLOW_MEM);
|
||||||
#endif //ESP_ROM_HAS_LP_ROM
|
#endif //ESP_ROM_HAS_LP_ROM
|
||||||
|
|
||||||
@@ -131,6 +138,6 @@ esp_err_t ulp_lp_core_load_binary(const uint8_t* program_binary, size_t program_
|
|||||||
void ulp_lp_core_stop(void)
|
void ulp_lp_core_stop(void)
|
||||||
{
|
{
|
||||||
/* Disable wake-up source and put lp core to sleep */
|
/* Disable wake-up source and put lp core to sleep */
|
||||||
REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN, 0);
|
lp_core_ll_set_wakeup_source(0);
|
||||||
REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_SLEEP_REQ, 1);
|
lp_core_ll_request_sleep();
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,7 @@
|
|||||||
#if CONFIG_IDF_TARGET_ESP32C6
|
#if CONFIG_IDF_TARGET_ESP32C6
|
||||||
#define LP_CORE_CPU_FREQUENCY_HZ 16000000
|
#define LP_CORE_CPU_FREQUENCY_HZ 16000000
|
||||||
#elif CONFIG_IDF_TARGET_ESP32P4
|
#elif CONFIG_IDF_TARGET_ESP32P4
|
||||||
#define LP_CORE_CPU_FREQUENCY_HZ 20000000
|
#define LP_CORE_CPU_FREQUENCY_HZ 16000000 // TRM says 20 MHz by default, but we tune it closer to 16 MHz
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static uint32_t lp_wakeup_cause = 0;
|
static uint32_t lp_wakeup_cause = 0;
|
||||||
@@ -108,7 +108,7 @@ void ulp_lp_core_delay_cycles(uint32_t cycles)
|
|||||||
|
|
||||||
void ulp_lp_core_halt(void)
|
void ulp_lp_core_halt(void)
|
||||||
{
|
{
|
||||||
REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_SLEEP_REQ, 1);
|
lp_core_ll_request_sleep();
|
||||||
|
|
||||||
while (1);
|
while (1);
|
||||||
}
|
}
|
||||||
@@ -116,8 +116,8 @@ void ulp_lp_core_halt(void)
|
|||||||
void ulp_lp_core_stop_lp_core(void)
|
void ulp_lp_core_stop_lp_core(void)
|
||||||
{
|
{
|
||||||
/* Disable wake-up source and put lp core to sleep */
|
/* Disable wake-up source and put lp core to sleep */
|
||||||
REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_WAKEUP_EN, 0);
|
lp_core_ll_set_wakeup_source(0);
|
||||||
REG_SET_FIELD(PMU_LP_CPU_PWR1_REG, PMU_LP_CPU_SLEEP_REQ, 1);
|
lp_core_ll_request_sleep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((noreturn)) abort(void)
|
void __attribute__((noreturn)) abort(void)
|
||||||
|
@@ -3,10 +3,6 @@
|
|||||||
components/ulp/test_apps/lp_core:
|
components/ulp/test_apps/lp_core:
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED != 1
|
- if: SOC_LP_CORE_SUPPORTED != 1
|
||||||
disable_test:
|
|
||||||
- if: IDF_TARGET in ["esp32p4"]
|
|
||||||
temporary: true
|
|
||||||
reason: not tested yet # TODO: IDF-8986
|
|
||||||
depends_components:
|
depends_components:
|
||||||
- ulp
|
- ulp
|
||||||
|
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include "esp_rom_caps.h"
|
||||||
#include "lp_core_test_app.h"
|
#include "lp_core_test_app.h"
|
||||||
#include "lp_core_test_app_counter.h"
|
#include "lp_core_test_app_counter.h"
|
||||||
#include "lp_core_test_app_set_timer_wakeup.h"
|
#include "lp_core_test_app_set_timer_wakeup.h"
|
||||||
@@ -215,6 +216,10 @@ TEST_CASE("LP Timer can wakeup lp core periodically", "[lp_core]")
|
|||||||
ulp_lp_core_cfg_t cfg = {
|
ulp_lp_core_cfg_t cfg = {
|
||||||
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
|
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
|
||||||
.lp_timer_sleep_duration_us = LP_TIMER_TEST_SLEEP_DURATION_US,
|
.lp_timer_sleep_duration_us = LP_TIMER_TEST_SLEEP_DURATION_US,
|
||||||
|
#if ESP_ROM_HAS_LP_ROM
|
||||||
|
/* ROM Boot takes quite a bit longer, which skews the numbers of wake-ups. skip rom boot to keep the calculation simple */
|
||||||
|
.skip_lp_rom_boot = true,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
load_and_start_lp_core_firmware(&cfg, lp_core_main_counter_bin_start, lp_core_main_counter_bin_end);
|
load_and_start_lp_core_firmware(&cfg, lp_core_main_counter_bin_start, lp_core_main_counter_bin_end);
|
||||||
@@ -273,6 +278,10 @@ TEST_CASE("LP core can schedule next wake-up time by itself", "[ulp]")
|
|||||||
/* Load ULP firmware and start the coprocessor */
|
/* Load ULP firmware and start the coprocessor */
|
||||||
ulp_lp_core_cfg_t cfg = {
|
ulp_lp_core_cfg_t cfg = {
|
||||||
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
|
.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER,
|
||||||
|
#if ESP_ROM_HAS_LP_ROM
|
||||||
|
/* ROM Boot takes quite a bit longer, which skews the numbers of wake-ups. skip rom boot to keep the calculation simple */
|
||||||
|
.skip_lp_rom_boot = true,
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
load_and_start_lp_core_firmware(&cfg, lp_core_main_set_timer_wakeup_bin_start, lp_core_main_set_timer_wakeup_bin_end);
|
load_and_start_lp_core_firmware(&cfg, lp_core_main_set_timer_wakeup_bin_start, lp_core_main_set_timer_wakeup_bin_end);
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
# SPDX-License-Identifier: CC0-1.0
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
from pytest_embedded import Dut
|
from pytest_embedded import Dut
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.esp32c6
|
@pytest.mark.esp32c6
|
||||||
|
@pytest.mark.esp32p4
|
||||||
@pytest.mark.generic
|
@pytest.mark.generic
|
||||||
def test_lp_core(dut: Dut) -> None:
|
def test_lp_core(dut: Dut) -> None:
|
||||||
dut.run_all_single_board_cases()
|
dut.run_all_single_board_cases()
|
||||||
|
Reference in New Issue
Block a user