ESP32-PaxCounter/src/reset.cpp

190 lines
4.9 KiB
C++
Raw Normal View History

// Basic Config
#include "globals.h"
#include "reset.h"
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;
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-03-20 20:13:34 +01:00
2020-12-10 15:10:28 +01:00
timeval sleep_stop_time;
void reset_rtc_vars(void) {
RTC_runmode = RUNMODE_POWERCYCLE;
RTC_restarts = 0;
}
void do_reset(bool warmstart) {
if (warmstart) {
2020-12-11 16:34:17 +01:00
ESP_LOGI(TAG, "restarting device (warmstart)");
} else {
#if (HAS_LORA)
2020-12-09 10:15:12 +01:00
if (RTC_runmode == RUNMODE_NORMAL) {
LMIC_shutdown();
2020-12-09 10:15:12 +01:00
}
#endif
2021-04-12 23:45:26 +02:00
reset_rtc_vars();
2020-12-11 16:34:17 +01:00
ESP_LOGI(TAG, "restarting device (coldstart)");
}
esp_restart();
}
void do_after_reset(void) {
struct timeval sleep_stop_time;
uint64_t sleep_time_ms;
// read (and initialize on first run) runtime settings from NVRAM
loadConfig();
2022-01-08 19:10:34 +01:00
// set time zone to user value from paxcounter.conf
#ifdef TIME_SYNC_TIMEZONE
setenv("TZ", TIME_SYNC_TIMEZONE, 1);
tzset();
ESP_LOGD(TAG, "Timezone set to %s", TIME_SYNC_TIMEZONE);
2022-01-08 19:10:34 +01:00
#endif
2020-12-26 18:29:10 +01:00
switch (rtc_get_reset_reason(0)) {
2022-08-19 18:18:47 +02:00
case RESET_REASON_CHIP_POWER_ON:
case RESET_REASON_SYS_BROWN_OUT:
reset_rtc_vars();
2020-12-26 18:29:10 +01:00
break;
2022-08-19 18:18:47 +02:00
case RESET_REASON_CPU0_SW:
// 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;
2022-08-19 18:18:47 +02:00
case RESET_REASON_CORE_DEEP_SLEEP:
// 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);
// do we have a valid time? -> set global variable
timeSource = timeIsValid(sleep_stop_time.tv_sec) ? _set : _unsynced;
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;
break;
default:
2019-10-27 16:13:33 +01:00
RTC_runmode = RUNMODE_POWERCYCLE;
2021-03-25 11:42:39 +01:00
RTC_restarts++;
break;
2020-12-26 18:29:10 +01:00
}
}
2023-03-08 15:53:30 +01:00
void enter_deepsleep(uint32_t wakeup_sec, gpio_num_t wakeup_gpio) {
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
// validate wake up pin, if we have
if (!GPIO_IS_VALID_GPIO(wakeup_gpio))
wakeup_gpio = GPIO_NUM_MAX;
2022-08-18 12:11:47 +02:00
// stop further enqueuing of senddata and MAC processing
libpax_counter_stop();
2020-12-22 19:13:46 +01:00
2022-08-18 12:11:47 +02:00
// switch off any power consuming hardware
2020-12-26 20:45:10 +01:00
#if (HAS_SDS011)
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...");
2022-11-20 17:17:07 +01:00
for (int 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
}
2022-11-20 17:17:07 +01:00
// wait up to 100secs until LMIC is idle
#if (HAS_LORA)
2022-11-20 17:17:07 +01:00
lora_waitforidle(100);
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
mqtt_deinit();
2020-12-11 16:34:17 +01:00
#endif
// shutdown SPI safely
#ifdef HAS_SPI
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
#ifdef HAS_DISPLAY
dp_shutdown();
#endif
2020-12-26 18:29:10 +01:00
// reduce power if has PMU or VEXT
#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);
#endif
2021-04-06 14:30:57 +02:00
// halt interrupts accessing i2c bus
mask_user_IRQ();
// shutdown i2c bus
i2c_deinit();
// configure wakeup sources
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html
2023-03-08 15:53:30 +01:00
#ifdef TIME_SYNC_INTERVAL
#if (SYNCWAKEUP) && (SLEEPCYCLE)
time_t now;
uint16_t shift_sec;
time(&now);
shift_sec = 3600 - (now + wakeup_sec) %
3600; // 1..3600 remaining seconds between planned
// wakeup time and following top-of-hour
if (shift_sec <= SYNCWAKEUP) // delay wakeup to catch top-of-hour
wakeup_sec += shift_sec;
else if (shift_sec >= (3600 - SYNCWAKEUP))
wakeup_sec = 3600 - shift_sec; // shorten wake up to next top-of-hour
#endif
#endif
// 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.
gettimeofday(&RTC_sleep_start_time, NULL);
2022-07-17 15:52:52 +02:00
RTC_millis += esp_timer_get_time() / 1000;
2020-12-09 10:15:12 +01:00
ESP_LOGI(TAG, "Going to sleep, good bye.");
// flush & close sd card, if we have
#if (HAS_SDCARD)
sdcard_close();
#endif
esp_deep_sleep_start();
2020-12-19 22:30:34 +01:00
}
2022-08-16 13:27:48 +02:00
unsigned long long uptime() {
return (RTC_millis + esp_timer_get_time() / 1000);
}