added new reset logic; deep sleep fixes
This commit is contained in:
parent
f3b3838e09
commit
bc034b1a67
@ -351,10 +351,11 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||
|
||||
0x09 reset functions (send this command with confirmed ack only to avoid boot loops!)
|
||||
|
||||
0 = restart device
|
||||
0 = restart device (coldstart)
|
||||
1 = reset MAC counter to zero
|
||||
2 = reset device to factory settings
|
||||
3 = flush send queues
|
||||
4 = restart device (warmstart)
|
||||
9 = reboot device to OTA update via Wifi mode
|
||||
|
||||
0x0A set LoRaWAN payload send cycle
|
||||
|
@ -51,10 +51,12 @@
|
||||
|
||||
enum sendprio_t { prio_low, prio_normal, prio_high };
|
||||
enum timesource_t { _gps, _rtc, _lora, _unsynced };
|
||||
|
||||
enum runmode_t {
|
||||
RUNMODE_POWERCYCLE = 0,
|
||||
RUNMODE_NORMAL,
|
||||
RUNMODE_UPDATE,
|
||||
RUNMODE_WAKEUP
|
||||
RUNMODE_WAKEUP,
|
||||
RUNMODE_UPDATE
|
||||
};
|
||||
|
||||
// Struct holding devices's runtime configuration
|
||||
@ -125,6 +127,7 @@ extern TaskHandle_t irqHandlerTask, ClockTask;
|
||||
extern TimerHandle_t WifiChanTimer;
|
||||
extern Timezone myTZ;
|
||||
extern time_t userUTCTime;
|
||||
extern RTC_DATA_ATTR runmode_t RTC_runmode;
|
||||
|
||||
// application includes
|
||||
#include "led.h"
|
||||
|
@ -22,7 +22,9 @@
|
||||
#endif
|
||||
|
||||
extern TaskHandle_t lmicTask, lorasendTask;
|
||||
extern RTC_DATA_ATTR int RTCseqnoUp, RTCseqnoDn;
|
||||
extern RTC_NOINIT_ATTR u4_t RTCnetid, RTCdevaddr;
|
||||
extern RTC_NOINIT_ATTR u1_t RTCnwkKey[16], RTCartKey[16];
|
||||
extern RTC_NOINIT_ATTR int RTCseqnoUp, RTCseqnoDn;
|
||||
|
||||
// table of LORAWAN MAC commands
|
||||
typedef struct {
|
||||
@ -31,7 +33,7 @@ typedef struct {
|
||||
const uint8_t params;
|
||||
} mac_t;
|
||||
|
||||
esp_err_t lora_stack_init(bool joined = false);
|
||||
esp_err_t lora_stack_init(bool do_join);
|
||||
void lora_setupForNetwork(bool preJoin);
|
||||
void lmictask(void *pvParameters);
|
||||
void gen_lora_deveui(uint8_t *pdeveui);
|
||||
@ -44,10 +46,10 @@ void showLoraKeys(void);
|
||||
void lora_send(void *pvParameters);
|
||||
void lora_enqueuedata(MessageBuffer_t *message);
|
||||
void lora_queuereset(void);
|
||||
static void IRAM_ATTR myEventCallback(void *pUserData, ev_t ev);
|
||||
static void IRAM_ATTR myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
|
||||
size_t nMsg);
|
||||
static void IRAM_ATTR myTxCallback(void *pUserData, int fSuccess);
|
||||
static void IRAM_ATTR myEventCallback(void *pUserData, ev_t ev);
|
||||
static void IRAM_ATTR myRxCallback(void *pUserData, uint8_t port,
|
||||
const uint8_t *pMsg, size_t nMsg);
|
||||
static void IRAM_ATTR myTxCallback(void *pUserData, int fSuccess);
|
||||
void mac_decode(const uint8_t cmd[], const uint8_t cmdlen, const mac_t table[],
|
||||
const uint8_t tablesize);
|
||||
uint8_t getBattLevel(void);
|
||||
@ -57,7 +59,7 @@ const char *getCrName(rps_t rps);
|
||||
|
||||
#if (TIME_SYNC_LORAWAN)
|
||||
static void user_request_network_time_callback(void *pVoidUserUTCTime,
|
||||
int flagSuccess);
|
||||
int flagSuccess);
|
||||
#endif
|
||||
|
||||
#endif
|
@ -7,7 +7,7 @@
|
||||
#include <esp_coexist.h> // needed for showing coex sw version
|
||||
|
||||
#include "globals.h"
|
||||
#include "power.h"
|
||||
#include "reset.h"
|
||||
#include "i2c.h"
|
||||
#include "blescan.h"
|
||||
#include "wifiscan.h"
|
||||
@ -16,7 +16,6 @@
|
||||
#include "beacon_array.h"
|
||||
#include "ota.h"
|
||||
#include "irqhandler.h"
|
||||
#include "led.h"
|
||||
#include "spislave.h"
|
||||
|
||||
#if (HAS_LORA)
|
||||
|
@ -3,15 +3,12 @@
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <driver/adc.h>
|
||||
#include <driver/rtc_io.h>
|
||||
#include <esp_adc_cal.h>
|
||||
#include "i2c.h"
|
||||
|
||||
#define DEFAULT_VREF 1100 // tbd: use adc2_vref_to_gpio() for better estimate
|
||||
#define NO_OF_SAMPLES 64 // we do some multisampling to get better values
|
||||
|
||||
extern RTC_DATA_ATTR runmode_t RTC_runmode;
|
||||
|
||||
uint16_t read_voltage(void);
|
||||
void calibrate_voltage(void);
|
||||
bool batt_sufficient(void);
|
||||
@ -19,13 +16,16 @@ void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio);
|
||||
int64_t exit_deepsleep(void);
|
||||
|
||||
#ifdef HAS_PMU
|
||||
|
||||
#include <axp20x.h>
|
||||
enum pmu_power_t { pmu_power_on, pmu_power_off, pmu_power_sleep };
|
||||
void AXP192_powerevent_IRQ(void);
|
||||
void AXP192_power(bool on);
|
||||
void AXP192_power(pmu_power_t powerlevel);
|
||||
void AXP192_init(void);
|
||||
void AXP192_showstatus(void);
|
||||
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
|
||||
#endif // HAS_PMU
|
||||
|
||||
#endif
|
@ -24,6 +24,6 @@ typedef struct {
|
||||
} cmd_t;
|
||||
|
||||
void rcommand(const uint8_t cmd[], const uint8_t cmdlength);
|
||||
void do_reset();
|
||||
void do_reset(bool warmstart);
|
||||
|
||||
#endif
|
||||
|
13
include/reset.h
Normal file
13
include/reset.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef _RESET_H
|
||||
#define _RESET_H
|
||||
|
||||
#include <driver/rtc_io.h>
|
||||
#include <rom/rtc.h>
|
||||
#include "i2c.h"
|
||||
|
||||
void do_reset(bool warmstart);
|
||||
void do_after_reset(int reason);
|
||||
void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio);
|
||||
int64_t exit_deepsleep(void);
|
||||
|
||||
#endif // _RESET_H
|
@ -43,7 +43,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
|
||||
|
||||
[common]
|
||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||
release_version = 1.9.64
|
||||
release_version = 1.9.7
|
||||
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
|
||||
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
|
||||
debug_level = 4
|
||||
|
@ -20,8 +20,15 @@ void doHousekeeping() {
|
||||
uptime();
|
||||
|
||||
// check if update mode trigger switch was set
|
||||
if (RTC_runmode == RUNMODE_UPDATE)
|
||||
do_reset();
|
||||
if (RTC_runmode == RUNMODE_UPDATE) {
|
||||
// check battery status if we can before doing ota
|
||||
if (batt_sufficient())
|
||||
do_reset(true); // warmstart to runmode update
|
||||
else {
|
||||
ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage);
|
||||
RTC_runmode == RUNMODE_NORMAL; // keep running in normal mode
|
||||
}
|
||||
}
|
||||
|
||||
// task storage debugging //
|
||||
ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d",
|
||||
@ -87,7 +94,7 @@ void doHousekeeping() {
|
||||
get_salt(); // get new salt for salting hashes
|
||||
|
||||
if (ESP.getMinFreeHeap() <= MEM_LOW) // check again
|
||||
do_reset(); // memory leak, reset device
|
||||
do_reset(true); // memory leak, reset device
|
||||
}
|
||||
|
||||
// check free PSRAM memory
|
||||
@ -98,7 +105,7 @@ void doHousekeeping() {
|
||||
get_salt(); // get new salt for salting hashes
|
||||
|
||||
if (ESP.getMinFreePsram() <= MEM_LOW) // check again
|
||||
do_reset(); // memory leak, reset device
|
||||
do_reset(true); // memory leak, reset device
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -18,9 +18,10 @@ static const char TAG[] = "lora";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
RTC_DATA_ATTR u4_t RTCnetid, RTCdevaddr;
|
||||
RTC_DATA_ATTR u1_t RTCnwkKey[16], RTCartKey[16];
|
||||
RTC_DATA_ATTR int RTCseqnoUp, RTCseqnoDn;
|
||||
// variable keep its values after restart or wakeup from sleep
|
||||
RTC_NOINIT_ATTR u4_t RTCnetid, RTCdevaddr;
|
||||
RTC_NOINIT_ATTR u1_t RTCnwkKey[16], RTCartKey[16];
|
||||
RTC_NOINIT_ATTR int RTCseqnoUp, RTCseqnoDn;
|
||||
|
||||
QueueHandle_t LoraSendQueue;
|
||||
TaskHandle_t lmicTask = NULL, lorasendTask = NULL;
|
||||
@ -107,10 +108,6 @@ void lora_setupForNetwork(bool preJoin) {
|
||||
getSfName(updr2rps(LMIC.datarate)),
|
||||
getBwName(updr2rps(LMIC.datarate)),
|
||||
getCrName(updr2rps(LMIC.datarate)));
|
||||
// store keys and counters in RTC memory
|
||||
LMIC_getSessionKeys(&RTCnetid, &RTCdevaddr, RTCnwkKey, RTCartKey);
|
||||
RTCseqnoUp = LMIC.seqnoUp;
|
||||
RTCseqnoDn = LMIC.seqnoDn;
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +292,7 @@ void lora_send(void *pvParameters) {
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t lora_stack_init(bool joined) {
|
||||
esp_err_t lora_stack_init(bool do_join) {
|
||||
assert(SEND_QUEUE_SIZE);
|
||||
LoraSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t));
|
||||
if (LoraSendQueue == 0) {
|
||||
@ -315,8 +312,10 @@ esp_err_t lora_stack_init(bool joined) {
|
||||
&lmicTask, // task handle
|
||||
1); // CPU core
|
||||
|
||||
// start join if we did not wakeup from sleep, else continue session
|
||||
if (!joined) {
|
||||
// Start join procedure if not already joined,
|
||||
// lora_setupForNetwork(true) is called by eventhandler when joined
|
||||
// else continue current session
|
||||
if (do_join) {
|
||||
if (!LMIC_startJoining())
|
||||
ESP_LOGI(TAG, "Already joined");
|
||||
} else {
|
||||
@ -324,7 +323,6 @@ esp_err_t lora_stack_init(bool joined) {
|
||||
LMIC_setSession(RTCnetid, RTCdevaddr, RTCnwkKey, RTCartKey);
|
||||
LMIC.seqnoUp = RTCseqnoUp;
|
||||
LMIC.seqnoDn = RTCseqnoDn;
|
||||
lora_setupForNetwork(true);
|
||||
}
|
||||
|
||||
// start lmic send task
|
||||
@ -498,8 +496,8 @@ static void myEventCallback(void *pUserData, ev_t ev) {
|
||||
}
|
||||
|
||||
// receive message handler
|
||||
static void myRxCallback(void *pUserData, uint8_t port,
|
||||
const uint8_t *pMsg, size_t nMsg) {
|
||||
static void myRxCallback(void *pUserData, uint8_t port, const uint8_t *pMsg,
|
||||
size_t nMsg) {
|
||||
|
||||
// display type of received data
|
||||
if (nMsg)
|
||||
|
34
src/main.cpp
34
src/main.cpp
@ -129,14 +129,12 @@ void setup() {
|
||||
esp_log_level_set("*", ESP_LOG_NONE);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Starting Software v%s", PROGVERSION);
|
||||
do_after_reset(rtc_get_reset_reason(0));
|
||||
|
||||
if (RTC_runmode == RUNMODE_WAKEUP)
|
||||
exit_deepsleep();
|
||||
else {
|
||||
|
||||
// print chip information on startup if in verbose mode
|
||||
// print chip information on startup if in verbose mode after coldstart
|
||||
#if (VERBOSE)
|
||||
|
||||
if (RTC_runmode == RUNMODE_POWERCYCLE) {
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
ESP_LOGI(TAG,
|
||||
@ -175,9 +173,8 @@ void setup() {
|
||||
#if (HAS_GPS)
|
||||
ESP_LOGI(TAG, "TinyGPS+ version %s", TinyGPSPlus::libraryVersion());
|
||||
#endif
|
||||
|
||||
#endif // VERBOSE
|
||||
}
|
||||
#endif // VERBOSE
|
||||
|
||||
// open i2c bus
|
||||
i2c_init();
|
||||
@ -200,8 +197,8 @@ void setup() {
|
||||
#ifdef HAS_DISPLAY
|
||||
strcat_P(features, " OLED");
|
||||
DisplayIsOn = cfg.screenon;
|
||||
init_display(RTC_runmode == RUNMODE_NORMAL ? true
|
||||
: false); // note: blocking call
|
||||
// display verbose info only after a coldstart (note: blocking call!)
|
||||
init_display(RTC_runmode == RUNMODE_POWERCYCLE ? true : false);
|
||||
#endif
|
||||
|
||||
// scan i2c bus for devices
|
||||
@ -217,7 +214,7 @@ void setup() {
|
||||
pinMode(BAT_MEASURE_EN, OUTPUT);
|
||||
#endif
|
||||
|
||||
// initialize leds
|
||||
// initialize leds
|
||||
#if (HAS_LED != NOT_A_PIN)
|
||||
pinMode(HAS_LED, OUTPUT);
|
||||
strcat_P(features, " LED");
|
||||
@ -270,10 +267,8 @@ void setup() {
|
||||
#if (USE_OTA)
|
||||
strcat_P(features, " OTA");
|
||||
// reboot to firmware update mode if ota trigger switch is set
|
||||
if (RTC_runmode == RUNMODE_UPDATE) {
|
||||
RTC_runmode = RUNMODE_NORMAL;
|
||||
if (RTC_runmode == RUNMODE_UPDATE)
|
||||
start_ota_update();
|
||||
}
|
||||
#endif
|
||||
|
||||
// start BLE scan callback if BLE function is enabled in NVRAM configuration
|
||||
@ -317,7 +312,8 @@ void setup() {
|
||||
// initialize LoRa
|
||||
#if (HAS_LORA)
|
||||
strcat_P(features, " LORA");
|
||||
assert(lora_stack_init(RTC_runmode == RUNMODE_WAKEUP ? true : false) ==
|
||||
// kick off join, except we come from sleep
|
||||
assert(lora_stack_init(RTC_runmode == RUNMODE_WAKEUP ? false : true) ==
|
||||
ESP_OK);
|
||||
#endif
|
||||
|
||||
@ -349,7 +345,7 @@ void setup() {
|
||||
strcat_P(features, " LPPPKD");
|
||||
#endif
|
||||
|
||||
// initialize RTC
|
||||
// initialize RTC
|
||||
#ifdef HAS_RTC
|
||||
strcat_P(features, " RTC");
|
||||
assert(rtc_init());
|
||||
@ -404,7 +400,7 @@ void setup() {
|
||||
assert(irqHandlerTask != NULL); // has interrupt handler task started?
|
||||
ESP_LOGI(TAG, "Starting Timers...");
|
||||
|
||||
// display interrupt
|
||||
// display interrupt
|
||||
#ifdef HAS_DISPLAY
|
||||
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
||||
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
|
||||
@ -414,7 +410,7 @@ void setup() {
|
||||
timerAlarmEnable(displayIRQ);
|
||||
#endif
|
||||
|
||||
// LED Matrix display interrupt
|
||||
// LED Matrix display interrupt
|
||||
#ifdef HAS_MATRIX_DISPLAY
|
||||
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
||||
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 3, count up
|
||||
@ -424,7 +420,7 @@ void setup() {
|
||||
timerAlarmEnable(matrixDisplayIRQ);
|
||||
#endif
|
||||
|
||||
// initialize button
|
||||
// initialize button
|
||||
#ifdef HAS_BUTTON
|
||||
strcat_P(features, " BTN_");
|
||||
#ifdef BUTTON_PULLUP
|
||||
|
@ -40,12 +40,6 @@ inline String getHeaderValue(String header, String headerName) {
|
||||
|
||||
void start_ota_update() {
|
||||
|
||||
// check battery status if we can before doing ota
|
||||
if (!batt_sufficient()) {
|
||||
ESP_LOGE(TAG, "Battery voltage %dmV too low for OTA", batt_voltage);
|
||||
return;
|
||||
}
|
||||
|
||||
switch_LED(LED_ON);
|
||||
|
||||
// init display
|
||||
@ -105,7 +99,7 @@ end:
|
||||
ESP_LOGI(TAG, "Rebooting to %s firmware", (ret == 0) ? "new" : "current");
|
||||
ota_display(5, "**", ""); // mark line rebooting
|
||||
delay(5000);
|
||||
ESP.restart();
|
||||
do_reset(false);
|
||||
|
||||
} // start_ota_update
|
||||
|
||||
|
152
src/power.cpp
152
src/power.cpp
@ -5,11 +5,21 @@
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
RTC_DATA_ATTR int64_t sleep_enter_time;
|
||||
RTC_DATA_ATTR runmode_t RTC_runmode = RUNMODE_NORMAL;
|
||||
#ifdef BAT_MEASURE_ADC
|
||||
esp_adc_cal_characteristics_t *adc_characs =
|
||||
(esp_adc_cal_characteristics_t *)calloc(
|
||||
1, sizeof(esp_adc_cal_characteristics_t));
|
||||
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
static const adc1_channel_t adc_channel = BAT_MEASURE_ADC;
|
||||
#else // ADC2
|
||||
static const adc2_channel_t adc_channel = BAT_MEASURE_ADC;
|
||||
#endif
|
||||
static const adc_atten_t atten = ADC_ATTEN_DB_11;
|
||||
static const adc_unit_t unit = ADC_UNIT_1;
|
||||
#endif // BAT_MEASURE_ADC
|
||||
|
||||
#ifdef HAS_PMU
|
||||
|
||||
AXP20X_Class pmu;
|
||||
|
||||
void AXP192_powerevent_IRQ(void) {
|
||||
@ -37,17 +47,17 @@ void AXP192_powerevent_IRQ(void) {
|
||||
if (pmu.isBattTempHighIRQ())
|
||||
ESP_LOGI(TAG, "Battery low temperature.");
|
||||
|
||||
// esp32 sleep mode, can be exited by pressing user button
|
||||
// short press -> esp32 deep sleep mode, can be exited by pressing user button
|
||||
#ifdef HAS_BUTTON
|
||||
if (pmu.isPEKShortPressIRQ() && (RTC_runmode == RUNMODE_NORMAL)) {
|
||||
enter_deepsleep(0, HAS_BUTTON);
|
||||
}
|
||||
#endif
|
||||
|
||||
// shutdown power
|
||||
// long press -> shutdown power, can be exited by another longpress
|
||||
if (pmu.isPEKLongtPressIRQ()) {
|
||||
AXP192_power(false); // switch off Lora, GPS, display
|
||||
pmu.shutdown(); // switch off device
|
||||
AXP192_power(pmu_power_off); // switch off Lora, GPS, display
|
||||
pmu.shutdown(); // switch off device
|
||||
}
|
||||
|
||||
pmu.clearIRQ();
|
||||
@ -56,19 +66,31 @@ void AXP192_powerevent_IRQ(void) {
|
||||
read_voltage();
|
||||
}
|
||||
|
||||
void AXP192_power(bool on) {
|
||||
if (on) {
|
||||
void AXP192_power(pmu_power_t powerlevel) {
|
||||
|
||||
switch (powerlevel) {
|
||||
|
||||
case pmu_power_off:
|
||||
pmu.setChgLEDMode(AXP20X_LED_OFF);
|
||||
pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF);
|
||||
pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF);
|
||||
pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF);
|
||||
//pmu.setPowerOutPut(AXP192_DCDC3, AXP202_OFF);
|
||||
break;
|
||||
|
||||
case pmu_power_sleep:
|
||||
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
|
||||
// we don't cut off DCDC1, because then display blocks i2c bus
|
||||
pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF); // gps off
|
||||
pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF); // lora off
|
||||
break;
|
||||
|
||||
default: // all rails power on
|
||||
pmu.setPowerOutPut(AXP192_LDO2, AXP202_ON); // Lora on T-Beam V1.0
|
||||
pmu.setPowerOutPut(AXP192_LDO3, AXP202_ON); // Gps on T-Beam V1.0
|
||||
pmu.setPowerOutPut(AXP192_DCDC1, AXP202_ON); // OLED on T-Beam v1.0
|
||||
pmu.setChgLEDMode(AXP20X_LED_LOW_LEVEL);
|
||||
// pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
|
||||
} else {
|
||||
pmu.setChgLEDMode(AXP20X_LED_OFF);
|
||||
// we don't cut off power of display, because then display blocks i2c bus
|
||||
// pmu.setPowerOutPut(AXP192_DCDC1, AXP202_OFF);
|
||||
pmu.setPowerOutPut(AXP192_LDO3, AXP202_OFF);
|
||||
pmu.setPowerOutPut(AXP192_LDO2, AXP202_OFF);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -109,7 +131,7 @@ void AXP192_init(void) {
|
||||
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true);
|
||||
|
||||
// switch power rails on
|
||||
AXP192_power(true);
|
||||
AXP192_power(pmu_power_on);
|
||||
|
||||
#ifdef PMU_INT
|
||||
pinMode(PMU_INT, INPUT_PULLUP);
|
||||
@ -125,7 +147,7 @@ void AXP192_init(void) {
|
||||
}
|
||||
}
|
||||
|
||||
// helper functions for mutexing i2c access
|
||||
// helper functions for mutexing pmu i2c access
|
||||
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
|
||||
@ -176,100 +198,6 @@ uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
|
||||
#endif // HAS_PMU
|
||||
|
||||
#ifdef BAT_MEASURE_ADC
|
||||
esp_adc_cal_characteristics_t *adc_characs =
|
||||
(esp_adc_cal_characteristics_t *)calloc(
|
||||
1, sizeof(esp_adc_cal_characteristics_t));
|
||||
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
static const adc1_channel_t adc_channel = BAT_MEASURE_ADC;
|
||||
#else // ADC2
|
||||
static const adc2_channel_t adc_channel = BAT_MEASURE_ADC;
|
||||
#endif
|
||||
static const adc_atten_t atten = ADC_ATTEN_DB_11;
|
||||
static const adc_unit_t unit = ADC_UNIT_1;
|
||||
|
||||
#endif // BAT_MEASURE_ADC
|
||||
|
||||
void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio) {
|
||||
|
||||
if ((!wakeup_sec) && (!wakeup_gpio) && (RTC_runmode == RUNMODE_NORMAL))
|
||||
return;
|
||||
|
||||
// set up power domains
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
|
||||
|
||||
// set wakeup timer
|
||||
if (wakeup_sec)
|
||||
esp_sleep_enable_timer_wakeup(wakeup_sec * 1000000);
|
||||
|
||||
// set wakeup gpio
|
||||
if (wakeup_gpio != NOT_A_PIN) {
|
||||
rtc_gpio_isolate(wakeup_gpio);
|
||||
esp_sleep_enable_ext1_wakeup(1ULL << wakeup_gpio, ESP_EXT1_WAKEUP_ALL_LOW);
|
||||
}
|
||||
|
||||
// store LMIC counters and time
|
||||
RTCseqnoUp = LMIC.seqnoUp;
|
||||
RTCseqnoDn = LMIC.seqnoDn;
|
||||
|
||||
// store sleep enter time
|
||||
sleep_enter_time = esp_timer_get_time();
|
||||
|
||||
// halt interrupts accessing i2c bus
|
||||
mask_user_IRQ();
|
||||
|
||||
// switch off display
|
||||
#ifdef HAS_DISPLAY
|
||||
shutdown_display();
|
||||
#endif
|
||||
|
||||
// switch off wifi & ble
|
||||
#if (BLECOUNTER)
|
||||
stop_BLEscan();
|
||||
#endif
|
||||
|
||||
// switch off power if has PMU
|
||||
#ifdef HAS_PMU
|
||||
AXP192_power(false); // switch off Lora, GPS, display
|
||||
#endif
|
||||
|
||||
// shutdown i2c bus
|
||||
i2c_deinit();
|
||||
|
||||
// enter sleep mode
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
int64_t exit_deepsleep(void) {
|
||||
|
||||
int64_t sleep_time_ms = (esp_timer_get_time() - sleep_enter_time) / 1000;
|
||||
|
||||
// switch on power if has PMU
|
||||
#ifdef HAS_PMU
|
||||
AXP192_power(true); // power on Lora, GPS, display
|
||||
#endif
|
||||
|
||||
// re-init i2c bus
|
||||
void i2c_init();
|
||||
|
||||
switch (esp_sleep_get_wakeup_cause()) {
|
||||
case ESP_SLEEP_WAKEUP_EXT1:
|
||||
case ESP_SLEEP_WAKEUP_TIMER:
|
||||
RTC_runmode = RUNMODE_WAKEUP;
|
||||
ESP_LOGI(TAG, "[%0.3f] wake up from deep sleep after %dms", sleep_time_ms);
|
||||
break;
|
||||
case ESP_SLEEP_WAKEUP_UNDEFINED:
|
||||
default:
|
||||
RTC_runmode = RUNMODE_NORMAL;
|
||||
}
|
||||
|
||||
if (RTC_runmode == RUNMODE_WAKEUP)
|
||||
return sleep_time_ms;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
void calibrate_voltage(void) {
|
||||
#ifdef BAT_MEASURE_ADC
|
||||
// configure ADC
|
||||
|
@ -5,21 +5,12 @@
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
// helper function
|
||||
void do_reset() {
|
||||
ESP_LOGI(TAG, "Remote command: restart device");
|
||||
#if (HAS_LORA)
|
||||
LMIC_shutdown();
|
||||
#endif
|
||||
delay(3000);
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
// set of functions that can be triggered by remote commands
|
||||
void set_reset(uint8_t val[]) {
|
||||
switch (val[0]) {
|
||||
case 0: // restart device
|
||||
do_reset();
|
||||
case 0: // restart device with cold start (clear RTC saved variables)
|
||||
ESP_LOGI(TAG, "Remote command: restart device cold");
|
||||
do_reset(false);
|
||||
break;
|
||||
case 1: // reset MAC counter
|
||||
ESP_LOGI(TAG, "Remote command: reset MAC counter");
|
||||
@ -34,6 +25,10 @@ void set_reset(uint8_t val[]) {
|
||||
ESP_LOGI(TAG, "Remote command: flush send queue");
|
||||
flushQueues();
|
||||
break;
|
||||
case 4: // restart device with warm start (keep RTC saved variables)
|
||||
ESP_LOGI(TAG, "Remote command: restart device warm");
|
||||
do_reset(true);
|
||||
break;
|
||||
case 9: // reset and ask for software update via Wifi OTA
|
||||
ESP_LOGI(TAG, "Remote command: software update via Wifi");
|
||||
#if (USE_OTA)
|
||||
@ -346,7 +341,7 @@ static cmd_t table[] = {
|
||||
{0x03, set_gps, 1, true}, {0x04, set_display, 1, true},
|
||||
{0x05, set_loradr, 1, true}, {0x06, set_lorapower, 1, true},
|
||||
{0x07, set_loraadr, 1, true}, {0x08, set_screensaver, 1, true},
|
||||
{0x09, set_reset, 1, true}, {0x0a, set_sendcycle, 1, true},
|
||||
{0x09, set_reset, 1, false}, {0x0a, set_sendcycle, 1, true},
|
||||
{0x0b, set_wifichancycle, 1, true}, {0x0c, set_blescantime, 1, true},
|
||||
{0x0d, set_vendorfilter, 1, false}, {0x0e, set_blescan, 1, true},
|
||||
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},
|
||||
|
134
src/reset.cpp
Normal file
134
src/reset.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
// Basic Config
|
||||
#include "globals.h"
|
||||
#include "reset.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
// variable keep its values after wakeup from sleep
|
||||
RTC_DATA_ATTR int64_t sleep_enter_time;
|
||||
// variable keep its values after restart or wakeup from sleep
|
||||
RTC_NOINIT_ATTR runmode_t RTC_runmode;
|
||||
|
||||
void do_reset(bool warmstart) {
|
||||
if (warmstart) {
|
||||
// store LMIC keys and counters in RTC memory
|
||||
#if (HAS_LORA)
|
||||
LMIC_getSessionKeys(&RTCnetid, &RTCdevaddr, RTCnwkKey, RTCartKey);
|
||||
RTCseqnoUp = LMIC.seqnoUp;
|
||||
RTCseqnoDn = LMIC.seqnoDn;
|
||||
#endif
|
||||
ESP_LOGI(TAG, "restarting device (warmstart), keeping runmode %d",
|
||||
RTC_runmode);
|
||||
} else {
|
||||
#if (HAS_LORA)
|
||||
if (RTC_runmode == RUNMODE_NORMAL)
|
||||
LMIC_shutdown();
|
||||
#endif
|
||||
RTC_runmode = RUNMODE_POWERCYCLE;
|
||||
ESP_LOGI(TAG, "restarting device (coldstart), set runmode %d", RTC_runmode);
|
||||
}
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
void do_after_reset(int reason) {
|
||||
|
||||
switch (reason) {
|
||||
|
||||
case POWERON_RESET: // 0x01 Vbat power on reset
|
||||
case RTCWDT_BROWN_OUT_RESET: // 0x0f Reset when the vdd voltage is not
|
||||
// stable
|
||||
RTC_runmode = RUNMODE_POWERCYCLE;
|
||||
break;
|
||||
|
||||
case DEEPSLEEP_RESET: // 0x05 Deep Sleep reset digital core
|
||||
RTC_runmode = RUNMODE_WAKEUP;
|
||||
exit_deepsleep();
|
||||
break;
|
||||
|
||||
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 SW_CPU_RESET: // 0x0c Software 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
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Starting Software v%s, runmode %d", PROGVERSION, RTC_runmode);
|
||||
}
|
||||
|
||||
void enter_deepsleep(const int wakeup_sec, const gpio_num_t wakeup_gpio) {
|
||||
|
||||
if ((!wakeup_sec) && (!wakeup_gpio) && (RTC_runmode == RUNMODE_NORMAL))
|
||||
return;
|
||||
|
||||
// set up power domains
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
|
||||
|
||||
// set wakeup timer
|
||||
if (wakeup_sec)
|
||||
esp_sleep_enable_timer_wakeup(wakeup_sec * 1000000);
|
||||
|
||||
// set wakeup gpio
|
||||
if (wakeup_gpio != NOT_A_PIN) {
|
||||
rtc_gpio_isolate(wakeup_gpio);
|
||||
esp_sleep_enable_ext1_wakeup(1ULL << wakeup_gpio, ESP_EXT1_WAKEUP_ALL_LOW);
|
||||
}
|
||||
|
||||
// store sleep enter time
|
||||
sleep_enter_time = esp_timer_get_time();
|
||||
|
||||
// store LMIC keys and counters in RTC memory
|
||||
#if (HAS_LORA)
|
||||
LMIC_getSessionKeys(&RTCnetid, &RTCdevaddr, RTCnwkKey, RTCartKey);
|
||||
RTCseqnoUp = LMIC.seqnoUp;
|
||||
RTCseqnoDn = LMIC.seqnoDn;
|
||||
#endif
|
||||
|
||||
// halt interrupts accessing i2c bus
|
||||
mask_user_IRQ();
|
||||
|
||||
// switch off display
|
||||
#ifdef HAS_DISPLAY
|
||||
shutdown_display();
|
||||
#endif
|
||||
|
||||
// switch off wifi & ble
|
||||
#if (BLECOUNTER)
|
||||
stop_BLEscan();
|
||||
#endif
|
||||
|
||||
// reduce power if has PMU
|
||||
#ifdef HAS_PMU
|
||||
AXP192_power(pmu_power_sleep);
|
||||
#endif
|
||||
|
||||
// shutdown i2c bus
|
||||
i2c_deinit();
|
||||
|
||||
// enter sleep mode
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
int64_t exit_deepsleep(void) {
|
||||
|
||||
int64_t sleep_time_ms = (esp_timer_get_time() - sleep_enter_time) / 1000;
|
||||
|
||||
// re-init i2c bus
|
||||
void i2c_init();
|
||||
|
||||
// switch on power if has PMU
|
||||
#ifdef HAS_PMU
|
||||
AXP192_power(pmu_power_on); // power on Lora, GPS, display
|
||||
#endif
|
||||
|
||||
return sleep_time_ms;
|
||||
}
|
Loading…
Reference in New Issue
Block a user