summaryrefslogtreecommitdiff
path: root/fw/esp32/components/eos/power.c
diff options
context:
space:
mode:
Diffstat (limited to 'fw/esp32/components/eos/power.c')
-rw-r--r--fw/esp32/components/eos/power.c190
1 files changed, 126 insertions, 64 deletions
diff --git a/fw/esp32/components/eos/power.c b/fw/esp32/components/eos/power.c
index 0cbb4e0..c659481 100644
--- a/fw/esp32/components/eos/power.c
+++ b/fw/esp32/components/eos/power.c
@@ -5,8 +5,10 @@
#include <freertos/queue.h>
#include <driver/gpio.h>
#include <esp_sleep.h>
+#include <esp_timer.h>
#include <esp_pm.h>
#include <esp_log.h>
+#include <esp32/rom/rtc.h>
#include "eos.h"
#include "net.h"
@@ -18,9 +20,10 @@
#define POWER_GPIO_UART 35
#define POWER_ETYPE_BTN 1
-#define POWER_ETYPE_SLEEP 2
-#define POWER_ETYPE_WAKE 3
-#define POWER_ETYPE_NETRDY 4
+#define POWER_ETYPE_SLEEP1 2
+#define POWER_ETYPE_SLEEP2 3
+#define POWER_ETYPE_WAKE 4
+#define POWER_ETYPE_NETRDY 5
typedef struct {
uint8_t type;
@@ -30,6 +33,8 @@ typedef struct {
};
} power_event_t;
+static esp_timer_handle_t timer;
+
static esp_pm_lock_handle_t power_lock_cpu_freq;
static esp_pm_lock_handle_t power_lock_apb_freq;
static esp_pm_lock_handle_t power_lock_no_sleep;
@@ -39,6 +44,7 @@ static const char *TAG = "EOS POWER";
static QueueHandle_t power_queue;
static volatile int init_done = 0;
+static volatile int wake_done = 0;
static void IRAM_ATTR btn_handler(void *arg) {
power_event_t evt;
@@ -79,62 +85,79 @@ static void IRAM_ATTR uart_wake_handler(void *arg) {
xQueueSendFromISR(power_queue, &evt, NULL);
}
-void power_sleep(uint8_t mode) {
- gpio_config_t io_conf;
+static void timer_handler(void *arg) {
+ power_event_t evt;
- eos_modem_sleep(mode);
- eos_net_sleep_done(mode);
+ evt.type = POWER_ETYPE_SLEEP2;
+ xQueueSendFromISR(power_queue, &evt, NULL);
+}
- switch (mode) {
- case EOS_PWR_SMODE_LIGHT:
- io_conf.intr_type = GPIO_INTR_DISABLE;
- io_conf.mode = GPIO_MODE_INPUT;
- io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_NET);
- io_conf.pull_up_en = 0;
- io_conf.pull_down_en = 0;
- gpio_config(&io_conf);
+void power_sleep_stage1(void) {
+ gpio_config_t io_conf = {};
+
+ eos_modem_sleep();
+ eos_net_sleep();
+
+ io_conf.intr_type = GPIO_INTR_DISABLE;
+ io_conf.mode = GPIO_MODE_INPUT;
+ io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_NET);
+ io_conf.pull_up_en = 0;
+ io_conf.pull_down_en = 0;
+ gpio_config(&io_conf);
- gpio_isr_handler_add(POWER_GPIO_BTN, btn_wake_handler, NULL);
- gpio_isr_handler_add(POWER_GPIO_NET, net_wake_handler, NULL);
- gpio_isr_handler_add(POWER_GPIO_UART, uart_wake_handler, NULL);
+ gpio_isr_handler_add(POWER_GPIO_BTN, btn_wake_handler, NULL);
+ gpio_isr_handler_add(POWER_GPIO_NET, net_wake_handler, NULL);
+ gpio_isr_handler_add(POWER_GPIO_UART, uart_wake_handler, NULL);
- esp_sleep_enable_gpio_wakeup();
- gpio_wakeup_enable(POWER_GPIO_BTN, GPIO_INTR_LOW_LEVEL);
- gpio_wakeup_enable(POWER_GPIO_NET, GPIO_INTR_LOW_LEVEL);
- gpio_wakeup_enable(POWER_GPIO_UART, GPIO_INTR_LOW_LEVEL);
+ esp_sleep_enable_gpio_wakeup();
+ gpio_wakeup_enable(POWER_GPIO_BTN, GPIO_INTR_LOW_LEVEL);
+ gpio_wakeup_enable(POWER_GPIO_NET, GPIO_INTR_LOW_LEVEL);
+ gpio_wakeup_enable(POWER_GPIO_UART, GPIO_INTR_LOW_LEVEL);
- ESP_LOGI(TAG, "SLEEP");
+ esp_timer_start_once(timer, 10 * 1000000);
- esp_pm_lock_release(power_lock_apb_freq);
- esp_pm_lock_release(power_lock_no_sleep);
+ esp_pm_lock_release(power_lock_cpu_freq);
+ esp_pm_lock_release(power_lock_apb_freq);
+ esp_pm_lock_release(power_lock_no_sleep);
+}
+void power_sleep_stage2(uint8_t mode) {
+ switch (mode) {
+ case EOS_PWR_SMODE_LIGHT: {
+ ESP_LOGI(TAG, "LIGHT SLEEP");
+
+ esp_light_sleep_start();
break;
+ }
+
+ case EOS_PWR_SMODE_DEEP: {
+ esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
- case EOS_PWR_SMODE_DEEP:
gpio_deep_sleep_hold_en();
esp_sleep_enable_ext0_wakeup(POWER_GPIO_BTN, 0);
- esp_sleep_enable_ext1_wakeup((uint64_t)1 << POWER_GPIO_UART, ESP_EXT1_WAKEUP_ALL_LOW);
+ // esp_sleep_enable_ext1_wakeup((uint64_t)1 << POWER_GPIO_UART, ESP_EXT1_WAKEUP_ALL_LOW);
- ESP_LOGI(TAG, "SLEEP");
+ ESP_LOGI(TAG, "DEEP SLEEP");
+ eos_modem_deep_sleep();
esp_deep_sleep_start();
break;
-
- default:
- break;
+ }
}
}
void power_wake_stage1(uint8_t source, uint8_t mode) {
- gpio_config_t io_conf;
-
if (mode == EOS_PWR_SMODE_LIGHT) {
+ gpio_config_t io_conf = {};
+
+ esp_pm_lock_acquire(power_lock_cpu_freq);
esp_pm_lock_acquire(power_lock_apb_freq);
esp_pm_lock_acquire(power_lock_no_sleep);
gpio_wakeup_disable(POWER_GPIO_BTN);
gpio_wakeup_disable(POWER_GPIO_NET);
gpio_wakeup_disable(POWER_GPIO_UART);
+ esp_sleep_disable_wakeup_source(ESP_SLEEP_WAKEUP_ALL);
gpio_isr_handler_remove(POWER_GPIO_NET);
io_conf.intr_type = GPIO_INTR_DISABLE;
@@ -147,8 +170,8 @@ void power_wake_stage1(uint8_t source, uint8_t mode) {
gpio_intr_disable(POWER_GPIO_BTN);
if ((source != EOS_PWR_WAKE_BTN) && (source != EOS_PWR_WAKE_NET)) {
- gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_OUTPUT);
gpio_set_level(POWER_GPIO_BTN, 0);
+ gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_OUTPUT);
vTaskDelay(200 / portTICK_PERIOD_MS);
gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_INPUT);
}
@@ -163,58 +186,77 @@ void power_wake_stage2(uint8_t source, uint8_t mode) {
gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL);
ESP_LOGI(TAG, "WAKE");
+ wake_done = 1;
}
static void power_event_task(void *pvParameters) {
- unsigned char *buf;
power_event_t evt;
uint8_t source;
uint8_t wakeup_cause;
uint8_t mode;
- int sleep;
+ int sleep1, sleep2;
+ mode = 0;
source = 0;
wakeup_cause = eos_power_wakeup_cause();
- if (wakeup_cause) {
+ if (wakeup_cause != EOS_PWR_WAKE_RST) {
mode = EOS_PWR_SMODE_DEEP;
- sleep = 1;
+ sleep1 = 1;
} else {
- mode = EOS_PWR_SMODE_LIGHT;
- sleep = 0;
+ sleep1 = 0;
}
+ sleep2 = 0;
while (1) {
if (xQueueReceive(power_queue, &evt, portMAX_DELAY)) {
switch (evt.type) {
- case POWER_ETYPE_SLEEP:
- if (!sleep) {
+ case POWER_ETYPE_SLEEP1: {
+ if (!sleep1) {
+ mode = EOS_PWR_SMODE_LIGHT;
+ power_sleep_stage1();
+ sleep1 = 1;
+ sleep2 = 1;
+ }
+ break;
+ }
+
+ case POWER_ETYPE_SLEEP2: {
+ if (sleep2) {
mode = EOS_PWR_SMODE_DEEP;
- power_sleep(mode);
- sleep = 1;
+ power_sleep_stage2(mode);
+ sleep2 = 0;
}
break;
+ }
- case POWER_ETYPE_WAKE:
- if (sleep) {
+ case POWER_ETYPE_WAKE: {
+ if (sleep1) {
source = evt.source;
power_wake_stage1(source, mode);
+ if (sleep2) {
+ esp_timer_stop(timer);
+ sleep2 = 0;
+ }
}
break;
+ }
- case POWER_ETYPE_NETRDY:
- if (sleep && source) {
- power_wake_stage2(source, mode);
- sleep = 0;
- source = 0;
- }
+ case POWER_ETYPE_NETRDY: {
+ power_wake_stage2(source, mode);
+ sleep1 = 0;
+ source = 0;
break;
+ }
+
+ case POWER_ETYPE_BTN: {
+ unsigned char *buf;
- case POWER_ETYPE_BTN:
buf = eos_net_alloc();
buf[0] = EOS_PWR_MTYPE_BUTTON;
buf[1] = evt.level;
eos_net_send(EOS_NET_MTYPE_POWER, buf, 2);
break;
+ }
default:
break;
@@ -226,7 +268,8 @@ static void power_event_task(void *pvParameters) {
void eos_power_init(void) {
esp_err_t ret;
- gpio_config_t io_conf;
+ gpio_config_t io_conf = {};
+ esp_timer_create_args_t timer_args = {};
esp_pm_config_esp32_t pwr_conf;
uint8_t wakeup_cause;
@@ -238,6 +281,13 @@ void eos_power_init(void) {
gpio_config(&io_conf);
gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL);
+ timer_args.callback = timer_handler,
+ timer_args.arg = NULL;
+ timer_args.name = "sleep";
+
+ ret = esp_timer_create(&timer_args, &timer);
+ assert(ret == ESP_OK);
+
/*
ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
assert(ret == ESP_OK);
@@ -272,7 +322,9 @@ void eos_power_init(void) {
xTaskCreate(power_event_task, "power_event", EOS_TASK_SSIZE_PWR, NULL, EOS_TASK_PRIORITY_PWR, NULL);
wakeup_cause = eos_power_wakeup_cause();
- if (wakeup_cause) eos_power_wake(wakeup_cause);
+ if (wakeup_cause != EOS_PWR_WAKE_RST) {
+ eos_power_wake(wakeup_cause);
+ }
init_done = 1;
ESP_LOGI(TAG, "INIT");
@@ -282,25 +334,35 @@ void eos_power_wait4init(void) {
while (!init_done);
}
+void eos_power_wait4wake(void) {
+ if (eos_power_wakeup_cause() == EOS_PWR_WAKE_RST) return;
+ while (!wake_done);
+}
+
uint8_t eos_power_wakeup_cause(void) {
- esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
+ esp_reset_reason_t reset_cause = esp_reset_reason();
+ esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
- switch (cause) {
- case ESP_SLEEP_WAKEUP_EXT0:
- return EOS_PWR_WAKE_BTN;
+ if (reset_cause == ESP_RST_DEEPSLEEP) {
+ switch (wakeup_cause) {
+ case ESP_SLEEP_WAKEUP_EXT0:
+ return EOS_PWR_WAKE_BTN;
- case ESP_SLEEP_WAKEUP_EXT1:
- return EOS_PWR_WAKE_UART;
+ case ESP_SLEEP_WAKEUP_EXT1:
+ return EOS_PWR_WAKE_UART;
- default:
- return EOS_PWR_WAKE_RST;
+ default:
+ return EOS_PWR_WAKE_UNDEF;
+ }
+ } else {
+ return EOS_PWR_WAKE_RST;
}
}
void eos_power_sleep(void) {
power_event_t evt;
- evt.type = POWER_ETYPE_SLEEP;
+ evt.type = POWER_ETYPE_SLEEP1;
evt.source = 0;
xQueueSend(power_queue, &evt, portMAX_DELAY);
}