From 31cd3f1294e62ec940f86dbd555eb61fe72ac2e5 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 28 Apr 2020 19:40:12 +0200 Subject: [PATCH 1/3] esp32s2: suspend UART output using XOFF before entering light sleep Same logic as for the ESP32, except two changes: * need to set UART_SW_FLOW_CON_EN bit for UART_FORCE_XOFF to take effect * need to check if the peripheral is not clockgated and out of reset --- components/esp32s2/sleep_modes.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/components/esp32s2/sleep_modes.c b/components/esp32s2/sleep_modes.c index 2fc3541a6..4d71206e4 100644 --- a/components/esp32s2/sleep_modes.c +++ b/components/esp32s2/sleep_modes.c @@ -34,6 +34,7 @@ #include "soc/soc_memory_layout.h" #include "soc/uart_caps.h" #include "hal/wdt_hal.h" +#include "hal/clk_gate_ll.h" #include "driver/rtc_io.h" #include "driver/uart.h" #include "freertos/FreeRTOS.h" @@ -144,21 +145,34 @@ void esp_deep_sleep(uint64_t time_in_us) static void IRAM_ATTR flush_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { - uart_tx_wait_idle(i); + if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) { + uart_tx_wait_idle(i); + } } } static void IRAM_ATTR suspend_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { - uart_tx_wait_idle(i); - /* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */ + if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) { + REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); + while (REG_GET_FIELD(UART_FSM_STATUS_REG(i), UART_ST_UTX_OUT) != 0) { + ; + } + } } } static void IRAM_ATTR resume_uarts(void) { - /* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */ + for (int i = 0; i < SOC_UART_NUM; ++i) { + if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) { + REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XON); + } + } } static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags) From 3a88ac790084961dec55b2f2350f5ff5805c74b6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 3 Jun 2020 15:43:25 +0200 Subject: [PATCH 2/3] soc: add periph_ll_periph_enabled to clk_gate_ll.h --- components/soc/src/esp32/include/hal/clk_gate_ll.h | 6 ++++++ components/soc/src/esp32s2/include/hal/clk_gate_ll.h | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/components/soc/src/esp32/include/hal/clk_gate_ll.h b/components/soc/src/esp32/include/hal/clk_gate_ll.h index 7849433bb..23e90cdaa 100644 --- a/components/soc/src/esp32/include/hal/clk_gate_ll.h +++ b/components/soc/src/esp32/include/hal/clk_gate_ll.h @@ -248,6 +248,12 @@ static inline void periph_ll_reset(periph_module_t periph) DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); } +static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) +{ + return DPORT_REG_GET_BIT(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)) == 0 && + DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/components/soc/src/esp32s2/include/hal/clk_gate_ll.h b/components/soc/src/esp32s2/include/hal/clk_gate_ll.h index 261398f95..8e93bece8 100644 --- a/components/soc/src/esp32s2/include/hal/clk_gate_ll.h +++ b/components/soc/src/esp32s2/include/hal/clk_gate_ll.h @@ -260,6 +260,12 @@ static inline void periph_ll_reset(periph_module_t periph) DPORT_CLEAR_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)); } +static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) +{ + return DPORT_REG_GET_BIT(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false)) != 0 && + DPORT_REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; +} + #ifdef __cplusplus } #endif From 4ed889dfa2668d4c2553a71f8d7e839ee25639f0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 16 Jun 2020 18:31:46 +0200 Subject: [PATCH 3/3] esp32s2: sleep_modes: remove dependency on driver/uart.h --- components/esp32s2/sleep_modes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/esp32s2/sleep_modes.c b/components/esp32s2/sleep_modes.c index 4d71206e4..6be663e4c 100644 --- a/components/esp32s2/sleep_modes.c +++ b/components/esp32s2/sleep_modes.c @@ -36,7 +36,6 @@ #include "hal/wdt_hal.h" #include "hal/clk_gate_ll.h" #include "driver/rtc_io.h" -#include "driver/uart.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "sdkconfig.h" @@ -585,9 +584,9 @@ esp_err_t esp_sleep_enable_gpio_wakeup(void) esp_err_t esp_sleep_enable_uart_wakeup(int uart_num) { - if (uart_num == UART_NUM_0) { + if (uart_num == 0) { s_config.wakeup_triggers |= RTC_UART0_TRIG_EN; - } else if (uart_num == UART_NUM_1) { + } else if (uart_num == 1) { s_config.wakeup_triggers |= RTC_UART1_TRIG_EN; } else { return ESP_ERR_INVALID_ARG;