Преглед изворни кода

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
Ivan Grokhotkov пре 5 година
родитељ
комит
5b291c032a
1 измењених фајлова са 18 додато и 4 уклоњено
  1. 18 4
      components/esp32s2/sleep_modes.c

+ 18 - 4
components/esp32s2/sleep_modes.c

@@ -34,6 +34,7 @@
 #include "soc/soc_memory_layout.h"
 #include "soc/soc_memory_layout.h"
 #include "soc/uart_caps.h"
 #include "soc/uart_caps.h"
 #include "hal/wdt_hal.h"
 #include "hal/wdt_hal.h"
+#include "hal/clk_gate_ll.h"
 #include "driver/rtc_io.h"
 #include "driver/rtc_io.h"
 #include "driver/uart.h"
 #include "driver/uart.h"
 #include "freertos/FreeRTOS.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)
 static void IRAM_ATTR flush_uarts(void)
 {
 {
     for (int i = 0; i < SOC_UART_NUM; ++i) {
     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)
 static void IRAM_ATTR suspend_uarts(void)
 {
 {
     for (int i = 0; i < SOC_UART_NUM; ++i) {
     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)
 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)
 static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)