From 375ac3b0c7e9ed8b2d2d0fc4d0700a23c8865836 Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Sun, 24 May 2020 00:00:38 +0200 Subject: esp32 deep sleep implemented --- code/esp32/components/eos/cell_modem.c | 36 ++++--- code/esp32/components/eos/include/cell.h | 4 +- code/esp32/components/eos/include/i2c.h | 1 + code/esp32/components/eos/include/net.h | 5 +- code/esp32/components/eos/include/power.h | 7 ++ code/esp32/components/eos/net.c | 17 ++- code/esp32/components/eos/power.c | 166 +++++++++++++++++++++--------- code/esp32/main/app_main.c | 7 +- 8 files changed, 171 insertions(+), 72 deletions(-) (limited to 'code') diff --git a/code/esp32/components/eos/cell_modem.c b/code/esp32/components/eos/cell_modem.c index 589f1d8..5315861 100644 --- a/code/esp32/components/eos/cell_modem.c +++ b/code/esp32/components/eos/cell_modem.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include "eos.h" @@ -44,7 +45,7 @@ static QueueHandle_t uart_queue; static char uart_buf[UART_SIZE_URC_BUF]; static unsigned int uart_buf_len; -static uint8_t uart_mode = EOS_CELL_UART_MODE_NONE; +static uint8_t uart_mode = EOS_CELL_UART_MODE_ATCMD; static SemaphoreHandle_t uart_mutex; static char ppp_apn[64]; @@ -107,10 +108,11 @@ static void uart_data_read(uint8_t mode) { } static void uart_event_task(void *pvParameters) { - char mode = EOS_CELL_UART_MODE_NONE; - char _mode = EOS_CELL_UART_MODE_NONE; + char mode = EOS_CELL_UART_MODE_ATCMD; + char _mode = EOS_CELL_UART_MODE_ATCMD; uart_event_t event; + xSemaphoreTake(uart_mutex, portMAX_DELAY); while (1) { /* Waiting for UART event. */ @@ -196,10 +198,10 @@ static int modem_atcmd_init(void) { r = at_expect("^ATE0", NULL, 1000); r = at_expect("^OK", "^ERROR", 1000); - eos_modem_write("AT+CSCLK=1\r", 11); - r = at_expect("^OK", "^ERROR", 1000); eos_modem_write("AT+CFGRI=1\r", 11); r = at_expect("^OK", "^ERROR", 1000); + eos_modem_write("AT+CSCLK=1\r", 11); + r = at_expect("^OK", "^ERROR", 1000); buf = eos_net_alloc(); buf[0] = EOS_CELL_MTYPE_READY; @@ -700,7 +702,7 @@ void eos_modem_give(void) { xSemaphoreGive(mutex); } -void eos_modem_sleep(void) { +void eos_modem_sleep(uint8_t mode) { int r; xSemaphoreTake(mutex, portMAX_DELAY); @@ -710,22 +712,30 @@ void eos_modem_sleep(void) { ESP_LOGE(TAG, "Obtaining mutex before sleep failed"); } gpio_set_level(UART_GPIO_DTR, 1); + if (mode == EOS_PWR_SMODE_DEEP) { + gpio_hold_en(UART_GPIO_DTR); + } } -void eos_modem_wake(uint8_t source) { +void eos_modem_wake(uint8_t source, uint8_t mode) { if (source == EOS_PWR_WAKE_UART) { modem_event_t evt; evt.type = MODEM_ETYPE_RI; xQueueSend(modem_queue, &evt, portMAX_DELAY); } - gpio_set_intr_type(UART_GPIO_RI, GPIO_INTR_NEGEDGE); - gpio_isr_handler_add(UART_GPIO_RI, uart_ri_isr_handler, NULL); - gpio_set_level(UART_GPIO_DTR, 0); - modem_set_mode(uart_mode); - xSemaphoreGive(uart_mutex); - xSemaphoreGive(mutex); + if (mode != EOS_PWR_SMODE_DEEP) { + gpio_set_intr_type(UART_GPIO_RI, GPIO_INTR_NEGEDGE); + gpio_isr_handler_add(UART_GPIO_RI, uart_ri_isr_handler, NULL); + gpio_set_level(UART_GPIO_DTR, 0); + + modem_set_mode(uart_mode); + xSemaphoreGive(uart_mutex); + xSemaphoreGive(mutex); + } else { + gpio_hold_dis(UART_GPIO_DTR); + } } void eos_ppp_set_apn(char *apn) { diff --git a/code/esp32/components/eos/include/cell.h b/code/esp32/components/eos/include/cell.h index 17847ce..23adecf 100644 --- a/code/esp32/components/eos/include/cell.h +++ b/code/esp32/components/eos/include/cell.h @@ -35,8 +35,8 @@ int eos_modem_set_mode(uint8_t mode); int eos_modem_take(uint32_t timeout); void eos_modem_give(void); -void eos_modem_sleep(void); -void eos_modem_wake(uint8_t source); +void eos_modem_sleep(uint8_t mode); +void eos_modem_wake(uint8_t source, uint8_t mode); void eos_ppp_set_apn(char *apn); void eos_ppp_set_auth(char *user, char *pass); diff --git a/code/esp32/components/eos/include/i2c.h b/code/esp32/components/eos/include/i2c.h index 995a77e..144f5e1 100644 --- a/code/esp32/components/eos/include/i2c.h +++ b/code/esp32/components/eos/include/i2c.h @@ -2,6 +2,7 @@ #include void eos_i2c_init(void); + int eos_i2c_read(uint8_t addr, uint8_t reg, uint8_t *data, size_t len); uint8_t eos_i2c_read8(uint8_t addr, uint8_t reg); int eos_i2c_write(uint8_t addr, uint8_t reg, uint8_t *data, size_t len); diff --git a/code/esp32/components/eos/include/net.h b/code/esp32/components/eos/include/net.h index 818776e..54bad6d 100644 --- a/code/esp32/components/eos/include/net.h +++ b/code/esp32/components/eos/include/net.h @@ -25,9 +25,10 @@ typedef void (*eos_net_fptr_t) (unsigned char, unsigned char *, uint16_t); void eos_net_init(void); + unsigned char *eos_net_alloc(void); void eos_net_free(unsigned char *buf); int eos_net_send(unsigned char mtype, unsigned char *buffer, uint16_t len, uint8_t flags); void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler); -void eos_net_sleep_done(void); -void eos_net_wake(uint8_t source); +void eos_net_sleep_done(uint8_t mode); +void eos_net_wake(uint8_t source, uint8_t mode); diff --git a/code/esp32/components/eos/include/power.h b/code/esp32/components/eos/include/power.h index 8a35a04..0a57b19 100644 --- a/code/esp32/components/eos/include/power.h +++ b/code/esp32/components/eos/include/power.h @@ -2,12 +2,19 @@ #define EOS_PWR_MTYPE_BUTTON 0 +#define EOS_PWR_WAKE_RST 0 #define EOS_PWR_WAKE_BTN 1 #define EOS_PWR_WAKE_NET 2 #define EOS_PWR_WAKE_MSG 3 #define EOS_PWR_WAKE_UART 4 +#define EOS_PWR_SMODE_LIGHT 1 +#define EOS_PWR_SMODE_DEEP 2 + void eos_power_init(void); + +void eos_power_wait4init(void); +uint8_t eos_power_wakeup_cause(void); void eos_power_sleep(void); void eos_power_wake(uint8_t source); void eos_power_net_ready(void); \ No newline at end of file diff --git a/code/esp32/components/eos/net.c b/code/esp32/components/eos/net.c index 07434f7..9a4a024 100644 --- a/code/esp32/components/eos/net.c +++ b/code/esp32/components/eos/net.c @@ -27,7 +27,7 @@ #define SPI_SIZE_BUF (EOS_NET_SIZE_BUF + 8) -static volatile char net_sleep; +static volatile char net_sleep = 0; static EOSBufQ net_buf_q; static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; @@ -94,6 +94,12 @@ static void net_xchg_task(void *pvParameters) { spi_tr.tx_buffer = buf_send; spi_tr.rx_buffer = buf_recv; + if (eos_power_wakeup_cause()) { + wake = 1; + repeat = 1; + } + + eos_power_wait4init(); while (1) { if (!repeat) { xSemaphoreTake(mutex, portMAX_DELAY); @@ -127,7 +133,7 @@ static void net_xchg_task(void *pvParameters) { buf_recv[1] = 0; buf_recv[2] = 0; spi_slave_transmit(VSPI_HOST, &spi_tr, portMAX_DELAY); - // ESP_LOGD(TAG, "RECV:%d", buf_recv[0]); + ESP_LOGD(TAG, "RECV:%d", buf_recv[0]); if (wake) { eos_power_net_ready(); @@ -154,9 +160,9 @@ static void net_xchg_task(void *pvParameters) { net_sleep = 0; xSemaphoreGive(mutex); + spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1); wake = 1; repeat = 1; - spi_slave_initialize(VSPI_HOST, &spi_bus_cfg, &spi_slave_cfg, 1); } continue; } @@ -258,15 +264,16 @@ void eos_net_set_handler(unsigned char mtype, eos_net_fptr_t handler) { mtype_handler[mtype-1] = handler; } -void eos_net_sleep_done(void) { +void eos_net_sleep_done(uint8_t mode) { gpio_set_level(SPI_GPIO_CTS, 1); vTaskDelay(200 / portTICK_PERIOD_MS); gpio_set_level(SPI_GPIO_CTS, 0); } -void eos_net_wake(uint8_t source) { +void eos_net_wake(uint8_t source, uint8_t mode) { int sleep; + if (mode == EOS_PWR_SMODE_DEEP) return; do { vTaskResume(net_xchg_task_handle); vTaskDelay(10 / portTICK_PERIOD_MS); diff --git a/code/esp32/components/eos/power.c b/code/esp32/components/eos/power.c index 77f2d05..f07e67b 100644 --- a/code/esp32/components/eos/power.c +++ b/code/esp32/components/eos/power.c @@ -13,14 +13,14 @@ #include "cell.h" #include "power.h" -#define POWER_GPIO_BTN 0 -#define POWER_GPIO_NET 5 -#define POWER_GPIO_UART 35 +#define POWER_GPIO_BTN 0 +#define POWER_GPIO_NET 5 +#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_BTN 1 +#define POWER_ETYPE_SLEEP 2 +#define POWER_ETYPE_WAKE 3 +#define POWER_ETYPE_NETRDY 4 typedef struct { uint8_t type; @@ -38,6 +38,8 @@ static const char *TAG = "EOS POWER"; static QueueHandle_t power_queue; +static volatile int init_done = 0; + static void IRAM_ATTR btn_handler(void *arg) { power_event_t evt; @@ -77,51 +79,71 @@ static void IRAM_ATTR uart_wake_handler(void *arg) { xQueueSendFromISR(power_queue, &evt, NULL); } -void power_sleep(void) { +void power_sleep(uint8_t mode) { gpio_config_t io_conf; - eos_modem_sleep(); + eos_modem_sleep(mode); + eos_net_sleep_done(mode); - 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); + 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); - 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); - 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); - eos_net_sleep_done(); + ESP_LOGD(TAG, "SLEEP"); - ESP_LOGD(TAG, "SLEEP"); + esp_pm_lock_release(power_lock_apb_freq); + esp_pm_lock_release(power_lock_no_sleep); - esp_pm_lock_release(power_lock_apb_freq); - esp_pm_lock_release(power_lock_no_sleep); -} + break; -void power_wake_stage1(uint8_t source) { - gpio_config_t io_conf; + 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_pm_lock_acquire(power_lock_apb_freq); - esp_pm_lock_acquire(power_lock_no_sleep); + ESP_LOGD(TAG, "SLEEP"); - gpio_wakeup_disable(POWER_GPIO_BTN); - gpio_wakeup_disable(POWER_GPIO_NET); - gpio_wakeup_disable(POWER_GPIO_UART); + esp_deep_sleep_start(); + break; - 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); + default: + break; + } +} + +void power_wake_stage1(uint8_t source, uint8_t mode) { + gpio_config_t io_conf; + + if (mode == EOS_PWR_SMODE_LIGHT) { + 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); + + 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)) { @@ -130,11 +152,12 @@ void power_wake_stage1(uint8_t source) { vTaskDelay(200 / portTICK_PERIOD_MS); gpio_set_direction(POWER_GPIO_BTN, GPIO_MODE_INPUT); } - eos_net_wake(source); + + eos_net_wake(source, mode); } -void power_wake_stage2(uint8_t source) { - eos_modem_wake(source); +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); @@ -145,15 +168,28 @@ void power_wake_stage2(uint8_t source) { static void power_event_task(void *pvParameters) { unsigned char *buf; power_event_t evt; - uint8_t source = 0; - int sleep = 0; + uint8_t source; + uint8_t wakeup_cause; + uint8_t mode; + int sleep; + + source = 0; + wakeup_cause = eos_power_wakeup_cause(); + if (wakeup_cause) { + mode = EOS_PWR_SMODE_DEEP; + sleep = 1; + } else { + mode = EOS_PWR_SMODE_LIGHT; + sleep = 0; + } while (1) { if (xQueueReceive(power_queue, &evt, portMAX_DELAY)) { switch (evt.type) { case POWER_ETYPE_SLEEP: if (!sleep) { - power_sleep(); + mode = EOS_PWR_SMODE_DEEP; + power_sleep(mode); sleep = 1; } break; @@ -161,13 +197,13 @@ static void power_event_task(void *pvParameters) { case POWER_ETYPE_WAKE: if (sleep) { source = evt.source; - power_wake_stage1(source); + power_wake_stage1(source, mode); } break; case POWER_ETYPE_NETRDY: if (sleep && source) { - power_wake_stage2(source); + power_wake_stage2(source, mode); sleep = 0; source = 0; } @@ -192,6 +228,7 @@ void eos_power_init(void) { esp_err_t ret; gpio_config_t io_conf; esp_pm_config_esp32_t pwr_conf; + uint8_t wakeup_cause; io_conf.intr_type = GPIO_INTR_ANYEDGE; io_conf.mode = GPIO_MODE_INPUT; @@ -201,8 +238,14 @@ void eos_power_init(void) { gpio_config(&io_conf); gpio_isr_handler_add(POWER_GPIO_BTN, btn_handler, NULL); - ret = esp_sleep_enable_gpio_wakeup(); + /* + 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); + */ ret = esp_pm_lock_create(ESP_PM_CPU_FREQ_MAX, 0, NULL, &power_lock_cpu_freq); assert(ret == ESP_OK); @@ -227,9 +270,34 @@ void eos_power_init(void) { 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_power_wake(wakeup_cause); + + init_done = 1; ESP_LOGI(TAG, "INIT"); } +void eos_power_wait4init(void) { + while (!init_done); +} + +uint8_t eos_power_wakeup_cause(void) { + esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause(); + + switch (cause) { + case ESP_SLEEP_WAKEUP_EXT0: + return EOS_PWR_WAKE_BTN; + + case ESP_SLEEP_WAKEUP_EXT1: + return EOS_PWR_WAKE_UART; + + default: + case ESP_SLEEP_WAKEUP_UNDEFINED: + return EOS_PWR_WAKE_RST; + } +} + void eos_power_sleep(void) { power_event_t evt; diff --git a/code/esp32/main/app_main.c b/code/esp32/main/app_main.c index bd2e3e1..b700a8e 100644 --- a/code/esp32/main/app_main.c +++ b/code/esp32/main/app_main.c @@ -1,5 +1,9 @@ +#include +#include + #include #include +#include #include "i2c.h" #include "cell.h" @@ -15,11 +19,12 @@ void app_main() { tcpip_adapter_init(); + eos_net_init(); + eos_pcm_init(); gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT); eos_modem_init(); - eos_net_init(); eos_cell_init(); eos_wifi_init(); eos_sock_init(); -- cgit v1.2.3