From 05a4a8d8645c88bd5b1cee6c83782b853687e301 Mon Sep 17 00:00:00 2001 From: Armando Date: Mon, 23 Nov 2020 19:31:50 +0800 Subject: [PATCH] uart: seperate sclk and baudrate setting --- components/driver/uart.c | 52 ++++++++++++++++++-- components/esp32/test/test_dport.c | 6 ++- components/esp_pm/pm_impl.c | 3 +- components/esp_system/test/test_sleep.c | 3 +- components/hal/esp32/include/hal/uart_ll.h | 7 +-- components/hal/esp32s2/include/hal/uart_ll.h | 7 +-- components/hal/esp32s3/include/hal/uart_ll.h | 5 +- components/hal/include/hal/uart_hal.h | 3 +- components/hal/uart_hal.c | 15 ++---- 9 files changed, 66 insertions(+), 35 deletions(-) diff --git a/components/driver/uart.c b/components/driver/uart.c index 49b718611d..8ef0977859 100644 --- a/components/driver/uart.c +++ b/components/driver/uart.c @@ -24,6 +24,7 @@ #include "freertos/ringbuf.h" #include "hal/uart_hal.h" #include "soc/uart_periph.h" +#include "soc/rtc_cntl_reg.h" #include "driver/uart.h" #include "driver/gpio.h" #include "driver/uart_select.h" @@ -84,6 +85,10 @@ static const char* UART_TAG = "uart"; .hw_enabled = false,\ } +#if SOC_UART_SUPPORT_RTC_CLK +#define RTC_ENABLED(uart_num) (BIT(uart_num)) +#endif + typedef struct { uart_event_type_t type; /*!< UART TX data type */ struct { @@ -158,6 +163,34 @@ static uart_context_t uart_context[UART_NUM_MAX] = { static portMUX_TYPE uart_selectlock = portMUX_INITIALIZER_UNLOCKED; +#if SOC_UART_SUPPORT_RTC_CLK + +static uint8_t rtc_enabled = 0; +static portMUX_TYPE rtc_num_spinlock = portMUX_INITIALIZER_UNLOCKED; + +static void rtc_clk_enable(uart_port_t uart_num) +{ + portENTER_CRITICAL(&rtc_num_spinlock); + if (!(rtc_enabled & RTC_ENABLED(uart_num))) { + rtc_enabled |= RTC_ENABLED(uart_num); + } + SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + portEXIT_CRITICAL(&rtc_num_spinlock); +} + +static void rtc_clk_disable(uart_port_t uart_num) +{ + assert(rtc_enabled & RTC_ENABLED(uart_num)); + + portENTER_CRITICAL(&rtc_num_spinlock); + rtc_enabled &= ~RTC_ENABLED(uart_num); + if (rtc_enabled == 0) { + CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); + } + portEXIT_CRITICAL(&rtc_num_spinlock); +} +#endif + static void uart_module_enable(uart_port_t uart_num) { UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); @@ -236,10 +269,8 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode) esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) { UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_FAIL); - uart_sclk_t source_clk = 0; UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - uart_hal_get_sclk(&(uart_context[uart_num].hal), &source_clk); - uart_hal_set_baudrate(&(uart_context[uart_num].hal), source_clk, baud_rate); + uart_hal_set_baudrate(&(uart_context[uart_num].hal), baud_rate); UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } @@ -626,10 +657,15 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf UART_CHECK((uart_config->flow_ctrl < UART_HW_FLOWCTRL_MAX), "hw_flowctrl mode error", ESP_FAIL); UART_CHECK((uart_config->data_bits < UART_DATA_BITS_MAX), "data bit error", ESP_FAIL); uart_module_enable(uart_num); +#if SOC_UART_SUPPORT_RTC_CLK + if (uart_config->source_clk == UART_SCLK_RTC) { + rtc_clk_enable(uart_num); + } +#endif UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_init(&(uart_context[uart_num].hal), uart_num); uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_config->source_clk); - uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->source_clk, uart_config->baud_rate); + uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->baud_rate); uart_hal_set_parity(&(uart_context[uart_num].hal), uart_config->parity); uart_hal_set_data_bit_num(&(uart_context[uart_num].hal), uart_config->data_bits); uart_hal_set_stop_bits(&(uart_context[uart_num].hal), uart_config->stop_bits); @@ -1417,6 +1453,14 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) heap_caps_free(p_uart_obj[uart_num]); p_uart_obj[uart_num] = NULL; +#if SOC_UART_SUPPORT_RTC_CLK + + uart_sclk_t sclk = 0; + uart_hal_get_sclk(&(uart_context[uart_num].hal), &sclk); + if (sclk == UART_SCLK_RTC) { + rtc_clk_disable(uart_num); + } +#endif uart_module_disable(uart_num); return ESP_OK; } diff --git a/components/esp32/test/test_dport.c b/components/esp32/test/test_dport.c index 84b62be367..c8719fcdb7 100644 --- a/components/esp32/test/test_dport.c +++ b/components/esp32/test/test_dport.c @@ -130,7 +130,8 @@ void run_tasks_with_change_freq_cpu(int cpu_freq_mhz) esp_rom_uart_tx_wait_idle(uart_num); rtc_clk_cpu_freq_set_config(&new_config); - uart_ll_set_baudrate(UART_LL_GET_HW(uart_num), UART_SCLK_APB, uart_baud); + uart_ll_set_sclk(UART_LL_GET_HW(uart_num), UART_SCLK_APB); + uart_ll_set_baudrate(UART_LL_GET_HW(uart_num), uart_baud); /* adjust RTOS ticks */ _xt_tick_divisor = cpu_freq_mhz * 1000000 / XT_TICK_PER_SEC; vTaskDelay(2); @@ -142,7 +143,8 @@ void run_tasks_with_change_freq_cpu(int cpu_freq_mhz) // return old freq. esp_rom_uart_tx_wait_idle(uart_num); rtc_clk_cpu_freq_set_config(&old_config); - uart_ll_set_baudrate(UART_LL_GET_HW(uart_num), UART_SCLK_APB, uart_baud); + uart_ll_set_sclk(UART_LL_GET_HW(uart_num), UART_SCLK_APB); + uart_ll_set_baudrate(UART_LL_GET_HW(uart_num), uart_baud); _xt_tick_divisor = old_config.freq_mhz * 1000000 / XT_TICK_PER_SEC; } diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 7a1990db0d..92ab65347d 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -689,7 +689,8 @@ void esp_pm_impl_init(void) #endif while(!uart_ll_is_tx_idle(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM))); /* When DFS is enabled, override system setting and use REFTICK as UART clock source */ - uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), clk_source, CONFIG_ESP_CONSOLE_UART_BAUDRATE); + uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), clk_source); + uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif // CONFIG_ESP_CONSOLE_UART #ifdef CONFIG_PM_TRACE diff --git a/components/esp_system/test/test_sleep.c b/components/esp_system/test/test_sleep.c index e7b5d9a1f9..9c3e8d9ad2 100644 --- a/components/esp_system/test/test_sleep.c +++ b/components/esp_system/test/test_sleep.c @@ -191,7 +191,8 @@ TEST_CASE("light sleep duration is correct", "[deepsleep][ignore]") TEST_CASE("light sleep and frequency switching", "[deepsleep]") { #ifndef CONFIG_PM_ENABLE - uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), UART_SCLK_REF_TICK, CONFIG_ESP_CONSOLE_UART_BAUDRATE); + uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), UART_SCLK_REF_TICK); + uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif rtc_cpu_freq_config_t config_xtal, config_default; diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index 87cc42d80a..47ed21abf7 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -102,16 +102,13 @@ static inline uint32_t uart_ll_get_sclk_freq(uart_dev_t *hw) * * @param hw Beginning address of the peripheral registers. * @param baud The baud-rate to be set. When the source clock is APB, the max baud-rate is `UART_LL_BITRATE_MAX` - * @param source_clk The UART source clock. The source clock can be APB clock or REF_TICK. - * If the source clock is REF_TICK, the UART can still work when the APB changes. - * + * @return None */ -static inline void uart_ll_set_baudrate(uart_dev_t *hw, uart_sclk_t source_clk, uint32_t baud) +static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) { uint32_t sclk_freq, clk_div; - uart_ll_set_sclk(hw, source_clk); sclk_freq = uart_ll_get_sclk_freq(hw); clk_div = ((sclk_freq) << 4) / baud; // The baud-rate configuration register is divided into diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index c8a721b940..6bc3b120d1 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -99,16 +99,13 @@ static inline uint32_t uart_ll_get_sclk_freq(uart_dev_t *hw) * * @param hw Beginning address of the peripheral registers. * @param baud The baud rate to be set. When the source clock is APB, the max baud rate is `UART_LL_BITRATE_MAX` - * @param source_clk The UART source clock. The source clock can be APB clock or REF_TICK. - * If the source clock is REF_TICK, the UART can still work when the APB changes. - * + * @return None */ -static inline void uart_ll_set_baudrate(uart_dev_t *hw, uart_sclk_t source_clk, uint32_t baud) +static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) { uint32_t sclk_freq, clk_div; - uart_ll_set_sclk(hw, source_clk); sclk_freq = uart_ll_get_sclk_freq(hw); clk_div = ((sclk_freq) << 4) / baud; // The baud rate configuration register is divided into diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 6a6be04c13..bd61350a3c 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -129,17 +129,14 @@ static inline uint32_t uart_ll_get_sclk_freq(uart_dev_t *hw) * @brief Configure the baud-rate. * * @param hw Beginning address of the peripheral registers. - * @param source_clk The UART source clock. The source clock can be APB clock, RTC clock or XTAL clock. - * If the source clock is RTC/XTAL, the UART can still work when the APB changes. * @param baud The baud rate to be set. When the source clock is APB, the max baud rate is `UART_LL_BITRATE_MAX` * * @return None */ -static inline void uart_ll_set_baudrate(uart_dev_t *hw, uart_sclk_t source_clk, uint32_t baud) +static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud) { uint32_t sclk_freq, clk_div; - uart_ll_set_sclk(hw, source_clk); sclk_freq = uart_ll_get_sclk_freq(hw); clk_div = ((sclk_freq) << 4) / baud; // The baud rate configuration register is divided into diff --git a/components/hal/include/hal/uart_hal.h b/components/hal/include/hal/uart_hal.h index 45ff08d53f..d236431dca 100644 --- a/components/hal/include/hal/uart_hal.h +++ b/components/hal/include/hal/uart_hal.h @@ -200,12 +200,11 @@ void uart_hal_get_sclk(uart_hal_context_t *hal, uart_sclk_t *sclk); * @brief Configure the UART baud-rate and select the source clock * * @param hal Context of the HAL layer - * @param source_clk The UART source clock. * @param baud_rate The baud-rate to be set * * @return None */ -void uart_hal_set_baudrate(uart_hal_context_t *hal, uart_sclk_t source_clk, uint32_t baud_rate); +void uart_hal_set_baudrate(uart_hal_context_t *hal, uint32_t baud_rate); /** * @brief Configure the UART stop bit diff --git a/components/hal/uart_hal.c b/components/hal/uart_hal.c index 4f243fab08..9fa9725768 100644 --- a/components/hal/uart_hal.c +++ b/components/hal/uart_hal.c @@ -14,17 +14,10 @@ // The HAL layer for UART (common part) #include "hal/uart_hal.h" -#include "soc/rtc_cntl_reg.h" void uart_hal_set_sclk(uart_hal_context_t *hal, uart_sclk_t sclk) { uart_ll_set_sclk(hal->dev, sclk); - -#if SOC_UART_SUPPORT_RTC_CLK - if (sclk == UART_SCLK_RTC) { - SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M); - } -#endif } void uart_hal_get_sclk(uart_hal_context_t *hal, uart_sclk_t *sclk) @@ -32,9 +25,9 @@ void uart_hal_get_sclk(uart_hal_context_t *hal, uart_sclk_t *sclk) uart_ll_get_sclk(hal->dev, sclk); } -void uart_hal_set_baudrate(uart_hal_context_t *hal, uart_sclk_t source_clk, uint32_t baud_rate) +void uart_hal_set_baudrate(uart_hal_context_t *hal, uint32_t baud_rate) { - uart_ll_set_baudrate(hal->dev, source_clk, baud_rate); + uart_ll_set_baudrate(hal->dev, baud_rate); } void uart_hal_get_baudrate(uart_hal_context_t *hal, uint32_t *baud_rate) @@ -144,11 +137,11 @@ void uart_hal_set_loop_back(uart_hal_context_t *hal, bool loop_back_en) void uart_hal_init(uart_hal_context_t *hal, int uart_num) { - // Set clock source + // Set default clock source uart_ll_set_sclk(hal->dev, UART_SCLK_APB); // Set default baud: 115200, use APB clock. const uint32_t baud_def = 115200; - uart_ll_set_baudrate(hal->dev, UART_SCLK_APB, baud_def); + uart_ll_set_baudrate(hal->dev, baud_def); // Set UART mode. uart_ll_set_mode(hal->dev, UART_MODE_UART); // Disable UART parity