2019-10-20 20:05:13 +02:00
|
|
|
// Basic Config
|
|
|
|
#include "globals.h"
|
|
|
|
#include "reset.h"
|
|
|
|
|
|
|
|
// Local logging tag
|
|
|
|
static const char TAG[] = __FILE__;
|
|
|
|
|
2020-12-09 10:15:12 +01:00
|
|
|
// Conversion factor for micro seconds to seconds
|
|
|
|
#define uS_TO_S_FACTOR 1000000ULL
|
|
|
|
|
2021-03-20 20:13:34 +01:00
|
|
|
// RTC_NOINIT_ATTR -> keep value after a software restart or system crash
|
|
|
|
RTC_NOINIT_ATTR runmode_t RTC_runmode;
|
2021-03-21 18:41:02 +01:00
|
|
|
RTC_NOINIT_ATTR uint32_t RTC_restarts;
|
2021-03-20 20:13:34 +01:00
|
|
|
|
|
|
|
// RTC_DATA_ATTR -> keep values after a wakeup from sleep
|
2020-12-10 15:10:28 +01:00
|
|
|
RTC_DATA_ATTR struct timeval RTC_sleep_start_time;
|
2020-12-21 22:11:41 +01:00
|
|
|
RTC_DATA_ATTR unsigned long long RTC_millis = 0;
|
2021-04-06 22:45:34 +02:00
|
|
|
RTC_DATA_ATTR time_t RTC_time = 0;
|
2021-03-20 20:13:34 +01:00
|
|
|
|
2020-12-10 15:10:28 +01:00
|
|
|
timeval sleep_stop_time;
|
2019-10-20 20:05:13 +02:00
|
|
|
|
2021-03-21 20:20:39 +01:00
|
|
|
void reset_rtc_vars(void) {
|
|
|
|
RTC_runmode = RUNMODE_POWERCYCLE;
|
|
|
|
RTC_restarts = 0;
|
|
|
|
}
|
|
|
|
|
2019-10-20 20:05:13 +02:00
|
|
|
void do_reset(bool warmstart) {
|
|
|
|
if (warmstart) {
|
2020-12-11 16:34:17 +01:00
|
|
|
ESP_LOGI(TAG, "restarting device (warmstart)");
|
2019-10-20 20:05:13 +02:00
|
|
|
} else {
|
|
|
|
#if (HAS_LORA)
|
2020-12-09 10:15:12 +01:00
|
|
|
if (RTC_runmode == RUNMODE_NORMAL) {
|
2019-10-20 20:05:13 +02:00
|
|
|
LMIC_shutdown();
|
2020-12-09 10:15:12 +01:00
|
|
|
}
|
2019-10-20 20:05:13 +02:00
|
|
|
#endif
|
|
|
|
RTC_runmode = RUNMODE_POWERCYCLE;
|
2020-12-11 16:34:17 +01:00
|
|
|
ESP_LOGI(TAG, "restarting device (coldstart)");
|
2019-10-20 20:05:13 +02:00
|
|
|
}
|
|
|
|
esp_restart();
|
|
|
|
}
|
|
|
|
|
2020-12-09 20:37:03 +01:00
|
|
|
void do_after_reset(void) {
|
2019-10-20 20:05:13 +02:00
|
|
|
|
2020-12-09 20:37:03 +01:00
|
|
|
struct timeval sleep_stop_time;
|
|
|
|
uint64_t sleep_time_ms;
|
2019-10-20 20:05:13 +02:00
|
|
|
|
2021-03-21 20:20:39 +01:00
|
|
|
// read (and initialize on first run) runtime settings from NVRAM
|
|
|
|
loadConfig();
|
|
|
|
|
2020-12-26 18:29:10 +01:00
|
|
|
switch (rtc_get_reset_reason(0)) {
|
2019-10-20 20:05:13 +02:00
|
|
|
|
2020-12-26 18:29:10 +01:00
|
|
|
case POWERON_RESET: // 0x01 Vbat power on reset
|
|
|
|
case RTCWDT_BROWN_OUT_RESET: // 0x0f Reset when the vdd voltage is not
|
|
|
|
// stable
|
2021-03-21 20:20:39 +01:00
|
|
|
reset_rtc_vars();
|
2020-12-26 18:29:10 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case SW_CPU_RESET: // 0x0c Software reset CPU
|
2021-03-21 18:41:02 +01:00
|
|
|
// keep previous set runmode (update / normal / maintenance)
|
2021-03-25 11:42:39 +01:00
|
|
|
RTC_restarts++;
|
2020-12-26 18:29:10 +01:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DEEPSLEEP_RESET: // 0x05 Deep Sleep reset digital core
|
2020-12-09 20:37:03 +01:00
|
|
|
// calculate time spent in deep sleep
|
|
|
|
gettimeofday(&sleep_stop_time, NULL);
|
|
|
|
sleep_time_ms =
|
|
|
|
(sleep_stop_time.tv_sec - RTC_sleep_start_time.tv_sec) * 1000 +
|
|
|
|
(sleep_stop_time.tv_usec - RTC_sleep_start_time.tv_usec) / 1000;
|
2020-12-19 12:27:07 +01:00
|
|
|
RTC_millis += sleep_time_ms; // increment system monotonic time
|
2021-04-06 22:45:34 +02:00
|
|
|
ESP_LOGI(TAG, "Time spent in deep sleep: %d ms", sleep_time_ms);
|
|
|
|
|
|
|
|
// set time
|
|
|
|
setMyTime(RTC_time + sleep_time_ms / 1000, sleep_time_ms % 1000, _set);
|
|
|
|
|
2020-12-26 20:45:10 +01:00
|
|
|
// set wakeup state, not if we have pending OTA update
|
|
|
|
if (RTC_runmode == RUNMODE_SLEEP)
|
|
|
|
RTC_runmode = RUNMODE_WAKEUP;
|
2019-10-20 20:05:13 +02:00
|
|
|
break;
|
|
|
|
|
2020-12-26 18:29:10 +01:00
|
|
|
case SW_RESET: // 0x03 Software reset digital core
|
|
|
|
case OWDT_RESET: // 0x04 Legacy watch dog reset digital core
|
|
|
|
case SDIO_RESET: // 0x06 Reset by SLC module, reset digital core
|
|
|
|
case TG0WDT_SYS_RESET: // 0x07 Timer Group0 Watch dog reset digital core
|
|
|
|
case TG1WDT_SYS_RESET: // 0x08 Timer Group1 Watch dog reset digital core
|
|
|
|
case RTCWDT_SYS_RESET: // 0x09 RTC Watch dog Reset digital core
|
|
|
|
case INTRUSION_RESET: // 0x0a Instrusion tested to reset CPU
|
|
|
|
case TGWDT_CPU_RESET: // 0x0b Time Group reset CPU
|
|
|
|
case RTCWDT_CPU_RESET: // 0x0d RTC Watch dog Reset CPU
|
|
|
|
case EXT_CPU_RESET: // 0x0e for APP CPU, reseted by PRO CPU
|
|
|
|
case RTCWDT_RTC_RESET: // 0x10 RTC Watch dog reset digital core and rtc mode
|
2019-10-20 20:05:13 +02:00
|
|
|
default:
|
2019-10-27 16:13:33 +01:00
|
|
|
RTC_runmode = RUNMODE_POWERCYCLE;
|
2021-03-25 11:42:39 +01:00
|
|
|
RTC_restarts++;
|
2019-10-20 20:05:13 +02:00
|
|
|
break;
|
2020-12-26 18:29:10 +01:00
|
|
|
}
|
2019-10-20 20:05:13 +02:00
|
|
|
}
|
|
|
|
|
2020-12-30 22:07:50 +01:00
|
|
|
void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
|
2020-12-10 15:10:28 +01:00
|
|
|
|
2020-12-28 18:31:31 +01:00
|
|
|
ESP_LOGI(TAG, "Preparing to sleep...");
|
2020-12-16 09:36:16 +01:00
|
|
|
|
2020-12-28 18:31:31 +01:00
|
|
|
RTC_runmode = RUNMODE_SLEEP;
|
2020-12-10 15:10:28 +01:00
|
|
|
int i;
|
|
|
|
|
2021-04-06 21:35:25 +02:00
|
|
|
// show message on display
|
|
|
|
#ifdef HAS_DISPLAY
|
|
|
|
dp_message("-GOING TO SLEEP-", 7, true);
|
|
|
|
#endif
|
|
|
|
|
2020-12-10 15:10:28 +01:00
|
|
|
// validate wake up pin, if we have
|
|
|
|
if (!GPIO_IS_VALID_GPIO(wakeup_gpio))
|
|
|
|
wakeup_gpio = GPIO_NUM_MAX;
|
2019-10-20 20:05:13 +02:00
|
|
|
|
2020-12-22 19:13:46 +01:00
|
|
|
// stop further enqueuing of senddata and MAC processing
|
2021-04-01 12:17:46 +02:00
|
|
|
libpax_counter_stop();
|
2020-12-22 19:13:46 +01:00
|
|
|
|
2020-12-26 20:45:10 +01:00
|
|
|
// switch off radio and other power consuming hardware
|
|
|
|
#if (HAS_SDS011)
|
2021-03-31 18:59:00 +02:00
|
|
|
sds011_sleep();
|
2020-12-26 20:45:10 +01:00
|
|
|
#endif
|
2020-12-21 19:35:21 +01:00
|
|
|
|
2020-12-10 15:10:28 +01:00
|
|
|
// wait a while (max 100 sec) to clear send queues
|
2020-12-09 10:15:12 +01:00
|
|
|
ESP_LOGI(TAG, "Waiting until send queues are empty...");
|
2020-12-28 18:31:31 +01:00
|
|
|
for (i = 100; i > 0; i--) {
|
2020-12-29 00:21:40 +01:00
|
|
|
if (allQueuesEmtpy())
|
2020-12-10 15:10:28 +01:00
|
|
|
break;
|
2020-12-29 00:21:40 +01:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
2020-12-10 15:10:28 +01:00
|
|
|
}
|
2019-10-20 20:05:13 +02:00
|
|
|
|
2021-04-06 21:35:25 +02:00
|
|
|
/// wait until LMIC is idle
|
2019-10-22 07:16:04 +02:00
|
|
|
#if (HAS_LORA)
|
2020-12-09 10:15:12 +01:00
|
|
|
ESP_LOGI(TAG, "Waiting until LMIC is idle...");
|
2020-12-28 18:31:31 +01:00
|
|
|
for (i = 100; i > 0; i--) {
|
2020-12-10 15:10:28 +01:00
|
|
|
if ((LMIC.opmode & OP_TXRXPEND) ||
|
|
|
|
os_queryTimeCriticalJobs(sec2osticks(wakeup_sec)))
|
2020-12-28 18:31:31 +01:00
|
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
2020-12-10 15:10:28 +01:00
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
2020-12-11 16:34:17 +01:00
|
|
|
#endif // (HAS_LORA)
|
2019-10-27 16:13:33 +01:00
|
|
|
|
2020-12-11 16:34:17 +01:00
|
|
|
// shutdown MQTT safely
|
|
|
|
#ifdef HAS_MQTT
|
2020-12-23 16:31:06 +01:00
|
|
|
mqtt_deinit();
|
2020-12-11 16:34:17 +01:00
|
|
|
#endif
|
|
|
|
|
|
|
|
// shutdown SPI safely
|
|
|
|
#ifdef HAS_SPI
|
2020-12-23 16:31:06 +01:00
|
|
|
spi_deinit();
|
2020-12-11 16:34:17 +01:00
|
|
|
#endif
|
|
|
|
|
2021-01-01 15:25:56 +01:00
|
|
|
// save LMIC state to RTC RAM
|
2020-12-11 16:34:17 +01:00
|
|
|
#if (HAS_LORA)
|
2020-12-09 10:15:12 +01:00
|
|
|
SaveLMICToRTC(wakeup_sec);
|
|
|
|
#endif // (HAS_LORA)
|
2019-10-27 16:13:33 +01:00
|
|
|
|
2020-12-11 16:34:17 +01:00
|
|
|
// set display to power save mode
|
2019-10-20 20:05:13 +02:00
|
|
|
#ifdef HAS_DISPLAY
|
2020-03-29 12:10:42 +02:00
|
|
|
dp_shutdown();
|
2019-10-20 20:05:13 +02:00
|
|
|
#endif
|
|
|
|
|
2020-12-26 18:29:10 +01:00
|
|
|
// reduce power if has PMU or VEXT
|
2019-10-20 20:05:13 +02:00
|
|
|
#ifdef HAS_PMU
|
|
|
|
AXP192_power(pmu_power_sleep);
|
2020-12-26 18:29:10 +01:00
|
|
|
#elif EXT_POWER_SW
|
|
|
|
digitalWrite(EXT_POWER_SW, EXT_POWER_OFF);
|
2019-10-20 20:05:13 +02:00
|
|
|
#endif
|
|
|
|
|
2021-04-06 14:30:57 +02:00
|
|
|
// halt interrupts accessing i2c bus
|
|
|
|
mask_user_IRQ();
|
|
|
|
|
2019-10-20 20:05:13 +02:00
|
|
|
// shutdown i2c bus
|
|
|
|
i2c_deinit();
|
|
|
|
|
2020-12-09 20:37:03 +01:00
|
|
|
// configure wakeup sources
|
|
|
|
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html
|
|
|
|
|
|
|
|
// set up RTC wakeup timer, if we have
|
|
|
|
if (wakeup_sec > 0) {
|
|
|
|
esp_sleep_enable_timer_wakeup(wakeup_sec * uS_TO_S_FACTOR);
|
|
|
|
}
|
|
|
|
|
|
|
|
// set wakeup gpio, if we have
|
|
|
|
if (wakeup_gpio != GPIO_NUM_MAX) {
|
|
|
|
rtc_gpio_isolate(wakeup_gpio); // minimize deep sleep current
|
|
|
|
esp_sleep_enable_ext1_wakeup(1ULL << wakeup_gpio, ESP_EXT1_WAKEUP_ALL_LOW);
|
|
|
|
}
|
|
|
|
|
2020-12-19 12:27:07 +01:00
|
|
|
// time stamp sleep start time and save system monotonic time. Deep sleep.
|
2020-12-09 20:37:03 +01:00
|
|
|
gettimeofday(&RTC_sleep_start_time, NULL);
|
2020-12-19 22:30:34 +01:00
|
|
|
RTC_millis += millis();
|
2021-04-06 22:45:34 +02:00
|
|
|
RTC_time = now();
|
2020-12-09 10:15:12 +01:00
|
|
|
ESP_LOGI(TAG, "Going to sleep, good bye.");
|
2019-10-20 20:05:13 +02:00
|
|
|
esp_deep_sleep_start();
|
2020-12-19 22:30:34 +01:00
|
|
|
}
|
|
|
|
|
2020-12-21 22:11:41 +01:00
|
|
|
unsigned long long uptime() { return (RTC_millis + millis()); }
|