From bc2a6bd73006846bb8f896e05995013c5df01c07 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Tue, 26 Sep 2023 17:42:03 +0800 Subject: [PATCH] feat(uart): spilt LP and HP uart set_baudrate function --- .../driver/include/esp_private/uart_private.h | 19 ++--- components/driver/uart/uart.c | 38 ++++++---- components/esp_pm/pm_impl.c | 5 +- components/esp_rom/include/esp_rom_uart.h | 2 + components/esp_system/port/cpu_start.c | 1 - .../esp_system_unity_tests/main/test_sleep.c | 4 +- components/hal/esp32/include/hal/uart_ll.h | 8 +- components/hal/esp32c2/include/hal/uart_ll.h | 8 +- components/hal/esp32c3/include/hal/uart_ll.h | 8 +- components/hal/esp32c6/include/hal/uart_ll.h | 60 ++++++++++----- components/hal/esp32h2/include/hal/uart_ll.h | 8 +- components/hal/esp32p4/include/hal/uart_ll.h | 76 ++++++++++++------- components/hal/esp32s2/include/hal/uart_ll.h | 8 +- components/hal/esp32s3/include/hal/uart_ll.h | 8 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 7 +- components/ulp/lp_core/lp_core_uart.c | 6 +- examples/system/.build-test-rules.yml | 8 +- 17 files changed, 155 insertions(+), 119 deletions(-) diff --git a/components/driver/include/esp_private/uart_private.h b/components/driver/include/esp_private/uart_private.h index 863ed73472..e132593b1e 100644 --- a/components/driver/include/esp_private/uart_private.h +++ b/components/driver/include/esp_private/uart_private.h @@ -7,27 +7,28 @@ #pragma once -#include "sdkconfig.h" +#include "soc/soc_caps.h" #include "esp_private/periph_ctrl.h" #ifdef __cplusplus extern "C" { #endif -#if (SOC_UART_LP_NUM >= 1) -#define LP_UART_CLK_ATOMIC() PERIPH_RCC_ATOMIC() -#endif - #if SOC_PERIPH_CLK_CTRL_SHARED -#define UART_SCLK_ATOMIC() PERIPH_RCC_ATOMIC() +#define HP_UART_SRC_CLK_ATOMIC() PERIPH_RCC_ATOMIC() #else -#define UART_SCLK_ATOMIC() +#define HP_UART_SRC_CLK_ATOMIC() #endif #if SOC_RCC_IS_INDEPENDENT -#define UART_CLK_ATOMIC() +#define HP_UART_BUS_CLK_ATOMIC() #else -#define UART_CLK_ATOMIC() PERIPH_RCC_ATOMIC() +#define HP_UART_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC() +#endif + +#if (SOC_UART_LP_NUM >= 1) +#define LP_UART_SRC_CLK_ATOMIC() PERIPH_RCC_ATOMIC() +#define LP_UART_BUS_CLK_ATOMIC() PERIPH_RCC_ATOMIC() #endif #ifdef __cplusplus diff --git a/components/driver/uart/uart.c b/components/driver/uart/uart.c index 31cc1e8de9..90dfae109d 100644 --- a/components/driver/uart/uart.c +++ b/components/driver/uart/uart.c @@ -179,24 +179,24 @@ static void uart_module_enable(uart_port_t uart_num) UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); if (uart_context[uart_num].hw_enabled != true) { if (uart_num < SOC_UART_HP_NUM) { - UART_CLK_ATOMIC() { + HP_UART_BUS_CLK_ATOMIC() { uart_ll_enable_bus_clock(uart_num, true); } if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM) { // Workaround for ESP32C3/S3: enable core reset before enabling uart module clock to prevent uart output // garbage value. #if SOC_UART_REQUIRE_CORE_RESET - UART_SCLK_ATOMIC(){ + HP_UART_SRC_CLK_ATOMIC(){ uart_hal_set_reset_core(&(uart_context[uart_num].hal), true); } - UART_CLK_ATOMIC() { + HP_UART_BUS_CLK_ATOMIC() { uart_ll_reset_register(uart_num); } - UART_SCLK_ATOMIC(){ + HP_UART_SRC_CLK_ATOMIC(){ uart_hal_set_reset_core(&(uart_context[uart_num].hal), false); } #else - UART_CLK_ATOMIC() { + HP_UART_BUS_CLK_ATOMIC() { uart_ll_reset_register(uart_num); } #endif @@ -204,7 +204,7 @@ static void uart_module_enable(uart_port_t uart_num) } #if (SOC_UART_LP_NUM >= 1) else { - LP_UART_CLK_ATOMIC() { + LP_UART_BUS_CLK_ATOMIC() { lp_uart_ll_enable_bus_clock(uart_num - SOC_UART_HP_NUM, true); lp_uart_ll_reset_register(uart_num - SOC_UART_HP_NUM); } @@ -220,13 +220,13 @@ static void uart_module_disable(uart_port_t uart_num) UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); if (uart_context[uart_num].hw_enabled != false) { if (uart_num != CONFIG_ESP_CONSOLE_UART_NUM && uart_num < SOC_UART_HP_NUM) { - UART_CLK_ATOMIC() { + HP_UART_BUS_CLK_ATOMIC() { uart_ll_enable_bus_clock(uart_num, false); } } #if (SOC_UART_LP_NUM >= 1) else if (uart_num >= SOC_UART_HP_NUM) { - LP_UART_CLK_ATOMIC() { + LP_UART_BUS_CLK_ATOMIC() { lp_uart_ll_enable_bus_clock(uart_num - SOC_UART_HP_NUM, false); } } @@ -306,9 +306,18 @@ esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baud_rate) ESP_RETURN_ON_ERROR(esp_clk_tree_src_get_freq_hz(src_clk, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq), UART_TAG, "Invalid src_clk"); UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); - UART_SCLK_ATOMIC() { - uart_hal_set_baudrate(&(uart_context[uart_num].hal), baud_rate, sclk_freq); + + if (uart_num < SOC_UART_HP_NUM) { + HP_UART_SRC_CLK_ATOMIC() { + uart_hal_set_baudrate(&(uart_context[uart_num].hal), baud_rate, sclk_freq); + } } +#if (SOC_UART_LP_NUM >= 1) + else { + lp_uart_ll_set_baudrate(uart_context[uart_num].hal.dev, baud_rate, sclk_freq); + } +#endif + UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } @@ -818,20 +827,19 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf UART_ENTER_CRITICAL(&(uart_context[uart_num].spinlock)); uart_hal_init(&(uart_context[uart_num].hal), uart_num); if (uart_num < SOC_UART_HP_NUM) { - UART_SCLK_ATOMIC() { + HP_UART_SRC_CLK_ATOMIC() { uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel); + uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->baud_rate, sclk_freq); } } #if (SOC_UART_LP_NUM >= 1) else { - LP_UART_CLK_ATOMIC() { + LP_UART_SRC_CLK_ATOMIC() { lp_uart_ll_set_source_clk(uart_context[uart_num].hal.dev, (soc_periph_lp_uart_clk_src_t)uart_sclk_sel); } + lp_uart_ll_set_baudrate(uart_context[uart_num].hal.dev, uart_config->baud_rate, sclk_freq); } #endif - UART_SCLK_ATOMIC() { - uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->baud_rate, sclk_freq); - } 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); diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 50f4772788..50ee36ecf8 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -43,7 +43,6 @@ #include "esp_private/sleep_cpu.h" #include "esp_private/sleep_gpio.h" #include "esp_private/sleep_modem.h" -#include "esp_private/periph_ctrl.h" #include "esp_sleep.h" #include "sdkconfig.h" @@ -742,13 +741,13 @@ void esp_pm_impl_init(void) ; } /* When DFS is enabled, override system setting and use REFTICK as UART clock source */ - UART_SCLK_ATOMIC() { + HP_UART_SRC_CLK_ATOMIC() { uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source); } uint32_t sclk_freq; esp_err_t err = uart_get_sclk_freq(clk_source, &sclk_freq); assert(err == ESP_OK); - UART_SCLK_ATOMIC() { + HP_UART_SRC_CLK_ATOMIC() { uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq); } #endif // CONFIG_ESP_CONSOLE_UART diff --git a/components/esp_rom/include/esp_rom_uart.h b/components/esp_rom/include/esp_rom_uart.h index 2e2904d573..c9350f5554 100644 --- a/components/esp_rom/include/esp_rom_uart.h +++ b/components/esp_rom/include/esp_rom_uart.h @@ -34,6 +34,8 @@ void esp_rom_uart_tx_wait_idle(uint8_t uart_no); * @param uart_no UART port number * @param clock_hz Source clock (in Hz) * @param baud_rate Baud rate to set + * + * @note Only for HP UART */ #define esp_rom_uart_set_clock_baudrate(uart_no, clock_hz, baud_rate) uart_ll_set_baudrate(UART_LL_GET_HW(uart_no), baud_rate, clock_hz) diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index 459632e01a..c66bb282aa 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -91,7 +91,6 @@ #include "esp_cpu.h" #include "esp_private/esp_clk.h" #include "spi_flash_mmap.h" -#include "esp_private/periph_ctrl.h" #if CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX || CONFIG_ESP32S3_TRAX #include "esp_private/trax.h" diff --git a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c index cc65f7f5c6..e5cb5a3176 100644 --- a/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c +++ b/components/esp_system/test_apps/esp_system_unity_tests/main/test_sleep.c @@ -230,12 +230,12 @@ TEST_CASE("light sleep and frequency switching", "[deepsleep]") #elif SOC_UART_SUPPORT_XTAL_CLK clk_source = UART_SCLK_XTAL; #endif - UART_SCLK_ATOMIC() { + HP_UART_SRC_CLK_ATOMIC() { uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source); } uint32_t sclk_freq; TEST_ESP_OK(uart_get_sclk_freq(clk_source, &sclk_freq)); - UART_SCLK_ATOMIC() { + HP_UART_SRC_CLK_ATOMIC() { uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq); } #endif diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index 45ce8b8e9c..2988523c42 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -11,7 +11,6 @@ #pragma once #include -#include "hal/assert.h" #include "hal/misc.h" #include "esp_attr.h" #include "soc/uart_reg.h" @@ -66,7 +65,6 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - HAL_ASSERT(uart_num < SOC_UART_HP_NUM); uint32_t uart_rst_bit = ((uart_num == 0) ? DPORT_UART_RST : (uart_num == 1) ? DPORT_UART1_RST : (uart_num == 2) ? DPORT_UART2_RST : 0); @@ -85,8 +83,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { uint32_t reg_val = DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG); - switch (uart_num) - { + switch (uart_num) { case 0: reg_val = reg_val & (~DPORT_UART_CLK_EN); reg_val = reg_val | (enable << 2); @@ -113,8 +110,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); diff --git a/components/hal/esp32c2/include/hal/uart_ll.h b/components/hal/esp32c2/include/hal/uart_ll.h index 8e5d1a24a1..dd9784b1a9 100644 --- a/components/hal/esp32c2/include/hal/uart_ll.h +++ b/components/hal/esp32c2/include/hal/uart_ll.h @@ -12,7 +12,6 @@ #include #include "hal/uart_types.h" #include "hal/misc.h" -#include "hal/assert.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/clk_tree_defs.h" @@ -69,7 +68,6 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - HAL_ASSERT(uart_num < SOC_UART_HP_NUM); uint32_t uart_rst_bit = ((uart_num == 0) ? SYSTEM_UART_RST : (uart_num == 1) ? SYSTEM_UART1_RST : 0); uint32_t uart_en_bit = ((uart_num == 0) ? SYSTEM_UART_CLK_EN : @@ -85,8 +83,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) */ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { - switch (uart_num) - { + switch (uart_num) { case 0: SYSTEM.perip_clk_en0.uart_clk_en = enable; break; @@ -107,8 +104,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: SYSTEM.perip_rst_en0.uart_rst = 1; SYSTEM.perip_rst_en0.uart_rst = 0; diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index d9148d5de7..409e1e463c 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -11,7 +11,6 @@ #pragma once #include -#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" @@ -69,7 +68,6 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - HAL_ASSERT(uart_num < SOC_UART_HP_NUM); uint32_t uart_rst_bit = ((uart_num == 0) ? SYSTEM_UART_RST : (uart_num == 1) ? SYSTEM_UART1_RST : 0); uint32_t uart_en_bit = ((uart_num == 0) ? SYSTEM_UART_CLK_EN : @@ -85,8 +83,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) */ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { - switch (uart_num) - { + switch (uart_num) { case 0: SYSTEM.perip_clk_en0.reg_uart_clk_en = enable; break; @@ -107,8 +104,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: SYSTEM.perip_rst_en0.reg_uart_rst = 1; SYSTEM.perip_rst_en0.reg_uart_rst = 0; diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index 6468eb3b46..f24c417053 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -85,6 +85,19 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Sync the update to UART core clock domain + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) +{ + hw->reg_update.reg_update = 1; + while (hw->reg_update.reg_update); +} + /****************************************** LP_UART Specific ********************************************/ /** * @brief Get the LP_UART source clock. @@ -131,6 +144,32 @@ static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_ /// LP_CLKRST.lpperi is a shared register, so this function must be used in an atomic way #define lp_uart_ll_set_source_clk(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_set_source_clk(__VA_ARGS__) +/** + * @brief Configure the lp uart baud-rate. + * + * @param hw Beginning address of the peripheral registers. + * @param baud The baud rate to be set. + * @param sclk_freq Frequency of the clock source of UART, in Hz. + * + * @return None + */ +FORCE_INLINE_ATTR void lp_uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq) +{ +#define DIV_UP(a, b) (((a) + (b) - 1) / (b)) + const uint32_t max_div = BIT(12) - 1; // UART divider integer part only has 12 bits + uint32_t sclk_div = DIV_UP(sclk_freq, (uint64_t)max_div * baud); + + if (sclk_div == 0) abort(); + + uint32_t clk_div = ((sclk_freq) << 4) / (baud * sclk_div); + // The baud rate configuration register is divided into + // an integer part and a fractional part. + hw->clkdiv_sync.clkdiv_int = clk_div >> 4; + hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); + uart_ll_update(hw); +} + /** * @brief Enable bus clock for the LP UART module * @@ -190,8 +229,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) */ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { - switch (uart_num) - { + switch (uart_num) { case 0: PCR.uart0_conf.uart0_clk_en = enable; break; @@ -211,8 +249,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: PCR.uart0_conf.uart0_rst_en = 1; PCR.uart0_conf.uart0_rst_en = 0; @@ -228,19 +265,6 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) } } -/** - * @brief Sync the update to UART core clock domain - * - * @param hw Beginning address of the peripheral registers. - * - * @return None. - */ -FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) -{ - hw->reg_update.reg_update = 1; - while (hw->reg_update.reg_update); -} - /** * @brief Configure the UART core reset. * @@ -382,7 +406,7 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint3 hw->clkdiv_sync.clkdiv_int = clk_div >> 4; hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; if ((hw) == &LP_UART) { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); + abort(); } else { UART_LL_PCR_REG_U32_SET(hw, sclk_conf, sclk_div_num, sclk_div - 1); } diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index 4927bc2559..eacd7f8edb 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -12,7 +12,6 @@ #include #include "esp_attr.h" -#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" @@ -91,7 +90,6 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - HAL_ASSERT(uart_num < SOC_UART_HP_NUM); uint32_t uart_clk_config_reg = ((uart_num == 0) ? PCR_UART0_CONF_REG : (uart_num == 1) ? PCR_UART1_CONF_REG : 0); uint32_t uart_rst_bit = ((uart_num == 0) ? PCR_UART0_RST_EN : @@ -109,8 +107,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) */ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { - switch (uart_num) - { + switch (uart_num) { case 0: PCR.uart0_conf.uart0_clk_en = enable; break; @@ -129,8 +126,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: PCR.uart0_conf.uart0_rst_en = 1; PCR.uart0_conf.uart0_rst_en = 0; diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index 383836b2c5..6efd8531f6 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -69,6 +69,19 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Sync the update to UART core clock domain + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) +{ + hw->reg_update.reg_update = 1; + while (hw->reg_update.reg_update); +} + /****************************************** LP_UART Specific ********************************************/ /** * @brief Get the LP_UART source clock. @@ -99,7 +112,7 @@ FORCE_INLINE_ATTR void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *sou * @param hw Address offset of the LP UART peripheral registers * @param src_clk Source clock for the LP UART peripheral */ -FORCE_INLINE_ATTR void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_clk_src_t src_clk) +static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_clk_src_t src_clk) { (void)hw; switch (src_clk) { @@ -121,13 +134,40 @@ FORCE_INLINE_ATTR void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_u // LPPERI.core_clk_sel is a shared register, so this function must be used in an atomic way #define lp_uart_ll_set_source_clk(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_set_source_clk(__VA_ARGS__) +/** + * @brief Configure the lp uart baud-rate. + * + * @param hw Beginning address of the peripheral registers. + * @param baud The baud rate to be set. + * @param sclk_freq Frequency of the clock source of UART, in Hz. + * + * @return None + */ +FORCE_INLINE_ATTR void lp_uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq) +{ +#define DIV_UP(a, b) (((a) + (b) - 1) / (b)) + const uint32_t max_div = BIT(12) - 1; // UART divider integer part only has 12 bits + uint32_t sclk_div = DIV_UP(sclk_freq, (uint64_t)max_div * baud); + if (sclk_div == 0) abort(); + + uint32_t clk_div = ((sclk_freq) << 4) / (baud * sclk_div); + // The baud rate configuration register is divided into + // an integer part and a fractional part. + hw->clkdiv_sync.clkdiv = clk_div >> 4; + hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; + //needs force u32 write + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); +#undef DIV_UP + uart_ll_update(hw); +} + /** * @brief Enable bus clock for the LP UART module * * @param hw_id LP UART instance ID * @param enable True to enable, False to disable */ -FORCE_INLINE_ATTR void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) +static inline void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) { (void)hw_id; LPPERI.clk_en.ck_en_lp_uart = enable; @@ -141,7 +181,7 @@ FORCE_INLINE_ATTR void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) * * @param hw_id LP UART instance ID */ -FORCE_INLINE_ATTR void lp_uart_ll_reset_register(int hw_id) +static inline void lp_uart_ll_reset_register(int hw_id) { (void)hw_id; LPPERI.reset_en.rst_en_lp_uart = 1; @@ -166,8 +206,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) bool uart_rst_en = false; bool uart_apb_en = false; bool uart_sys_en = false; - switch (uart_num) - { + switch (uart_num) { case 0: uart_rst_en = HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart0_apb; uart_apb_en = HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart0_apb_clk_en; @@ -204,10 +243,9 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). * @param enable true to enable, false to disable */ -FORCE_INLINE_ATTR void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { - switch (uart_num) - { + switch (uart_num) { case 0: HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart0_apb_clk_en = enable; HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart0_sys_clk_en = enable; @@ -243,10 +281,9 @@ FORCE_INLINE_ATTR void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enabl * @brief Reset UART module * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). */ -FORCE_INLINE_ATTR void uart_ll_reset_register(uart_port_t uart_num) +static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart0_apb = 1; HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart0_apb = 0; @@ -278,19 +315,6 @@ FORCE_INLINE_ATTR void uart_ll_reset_register(uart_port_t uart_num) // HP_SYS_CLKRST.hp_rst_en1 is a shared register, so this function must be used in an atomic way #define uart_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_reset_register(__VA_ARGS__) -/** - * @brief Sync the update to UART core clock domain - * - * @param hw Beginning address of the peripheral registers. - * - * @return None. - */ -FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) -{ - hw->reg_update.reg_update = 1; - while (hw->reg_update.reg_update); -} - /** * @brief Configure the UART core reset. * @@ -490,8 +514,8 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint3 HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl114, reg_uart3_sclk_div_num, sclk_div - 1); } else if ((hw) == &UART4) { HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num, sclk_div - 1); - } else if ((hw) == &LP_UART) { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); + } else { + abort(); } #undef DIV_UP uart_ll_update(hw); diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index ab7d4941be..6f7a804abc 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -11,7 +11,6 @@ #pragma once #include -#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" @@ -65,7 +64,6 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - HAL_ASSERT(uart_num < SOC_UART_HP_NUM); uint32_t uart_rst_bit = ((uart_num == 0) ? DPORT_UART_RST : (uart_num == 1) ? DPORT_UART1_RST : 0); uint32_t uart_en_bit = ((uart_num == 0) ? DPORT_UART_CLK_EN : @@ -82,8 +80,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { uint32_t reg_val = READ_PERI_REG(DPORT_PERIP_CLK_EN0_REG); - switch (uart_num) - { + switch (uart_num) { case 0: reg_val = reg_val & (~DPORT_UART_CLK_EN); reg_val = reg_val | (enable << DPORT_UART_CLK_EN_S); @@ -106,8 +103,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART_RST); diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 37af33b240..265fa7d24d 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -11,7 +11,6 @@ #pragma once #include -#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" @@ -69,7 +68,6 @@ typedef enum { */ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) { - HAL_ASSERT(uart_num < SOC_UART_HP_NUM); uint32_t uart_rst_bit = ((uart_num == 0) ? SYSTEM_UART_RST : (uart_num == 1) ? SYSTEM_UART1_RST : (uart_num == 2) ? SYSTEM_UART2_RST : 0); @@ -87,8 +85,7 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) */ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) { - switch (uart_num) - { + switch (uart_num) { case 0: SYSTEM.perip_clk_en0.uart_clk_en = enable; break; @@ -112,8 +109,7 @@ static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) */ static inline void uart_ll_reset_register(uart_port_t uart_num) { - switch (uart_num) - { + switch (uart_num) { case 0: SYSTEM.perip_rst_en0.uart_rst = 1; SYSTEM.perip_rst_en0.uart_rst = 0; diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 0a8bec16fc..7e9d7e61c9 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -278,7 +278,12 @@ typedef enum { LP_UART_SCLK_LP_FAST = SOC_MOD_CLK_RTC_FAST, /*!< LP_UART source clock is LP(RTC)_FAST */ LP_UART_SCLK_XTAL_D2 = SOC_MOD_CLK_XTAL_D2, /*!< LP_UART source clock is XTAL_D2 */ LP_UART_SCLK_LP_PLL = SOC_MOD_CLK_LP_PLL, /*!< LP_UART source clock is LP_PLL (8M PLL) */ - LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_XTAL_D2, /*!< LP_UART source clock default choice is XTAL_D2 */ +#if SOC_CLK_TREE_SUPPORTED + LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_RTC_FAST, +#else + LP_UART_SCLK_DEFAULT = SOC_MOD_CLK_XTAL_D2, /*!< LP_UART source clock default choice is XTAL_D2 */ +#endif + } soc_periph_lp_uart_clk_src_t; //////////////////////////////////////////////////MCPWM///////////////////////////////////////////////////////////////// diff --git a/components/ulp/lp_core/lp_core_uart.c b/components/ulp/lp_core/lp_core_uart.c index 94e22e85d6..4a4fad93a1 100644 --- a/components/ulp/lp_core/lp_core_uart.c +++ b/components/ulp/lp_core/lp_core_uart.c @@ -48,14 +48,12 @@ static esp_err_t lp_core_uart_param_config(const lp_core_uart_cfg_t *cfg) } // LP UART clock source is mixed with other peripherals in the same register - PERIPH_RCC_ATOMIC() { + LP_UART_SRC_CLK_ATOMIC() { lp_uart_ll_set_source_clk(hal.dev, clk_src); } /* Override protocol parameters from the configuration */ - UART_SCLK_ATOMIC() { - uart_hal_set_baudrate(&hal, cfg->uart_proto_cfg.baud_rate, sclk_freq); - } + lp_uart_ll_set_baudrate(hal.dev, cfg->uart_proto_cfg.baud_rate, sclk_freq); uart_hal_set_parity(&hal, cfg->uart_proto_cfg.parity); uart_hal_set_data_bit_num(&hal, cfg->uart_proto_cfg.data_bits); uart_hal_set_stop_bits(&hal, cfg->uart_proto_cfg.stop_bits); diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index c0ac2807a0..79a808ee1b 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -204,12 +204,12 @@ examples/system/ulp/lp_core/lp_i2c: - if: SOC_LP_I2C_SUPPORTED == 1 examples/system/ulp/lp_core/lp_uart/lp_uart_echo: - enable: - - if: SOC_ULP_LP_UART_SUPPORTED == 1 + disable: + - if: SOC_ULP_LP_UART_SUPPORTED != 1 examples/system/ulp/lp_core/lp_uart/lp_uart_print: - enable: - - if: SOC_ULP_LP_UART_SUPPORTED == 1 + disable: + - if: SOC_ULP_LP_UART_SUPPORTED != 1 examples/system/ulp/ulp_fsm/ulp: disable: