mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
fix(ulp): fixed lp-core not booting during sleep
LP core was unable to boot when system was in deepsleep. This was due to lp uart init in LP rom using XTAL as clk source, which is normally powered down during sleep. This would cause lp uart to get stuck while printing ROM output, and the app would never boot. Also fixed wrong wakeup cause used by HP core for ULP wake up
This commit is contained in:
parent
eded4eabf6
commit
1fa59c442b
@ -11,7 +11,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define PMU_SDIO_WAKEUP_EN BIT(0)
|
#define PMU_SDIO_WAKEUP_EN BIT(0)
|
||||||
#define PMU_SW_WAKEUP_HP_EN BIT(1)
|
#define PMU_LP_CORE_WAKEUP_EN BIT(1)
|
||||||
#define PMU_GPIO_WAKEUP_EN BIT(2)
|
#define PMU_GPIO_WAKEUP_EN BIT(2)
|
||||||
#define PMU_USB_WAKEUP_EN BIT(3)
|
#define PMU_USB_WAKEUP_EN BIT(3)
|
||||||
#define PMU_UART4_WAKEUP_EN BIT(4)
|
#define PMU_UART4_WAKEUP_EN BIT(4)
|
||||||
@ -26,7 +26,7 @@ extern "C" {
|
|||||||
#define PMU_LP_TIMER_WAKEUP_EN BIT(13)
|
#define PMU_LP_TIMER_WAKEUP_EN BIT(13)
|
||||||
#define PMU_BOD_WAKEUP_EN BIT(14)
|
#define PMU_BOD_WAKEUP_EN BIT(14)
|
||||||
#define PMU_VDDBAT_UNDERVOLT_WAKEUP_EN BIT(15)
|
#define PMU_VDDBAT_UNDERVOLT_WAKEUP_EN BIT(15)
|
||||||
#define PMU_LP_CORE_WAKEUP_EN BIT(16)
|
#define PMU_LP_CORE_TRAP_WAKEUP_EN BIT(16)
|
||||||
#define PMU_ETM_WAKEUP_EN BIT(17)
|
#define PMU_ETM_WAKEUP_EN BIT(17)
|
||||||
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
|
#define PMU_LP_TIMER1_WAKEUP_EN BIT(18)
|
||||||
#define PMU_LP_I2S_WAKEUP_EN BIT(19)
|
#define PMU_LP_I2S_WAKEUP_EN BIT(19)
|
||||||
|
@ -50,6 +50,9 @@ extern "C" {
|
|||||||
* RTC_CNTL_STORE5_REG APB bus frequency
|
* RTC_CNTL_STORE5_REG APB bus frequency
|
||||||
* RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY
|
* RTC_CNTL_STORE6_REG FAST_RTC_MEMORY_ENTRY
|
||||||
* RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC
|
* RTC_CNTL_STORE7_REG FAST_RTC_MEMORY_CRC
|
||||||
|
* LP_SYS_LP_STORE8_REG sleep mode and wake stub address
|
||||||
|
* LP_SYS_LP_STORE9_REG LP_UART_INIT_CTRL
|
||||||
|
* LP_SYS_LP_STORE10_REG LP_ROM_LOG_CTRL
|
||||||
*************************************************************************************
|
*************************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -75,6 +78,10 @@ extern "C" {
|
|||||||
#define RTC_SLEEP_WAKE_STUB_ADDR_REG LP_SYSTEM_REG_LP_STORE8_REG
|
#define RTC_SLEEP_WAKE_STUB_ADDR_REG LP_SYSTEM_REG_LP_STORE8_REG
|
||||||
#define RTC_SLEEP_MODE_REG LP_SYSTEM_REG_LP_STORE8_REG
|
#define RTC_SLEEP_MODE_REG LP_SYSTEM_REG_LP_STORE8_REG
|
||||||
|
|
||||||
|
// lp uart init status, 0 - need init, 1 - no init.
|
||||||
|
#define LP_UART_INIT_CTRL_REG LP_SYSTEM_REG_LP_STORE9_REG
|
||||||
|
#define ROM_LOG_CTRL_REG LP_SYSTEM_REG_LP_STORE10_REG
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AWAKE = 0, //<CPU ON
|
AWAKE = 0, //<CPU ON
|
||||||
LIGHT_SLEEP = BIT0, //CPU waiti, PLL ON. We don't need explicitly set this mode.
|
LIGHT_SLEEP = BIT0, //CPU waiti, PLL ON. We don't need explicitly set this mode.
|
||||||
|
@ -18,6 +18,10 @@
|
|||||||
#include "ulp_lp_core_lp_timer_shared.h"
|
#include "ulp_lp_core_lp_timer_shared.h"
|
||||||
#include "hal/lp_core_ll.h"
|
#include "hal/lp_core_ll.h"
|
||||||
|
|
||||||
|
#if CONFIG_IDF_TARGET_ESP32P4
|
||||||
|
#include "esp32p4/rom/rtc.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5
|
#if CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5
|
||||||
#define LP_CORE_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
|
#define LP_CORE_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||||
#else
|
#else
|
||||||
@ -67,6 +71,12 @@ esp_err_t ulp_lp_core_run(ulp_lp_core_cfg_t* cfg)
|
|||||||
boot_addr = (intptr_t)(&_rtc_ulp_memory_start);
|
boot_addr = (intptr_t)(&_rtc_ulp_memory_start);
|
||||||
} else {
|
} else {
|
||||||
boot_addr = SOC_LP_ROM_LOW;
|
boot_addr = SOC_LP_ROM_LOW;
|
||||||
|
/* Disable UART init in ROM, it defaults to XTAL clk src
|
||||||
|
* which is not powered on during deep sleep
|
||||||
|
* This will cause the ROM code to get stuck during UART output
|
||||||
|
* if used
|
||||||
|
*/
|
||||||
|
REG_SET_BIT(LP_UART_INIT_CTRL_REG, 1 << 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
lp_core_ll_set_boot_address(boot_addr);
|
lp_core_ll_set_boot_address(boot_addr);
|
||||||
|
@ -29,6 +29,8 @@ void lp_core_printf(const char* format, ...);
|
|||||||
*
|
*
|
||||||
* @note This function must be called before printing anything when the LP core boots from LP ROM but does not install
|
* @note This function must be called before printing anything when the LP core boots from LP ROM but does not install
|
||||||
* putc handler. This is possible when the LP ROM is instructed so by setting bit#1 in the LP_SYSTEM_REG_LP_STORE9_REG register.
|
* putc handler. This is possible when the LP ROM is instructed so by setting bit#1 in the LP_SYSTEM_REG_LP_STORE9_REG register.
|
||||||
|
* Disabling ROM UART init is default behavior in IDF, since the clock configured by the ROM code for UART (XTAL) is normally
|
||||||
|
* powered down during sleep.
|
||||||
*/
|
*/
|
||||||
extern void ets_install_uart_printf(void);
|
extern void ets_install_uart_printf(void);
|
||||||
void (*lp_core_install_uart_printf)(void) = ets_install_uart_printf;
|
void (*lp_core_install_uart_printf)(void) = ets_install_uart_printf;
|
||||||
|
@ -121,7 +121,7 @@ TEST_CASE("Test LP core delay", "[lp_core]")
|
|||||||
#define LP_TIMER_TEST_DURATION_S (5)
|
#define LP_TIMER_TEST_DURATION_S (5)
|
||||||
#define LP_TIMER_TEST_SLEEP_DURATION_US (20000)
|
#define LP_TIMER_TEST_SLEEP_DURATION_US (20000)
|
||||||
|
|
||||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4, ESP32C5)
|
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5)
|
||||||
|
|
||||||
static void do_ulp_wakeup_deepsleep(lp_core_test_commands_t ulp_cmd)
|
static void do_ulp_wakeup_deepsleep(lp_core_test_commands_t ulp_cmd)
|
||||||
{
|
{
|
||||||
@ -177,6 +177,10 @@ static void do_ulp_wakeup_with_lp_timer_deepsleep(void)
|
|||||||
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);
|
||||||
@ -212,7 +216,7 @@ TEST_CASE_MULTIPLE_STAGES("LP Timer can wakeup lp core periodically during deep
|
|||||||
do_ulp_wakeup_with_lp_timer_deepsleep,
|
do_ulp_wakeup_with_lp_timer_deepsleep,
|
||||||
check_reset_reason_and_sleep_duration);
|
check_reset_reason_and_sleep_duration);
|
||||||
|
|
||||||
#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32P4, ESP32C5)
|
#endif //#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C5)
|
||||||
|
|
||||||
TEST_CASE("LP Timer can wakeup lp core periodically", "[lp_core]")
|
TEST_CASE("LP Timer can wakeup lp core periodically", "[lp_core]")
|
||||||
{
|
{
|
||||||
|
@ -165,9 +165,9 @@ To enhance the capabilities of the ULP LP-Core coprocessor, it has access to per
|
|||||||
ULP LP-Core ROM
|
ULP LP-Core ROM
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
The ULP LP-Core ROM is a small pre-built piece of code located in LP-ROM, which is not modifiable by users. Similar to the bootloader ROM code ran by the main CPU, this code is executed when the ULP LP-Core coprocessor is started. The ROM code initializes the ULP LP-Core coprocessor and then jumps to the user program. The ROM code is responsible for initializing the LP UART and printing boot messages.
|
The ULP LP-Core ROM is a small pre-built piece of code located in LP-ROM, which is not modifiable by users. Similar to the bootloader ROM code ran by the main CPU, this code is executed when the ULP LP-Core coprocessor is started. The ROM code initializes the ULP LP-Core coprocessor and then jumps to the user program. The ROM code also prints boot messages if the LP UART has been initialized.
|
||||||
|
|
||||||
The ROM code is not executed if :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` is set to true. This is useful when you need the ULP to wake-up as quickly as possible and the extra overhead of initializing UART and printing is unwanted.
|
The ROM code is not executed if :cpp:member:`ulp_lp_core_cfg_t::skip_lp_rom_boot` is set to true. This is useful when you need the ULP to wake-up as quickly as possible and the extra overhead of initializing and printing is unwanted.
|
||||||
|
|
||||||
In addition to the boot-up code mentioned above the ROM code also provides the following functions and interfaces:
|
In addition to the boot-up code mentioned above the ROM code also provides the following functions and interfaces:
|
||||||
|
|
||||||
|
@ -261,10 +261,6 @@ examples/system/task_watchdog:
|
|||||||
examples/system/ulp/lp_core/gpio:
|
examples/system/ulp/lp_core/gpio:
|
||||||
enable:
|
enable:
|
||||||
- if: SOC_LP_CORE_SUPPORTED == 1
|
- if: SOC_LP_CORE_SUPPORTED == 1
|
||||||
disable:
|
|
||||||
- if: IDF_TARGET == "esp32p4"
|
|
||||||
temporary: true
|
|
||||||
reason: target esp32p4 is not supported yet, TODO IDF-7536
|
|
||||||
depends_components:
|
depends_components:
|
||||||
- ulp
|
- ulp
|
||||||
|
|
||||||
@ -281,18 +277,12 @@ examples/system/ulp/lp_core/lp_i2c:
|
|||||||
examples/system/ulp/lp_core/lp_uart/lp_uart_echo:
|
examples/system/ulp/lp_core/lp_uart/lp_uart_echo:
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_ULP_LP_UART_SUPPORTED != 1
|
- if: SOC_ULP_LP_UART_SUPPORTED != 1
|
||||||
- if: IDF_TARGET == "esp32p4"
|
|
||||||
temporary: true
|
|
||||||
reason: target esp32p4 is not supported yet TODO IDF-9407
|
|
||||||
depends_components:
|
depends_components:
|
||||||
- ulp
|
- ulp
|
||||||
|
|
||||||
examples/system/ulp/lp_core/lp_uart/lp_uart_print:
|
examples/system/ulp/lp_core/lp_uart/lp_uart_print:
|
||||||
disable:
|
disable:
|
||||||
- if: SOC_ULP_LP_UART_SUPPORTED != 1
|
- if: SOC_ULP_LP_UART_SUPPORTED != 1
|
||||||
- if: IDF_TARGET == "esp32p4"
|
|
||||||
temporary: true
|
|
||||||
reason: target esp32p4 is not supported yet TODO IDF-9407
|
|
||||||
depends_components:
|
depends_components:
|
||||||
- ulp
|
- ulp
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C6 |
|
| Supported Targets | ESP32-C6 | ESP32-P4 |
|
||||||
| ----------------- | -------- |
|
| ----------------- | -------- | -------- |
|
||||||
|
|
||||||
# LP Core simple example with GPIO Polling:
|
# LP Core simple example with GPIO Polling:
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C6 |
|
| Supported Targets | ESP32-C6 | ESP32-P4 |
|
||||||
| ----------------- | -------- |
|
| ----------------- | -------- | -------- |
|
||||||
|
|
||||||
# LP UART Echo Example
|
# LP UART Echo Example
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
| Supported Targets | ESP32-C6 |
|
| Supported Targets | ESP32-C6 | ESP32-P4 |
|
||||||
| ----------------- | -------- |
|
| ----------------- | -------- | -------- |
|
||||||
|
|
||||||
# LP UART Print Example
|
# LP UART Print Example
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ static bool ulp_is_running(uint32_t *counter_variable)
|
|||||||
uint32_t start_cnt = *counter_variable;
|
uint32_t start_cnt = *counter_variable;
|
||||||
|
|
||||||
/* Wait a few ULP wakeup cycles to ensure ULP has run */
|
/* Wait a few ULP wakeup cycles to ensure ULP has run */
|
||||||
vTaskDelay((5 * ULP_SLEEP_DURATION_US / 1000) / portTICK_PERIOD_MS);
|
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
uint32_t end_cnt = *counter_variable;
|
uint32_t end_cnt = *counter_variable;
|
||||||
printf("start run count: %" PRIu32 ", end run count %" PRIu32 "\n", start_cnt, end_cnt);
|
printf("start run count: %" PRIu32 ", end run count %" PRIu32 "\n", start_cnt, end_cnt);
|
||||||
|
Loading…
Reference in New Issue
Block a user