Enter deep sleep in custom start_cpu0
Posted: Thu Jul 09, 2020 6:23 pm
Hello there fellow esp-enthusiats,
I am working on a project, where the esp in normal operation is powered by a power source. If the power source disconnects, a battery supplies the voltage. In order to not drain the batteries, the esp is supposed to enter deep sleep mode. This all works fine.
But after a reset, if powered by battery I want to enter deepsleep ASAP. Waiting for start_cpu0 and start_cpu1 adds about about 300ms.
My idea: check power source in a custom start_cpu0, if battery enter deep sleep, else run start_cpu0_default().
The code compiles, but the chip keeps waking up with "ESP_SLEEP_WAKEUP_UNDEFINED".
The same code seems to work fine, if i push the deep_sleep start into app_main.
I am not getting any error messages.
Is there a way to enter deepsleep during start_cpu0, or do I just have to live with the added 300ms for cpu start up time?
For reference the condensed code below:
I am working on a project, where the esp in normal operation is powered by a power source. If the power source disconnects, a battery supplies the voltage. In order to not drain the batteries, the esp is supposed to enter deep sleep mode. This all works fine.
But after a reset, if powered by battery I want to enter deepsleep ASAP. Waiting for start_cpu0 and start_cpu1 adds about about 300ms.
My idea: check power source in a custom start_cpu0, if battery enter deep sleep, else run start_cpu0_default().
The code compiles, but the chip keeps waking up with "ESP_SLEEP_WAKEUP_UNDEFINED".
The same code seems to work fine, if i push the deep_sleep start into app_main.
I am not getting any error messages.
Is there a way to enter deepsleep during start_cpu0, or do I just have to live with the added 300ms for cpu start up time?
For reference the condensed code below:
Code: Select all
#include <stdio.h>
#include "sdkconfig.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_sleep.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define DEEPSLEEP_DURING_STARTCPU // whether to evoke go_to_sleep during cpu_start0 or app_main
void start_cpu0_default(void);
static const char * TAG = "cstm_cpu_start";
#define GPIO_WAKEUP 35
#define WAKE_UP_LEVEL 1 // if level of GPIO_WAKEUP == WAKE_UP_LEVEL chip should be running, else sleeping
#define WAKE_UP_LEVEL_STR "1"
/// @brief check level of GPIO_WAKEUP == WAKE_UP_LEVEL, if so run, else go to sleep
void go_to_sleep(){
rtc_gpio_init(GPIO_WAKEUP);
rtc_gpio_set_direction(GPIO_WAKEUP, RTC_GPIO_MODE_INPUT_ONLY);
int32_t level = rtc_gpio_get_level(GPIO_WAKEUP);
if(level==0)
ESP_EARLY_LOGI(TAG, "Level of gpio_wakeup_pin: 0, wake_up_level="WAKE_UP_LEVEL_STR);
else
ESP_EARLY_LOGI(TAG, "Level of gpio_wakeup_pin: 1, wake_up_level="WAKE_UP_LEVEL_STR);
// if level isn't wakeup level, go back to sleep (possible sources e.g. brown out reset)
if(WAKE_UP_LEVEL != level){
ESP_EARLY_LOGI(TAG, "Erroneous start, entering deep sleep.");
esp_sleep_source_t cause = esp_sleep_get_wakeup_cause();
switch(cause){
case ESP_SLEEP_WAKEUP_UNDEFINED:
ESP_EARLY_LOGI(TAG, "UNDEF");
break;
case ESP_SLEEP_WAKEUP_EXT1: //!< Wakeup caused by external signal using RTC_CNTL
ESP_EARLY_LOGI(TAG, "EXT1");
break;
default:
ESP_EARLY_LOGI(TAG, "Unexpected wakeup reason");
break;
}
// Isolate all rtc pins to prevent power leaking
gpio_num_t rtc_pins[] = {36, 37, 38, 39, 34, 35, 32, 33, 25, 26, 27, 14, 12, 13, 15, 2, 0, 4};
for(int i = 0; i < 18; i++){
if (rtc_pins[i] != GPIO_WAKEUP){
rtc_gpio_isolate(rtc_pins[i]);
}
}
// set sleep properties
esp_err_t err[4];
// RTC IO, sensors and ULP co-processor
err[0] = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF);
// RTC slow memory
err[1] = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_OFF);
// RTC fast memory
err[2] = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
// XTAL oscillator
err[3] = esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_OFF);
for (int i = 0; i < 4; i++){
if(ESP_OK != err[i]){
ESP_EARLY_LOGE(TAG, "Failed setting esp_sleep_pd_config arg %i.", i);
}
}
// set wake up source
esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
const uint64_t ext_wakeup_pin_mask = 1ULL << GPIO_WAKEUP;
#if WAKE_UP_LEVEL == 1
esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_mask, ESP_EXT1_WAKEUP_ANY_HIGH);
#else
esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_mask, ESP_EXT1_WAKEUP_ALL_LOW);
#endif
// enter deep sleep
ESP_EARLY_LOGI(TAG, "Entering deep sleep.");
ets_delay_us(1e6); // will delete as soon as it works, just stops your console from being flooded :)
esp_deep_sleep_start();
}
}
/// @brief replaces default start_cpu0, checks if module should be sleeping, if not runs start_cpu0_default()
void IRAM_ATTR start_cpu0(void){
ESP_EARLY_LOGI(TAG, "Running custom start_cpu0 routine.");
#ifdef DEEPSLEEP_DURING_STARTCPU
go_to_sleep();
#endif
ESP_EARLY_LOGI(TAG, "Wake up, running regular start procedure");
start_cpu0_default();
}
void app_main(void){
#ifndef DEEPSLEEP_DURING_STARTCPU
go_to_sleep();
#endif
ESP_LOGI(TAG, "Wakeup occured, running app.");
while(1){
//rest of the app would go here
vTaskDelay(portMAX_DELAY);
}
}