From 5b291c032aaec9701b5a65c331f9715588b1f1f4 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 28 Apr 2020 19:40:12 +0200 Subject: [PATCH] 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)