Enter deep sleep in custom start_cpu0

kindaTall
Posts: 6
Joined: Mon Jan 20, 2020 4:21 pm

Enter deep sleep in custom start_cpu0

Postby kindaTall » 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:

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);
	}
}


Who is online

Users browsing this forum: No registered users and 100 guests