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.c448
1 files changed, 175 insertions, 273 deletions
diff --git a/fw/esp32/components/eos/power.c b/fw/esp32/components/eos/power.c
index b98c0ec..27c44a5 100644
--- a/fw/esp32/components/eos/power.c
+++ b/fw/esp32/components/eos/power.c
@@ -4,37 +4,30 @@
#include <freertos/task.h>
#include <freertos/queue.h>
#include <driver/gpio.h>
+#include <driver/rtc_io.h>
+#include <driver/uart.h>
+
+#include <esp_system.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"
+#include "app.h"
#include "cell.h"
#include "power.h"
-#define POWER_GPIO_BTN 0
-#define POWER_GPIO_NET 5
-#define POWER_GPIO_UART 35
-
-#define POWER_ETYPE_BTN 1
-#define POWER_ETYPE_SLEEP1 2
-#define POWER_ETYPE_SLEEP2 3
-#define POWER_ETYPE_WAKE 4
-#define POWER_ETYPE_NETRDY 5
+#define PWR_ETYPE_SLEEP_REQ 1
+#define PWR_ETYPE_SLEEP_RDY 2
+#define PWR_ETYPE_WAKE 3
typedef struct {
uint8_t type;
- union {
- uint8_t source;
- uint8_t level;
- };
+ uint8_t mode;
+ uint32_t dev;
} 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;
@@ -43,232 +36,119 @@ 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;
-
- evt.type = POWER_ETYPE_BTN;
- evt.level = gpio_get_level(POWER_GPIO_BTN);
- xQueueSendFromISR(power_queue, &evt, NULL);
-}
-
-static void IRAM_ATTR btn_wake_handler(void *arg) {
- power_event_t evt;
-
- gpio_intr_disable(POWER_GPIO_BTN);
-
- evt.type = POWER_ETYPE_WAKE;
- evt.source = EOS_PWR_WAKE_BTN;
- xQueueSendFromISR(power_queue, &evt, NULL);
-
-}
-
static void IRAM_ATTR net_wake_handler(void *arg) {
power_event_t evt;
- gpio_intr_disable(POWER_GPIO_NET);
-
- evt.type = POWER_ETYPE_WAKE;
- evt.source = EOS_PWR_WAKE_NET;
+ evt.type = PWR_ETYPE_WAKE;
+ evt.dev = EOS_PWR_DEV_NET;
xQueueSendFromISR(power_queue, &evt, NULL);
}
-static void IRAM_ATTR uart_wake_handler(void *arg) {
+static void IRAM_ATTR app_wake_handler(void *arg) {
power_event_t evt;
- gpio_intr_disable(POWER_GPIO_UART);
-
- evt.type = POWER_ETYPE_WAKE;
- evt.source = EOS_PWR_WAKE_UART;
+ evt.type = PWR_ETYPE_WAKE;
+ evt.dev = EOS_PWR_DEV_APP;
xQueueSendFromISR(power_queue, &evt, NULL);
}
-static void timer_handler(void *arg) {
+static void IRAM_ATTR modem_wake_handler(void *arg) {
power_event_t evt;
- evt.type = POWER_ETYPE_SLEEP2;
+ evt.type = PWR_ETYPE_WAKE;
+ evt.dev = EOS_PWR_DEV_MODEM;
xQueueSendFromISR(power_queue, &evt, NULL);
}
-static void power_sleep_stage1(int modem_wake_en) {
- 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);
- if (modem_wake_en) {
- 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);
- if (modem_wake_en) {
- gpio_wakeup_enable(POWER_GPIO_UART, GPIO_INTR_LOW_LEVEL);
- }
-
- esp_timer_start_once(timer, 10 * 1000000);
-
- esp_pm_lock_release(power_lock_cpu_freq);
- esp_pm_lock_release(power_lock_apb_freq);
- esp_pm_lock_release(power_lock_no_sleep);
-}
-
-static void power_sleep_stage2(int modem_wake_en, 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);
-
- gpio_deep_sleep_hold_en();
- esp_sleep_enable_ext0_wakeup(POWER_GPIO_BTN, 0);
- if (modem_wake_en) {
- esp_sleep_enable_ext1_wakeup((uint64_t)1 << POWER_GPIO_UART, ESP_EXT1_WAKEUP_ALL_LOW);
- }
-
- ESP_LOGI(TAG, "DEEP SLEEP");
-
- eos_modem_deep_sleep();
- esp_deep_sleep_start();
- break;
- }
- }
-}
-
-static void power_wake_stage1(uint8_t source, uint8_t mode) {
- 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;
- io_conf.mode = GPIO_MODE_DISABLE;
- 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_intr_disable(POWER_GPIO_BTN);
- if ((source != EOS_PWR_WAKE_BTN) && (source != EOS_PWR_WAKE_NET)) {
- 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);
- }
-
- eos_net_wake(source, mode);
-}
-
-static void power_wake_stage2(uint8_t source, uint8_t mode) {
- eos_modem_wake(source, mode);
-
- gpio_set_intr_type(POWER_GPIO_BTN, GPIO_INTR_ANYEDGE);
- gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL);
-
- ESP_LOGI(TAG, "WAKE");
- wake_done = 1;
-}
-
static void power_event_task(void *pvParameters) {
power_event_t evt;
- uint8_t source;
- uint8_t wakeup_cause;
uint8_t mode;
- int sleep1, sleep2;
- int modem_wake_en;
+ uint32_t sleep_req, sleep_rdy;
+ int sys_sleep;
mode = 0;
- source = 0;
- wakeup_cause = eos_power_wakeup_cause();
- if (wakeup_cause != EOS_PWR_WAKE_RST) {
- mode = EOS_PWR_SMODE_DEEP;
- sleep1 = 1;
- } else {
- sleep1 = 0;
- }
- sleep2 = 0;
- modem_wake_en = 0;
-
+ sys_sleep = 0;
+ sleep_req = 0;
+ sleep_rdy = 0;
while (1) {
if (xQueueReceive(power_queue, &evt, portMAX_DELAY)) {
switch (evt.type) {
- case POWER_ETYPE_SLEEP1: {
- if (!sleep1) {
- modem_wake_en = eos_modem_present();
- mode = EOS_PWR_SMODE_LIGHT;
- power_sleep_stage1(modem_wake_en);
- sleep1 = 1;
- sleep2 = 1;
+ case PWR_ETYPE_SLEEP_REQ: {
+ if (evt.mode) mode = evt.mode;
+ if ((evt.dev & EOS_PWR_DEV_NET) && !(sleep_req & EOS_PWR_DEV_NET)) {
+ eos_net_sleep_req();
}
- break;
- }
-
- case POWER_ETYPE_SLEEP2: {
- if (sleep2) {
- mode = EOS_PWR_SMODE_DEEP;
- power_sleep_stage2(modem_wake_en, mode);
- sleep2 = 0;
+ if ((evt.dev & EOS_PWR_DEV_APP) && !(sleep_req & EOS_PWR_DEV_APP)) {
+ eos_app_sleep_req();
}
- break;
- }
-
- case POWER_ETYPE_WAKE: {
- if (sleep1) {
- source = evt.source;
- power_wake_stage1(source, mode);
- if (sleep2) {
- esp_timer_stop(timer);
- sleep2 = 0;
- }
+ if ((evt.dev & EOS_PWR_DEV_MODEM) && !(sleep_req & EOS_PWR_DEV_MODEM)) {
+ eos_modem_sleep_req();
+ }
+ sleep_req |= evt.dev;
+ if (sleep_rdy == EOS_PWR_DEV_ALL) {
+ eos_power_sleep_rdy(0);
}
break;
}
- case POWER_ETYPE_NETRDY: {
- power_wake_stage2(source, mode);
- sleep1 = 0;
- source = 0;
+ case PWR_ETYPE_SLEEP_RDY: {
+ gpio_config_t io_conf = {
+ .mode = GPIO_MODE_INPUT,
+ .intr_type = GPIO_INTR_NEGEDGE,
+ .pull_up_en = 1,
+ .pull_down_en = 0,
+ };
+
+ if (evt.dev & EOS_PWR_DEV_NET) {
+ io_conf.pin_bit_mask = BIT64(EOS_PWR_GPIO_NET);
+ gpio_config(&io_conf);
+ gpio_isr_handler_add(EOS_PWR_GPIO_NET, net_wake_handler, NULL);
+ }
+ if (evt.dev & EOS_PWR_DEV_APP) {
+ io_conf.pin_bit_mask = BIT64(EOS_PWR_GPIO_APP);
+ gpio_config(&io_conf);
+ gpio_isr_handler_add(EOS_PWR_GPIO_APP, app_wake_handler, NULL);
+ }
+ if (evt.dev & EOS_PWR_DEV_MODEM) {
+ io_conf.pin_bit_mask = BIT64(EOS_PWR_GPIO_MODEM);
+ gpio_config(&io_conf);
+ gpio_isr_handler_add(EOS_PWR_GPIO_MODEM, modem_wake_handler, NULL);
+ }
+ sleep_rdy |= evt.dev;
+ if (!sys_sleep && mode && (sleep_rdy == EOS_PWR_DEV_ALL)) {
+ sys_sleep = 1;
+ eos_power_sys_sleep(mode);
+ }
break;
}
- case POWER_ETYPE_BTN: {
- unsigned char *buf;
-
- buf = eos_net_alloc();
- buf[0] = EOS_PWR_MTYPE_BUTTON;
- buf[1] = evt.level;
- eos_net_send(EOS_NET_MTYPE_POWER, buf, 2);
+ case PWR_ETYPE_WAKE: {
+ ESP_LOGI(TAG, "WAKE:0x%.8lX", evt.dev);
+ if (sys_sleep) {
+ eos_power_sys_wake(mode);
+ sys_sleep = 0;
+ mode = 0;
+ }
+ if ((evt.dev & EOS_PWR_DEV_NET) && (sleep_rdy & EOS_PWR_DEV_NET)) {
+ gpio_isr_handler_remove(EOS_PWR_GPIO_NET);
+ gpio_reset_pin(EOS_PWR_GPIO_NET);
+ eos_net_wake();
+ }
+ if ((evt.dev & EOS_PWR_DEV_APP) && (sleep_rdy & EOS_PWR_DEV_APP)) {
+ gpio_isr_handler_remove(EOS_PWR_GPIO_APP);
+ gpio_reset_pin(EOS_PWR_GPIO_APP);
+ eos_app_wake();
+ }
+ if ((evt.dev & EOS_PWR_DEV_MODEM) && (sleep_rdy & EOS_PWR_DEV_MODEM)) {
+ gpio_isr_handler_remove(EOS_PWR_GPIO_MODEM);
+ gpio_reset_pin(EOS_PWR_GPIO_MODEM);
+ eos_modem_wake();
+ }
+ sleep_req &= ~evt.dev;
+ sleep_rdy &= ~evt.dev;
+ ESP_LOGI(TAG, "WAKE DONE:0x%.8lX", evt.dev);
break;
}
-
- default:
- break;
}
}
}
@@ -276,35 +156,9 @@ static void power_event_task(void *pvParameters) {
}
void eos_power_init(void) {
- esp_err_t ret;
- gpio_config_t io_conf = {};
- esp_timer_create_args_t timer_args = {};
- esp_pm_config_esp32_t pwr_conf;
- uint8_t wakeup_cause;
-
- io_conf.intr_type = GPIO_INTR_ANYEDGE;
- io_conf.mode = GPIO_MODE_INPUT;
- io_conf.pin_bit_mask = ((uint64_t)1 << POWER_GPIO_BTN);
- io_conf.pull_up_en = 1;
- io_conf.pull_down_en = 0;
- 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);
- ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_ON);
- assert(ret == ESP_OK);
- ret = esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON);
- assert(ret == ESP_OK);
- */
+ esp_err_t ret;
+ esp_pm_config_t pwr_conf;
ret = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, NULL, &power_lock_cpu_freq);
assert(ret == ESP_OK);
@@ -326,70 +180,118 @@ void eos_power_init(void) {
ret = esp_pm_configure(&pwr_conf);
assert(ret == ESP_OK);
+ */
- power_queue = xQueueCreate(4, sizeof(power_event_t));
- 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_PWR_WAKE_RST) {
- eos_power_wake(wakeup_cause);
+ if (esp_reset_reason() == ESP_RST_DEEPSLEEP) {
+ rtc_gpio_deinit(EOS_PWR_GPIO_NET);
+ rtc_gpio_deinit(EOS_PWR_GPIO_APP);
+ rtc_gpio_deinit(EOS_PWR_GPIO_MODEM);
+ eos_power_sys_wake(EOS_PWR_SMODE_DEEP);
}
- init_done = 1;
+ power_queue = xQueueCreate(4, sizeof(power_event_t));
+ assert(power_queue != NULL);
+
ESP_LOGI(TAG, "INIT");
}
-void eos_power_wait4init(void) {
- while (!init_done);
-}
+void eos_power_run(void) {
+ BaseType_t rv;
-void eos_power_wait4wake(void) {
- if (eos_power_wakeup_cause() == EOS_PWR_WAKE_RST) return;
- while (!wake_done);
-}
+ rv = xTaskCreate(power_event_task, "power_event", EOS_TASK_SSIZE_PWR, NULL, EOS_TASK_PRIORITY_PWR, NULL);
+ assert(rv == pdPASS);
-uint8_t eos_power_wakeup_cause(void) {
- esp_reset_reason_t reset_cause = esp_reset_reason();
- esp_sleep_wakeup_cause_t wakeup_cause = esp_sleep_get_wakeup_cause();
+ ESP_LOGI(TAG, "RUN");
+}
- if (reset_cause == ESP_RST_DEEPSLEEP) {
- switch (wakeup_cause) {
- case ESP_SLEEP_WAKEUP_EXT0:
- return EOS_PWR_WAKE_BTN;
+void eos_power_sys_sleep(uint8_t mode) {
+ switch (mode) {
+ case EOS_PWR_SMODE_TICKLESS: {
+ esp_pm_lock_release(power_lock_cpu_freq);
+ esp_pm_lock_release(power_lock_apb_freq);
+ esp_pm_lock_release(power_lock_no_sleep);
+ break;
+ }
- case ESP_SLEEP_WAKEUP_EXT1:
- return EOS_PWR_WAKE_UART;
+ case EOS_PWR_SMODE_LIGHT:
+ case EOS_PWR_SMODE_DEEP: {
+ esp_err_t ret;
+
+ /* in case of missing modem */
+ rtc_gpio_pullup_en(EOS_PWR_GPIO_MODEM);
+ esp_sleep_enable_ext1_wakeup_io(EOS_PWR_DEV_ALL, ESP_EXT1_WAKEUP_ANY_LOW);
+ if (mode == EOS_PWR_SMODE_DEEP) {
+ gpio_deep_sleep_hold_en();
+ esp_deep_sleep_start();
+ } else {
+ ESP_LOGI(TAG, "LIGHT SLEEP");
+ uart_wait_tx_idle_polling(UART_NUM_0);
+ ret = esp_light_sleep_start();
+ ESP_LOGI(TAG, "LIGHT WAKE: %d", ret);
+ eos_power_wake(eos_power_wakeup_source());
+ }
+ break;
+ }
+ }
+}
- default:
- return EOS_PWR_WAKE_UNDEF;
+void eos_power_sys_wake(uint8_t mode) {
+ switch (mode) {
+ case EOS_PWR_SMODE_TICKLESS: {
+ esp_pm_lock_acquire(power_lock_cpu_freq);
+ esp_pm_lock_acquire(power_lock_apb_freq);
+ esp_pm_lock_acquire(power_lock_no_sleep);
+ break;
+ }
+ case EOS_PWR_SMODE_LIGHT:
+ case EOS_PWR_SMODE_DEEP: {
+ rtc_gpio_pullup_dis(EOS_PWR_GPIO_MODEM);
+ esp_sleep_disable_ext1_wakeup_io(0);
+ if (mode == EOS_PWR_SMODE_DEEP) {
+ gpio_deep_sleep_hold_dis();
+ }
+ break;
}
+ }
+}
+
+uint32_t eos_power_wakeup_source(void) {
+ esp_sleep_wakeup_cause_t wakeup_cause;
+ uint32_t dev;
+
+ dev = EOS_PWR_DEV_NONE;
+ wakeup_cause = esp_sleep_get_wakeup_cause();
+ if (wakeup_cause == ESP_SLEEP_WAKEUP_EXT1) {
+ dev = esp_sleep_get_ext1_wakeup_status();
+ return dev;
} else {
- return EOS_PWR_WAKE_RST;
+ ESP_LOGE(TAG, "BAD WAKEUP CAUSE");
}
+ return dev;
}
-void eos_power_sleep(void) {
+void eos_power_sleep_req(uint8_t mode, uint32_t dev) {
power_event_t evt;
- evt.type = POWER_ETYPE_SLEEP1;
- evt.source = 0;
+ evt.type = PWR_ETYPE_SLEEP_REQ;
+ evt.mode = mode;
+ evt.dev = dev;
xQueueSend(power_queue, &evt, portMAX_DELAY);
}
-void eos_power_wake(uint8_t source) {
+void eos_power_sleep_rdy(uint32_t dev) {
power_event_t evt;
- evt.type = POWER_ETYPE_WAKE;
- evt.source = source;
-
+ evt.type = PWR_ETYPE_SLEEP_RDY;
+ evt.dev = dev;
xQueueSend(power_queue, &evt, portMAX_DELAY);
}
-void eos_power_net_ready(void) {
+void eos_power_wake(uint32_t dev) {
power_event_t evt;
- evt.type = POWER_ETYPE_NETRDY;
- evt.source = 0;
-
+ ESP_LOGI(TAG, "WAKE SENT");
+ evt.type = PWR_ETYPE_WAKE;
+ evt.dev = dev;
xQueueSend(power_queue, &evt, portMAX_DELAY);
}