diff --git a/components/esp_system/sleep_modes.c b/components/esp_system/sleep_modes.c index b21a43d077..4ecf1da2d7 100644 --- a/components/esp_system/sleep_modes.c +++ b/components/esp_system/sleep_modes.c @@ -232,20 +232,17 @@ static void IRAM_ATTR flush_uarts(void) static void IRAM_ATTR suspend_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { -#ifdef CONFIG_IDF_TARGET_ESP32 - /* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */ - REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF); - while (REG_GET_FIELD(UART_STATUS_REG(i), UART_ST_UTX_OUT) != 0) { - ; - } -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - 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) { - ; - } - } +#ifndef CONFIG_IDF_TARGET_ESP32 + if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) continue; +#endif + uart_ll_force_xoff(i); +#if SOC_UART_SUPPORT_FSM_TX_WAIT_SEND + uint32_t uart_fsm = 0; + do { + uart_fsm = uart_ll_get_fsm_status(i); + } while (!(uart_fsm == UART_FSM_IDLE || uart_fsm == UART_FSM_TX_WAIT_SEND)); +#else + while (uart_ll_get_fsm_status(i) != 0) {} #endif } } @@ -253,17 +250,10 @@ static void IRAM_ATTR suspend_uarts(void) static void IRAM_ATTR resume_uarts(void) { for (int i = 0; i < SOC_UART_NUM; ++i) { -#ifdef CONFIG_IDF_TARGET_ESP32 - 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_FORCE_XON); -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - 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); - } +#ifndef CONFIG_IDF_TARGET_ESP32 + if (!periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) continue; #endif + uart_ll_force_xon(i); } } diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index e749014a72..66f4c028d1 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -894,6 +894,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return tout_thrd; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + /* Note: Set `UART_FORCE_XOFF` can't stop new Tx request. */ + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #undef UART_LL_TOUT_REF_FACTOR_DEFAULT #ifdef __cplusplus diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index cd39b40afe..a06cc72d70 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -884,6 +884,47 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return UART_RX_TOUT_THRHD_V; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); + REG_SET_BIT(UART_ID_REG(uart_num), UART_UPDATE); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); + REG_SET_BIT(UART_ID_REG(uart_num), UART_UPDATE); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index 012396a0ee..e0685fd713 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -826,6 +826,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return UART_RX_TOUT_THRHD_V; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 14d6be3593..c5a167b298 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -852,6 +852,45 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) return UART_RX_TOUT_THRHD_V; } +/** + * @brief Force UART xoff. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xoff(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); +} + +/** + * @brief Force UART xon. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return None. + */ +static inline void uart_ll_force_xon(uart_port_t uart_num) +{ + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XOFF); + REG_SET_BIT(UART_FLOW_CONF_REG(uart_num), UART_FORCE_XON); + REG_CLR_BIT(UART_FLOW_CONF_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); +} + +/** + * @brief Get UART final state machine status. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return UART module FSM status. + */ +static inline uint32_t uart_ll_get_fsm_status(uart_port_t uart_num) +{ + return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); +} + #ifdef __cplusplus } #endif diff --git a/components/soc/esp32c3/include/soc/uart_caps.h b/components/soc/esp32c3/include/soc/uart_caps.h index 28a3c43b30..bcbca36a3b 100644 --- a/components/soc/esp32c3/include/soc/uart_caps.h +++ b/components/soc/esp32c3/include/soc/uart_caps.h @@ -27,6 +27,11 @@ extern "C" { // ESP32-C3 have 2 UART #define SOC_UART_NUM (2) +// UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled +#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +#define UART_FSM_IDLE (0x0) +#define UART_FSM_TX_WAIT_SEND (0xf) + #ifdef __cplusplus } #endif