From c7afa0dcefb61db53371634ec8627d7eaef063fc Mon Sep 17 00:00:00 2001 From: gaoxu Date: Thu, 7 Sep 2023 15:40:14 +0800 Subject: [PATCH 1/5] feat(uart): uart(hp,lp) support on esp32p4 --- .../driver/test_apps/uart/main/test_uart.c | 2 +- components/driver/uart/uart.c | 79 ++- .../port/esp32p4/esp_clk_tree.c | 6 + components/hal/esp32p4/include/hal/uart_ll.h | 542 +++++++++++++----- components/hal/include/hal/uart_types.h | 8 +- .../esp32p4/include/soc/Kconfig.soc_caps.in | 8 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 18 +- .../soc/esp32p4/include/soc/lpperi_struct.h | 3 +- components/soc/esp32p4/include/soc/soc_caps.h | 9 +- .../soc/esp32p4/include/soc/uart_channel.h | 32 +- .../soc/esp32p4/include/soc/uart_pins.h | 65 +++ .../soc/esp32p4/include/soc/uart_struct.h | 21 +- .../soc/esp32p4/ld/esp32p4.peripherals.ld | 1 + components/soc/esp32p4/uart_periph.c | 203 +++++++ 14 files changed, 833 insertions(+), 164 deletions(-) diff --git a/components/driver/test_apps/uart/main/test_uart.c b/components/driver/test_apps/uart/main/test_uart.c index ccf2fc7ff7..688040e649 100644 --- a/components/driver/test_apps/uart/main/test_uart.c +++ b/components/driver/test_apps/uart/main/test_uart.c @@ -389,7 +389,7 @@ TEST_CASE("uart int state restored after flush", "[uart]") }; const uart_port_t uart_echo = UART_NUM_1; - const int uart_tx_signal = U1TXD_OUT_IDX; + const int uart_tx_signal = uart_periph_signal[uart_echo].pins[SOC_UART_TX_PIN_IDX].signal; const int uart_tx = UART1_TX_PIN; const int uart_rx = UART1_RX_PIN; const int buf_size = 256; diff --git a/components/driver/uart/uart.c b/components/driver/uart/uart.c index 543aeb4771..b4104ed020 100644 --- a/components/driver/uart/uart.c +++ b/components/driver/uart/uart.c @@ -159,6 +159,12 @@ static uart_context_t uart_context[UART_NUM_MAX] = { #if SOC_UART_HP_NUM > 2 UART_CONTEX_INIT_DEF(UART_NUM_2), #endif +#if SOC_UART_HP_NUM > 3 + UART_CONTEX_INIT_DEF(UART_NUM_3), +#endif +#if SOC_UART_HP_NUM > 4 + UART_CONTEX_INIT_DEF(UART_NUM_4), +#endif #if (SOC_UART_LP_NUM >= 1) UART_CONTEX_INIT_DEF(LP_UART_NUM_0), #endif @@ -643,7 +649,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r ESP_RETURN_ON_FALSE((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), ESP_FAIL, UART_TAG, "rts_io_num error"); ESP_RETURN_ON_FALSE((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), ESP_FAIL, UART_TAG, "cts_io_num error"); } -#if (SOC_UART_LP_NUM >= 1) +#if (SOC_UART_LP_NUM >= 1 && !SOC_LP_GPIO_MATRIX_SUPPORTED) else { // LP_UART has its fixed IOs const uart_periph_sig_t *pins = uart_periph_signal[uart_num].pins; ESP_RETURN_ON_FALSE((tx_io_num < 0 || (tx_io_num == pins[SOC_UART_TX_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "tx_io_num error"); @@ -655,31 +661,76 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r /* In the following statements, if the io_num is negative, no need to configure anything. */ if (tx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO); + if (uart_num < SOC_UART_HP_NUM) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO); gpio_set_level(tx_io_num, 1); esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + //TODO:IDF-7815 + rtc_gpio_set_direction(tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); + rtc_gpio_init(tx_io_num); + rtc_gpio_iomux_func_sel(tx_io_num, 1); + LP_GPIO.func10_out_sel_cfg.reg_gpio_func10_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_TX_PIN_IDX].signal; + } +#endif } if (rx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO); - gpio_set_pull_mode(rx_io_num, GPIO_PULLUP_ONLY); - gpio_set_direction(rx_io_num, GPIO_MODE_INPUT); - esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + if (uart_num < SOC_UART_HP_NUM) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO); + gpio_set_pull_mode(rx_io_num, GPIO_PULLUP_ONLY); + gpio_set_direction(rx_io_num, GPIO_MODE_INPUT); + esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + //TODO:IDF-7815 + rtc_gpio_set_direction(rx_io_num, RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_init(rx_io_num); + rtc_gpio_iomux_func_sel(rx_io_num, 1); + LP_GPIO.func2_in_sel_cfg.reg_gpio_sig2_in_sel = 1; + LP_GPIO.func2_in_sel_cfg.reg_gpio_func2_in_sel = 11; + } +#endif } if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO); - gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT); - esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); + if (uart_num < SOC_UART_HP_NUM) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO); + gpio_set_direction(rts_io_num, GPIO_MODE_OUTPUT); + esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + //TODO:IDF-7815 + rtc_gpio_set_direction(rts_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); + rtc_gpio_init(rts_io_num); + rtc_gpio_iomux_func_sel(rts_io_num, 1); + LP_GPIO.func10_out_sel_cfg.reg_gpio_func12_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_RTS_PIN_IDX].signal; + } +#endif } if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO); - gpio_set_pull_mode(cts_io_num, GPIO_PULLUP_ONLY); - gpio_set_direction(cts_io_num, GPIO_MODE_INPUT); - esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0); + if (uart_num < SOC_UART_HP_NUM) { + gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO); + gpio_set_pull_mode(cts_io_num, GPIO_PULLUP_ONLY); + gpio_set_direction(cts_io_num, GPIO_MODE_INPUT); + esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + //TODO:IDF-7815 + rtc_gpio_set_direction(cts_io_num, RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_init(cts_io_num); + rtc_gpio_iomux_func_sel(cts_io_num, 1); + LP_GPIO.func2_in_sel_cfg.reg_gpio_sig3_in_sel = 1; + LP_GPIO.func2_in_sel_cfg.reg_gpio_func3_in_sel = 13; + } +#endif } - return ESP_OK; } diff --git a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c index 3a1c3598b3..b538989239 100644 --- a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c @@ -25,6 +25,12 @@ uint32_t *freq_value) case SOC_MOD_CLK_XTAL: clk_src_freq = 40 * MHZ; break; + case SOC_MOD_CLK_XTAL_D2: + clk_src_freq = (40* MHZ) >> 1; + break; + case SOC_MOD_CLK_LP_PLL: + clk_src_freq = 8 * MHZ; + break; default: break; } diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index 3b3dbbbc88..1607febcc3 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -10,24 +10,34 @@ #pragma once +#include "esp_attr.h" #include "hal/misc.h" #include "hal/assert.h" #include "hal/uart_types.h" -#include "soc/uart_periph.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/hp_sys_clkrst_struct.h" +#include "soc/lp_uart_reg.h" +#include "soc/lp_clkrst_struct.h" +#include "soc/lpperi_struct.h" #ifdef __cplusplus extern "C" { #endif -//TODO: IDF-6511 - // The default fifo depth #define UART_LL_FIFO_DEF_LEN (SOC_UART_FIFO_LEN) +#define LP_UART_LL_FIFO_DEF_LEN (SOC_LP_UART_FIFO_LEN) + // Get UART hardware instance with giving uart num -#define UART_LL_GET_HW(num) (((num) == 0) ? (&UART0) : (&UART1)) +#define UART_LL_GET_HW(num) \ + ((num) == 0 ? (&UART0) : \ + (num) == 1 ? (&UART1) : \ + (num) == 2 ? (&UART2) : \ + (num) == 3 ? (&UART3) : \ + (num) == 4 ? (&UART4) : (&LP_UART)) + +#define UART_LL_REG_FIELD_BIT_SHIFT(hw) (((hw) == &LP_UART) ? 3 : 0) #define UART_LL_MIN_WAKEUP_THRESH (2) #define UART_LL_INTR_MASK (0x7ffff) //All interrupt mask @@ -59,6 +69,83 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/****************************************** LP_UART Specific ********************************************/ +/** + * @brief Get the LP_UART source clock. + * + * @param hw Beginning address of the peripheral registers. + * @param source_clk Current LP_UART clock source, one in soc_periph_lp_uart_clk_src_t. + */ +FORCE_INLINE_ATTR void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk) +{ + (void)hw; + switch (LPPERI.core_clk_sel.lp_uart_clk_sel) { + default: + case 0: + *source_clk = (soc_module_clk_t)LP_UART_SCLK_LP_FAST; + break; + case 1: + *source_clk = (soc_module_clk_t)LP_UART_SCLK_XTAL_D2; + break; + } +} + +/** + * @brief Set LP UART source clock + * + * @param hw Address offset of the LP UART peripheral registers + * @param src_clk Source clock for the LP UART peripheral + */ +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) { + case LP_UART_SCLK_LP_FAST: + LPPERI.core_clk_sel.lp_uart_clk_sel = 0; + break; + case LP_UART_SCLK_XTAL_D2: + LPPERI.core_clk_sel.lp_uart_clk_sel = 1; + break; + default: + // Invalid LP_UART clock source + HAL_ASSERT(false); + } +} + +/// 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 Enable bus clock for the LP UART module + * + * @param hw_id LP UART instance ID + * @param enable True to enable, False to disable + */ +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; +} + +/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way +#define lp_uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset LP UART module + * + * @param hw_id LP UART instance ID + */ +static inline void lp_uart_ll_reset_register(int hw_id) +{ + (void)hw_id; + LPPERI.reset_en.rst_en_lp_uart = 1; + LPPERI.reset_en.rst_en_lp_uart = 0; +} + +/// LPPERI.reset_en is a shared register, so this function must be used in an atomic way +#define lp_uart_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_reset_register(__VA_ARGS__) + +/*************************************** General LL functions ******************************************/ /** * @brief Sync the update to UART core clock domain * @@ -66,7 +153,7 @@ typedef enum { * * @return None. */ -static inline void uart_ll_update(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) { hw->reg_update.reg_update = 1; while (hw->reg_update.reg_update); @@ -80,10 +167,24 @@ static inline void uart_ll_update(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) +FORCE_INLINE_ATTR void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) { - // hw->clk_conf.rst_core = core_rst_en; - HAL_ASSERT(false); + + if ((hw) == &UART0) { + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart0_core = core_rst_en; + } else if ((hw) == &UART1) { + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_core = core_rst_en; + } else if ((hw) == &UART2) { + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_core = core_rst_en; + } else if ((hw) == &UART3) { + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_core = core_rst_en; + } else if ((hw) == &UART4) { + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_core = core_rst_en; + } else { + // LP_UART reset shares the same register with other LP peripherals + // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + abort(); + } } /** @@ -93,12 +194,39 @@ static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) * * @return None. */ -static inline void uart_ll_sclk_enable(uart_dev_t *hw) + +FORCE_INLINE_ATTR void uart_ll_sclk_enable(uart_dev_t *hw) { - // hw->clk_conf.sclk_en = 1; - // hw->clk_conf.rx_sclk_en = 1; - // hw->clk_conf.tx_sclk_en = 1; - HAL_ASSERT(false); + if ((hw) == &UART0) { + HP_SYS_CLKRST.peri_clk_ctrl110.reg_uart0_clk_en = 1; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart0_sys_clk_en = 1; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart0_apb_clk_en = 1; + } else if ((hw) == &UART1) { + HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart1_clk_en = 1; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = 1; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = 1; + } else if ((hw) == &UART2) { + HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart2_clk_en = 1; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = 1; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = 1; + } else if ((hw) == &UART3) { + HP_SYS_CLKRST.peri_clk_ctrl113.reg_uart3_clk_en = 1; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = 1; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = 1; + } else if ((hw) == &UART4) { + HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_en = 1; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = 1; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = 1; + } else { + // LP_UART reset shares the same register with other LP peripherals + // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + abort(); + } } /** @@ -108,12 +236,38 @@ static inline void uart_ll_sclk_enable(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_sclk_disable(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) { - // hw->clk_conf.sclk_en = 0; - // hw->clk_conf.rx_sclk_en = 0; - // hw->clk_conf.tx_sclk_en = 0; - HAL_ASSERT(false); + if ((hw) == &UART0) { + HP_SYS_CLKRST.peri_clk_ctrl110.reg_uart0_clk_en = 0; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart0_sys_clk_en = 0; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart0_apb_clk_en = 0; + } else if ((hw) == &UART1) { + HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart1_clk_en = 0; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = 0; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = 0; + } else if ((hw) == &UART2) { + HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart2_clk_en = 0; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = 0; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = 0; + } else if ((hw) == &UART3) { + HP_SYS_CLKRST.peri_clk_ctrl113.reg_uart3_clk_en = 0; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = 0; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = 0; + } else if ((hw) == &UART4) { + HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_en = 0; + //To do: call these two in clk_gate_ll.h + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = 0; + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = 0; + } else { + // LP_UART reset shares the same register with other LP peripherals + // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + abort(); + } } /** @@ -125,8 +279,38 @@ static inline void uart_ll_sclk_disable(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_clk) +FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_clk) { + uint32_t sel_value = 0; + switch (source_clk) { + case UART_SCLK_XTAL: + sel_value = 0; + break; + case UART_SCLK_RTC: + sel_value = 1; + break; + case UART_SCLK_PLL_F80M: + sel_value = 2; + break; + default: + // Invalid HP_UART clock source + abort(); + } + if ((hw) == &UART0) { + HP_SYS_CLKRST.peri_clk_ctrl110.reg_uart0_clk_src_sel = sel_value; + } else if ((hw) == &UART1) { + HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart1_clk_src_sel = sel_value; + } else if ((hw) == &UART2) { + HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart2_clk_src_sel = sel_value; + } else if ((hw) == &UART3) { + HP_SYS_CLKRST.peri_clk_ctrl113.reg_uart3_clk_src_sel = sel_value; + } else if ((hw) == &UART4) { + HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_src_sel = sel_value; + } else { + // LP_UART reset shares the same register with other LP peripherals + // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + abort(); + } } /** @@ -137,8 +321,36 @@ static inline void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_clk) * * @return None. */ -static inline void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk) +FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk) { + uint32_t sel_value = 0; + if ((hw) == &UART0) { + sel_value = HP_SYS_CLKRST.peri_clk_ctrl110.reg_uart0_clk_src_sel; + } else if ((hw) == &UART1) { + sel_value = HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart1_clk_src_sel; + } else if ((hw) == &UART2) { + sel_value = HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart2_clk_src_sel; + } else if ((hw) == &UART3) { + sel_value = HP_SYS_CLKRST.peri_clk_ctrl113.reg_uart3_clk_src_sel; + } else if ((hw) == &UART4) { + sel_value = HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_src_sel; + } + if ((hw) != &LP_UART) { + switch (sel_value) { + default: + case 1: + *source_clk = (soc_module_clk_t)UART_SCLK_RTC; + break; + case 0: + *source_clk = (soc_module_clk_t)UART_SCLK_XTAL; + break; + case 2: + *source_clk = (soc_module_clk_t)UART_SCLK_PLL_F80M; + break; + } + } else { + lp_uart_ll_get_sclk(hw, source_clk); + } } /** @@ -150,27 +362,37 @@ static inline void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source_clk * * @return None */ -static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq) +FORCE_INLINE_ATTR void 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 - int sclk_div = DIV_UP(sclk_freq, max_div * baud); - - 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 - if ((hw) == &UART0) { - HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart0_sclk_div_num = sclk_div - 1; + if ((hw) == &LP_UART){ + uint32_t clk_div = ((sclk_freq) << 4) / (baud); + hw->clkdiv_sync.clkdiv = clk_div >> 4; + hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; } else { - HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart1_sclk_div_num = sclk_div - 1; - } +#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 + int sclk_div = DIV_UP(sclk_freq, max_div * baud); + 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 + if ((hw) == &UART0) { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl111, reg_uart0_sclk_div_num, sclk_div - 1); + } else if ((hw) == &UART1){ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl112, reg_uart1_sclk_div_num, sclk_div - 1); + } else if ((hw) == &UART2){ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl113, reg_uart2_sclk_div_num, sclk_div - 1); + } else if ((hw) == &UART3){ + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl114, reg_uart3_sclk_div_num, sclk_div - 1); + } else { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num, sclk_div - 1); + } + } #undef DIV_UP - uart_ll_update(hw); // TODO: IDF-5338 + uart_ll_update(hw); } /** @@ -181,12 +403,25 @@ static inline void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t * * @return The current baudrate */ -static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq) +FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq) { - // typeof(hw->clkdiv_sync) div_reg = hw->clkdiv_sync; - // return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * (HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1)); - HAL_ASSERT(false); - return 115200; // TODO: IDF-5338 + typeof(hw->clkdiv_sync) div_reg; + div_reg.val = hw->clkdiv_sync.val; + int sclk_div = 0; + if ((hw) == &UART0) { + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl111, reg_uart0_sclk_div_num) + 1; + } else if ((hw) == &UART1){ + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl112, reg_uart1_sclk_div_num) + 1; + } else if ((hw) == &UART2){ + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl113, reg_uart2_sclk_div_num) + 1; + } else if ((hw) == &UART3){ + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl114, reg_uart3_sclk_div_num) + 1; + } else if ((hw) == &UART4){ + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num) + 1; + } else { + return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag)); + } + return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * sclk_div); } /** @@ -197,9 +432,9 @@ static inline uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_freq) * * @return None */ -static inline void uart_ll_ena_intr_mask(uart_dev_t *hw, uint32_t mask) +FORCE_INLINE_ATTR void uart_ll_ena_intr_mask(uart_dev_t *hw, uint32_t mask) { - hw->int_ena.val |= mask; + hw->int_ena.val = hw->int_ena.val | mask; } /** @@ -210,9 +445,9 @@ static inline void uart_ll_ena_intr_mask(uart_dev_t *hw, uint32_t mask) * * @return None */ -static inline void uart_ll_disable_intr_mask(uart_dev_t *hw, uint32_t mask) +FORCE_INLINE_ATTR void uart_ll_disable_intr_mask(uart_dev_t *hw, uint32_t mask) { - hw->int_ena.val &= (~mask); + hw->int_ena.val = hw->int_ena.val & (~mask); } /** @@ -222,7 +457,7 @@ static inline void uart_ll_disable_intr_mask(uart_dev_t *hw, uint32_t mask) * * @return The UART interrupt status. */ -static inline uint32_t uart_ll_get_intraw_mask(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_intraw_mask(uart_dev_t *hw) { return hw->int_raw.val; } @@ -234,7 +469,7 @@ static inline uint32_t uart_ll_get_intraw_mask(uart_dev_t *hw) * * @return The UART interrupt status. */ -static inline uint32_t uart_ll_get_intsts_mask(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_intsts_mask(uart_dev_t *hw) { return hw->int_st.val; } @@ -247,7 +482,7 @@ static inline uint32_t uart_ll_get_intsts_mask(uart_dev_t *hw) * * @return None */ -static inline void uart_ll_clr_intsts_mask(uart_dev_t *hw, uint32_t mask) +FORCE_INLINE_ATTR void uart_ll_clr_intsts_mask(uart_dev_t *hw, uint32_t mask) { hw->int_clr.val = mask; } @@ -259,7 +494,7 @@ static inline void uart_ll_clr_intsts_mask(uart_dev_t *hw, uint32_t mask) * * @return interrupt enable value */ -static inline uint32_t uart_ll_get_intr_ena_status(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_intr_ena_status(uart_dev_t *hw) { return hw->int_ena.val; } @@ -273,10 +508,10 @@ static inline uint32_t uart_ll_get_intr_ena_status(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_t rd_len) +FORCE_INLINE_ATTR void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_t rd_len) { for (int i = 0; i < (int)rd_len; i++) { - buf[i] = HAL_FORCE_READ_U32_REG_FIELD(hw->fifo, rxfifo_rd_byte); + buf[i] = hw->fifo.rxfifo_rd_byte; } } @@ -289,10 +524,10 @@ static inline void uart_ll_read_rxfifo(uart_dev_t *hw, uint8_t *buf, uint32_t rd * * @return None */ -static inline void uart_ll_write_txfifo(uart_dev_t *hw, const uint8_t *buf, uint32_t wr_len) +FORCE_INLINE_ATTR void uart_ll_write_txfifo(uart_dev_t *hw, const uint8_t *buf, uint32_t wr_len) { for (int i = 0; i < (int)wr_len; i++) { - HAL_FORCE_MODIFY_U32_REG_FIELD(hw->fifo, rxfifo_rd_byte, buf[i]); + hw->fifo.rxfifo_rd_byte = buf[i]; } } @@ -303,7 +538,7 @@ static inline void uart_ll_write_txfifo(uart_dev_t *hw, const uint8_t *buf, uint * * @return None */ -static inline void uart_ll_rxfifo_rst(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_rxfifo_rst(uart_dev_t *hw) { hw->conf0_sync.rxfifo_rst = 1; uart_ll_update(hw); @@ -318,7 +553,7 @@ static inline void uart_ll_rxfifo_rst(uart_dev_t *hw) * * @return None */ -static inline void uart_ll_txfifo_rst(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_txfifo_rst(uart_dev_t *hw) { hw->conf0_sync.txfifo_rst = 1; uart_ll_update(hw); @@ -333,9 +568,9 @@ static inline void uart_ll_txfifo_rst(uart_dev_t *hw) * * @return The readable data length in rxfifo. */ -static inline uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) { - return hw->status.rxfifo_cnt; + return (hw->status.rxfifo_cnt) >> UART_LL_REG_FIELD_BIT_SHIFT(hw); } /** @@ -345,9 +580,11 @@ static inline uint32_t uart_ll_get_rxfifo_len(uart_dev_t *hw) * * @return The data length of txfifo can be written. */ -static inline uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw) { - return UART_LL_FIFO_DEF_LEN - hw->status.txfifo_cnt; + uint32_t total_fifo_len = ((hw) == &LP_UART) ? LP_UART_LL_FIFO_DEF_LEN : UART_LL_FIFO_DEF_LEN; + uint32_t txfifo_len = (hw->status.txfifo_cnt) >> UART_LL_REG_FIELD_BIT_SHIFT(hw); + return (total_fifo_len - txfifo_len); } /** @@ -358,7 +595,7 @@ static inline uint32_t uart_ll_get_txfifo_len(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_bit) +FORCE_INLINE_ATTR void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_bit) { hw->conf0_sync.stop_bit_num = stop_bit; uart_ll_update(hw); @@ -372,7 +609,7 @@ static inline void uart_ll_set_stop_bits(uart_dev_t *hw, uart_stop_bits_t stop_b * * @return None. */ -static inline void uart_ll_get_stop_bits(uart_dev_t *hw, uart_stop_bits_t *stop_bit) +FORCE_INLINE_ATTR void uart_ll_get_stop_bits(uart_dev_t *hw, uart_stop_bits_t *stop_bit) { *stop_bit = (uart_stop_bits_t)hw->conf0_sync.stop_bit_num; } @@ -385,7 +622,7 @@ static inline void uart_ll_get_stop_bits(uart_dev_t *hw, uart_stop_bits_t *stop_ * * @return None. */ -static inline void uart_ll_set_parity(uart_dev_t *hw, uart_parity_t parity_mode) +FORCE_INLINE_ATTR void uart_ll_set_parity(uart_dev_t *hw, uart_parity_t parity_mode) { if (parity_mode != UART_PARITY_DISABLE) { hw->conf0_sync.parity = parity_mode & 0x1; @@ -402,7 +639,7 @@ static inline void uart_ll_set_parity(uart_dev_t *hw, uart_parity_t parity_mode) * * @return None. */ -static inline void uart_ll_get_parity(uart_dev_t *hw, uart_parity_t *parity_mode) +FORCE_INLINE_ATTR void uart_ll_get_parity(uart_dev_t *hw, uart_parity_t *parity_mode) { if (hw->conf0_sync.parity_en) { *parity_mode = (uart_parity_t)(0x2 | hw->conf0_sync.parity); @@ -416,13 +653,13 @@ static inline void uart_ll_get_parity(uart_dev_t *hw, uart_parity_t *parity_mode * it will produce rxfifo_full_int_raw interrupt. * * @param hw Beginning address of the peripheral registers. - * @param full_thrhd The full threshold value of the rxfifo. `full_thrhd` should be less than `UART_LL_FIFO_DEF_LEN`. + * @param full_thrhd The full threshold value of the rxfifo. `full_thrhd` should be less than `(LP_)UART_LL_FIFO_DEF_LEN`. * * @return None. */ -static inline void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thrhd) +FORCE_INLINE_ATTR void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thrhd) { - hw->conf1.rxfifo_full_thrhd = full_thrhd; + hw->conf1.rxfifo_full_thrhd = full_thrhd << UART_LL_REG_FIELD_BIT_SHIFT(hw); } /** @@ -434,9 +671,9 @@ static inline void uart_ll_set_rxfifo_full_thr(uart_dev_t *hw, uint16_t full_thr * * @return None. */ -static inline void uart_ll_set_txfifo_empty_thr(uart_dev_t *hw, uint16_t empty_thrhd) +FORCE_INLINE_ATTR void uart_ll_set_txfifo_empty_thr(uart_dev_t *hw, uint16_t empty_thrhd) { - hw->conf1.txfifo_empty_thrhd = empty_thrhd; + hw->conf1.txfifo_empty_thrhd = empty_thrhd << UART_LL_REG_FIELD_BIT_SHIFT(hw); } /** @@ -448,7 +685,7 @@ static inline void uart_ll_set_txfifo_empty_thr(uart_dev_t *hw, uint16_t empty_t * * @return None. */ -static inline void uart_ll_set_rx_idle_thr(uart_dev_t *hw, uint32_t rx_idle_thr) +FORCE_INLINE_ATTR void uart_ll_set_rx_idle_thr(uart_dev_t *hw, uint32_t rx_idle_thr) { hw->idle_conf_sync.rx_idle_thrhd = rx_idle_thr; uart_ll_update(hw); @@ -462,7 +699,7 @@ static inline void uart_ll_set_rx_idle_thr(uart_dev_t *hw, uint32_t rx_idle_thr) * * @return None. */ -static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) +FORCE_INLINE_ATTR void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) { hw->idle_conf_sync.tx_idle_num = idle_num; uart_ll_update(hw); @@ -476,7 +713,7 @@ static inline void uart_ll_set_tx_idle_num(uart_dev_t *hw, uint32_t idle_num) * * @return None. */ -static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) +FORCE_INLINE_ATTR void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) { if (break_num > 0) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->txbrk_conf_sync, tx_brk_num, break_num); @@ -496,11 +733,11 @@ static inline void uart_ll_tx_break(uart_dev_t *hw, uint32_t break_num) * * @return None. */ -static inline void uart_ll_set_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t flow_ctrl, uint32_t rx_thrs) +FORCE_INLINE_ATTR void uart_ll_set_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t flow_ctrl, uint32_t rx_thrs) { //only when UART_HW_FLOWCTRL_RTS is set , will the rx_thresh value be set. if (flow_ctrl & UART_HW_FLOWCTRL_RTS) { - hw->hwfc_conf_sync.rx_flow_thrhd = rx_thrs; + hw->hwfc_conf_sync.rx_flow_thrhd = rx_thrs << UART_LL_REG_FIELD_BIT_SHIFT(hw); hw->hwfc_conf_sync.rx_flow_en = 1; } else { hw->hwfc_conf_sync.rx_flow_en = 0; @@ -521,7 +758,7 @@ static inline void uart_ll_set_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_ * * @return None. */ -static inline void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t *flow_ctrl) +FORCE_INLINE_ATTR void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_t *flow_ctrl) { *flow_ctrl = UART_HW_FLOWCTRL_DISABLE; if (hw->hwfc_conf_sync.rx_flow_en) { @@ -541,13 +778,13 @@ static inline void uart_ll_get_hw_flow_ctrl(uart_dev_t *hw, uart_hw_flowcontrol_ * * @return None. */ -static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t *flow_ctrl, bool sw_flow_ctrl_en) +FORCE_INLINE_ATTR void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t *flow_ctrl, bool sw_flow_ctrl_en) { if (sw_flow_ctrl_en) { hw->swfc_conf0_sync.xonoff_del = 1; hw->swfc_conf0_sync.sw_flow_con_en = 1; - hw->swfc_conf1.xon_threshold = flow_ctrl->xon_thrd; - hw->swfc_conf1.xoff_threshold = flow_ctrl->xoff_thrd; + hw->swfc_conf1.xon_threshold = (flow_ctrl->xon_thrd) << UART_LL_REG_FIELD_BIT_SHIFT(hw); + hw->swfc_conf1.xoff_threshold = (flow_ctrl->xoff_thrd) << UART_LL_REG_FIELD_BIT_SHIFT(hw); HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0_sync, xon_char, flow_ctrl->xon_char); HAL_FORCE_MODIFY_U32_REG_FIELD(hw->swfc_conf0_sync, xoff_char, flow_ctrl->xoff_char); } else { @@ -570,15 +807,14 @@ static inline void uart_ll_set_sw_flow_ctrl(uart_dev_t *hw, uart_sw_flowctrl_t * * * @return None. */ -static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) +FORCE_INLINE_ATTR void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_char) { - // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char_sync, data, cmd_char->cmd_char); - // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char_sync, char_num, cmd_char->char_num); - // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt_sync, post_idle_num, cmd_char->post_idle); - // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt_sync, pre_idle_num, cmd_char->pre_idle); - // HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout_sync, rx_gap_tout, cmd_char->gap_tout); - // uart_ll_update(hw); - HAL_ASSERT(false); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char_sync, at_cmd_char, cmd_char->cmd_char); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_char_sync, char_num, cmd_char->char_num); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_postcnt_sync, post_idle_num, cmd_char->post_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_precnt_sync, pre_idle_num, cmd_char->pre_idle); + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->at_cmd_gaptout_sync, rx_gap_tout, cmd_char->gap_tout); + uart_ll_update(hw); } /** @@ -589,7 +825,7 @@ static inline void uart_ll_set_at_cmd_char(uart_dev_t *hw, uart_at_cmd_t *cmd_ch * * @return None. */ -static inline void uart_ll_set_data_bit_num(uart_dev_t *hw, uart_word_length_t data_bit) +FORCE_INLINE_ATTR void uart_ll_set_data_bit_num(uart_dev_t *hw, uart_word_length_t data_bit) { hw->conf0_sync.bit_num = data_bit; uart_ll_update(hw); @@ -603,7 +839,7 @@ static inline void uart_ll_set_data_bit_num(uart_dev_t *hw, uart_word_length_t d * * @return None. */ -static inline void uart_ll_set_rts_active_level(uart_dev_t *hw, int level) +FORCE_INLINE_ATTR void uart_ll_set_rts_active_level(uart_dev_t *hw, int level) { hw->conf0_sync.sw_rts = level & 0x1; uart_ll_update(hw); @@ -617,7 +853,7 @@ static inline void uart_ll_set_rts_active_level(uart_dev_t *hw, int level) * * @return None. */ -static inline void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level) +FORCE_INLINE_ATTR void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level) { hw->conf1.sw_dtr = level & 0x1; } @@ -631,7 +867,7 @@ static inline void uart_ll_set_dtr_active_level(uart_dev_t *hw, int level) * * @return None. */ -static inline void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd) +FORCE_INLINE_ATTR void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd) { hw->sleep_conf2.active_threshold = wakeup_thrd - UART_LL_MIN_WAKEUP_THRESH; } @@ -643,8 +879,12 @@ static inline void uart_ll_set_wakeup_thrd(uart_dev_t *hw, uint32_t wakeup_thrd) * * @return None. */ -static inline void uart_ll_set_mode_normal(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_set_mode_normal(uart_dev_t *hw) { + // This function is only for HP_UART use + // LP_UART can only work in normal mode + // lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + hw->rs485_conf_sync.rs485_en = 0; hw->rs485_conf_sync.rs485tx_rx_en = 0; hw->rs485_conf_sync.rs485rxby_tx_en = 0; @@ -659,8 +899,12 @@ static inline void uart_ll_set_mode_normal(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw) { + // This function is only for HP_UART use + // LP_UART can only work in normal mode + // lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + // Application software control, remove echo hw->rs485_conf_sync.rs485rxby_tx_en = 1; hw->conf0_sync.irda_en = 0; @@ -679,8 +923,12 @@ static inline void uart_ll_set_mode_rs485_app_ctrl(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw) { + // This function is only for HP_UART use + // LP_UART can only work in normal mode + // lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + // Enable receiver, sw_rts = 1 generates low level on RTS pin hw->conf0_sync.sw_rts = 1; // Half duplex mode @@ -702,8 +950,12 @@ static inline void uart_ll_set_mode_rs485_half_duplex(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_mode_collision_detect(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_set_mode_collision_detect(uart_dev_t *hw) { + // This function is only for HP_UART use + // LP_UART can only work in normal mode + // lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + hw->conf0_sync.irda_en = 0; // Enable full-duplex mode hw->rs485_conf_sync.rs485tx_rx_en = 1; @@ -723,8 +975,12 @@ static inline void uart_ll_set_mode_collision_detect(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_mode_irda(uart_dev_t *hw) +FORCE_INLINE_ATTR void uart_ll_set_mode_irda(uart_dev_t *hw) { + // This function is only for HP_UART use + // LP_UART can only work in normal mode + // lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + hw->rs485_conf_sync.rs485_en = 0; hw->rs485_conf_sync.rs485tx_rx_en = 0; hw->rs485_conf_sync.rs485rxby_tx_en = 0; @@ -741,7 +997,7 @@ static inline void uart_ll_set_mode_irda(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) +FORCE_INLINE_ATTR void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) { switch (mode) { default: @@ -749,15 +1005,19 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) uart_ll_set_mode_normal(hw); break; case UART_MODE_RS485_COLLISION_DETECT: + // Only HP_UART support this mode uart_ll_set_mode_collision_detect(hw); break; case UART_MODE_RS485_APP_CTRL: + // Only HP_UART support this mode uart_ll_set_mode_rs485_app_ctrl(hw); break; case UART_MODE_RS485_HALF_DUPLEX: + // Only HP_UART support this mode uart_ll_set_mode_rs485_half_duplex(hw); break; case UART_MODE_IRDA: + // Only HP_UART support this mode uart_ll_set_mode_irda(hw); break; } @@ -772,11 +1032,10 @@ static inline void uart_ll_set_mode(uart_dev_t *hw, uart_mode_t mode) * * @return None. */ -static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) +FORCE_INLINE_ATTR void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, uint8_t *char_num) { - // *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char_sync, data); - // *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char_sync, char_num); - HAL_ASSERT(false); + *cmd_char = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char_sync, at_cmd_char); + *char_num = HAL_FORCE_READ_U32_REG_FIELD(hw->at_cmd_char_sync, char_num); } /** @@ -786,7 +1045,7 @@ static inline void uart_ll_get_at_cmd_char(uart_dev_t *hw, uint8_t *cmd_char, ui * * @return The UART wakeup threshold value. */ -static inline uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw) { return hw->sleep_conf2.active_threshold + UART_LL_MIN_WAKEUP_THRESH; } @@ -799,7 +1058,7 @@ static inline uint32_t uart_ll_get_wakeup_thrd(uart_dev_t *hw) * * @return The bit mode. */ -static inline void uart_ll_get_data_bit_num(uart_dev_t *hw, uart_word_length_t *data_bit) +FORCE_INLINE_ATTR void uart_ll_get_data_bit_num(uart_dev_t *hw, uart_word_length_t *data_bit) { *data_bit = (uart_word_length_t)hw->conf0_sync.bit_num; } @@ -811,9 +1070,9 @@ static inline void uart_ll_get_data_bit_num(uart_dev_t *hw, uart_word_length_t * * * @return True if the state machine is in the IDLE state, otherwise false is returned. */ -static inline bool uart_ll_is_tx_idle(uart_dev_t *hw) +FORCE_INLINE_ATTR bool uart_ll_is_tx_idle(uart_dev_t *hw) { - return ((hw->status.txfifo_cnt == 0) && (hw->fsm_status.st_utx_out == 0)); + return ((((hw->status.txfifo_cnt) >> UART_LL_REG_FIELD_BIT_SHIFT(hw)) == 0) && (hw->fsm_status.st_utx_out == 0)); } /** @@ -823,7 +1082,7 @@ static inline bool uart_ll_is_tx_idle(uart_dev_t *hw) * * @return True if hw rts flow control is enabled, otherwise false is returned. */ -static inline bool uart_ll_is_hw_rts_en(uart_dev_t *hw) +FORCE_INLINE_ATTR bool uart_ll_is_hw_rts_en(uart_dev_t *hw) { return hw->hwfc_conf_sync.rx_flow_en; } @@ -835,7 +1094,7 @@ static inline bool uart_ll_is_hw_rts_en(uart_dev_t *hw) * * @return True if hw cts flow control is enabled, otherwise false is returned. */ -static inline bool uart_ll_is_hw_cts_en(uart_dev_t *hw) +FORCE_INLINE_ATTR bool uart_ll_is_hw_cts_en(uart_dev_t *hw) { return hw->conf0_sync.tx_flow_en; } @@ -848,13 +1107,13 @@ static inline bool uart_ll_is_hw_cts_en(uart_dev_t *hw) * * @return None */ -static inline void uart_ll_set_loop_back(uart_dev_t *hw, bool loop_back_en) +FORCE_INLINE_ATTR void uart_ll_set_loop_back(uart_dev_t *hw, bool loop_back_en) { hw->conf0_sync.loopback = loop_back_en; uart_ll_update(hw); } -static inline void uart_ll_xon_force_on(uart_dev_t *hw, bool always_on) +FORCE_INLINE_ATTR void uart_ll_xon_force_on(uart_dev_t *hw, bool always_on) { hw->swfc_conf0_sync.force_xon = 1; uart_ll_update(hw); @@ -873,8 +1132,11 @@ static inline void uart_ll_xon_force_on(uart_dev_t *hw, bool always_on) * * @return None. */ -static inline void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask) +FORCE_INLINE_ATTR void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask) { + // LP_UART does not support UART_SIGNAL_IRDA_TX_INV and UART_SIGNAL_IRDA_RX_INV + // lp_uart_dev_t has no these fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + typeof(hw->conf0_sync) conf0_reg; conf0_reg.val = hw->conf0_sync.val; conf0_reg.irda_tx_inv = (inv_mask & UART_SIGNAL_IRDA_TX_INV) ? 1 : 0; @@ -901,7 +1163,7 @@ static inline void uart_ll_inverse_signal(uart_dev_t *hw, uint32_t inv_mask) * * @return None. */ -static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd) +FORCE_INLINE_ATTR void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd) { uint16_t tout_val = tout_thrd; if(tout_thrd > 0) { @@ -920,7 +1182,7 @@ static inline void uart_ll_set_rx_tout(uart_dev_t *hw, uint16_t tout_thrd) * * @return tout_thr The timeout threshold value. If timeout feature is disabled returns 0. */ -static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw) +FORCE_INLINE_ATTR uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw) { uint16_t tout_thrd = 0; if(hw->tout_conf_sync.rx_tout_en > 0) { @@ -936,9 +1198,9 @@ static inline uint16_t uart_ll_get_rx_tout_thr(uart_dev_t *hw) * * @return maximum timeout threshold. */ -static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) +FORCE_INLINE_ATTR uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) { - return UART_RX_TOUT_THRHD_V; + return ((hw) == &LP_UART) ? LP_UART_RX_TOUT_THRHD_V : UART_RX_TOUT_THRHD_V; } /** @@ -947,8 +1209,11 @@ static inline uint16_t uart_ll_max_tout_thrd(uart_dev_t *hw) * @param hw Beginning address of the peripheral registers. * @param enable Boolean marking whether the auto baudrate should be enabled or not. */ -static inline void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable) +FORCE_INLINE_ATTR void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable) { + // LP_UART does not support autobaud + // lp_uart_dev_t has no following fields (reserved), but no harm since we map the LP_UART instance to the uart_dev_t struct + hw->conf0_sync.autobaud_en = enable ? 1 : 0; uart_ll_update(hw); } @@ -958,7 +1223,7 @@ static inline void uart_ll_set_autobaud_en(uart_dev_t *hw, bool enable) * * @param hw Beginning address of the peripheral registers. */ -static inline uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw) { return hw->rxd_cnt.rxd_edge_cnt; } @@ -968,7 +1233,7 @@ static inline uint32_t uart_ll_get_rxd_edge_cnt(uart_dev_t *hw) * * @param hw Beginning address of the peripheral registers. */ -static inline uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw) { return hw->pospulse.posedge_min_cnt; } @@ -978,7 +1243,7 @@ static inline uint32_t uart_ll_get_pos_pulse_cnt(uart_dev_t *hw) * * @param hw Beginning address of the peripheral registers. */ -static inline uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw) { return hw->negpulse.negedge_min_cnt; } @@ -988,7 +1253,7 @@ static inline uint32_t uart_ll_get_neg_pulse_cnt(uart_dev_t *hw) * * @param hw Beginning address of the peripheral registers. */ -static inline uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw) { return hw->highpulse.highpulse_min_cnt; } @@ -998,7 +1263,7 @@ static inline uint32_t uart_ll_get_high_pulse_cnt(uart_dev_t *hw) * * @param hw Beginning address of the peripheral registers. */ -static inline uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw) +FORCE_INLINE_ATTR uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw) { return hw->lowpulse.lowpulse_min_cnt; } @@ -1010,12 +1275,13 @@ static inline uint32_t uart_ll_get_low_pulse_cnt(uart_dev_t *hw) * * @return None. */ -static inline void uart_ll_force_xoff(uart_port_t uart_num) +FORCE_INLINE_ATTR void uart_ll_force_xoff(uart_port_t uart_num) { - // REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XON); - // REG_SET_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF); - // uart_ll_update(UART_LL_GET_HW(uart_num)); - HAL_ASSERT(false); + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->swfc_conf0_sync.force_xon = 0; + hw->swfc_conf0_sync.sw_flow_con_en = 1; + hw->swfc_conf0_sync.force_xoff = 1; + uart_ll_update(hw); } /** @@ -1025,13 +1291,14 @@ static inline void uart_ll_force_xoff(uart_port_t uart_num) * * @return None. */ -static inline void uart_ll_force_xon(uart_port_t uart_num) +FORCE_INLINE_ATTR void uart_ll_force_xon(uart_port_t uart_num) { - // REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XOFF); - // REG_SET_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_FORCE_XON); - // REG_CLR_BIT(UART_SWFC_CONF0_SYNC_REG(uart_num), UART_SW_FLOW_CON_EN | UART_FORCE_XON); - // uart_ll_update(UART_LL_GET_HW(uart_num)); - HAL_ASSERT(false); + uart_dev_t *hw = UART_LL_GET_HW(uart_num); + hw->swfc_conf0_sync.force_xoff = 0; + hw->swfc_conf0_sync.force_xon = 1; + hw->swfc_conf0_sync.sw_flow_con_en = 0; + hw->swfc_conf0_sync.force_xon = 0; + uart_ll_update(hw); } /** @@ -1041,11 +1308,24 @@ static inline void uart_ll_force_xon(uart_port_t uart_num) * * @return UART module FSM status. */ -static inline uint32_t uart_ll_get_tx_fsm_status(uart_port_t uart_num) +FORCE_INLINE_ATTR uint32_t uart_ll_get_tx_fsm_status(uart_port_t uart_num) { return REG_GET_FIELD(UART_FSM_STATUS_REG(uart_num), UART_ST_UTX_OUT); } +/** + * @brief Configure UART whether to discard when receiving wrong data + * + * @param hw Beginning address of the peripheral registers. + * @param discard true: Receiver stops storing data into FIFO when data is wrong + * false: Receiver continue storing data into FIFO when data is wrong + */ +FORCE_INLINE_ATTR void uart_ll_discard_error_data(uart_dev_t *hw, bool discard) +{ + hw->conf0_sync.err_wr_mask = discard ? 1 : 0; + uart_ll_update(hw); +} + #ifdef __cplusplus } #endif diff --git a/components/hal/include/hal/uart_types.h b/components/hal/include/hal/uart_types.h index cef1ca85fb..b97944abea 100644 --- a/components/hal/include/hal/uart_types.h +++ b/components/hal/include/hal/uart_types.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +25,12 @@ typedef enum { #if SOC_UART_HP_NUM > 2 UART_NUM_2, /*!< UART port 2 */ #endif +#if SOC_UART_HP_NUM > 3 + UART_NUM_3, /*!< UART port 3 */ +#endif +#if SOC_UART_HP_NUM > 4 + UART_NUM_4, /*!< UART port 4 */ +#endif #if (SOC_UART_LP_NUM >= 1) LP_UART_NUM_0, /*!< LP UART port 0 */ #endif diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index 36583829ab..ca2952ae5a 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1037,16 +1037,20 @@ config SOC_FLASH_ENCRYPTION_XTS_AES_128 config SOC_UART_NUM int - default 2 + default 5 config SOC_UART_HP_NUM int - default 2 + default 5 config SOC_UART_FIFO_LEN int default 128 +config SOC_LP_UART_FIFO_LEN + int + default 16 + config SOC_UART_BITRATE_MAX int default 5000000 diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 664e5d4b7b..9fb5ec412b 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -151,7 +151,10 @@ typedef enum { SOC_MOD_CLK_RC_FAST, /*!< RC_FAST_CLK comes from the internal 20MHz rc oscillator, passing a clock gating to the peripherals */ SOC_MOD_CLK_XTAL, /*!< XTAL_CLK comes from the external 40MHz crystal */ SOC_MOD_CLK_APLL, /*!< Audio PLL is sourced from PLL, and its frequency is configurable through APLL configuration registers */ + // For LP peripherals + SOC_MOD_CLK_XTAL_D2, /*!< XTAL_D2_CLK comes from the external 40MHz crystal, passing a div of 2 to the LP peripherals */ SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ + SOC_MOD_CLK_LP_PLL, } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER////////////////////////////////////////////////////////////// @@ -254,7 +257,6 @@ typedef enum { ///////////////////////////////////////////////////UART///////////////////////////////////////////////////////////////// -//TODO: IDF-6511 /** * @brief Type of UART clock source, reserved for the legacy UART driver */ @@ -262,9 +264,23 @@ typedef enum { UART_SCLK_PLL_F80M = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock is PLL_F80M */ UART_SCLK_RTC = SOC_MOD_CLK_RC_FAST, /*!< UART source clock is RC_FAST */ UART_SCLK_XTAL = SOC_MOD_CLK_XTAL, /*!< UART source clock is XTAL */ +#if SOC_CLK_TREE_SUPPORTED UART_SCLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock default choice is PLL_F80M */ +#else + UART_SCLK_DEFAULT = SOC_MOD_CLK_XTAL, /*!< UART source clock default choice is XTAL for FPGA environment */ +#endif } soc_periph_uart_clk_src_legacy_t; +/** + * @brief Type of LP_UART clock source + */ +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 */ +} soc_periph_lp_uart_clk_src_t; + //////////////////////////////////////////////////MCPWM///////////////////////////////////////////////////////////////// /** diff --git a/components/soc/esp32p4/include/soc/lpperi_struct.h b/components/soc/esp32p4/include/soc/lpperi_struct.h index 8fccb45de6..34cbda01df 100644 --- a/components/soc/esp32p4/include/soc/lpperi_struct.h +++ b/components/soc/esp32p4/include/soc/lpperi_struct.h @@ -348,7 +348,7 @@ typedef union { } lpperi_date_reg_t; -typedef struct { +typedef struct lpperi_dev_t { volatile lpperi_clk_en_reg_t clk_en; volatile lpperi_core_clk_sel_reg_t core_clk_sel; volatile lpperi_reset_en_reg_t reset_en; @@ -364,6 +364,7 @@ typedef struct { volatile lpperi_date_reg_t date; } lpperi_dev_t; +extern lpperi_dev_t LPPERI; #ifndef __cplusplus _Static_assert(sizeof(lpperi_dev_t) == 0x400, "Invalid size of lpperi_dev_t structure"); diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 857fdf8dff..a3d1d0a665 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -208,6 +208,7 @@ // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) +// #define SOC_LP_GPIO_MATRIX_SUPPORTED (1) /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 16 #define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 /* This macro indicates that the target has separate RTC IOMUX hardware feature, @@ -470,11 +471,13 @@ /*-------------------------- MEMPROT CAPS ------------------------------------*/ /*-------------------------- UART CAPS ---------------------------------------*/ -// ESP32-P4 has 2 UARTs -#define SOC_UART_NUM (2) -#define SOC_UART_HP_NUM (2) +// ESP32-P4 has 6 UARTs (5 HP UART, and 1 LP UART) +// The RTC GPIO and sigmap is not supported yet, so make SOC_UART_NUM->5 to avoid lp-uart build errors +#define SOC_UART_NUM (5) +#define SOC_UART_HP_NUM (5) // #define SOC_UART_LP_NUM (1U) #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ +#define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ #define SOC_UART_SUPPORT_PLL_F80M_CLK (1) /*!< Support PLL_F80M as the clock source */ #define SOC_UART_SUPPORT_RTC_CLK (1) /*!< Support RTC clock as the clock source */ diff --git a/components/soc/esp32p4/include/soc/uart_channel.h b/components/soc/esp32p4/include/soc/uart_channel.h index c04136b38d..cf01427ec9 100644 --- a/components/soc/esp32p4/include/soc/uart_channel.h +++ b/components/soc/esp32p4/include/soc/uart_channel.h @@ -4,6 +4,36 @@ * SPDX-License-Identifier: Apache-2.0 */ -// This file defines GPIO lookup macros for available UART IO_MUX pins on ESP32C6. +// This file defines GPIO lookup macros for available UART IO_MUX pins on ESP32P4. #pragma once + +//UART0 channels +#define UART_GPIO37_DIRECT_CHANNEL UART_NUM_0 +#define UART_NUM_0_TXD_DIRECT_GPIO_NUM 37 +#define UART_GPIO38_DIRECT_CHANNEL UART_NUM_0 +#define UART_NUM_0_RXD_DIRECT_GPIO_NUM 38 +#define UART_GPIO8_DIRECT_CHANNEL UART_NUM_0 +#define UART_NUM_0_RTS_DIRECT_GPIO_NUM 8 +#define UART_GPIO9_DIRECT_CHANNEL UART_NUM_0 +#define UART_NUM_0_CTS_DIRECT_GPIO_NUM 9 + +#define UART_TXD_GPIO37_DIRECT_CHANNEL UART_GPIO38_DIRECT_CHANNEL +#define UART_RXD_GPIO38_DIRECT_CHANNEL UART_GPIO38_DIRECT_CHANNEL +#define UART_RTS_GPIO8_DIRECT_CHANNEL UART_GPIO8_DIRECT_CHANNEL +#define UART_CTS_GPIO9_DIRECT_CHANNEL UART_GPIO9_DIRECT_CHANNEL + +//UART1 channels +#define UART_GPIO10_DIRECT_CHANNEL UART_NUM_1 +#define UART_NUM_1_TXD_DIRECT_GPIO_NUM 10 +#define UART_GPIO11_DIRECT_CHANNEL UART_NUM_1 +#define UART_NUM_1_RXD_DIRECT_GPIO_NUM 11 +#define UART_GPIO12_DIRECT_CHANNEL UART_NUM_1 +#define UART_NUM_1_RTS_DIRECT_GPIO_NUM 12 +#define UART_GPIO13_DIRECT_CHANNEL UART_NUM_1 +#define UART_NUM_1_CTS_DIRECT_GPIO_NUM 13 + +#define UART_TXD_GPIO10_DIRECT_CHANNEL UART_GPIO10_DIRECT_CHANNEL +#define UART_RXD_GPIO11_DIRECT_CHANNEL UART_GPIO11_DIRECT_CHANNEL +#define UART_RTS_GPIO12_DIRECT_CHANNEL UART_GPIO12_DIRECT_CHANNEL +#define UART_CTS_GPIO13_DIRECT_CHANNEL UART_GPIO13_DIRECT_CHANNEL diff --git a/components/soc/esp32p4/include/soc/uart_pins.h b/components/soc/esp32p4/include/soc/uart_pins.h index a5d49ea6e7..d7d8da9562 100644 --- a/components/soc/esp32p4/include/soc/uart_pins.h +++ b/components/soc/esp32p4/include/soc/uart_pins.h @@ -10,3 +10,68 @@ /* Specify the number of pins for UART */ #define SOC_UART_PINS_COUNT (4) + +/* Specify the GPIO pin number for each UART signal in the IOMUX */ +#define U0RXD_GPIO_NUM 38 +#define U0TXD_GPIO_NUM 37 +#define U0RTS_GPIO_NUM 8 +#define U0CTS_GPIO_NUM 9 + +#define U1RXD_GPIO_NUM 11 +#define U1TXD_GPIO_NUM 10 +#define U1RTS_GPIO_NUM 12 +#define U1CTS_GPIO_NUM 13 + +#define U2RXD_GPIO_NUM (-1) +#define U2TXD_GPIO_NUM (-1) +#define U2RTS_GPIO_NUM (-1) +#define U2CTS_GPIO_NUM (-1) + +#define U3RXD_GPIO_NUM (-1) +#define U3TXD_GPIO_NUM (-1) +#define U3RTS_GPIO_NUM (-1) +#define U3CTS_GPIO_NUM (-1) + +#define U4RXD_GPIO_NUM (-1) +#define U4TXD_GPIO_NUM (-1) +#define U4RTS_GPIO_NUM (-1) +#define U4CTS_GPIO_NUM (-1) + +#define LP_U0RXD_GPIO_NUM 15 +#define LP_U0TXD_GPIO_NUM 14 +#define LP_U0RTS_GPIO_NUM (-1) +#define LP_U0CTS_GPIO_NUM (-1) + +/* The following defines are necessary for reconfiguring the UART + * to use IOMUX, at runtime. */ +#define U0TXD_MUX_FUNC (FUNC_GPIO37_UART0_TXD_PAD) +#define U0RXD_MUX_FUNC (FUNC_GPIO38_UART0_RXD_PAD) +#define U0RTS_MUX_FUNC (FUNC_GPIO8_UART0_RTS_PAD) +#define U0CTS_MUX_FUNC (FUNC_GPIO9_UART0_CTS_PAD) + +/* Same goes for UART1 */ +#define U1TXD_MUX_FUNC (FUNC_GPIO10_UART1_TXD_PAD) +#define U1RXD_MUX_FUNC (FUNC_GPIO11_UART1_RXD_PAD) +#define U1RTS_MUX_FUNC (FUNC_GPIO12_UART1_RTS_PAD) +#define U1CTS_MUX_FUNC (FUNC_GPIO13_UART1_CTS_PAD) + +/* No func for the following pins, they shall not be used */ +#define U2TXD_MUX_FUNC (-1) +#define U2RXD_MUX_FUNC (-1) +#define U2RTS_MUX_FUNC (-1) +#define U2CTS_MUX_FUNC (-1) + +#define U3TXD_MUX_FUNC (-1) +#define U3RXD_MUX_FUNC (-1) +#define U3RTS_MUX_FUNC (-1) +#define U3CTS_MUX_FUNC (-1) + +#define U4TXD_MUX_FUNC (-1) +#define U4RXD_MUX_FUNC (-1) +#define U4RTS_MUX_FUNC (-1) +#define U4CTS_MUX_FUNC (-1) + +#define LP_U0TXD_MUX_FUNC (0) +#define LP_U0RXD_MUX_FUNC (0) +#define LP_U0RTS_MUX_FUNC (-1) +#define LP_U0CTS_MUX_FUNC (-1) diff --git a/components/soc/esp32p4/include/soc/uart_struct.h b/components/soc/esp32p4/include/soc/uart_struct.h index 735f4ad96a..6c8375d5c1 100644 --- a/components/soc/esp32p4/include/soc/uart_struct.h +++ b/components/soc/esp32p4/include/soc/uart_struct.h @@ -19,8 +19,7 @@ typedef union { /** rxfifo_rd_byte : RO; bitpos: [7:0]; default: 0; * UART $n accesses FIFO via this register. */ - uint32_t rxfifo_rd_byte:8; - uint32_t reserved_8:24; + uint32_t rxfifo_rd_byte:32; }; uint32_t val; } uart_fifo_reg_t; @@ -1216,7 +1215,7 @@ typedef union { } uart_id_reg_t; -typedef struct { +typedef struct uart_dev_t{ volatile uart_fifo_reg_t fifo; volatile uart_int_raw_reg_t int_raw; volatile uart_int_st_reg_t int_st; @@ -1246,12 +1245,12 @@ typedef struct { volatile uart_mem_tx_status_reg_t mem_tx_status; volatile uart_mem_rx_status_reg_t mem_rx_status; volatile uart_fsm_status_reg_t fsm_status; - volatile uart_pospulse_reg_t pospulse; - volatile uart_negpulse_reg_t negpulse; - volatile uart_lowpulse_reg_t lowpulse; - volatile uart_highpulse_reg_t highpulse; - volatile uart_rxd_cnt_reg_t rxd_cnt; - volatile uart_clk_conf_reg_t clk_conf; + volatile uart_pospulse_reg_t pospulse; /* LP_UART instance has this register reserved */ + volatile uart_negpulse_reg_t negpulse; /* LP_UART instance has this register reserved */ + volatile uart_lowpulse_reg_t lowpulse; /* LP_UART instance has this register reserved */ + volatile uart_highpulse_reg_t highpulse; /* LP_UART instance has this register reserved */ + volatile uart_rxd_cnt_reg_t rxd_cnt; /* LP_UART instance has this register reserved */ + volatile uart_clk_conf_reg_t clk_conf; /* UART0/1/2/3/4 instance have this register reserved, configure in corresponding PCR registers */ volatile uart_date_reg_t date; volatile uart_afifo_status_reg_t afifo_status; uint32_t reserved_094; @@ -1261,6 +1260,10 @@ typedef struct { extern uart_dev_t UART0; extern uart_dev_t UART1; +extern uart_dev_t UART2; +extern uart_dev_t UART3; +extern uart_dev_t UART4; +extern uart_dev_t LP_UART; #ifndef __cplusplus _Static_assert(sizeof(uart_dev_t) == 0xa0, "Invalid size of uart_dev_t structure"); diff --git a/components/soc/esp32p4/ld/esp32p4.peripherals.ld b/components/soc/esp32p4/ld/esp32p4.peripherals.ld index 40e8213dfd..059a30e4b7 100644 --- a/components/soc/esp32p4/ld/esp32p4.peripherals.ld +++ b/components/soc/esp32p4/ld/esp32p4.peripherals.ld @@ -68,6 +68,7 @@ PROVIDE ( PMU = 0x50115000 ); PROVIDE ( LP_SYS = 0x50110000 ); PROVIDE ( LP_AON_CLKRST = 0x50111000 ); PROVIDE ( EFUSE = 0x5012D000 ); +PROVIDE ( LPPERI = 0x50120000 ); PROVIDE ( LP_TIMER = 0x50112000 ); PROVIDE ( LP_UART = 0x50121000 ); PROVIDE ( LP_I2C = 0x50122000 ); diff --git a/components/soc/esp32p4/uart_periph.c b/components/soc/esp32p4/uart_periph.c index 2b0c63eb1b..76047b25a1 100644 --- a/components/soc/esp32p4/uart_periph.c +++ b/components/soc/esp32p4/uart_periph.c @@ -5,10 +5,213 @@ */ #include "soc/uart_periph.h" +#include "soc/lp_gpio_sig_map.h" /* Bunch of constants for every UART peripheral: GPIO signals, irqs, hw addr of registers etc */ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { + { // HP UART0 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U0TXD_GPIO_NUM, + .iomux_func = U0TXD_MUX_FUNC, + .input = 0, + .signal = UART0_TXD_PAD_OUT_IDX, + }, + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = UART0_RXD_PAD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = UART0_RTS_PAD_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = UART0_CTS_PAD_IN_IDX, + } + }, + .irq = ETS_UART0_INTR_SOURCE, + .module = PERIPH_UART0_MODULE, + }, + + { // HP UART1 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U1TXD_GPIO_NUM, + .iomux_func = U1TXD_MUX_FUNC, + .input = 0, + .signal = UART1_TXD_PAD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = UART1_RXD_PAD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = UART1_RTS_PAD_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = UART1_CTS_PAD_IN_IDX, + }, + }, + .irq = ETS_UART1_INTR_SOURCE, + .module = PERIPH_UART1_MODULE, + }, + + { // HP UART2 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U2TXD_GPIO_NUM, + .iomux_func = U2TXD_MUX_FUNC, + .input = 0, + .signal = UART2_TXD_PAD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U2RXD_GPIO_NUM, + .iomux_func = U2RXD_MUX_FUNC, + .input = 1, + .signal = UART2_RXD_PAD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U2RTS_GPIO_NUM, + .iomux_func = U2RTS_MUX_FUNC, + .input = 0, + .signal = UART2_RTS_PAD_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U2CTS_GPIO_NUM, + .iomux_func = U2CTS_MUX_FUNC, + .input = 1, + .signal = UART2_CTS_PAD_IN_IDX, + }, + }, + .irq = ETS_UART2_INTR_SOURCE, + .module = PERIPH_UART2_MODULE, + }, + + { // HP UART3 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U3TXD_GPIO_NUM, + .iomux_func = U3TXD_MUX_FUNC, + .input = 0, + .signal = UART3_TXD_PAD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U3RXD_GPIO_NUM, + .iomux_func = U3RXD_MUX_FUNC, + .input = 1, + .signal = UART3_RXD_PAD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U3RTS_GPIO_NUM, + .iomux_func = U3RTS_MUX_FUNC, + .input = 0, + .signal = UART3_RTS_PAD_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U3CTS_GPIO_NUM, + .iomux_func = U3CTS_MUX_FUNC, + .input = 1, + .signal = UART3_CTS_PAD_IN_IDX, + }, + }, + .irq = ETS_UART3_INTR_SOURCE, + .module = PERIPH_UART3_MODULE, + }, + + { // HP UART4 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = U4TXD_GPIO_NUM, + .iomux_func = U4TXD_MUX_FUNC, + .input = 0, + .signal = UART4_TXD_PAD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U4RXD_GPIO_NUM, + .iomux_func = U4RXD_MUX_FUNC, + .input = 1, + .signal = UART4_RXD_PAD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U4RTS_GPIO_NUM, + .iomux_func = U4RTS_MUX_FUNC, + .input = 0, + .signal = UART4_RTS_PAD_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U4CTS_GPIO_NUM, + .iomux_func = U4CTS_MUX_FUNC, + .input = 1, + .signal = UART4_CTS_PAD_IN_IDX, + }, + }, + .irq = ETS_UART4_INTR_SOURCE, + .module = PERIPH_UART4_MODULE, + }, + //TODO:IDF-7815 + // { // LP UART0 + // .pins = { + // [SOC_UART_TX_PIN_IDX] = { + // .default_gpio = LP_U0TXD_GPIO_NUM, + // .iomux_func = LP_U0TXD_MUX_FUNC, + // .input = 0, + // .signal = LP_UART_TXD_PAD_OUT_IDX, + // }, + + // [SOC_UART_RX_PIN_IDX] = { + // .default_gpio = LP_U0RXD_GPIO_NUM, + // .iomux_func = LP_U0RXD_MUX_FUNC, + // .input = 1, + // .signal = LP_UART_RXD_PAD_IN_IDX, + // }, + + // [SOC_UART_RTS_PIN_IDX] = { + // .default_gpio = LP_U0RTS_GPIO_NUM, + // .iomux_func = LP_U0RTS_MUX_FUNC, + // .input = 0, + // .signal = LP_UART_RTSN_PAD_OUT_IDX, + // }, + + // [SOC_UART_CTS_PIN_IDX] = { + // .default_gpio = LP_U0CTS_GPIO_NUM, + // .iomux_func = LP_U0CTS_MUX_FUNC, + // .input = 1, + // .signal = LP_UART_CTSN_PAD_IN_IDX, + // }, + // }, + // .irq = ETS_LP_UART_INTR_SOURCE, + // .module = PERIPH_LP_UART0_MODULE, + // }, }; From 4541ad134dc50c1de83e64d8ce5a31eff096eb38 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Thu, 14 Sep 2023 09:23:20 +0800 Subject: [PATCH 2/5] feat(uart): add RCC atomic block to uart/lp-uart peripheral --- .../src/bootloader_console.c | 1 + .../driver/include/esp_private/uart_private.h | 35 ++++ components/driver/uart/uart.c | 62 ++++-- .../port/esp32p4/esp_clk_tree.c | 2 +- components/esp_pm/pm_impl.c | 15 +- components/esp_rom/patches/esp_rom_uart.c | 6 +- components/esp_system/port/cpu_start.c | 13 +- .../esp_system_unity_tests/main/test_sleep.c | 10 +- components/hal/esp32/include/hal/uart_ll.h | 61 +++++- components/hal/esp32c2/include/hal/uart_ll.h | 50 ++++- components/hal/esp32c3/include/hal/uart_ll.h | 55 +++++ components/hal/esp32c6/include/hal/uart_ll.h | 45 ++++ components/hal/esp32h2/include/hal/uart_ll.h | 43 ++++ .../hal/esp32p4/include/hal/clk_gate_ll.h | 35 ---- components/hal/esp32p4/include/hal/uart_ll.h | 194 ++++++++++++------ components/hal/esp32s2/include/hal/uart_ll.h | 54 ++++- components/hal/esp32s3/include/hal/uart_ll.h | 55 +++++ components/hal/include/hal/uart_hal.h | 42 ++-- components/hal/uart_hal.c | 12 +- .../soc/esp32p4/include/soc/uart_struct.h | 16 +- components/ulp/lp_core/lp_core_uart.c | 5 +- 21 files changed, 643 insertions(+), 168 deletions(-) create mode 100644 components/driver/include/esp_private/uart_private.h diff --git a/components/bootloader_support/src/bootloader_console.c b/components/bootloader_support/src/bootloader_console.c index b7d6d42a6e..7df9824d67 100644 --- a/components/bootloader_support/src/bootloader_console.c +++ b/components/bootloader_support/src/bootloader_console.c @@ -77,6 +77,7 @@ void bootloader_console_init(void) #if ESP_ROM_UART_CLK_IS_XTAL clock_hz = (uint32_t)rtc_clk_xtal_freq_get() * MHZ; // From esp32-s3 on, UART clk source is selected to XTAL in ROM #endif + int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused)); // To avoid build errors/warnings about __DECLARE_RCC_ATOMIC_ENV esp_rom_uart_set_clock_baudrate(uart_num, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); } #endif // CONFIG_ESP_CONSOLE_UART diff --git a/components/driver/include/esp_private/uart_private.h b/components/driver/include/esp_private/uart_private.h new file mode 100644 index 0000000000..8d96de2624 --- /dev/null +++ b/components/driver/include/esp_private/uart_private.h @@ -0,0 +1,35 @@ + +/* + * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include "sdkconfig.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 CONFIG_IDF_TARGET_ESP32P4 +#define UART_SCLK_ATOMIC() PERIPH_RCC_ATOMIC() +#else +#define UART_SCLK_ATOMIC() +#endif + +#if SOC_RCC_IS_INDEPENDENT +#define UART_CLK_ATOMIC() +#else +#define UART_CLK_ATOMIC() PERIPH_RCC_ATOMIC() +#endif + +#ifdef __cplusplus +} +#endif diff --git a/components/driver/uart/uart.c b/components/driver/uart/uart.c index b4104ed020..bf4609a435 100644 --- a/components/driver/uart/uart.c +++ b/components/driver/uart/uart.c @@ -26,6 +26,7 @@ #include "driver/gpio.h" #include "driver/rtc_io.h" #include "driver/uart_select.h" +#include "esp_private/uart_private.h" #include "esp_private/periph_ctrl.h" #include "esp_clk_tree.h" #include "sdkconfig.h" @@ -177,22 +178,32 @@ 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) { - periph_module_enable(uart_periph_signal[uart_num].module); + UART_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_hal_set_reset_core(&(uart_context[uart_num].hal), true); - periph_module_reset(uart_periph_signal[uart_num].module); - uart_hal_set_reset_core(&(uart_context[uart_num].hal), false); + UART_SCLK_ATOMIC(){ + uart_hal_set_reset_core(&(uart_context[uart_num].hal), true); + } + UART_CLK_ATOMIC() { + uart_ll_reset_register(uart_num); + } + UART_SCLK_ATOMIC(){ + uart_hal_set_reset_core(&(uart_context[uart_num].hal), false); + } #else - periph_module_reset(uart_periph_signal[uart_num].module); + UART_CLK_ATOMIC() { + uart_ll_reset_register(uart_num); + } #endif } } #if (SOC_UART_LP_NUM >= 1) else { - PERIPH_RCC_ATOMIC() { + LP_UART_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); } @@ -208,11 +219,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) { - periph_module_disable(uart_periph_signal[uart_num].module); + UART_CLK_ATOMIC() { + uart_ll_enable_bus_clock(uart_num, false); + } } #if (SOC_UART_LP_NUM >= 1) else if (uart_num >= SOC_UART_HP_NUM) { - PERIPH_RCC_ATOMIC() { + LP_UART_CLK_ATOMIC() { lp_uart_ll_enable_bus_clock(uart_num - SOC_UART_HP_NUM, false); } } @@ -292,7 +305,9 @@ 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_hal_set_baudrate(&(uart_context[uart_num].hal), baud_rate, sclk_freq); + UART_SCLK_ATOMIC() { + uart_hal_set_baudrate(&(uart_context[uart_num].hal), baud_rate, sclk_freq); + } UART_EXIT_CRITICAL(&(uart_context[uart_num].spinlock)); return ESP_OK; } @@ -649,13 +664,20 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r ESP_RETURN_ON_FALSE((rts_io_num < 0 || (GPIO_IS_VALID_OUTPUT_GPIO(rts_io_num))), ESP_FAIL, UART_TAG, "rts_io_num error"); ESP_RETURN_ON_FALSE((cts_io_num < 0 || (GPIO_IS_VALID_GPIO(cts_io_num))), ESP_FAIL, UART_TAG, "cts_io_num error"); } -#if (SOC_UART_LP_NUM >= 1 && !SOC_LP_GPIO_MATRIX_SUPPORTED) - else { // LP_UART has its fixed IOs +#if (SOC_UART_LP_NUM >= 1) + else { // LP_UART IO check const uart_periph_sig_t *pins = uart_periph_signal[uart_num].pins; +#if !SOC_LP_GPIO_MATRIX_SUPPORTED + // LP_UART has its fixed IOs ESP_RETURN_ON_FALSE((tx_io_num < 0 || (tx_io_num == pins[SOC_UART_TX_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "tx_io_num error"); ESP_RETURN_ON_FALSE((rx_io_num < 0 || (rx_io_num == pins[SOC_UART_RX_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "rx_io_num error"); ESP_RETURN_ON_FALSE((rts_io_num < 0 || (rts_io_num == pins[SOC_UART_RTS_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "rts_io_num error"); ESP_RETURN_ON_FALSE((cts_io_num < 0 || (cts_io_num == pins[SOC_UART_CTS_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "cts_io_num error"); + +#else // SOC_LP_GPIO_MATRIX_SUPPORTED + // LP_UART IOs can be routed any LP_IOs + //TODO: IDF-7815, check for LP_IO 0~15 +#endif // SOC_LP_GPIO_MATRIX_SUPPORTED } #endif @@ -663,8 +685,8 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r if (tx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) { if (uart_num < SOC_UART_HP_NUM) { gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO); - gpio_set_level(tx_io_num, 1); - esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + gpio_set_level(tx_io_num, 1); + esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); } #if SOC_LP_GPIO_MATRIX_SUPPORTED else { @@ -672,7 +694,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r rtc_gpio_set_direction(tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); rtc_gpio_init(tx_io_num); rtc_gpio_iomux_func_sel(tx_io_num, 1); - LP_GPIO.func10_out_sel_cfg.reg_gpio_func10_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_TX_PIN_IDX].signal; + LP_GPIO.func10_out_sel_cfg.reg_gpio_func10_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_TX_PIN_IDX].signal; } #endif } @@ -708,7 +730,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r rtc_gpio_set_direction(rts_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); rtc_gpio_init(rts_io_num); rtc_gpio_iomux_func_sel(rts_io_num, 1); - LP_GPIO.func10_out_sel_cfg.reg_gpio_func12_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_RTS_PIN_IDX].signal; + LP_GPIO.func10_out_sel_cfg.reg_gpio_func12_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_RTS_PIN_IDX].signal; } #endif } @@ -794,16 +816,20 @@ 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_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel); + UART_SCLK_ATOMIC() { + uart_hal_set_sclk(&(uart_context[uart_num].hal), uart_sclk_sel); + } } #if (SOC_UART_LP_NUM >= 1) else { - PERIPH_RCC_ATOMIC() { + LP_UART_CLK_ATOMIC() { lp_uart_ll_set_source_clk(uart_context[uart_num].hal.dev, (soc_periph_lp_uart_clk_src_t)uart_sclk_sel); } } #endif - uart_hal_set_baudrate(&(uart_context[uart_num].hal), uart_config->baud_rate, sclk_freq); + 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_hw_support/port/esp32p4/esp_clk_tree.c b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c index b538989239..22ac4ccd26 100644 --- a/components/esp_hw_support/port/esp32p4/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32p4/esp_clk_tree.c @@ -26,7 +26,7 @@ uint32_t *freq_value) clk_src_freq = 40 * MHZ; break; case SOC_MOD_CLK_XTAL_D2: - clk_src_freq = (40* MHZ) >> 1; + clk_src_freq = (40 * MHZ) >> 1; break; case SOC_MOD_CLK_LP_PLL: clk_src_freq = 8 * MHZ; diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index 417b046d30..e3d39d17d8 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -17,6 +17,7 @@ #include "esp_cpu.h" #include "esp_private/crosscore_int.h" +#include "esp_private/uart_private.h" #include "soc/rtc.h" #include "hal/uart_ll.h" @@ -42,6 +43,7 @@ #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" @@ -736,14 +738,19 @@ void esp_pm_impl_init(void) #else #error "No UART clock source is aware of DFS" #endif // SOC_UART_SUPPORT_xxx - while(!uart_ll_is_tx_idle(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM))); + 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_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source); - + UART_SCLK_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_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq); + UART_SCLK_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 #ifdef CONFIG_PM_TRACE diff --git a/components/esp_rom/patches/esp_rom_uart.c b/components/esp_rom/patches/esp_rom_uart.c index bae29dd553..743d1c9d0b 100644 --- a/components/esp_rom/patches/esp_rom_uart.c +++ b/components/esp_rom/patches/esp_rom_uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +25,10 @@ IRAM_ATTR void esp_rom_uart_tx_wait_idle(uint8_t uart_no) IRAM_ATTR void esp_rom_uart_set_clock_baudrate(uint8_t uart_no, uint32_t clock_hz, uint32_t baud_rate) { +// To avoid build errors about __DECLARE_RCC_ATOMIC_ENV +#if !BOOTLOADER_BUILD + int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused)); +#endif 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 b5c0fb417e..cf7b749083 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -91,6 +91,7 @@ #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" @@ -143,6 +144,13 @@ static volatile bool s_cpu_inited[SOC_CPU_CORES_NUM] = { false }; static volatile bool s_resume_cores; #endif +#if CONFIG_IDF_TARGET_ESP32P4 +#define UART_START_SCLK_ATOMIC() PERIPH_RCC_ATOMIC() +#else +// #define UART_START_SCLK_ATOMIC() for(int i = 1, __DECLARE_RCC_ATOMIC_ENV; i < 1; i--) +#define UART_START_SCLK_ATOMIC() int __DECLARE_RCC_ATOMIC_ENV; +#endif + static void core_intr_matrix_clear(void) { uint32_t core_id = esp_cpu_get_core_id(); @@ -682,7 +690,10 @@ void IRAM_ATTR call_start_cpu0(void) clock_hz = esp_clk_xtal_freq(); // From esp32-s3 on, UART clock source is selected to XTAL in ROM #endif esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); - esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_UART_NUM, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); + UART_START_SCLK_ATOMIC() { + (void) __DECLARE_RCC_ATOMIC_ENV; // To avoid build warning about __DECLARE_RCC_ATOMIC_ENV defined but not used on P4 + esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_UART_NUM, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); + } #endif #endif 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 5ad3f47dd5..cc65f7f5c6 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 @@ -26,6 +26,7 @@ #include "esp_rom_sys.h" #include "esp_timer.h" #include "esp_private/esp_clk.h" +#include "esp_private/uart_private.h" #include "esp_random.h" #include "nvs_flash.h" #include "nvs.h" @@ -229,11 +230,14 @@ TEST_CASE("light sleep and frequency switching", "[deepsleep]") #elif SOC_UART_SUPPORT_XTAL_CLK clk_source = UART_SCLK_XTAL; #endif - uart_ll_set_sclk(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), (soc_module_clk_t)clk_source); - + UART_SCLK_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_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq); + UART_SCLK_ATOMIC() { + uart_ll_set_baudrate(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM), CONFIG_ESP_CONSOLE_UART_BAUDRATE, sclk_freq); + } #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 bf27a1870f..fbd970c9f2 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,7 @@ #include "esp_attr.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" +#include "soc/dport_reg.h" #include "hal/uart_types.h" #ifdef __cplusplus @@ -55,6 +56,64 @@ typedef enum { UART_INTR_CMD_CHAR_DET = (0x1<<18), } uart_intr_t; +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +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) + { + case 0: + reg_val = reg_val & (~DPORT_UART_CLK_EN); + reg_val = reg_val | (enable << 2); + break; + case 1: + reg_val = reg_val & (~DPORT_UART1_CLK_EN); + reg_val = reg_val | (enable << 5); + break; + case 2: + reg_val = reg_val & (~DPORT_UART2_CLK_EN); + reg_val = reg_val | (enable << 23); + break; + default: + abort(); + break; + } + DPORT_WRITE_PERI_REG(DPORT_PERIP_CLK_EN_REG, reg_val); +} +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t 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); + break; + case 1: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); + break; + case 2: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART2_RST); + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_rst_enx are shared registers, 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 Set the UART source clock. * diff --git a/components/hal/esp32c2/include/hal/uart_ll.h b/components/hal/esp32c2/include/hal/uart_ll.h index 6b8cd9be26..46bea10726 100644 --- a/components/hal/esp32c2/include/hal/uart_ll.h +++ b/components/hal/esp32c2/include/hal/uart_ll.h @@ -11,10 +11,11 @@ #include #include "hal/uart_types.h" +#include "hal/misc.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/clk_tree_defs.h" -#include "hal/misc.h" +#include "soc/system_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -97,6 +98,53 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) hw->clk_conf.tx_sclk_en = 0; } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_clk_en0.uart_clk_en = enable; + break; + case 1: + SYSTEM.perip_clk_en0.uart1_clk_en = enable; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_clk_en0 is a shared register, so this function must be used in an atomic way +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_rst_en0.uart_rst = 1; + SYSTEM.perip_rst_en0.uart_rst = 0; + break; + case 1: + SYSTEM.perip_rst_en0.uart1_rst = 1; + SYSTEM.perip_rst_en0.uart1_rst = 0; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_rst_en0 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 Set the UART source clock. * diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 95a0df391a..3a19a9a6da 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -15,6 +15,7 @@ #include "hal/uart_types.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" +#include "soc/system_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -97,6 +98,60 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) hw->clk_conf.tx_sclk_en = 0; } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_clk_en0.reg_uart_clk_en = enable; + break; + case 1: + SYSTEM.perip_clk_en0.reg_uart1_clk_en = enable; + break; + case 2: + SYSTEM.perip_clk_en1.reg_uart2_clk_en = enable; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_rst_en0.reg_uart_rst = 1; + SYSTEM.perip_rst_en0.reg_uart_rst = 0; + break; + case 1: + SYSTEM.perip_rst_en0.reg_uart1_rst = 1; + SYSTEM.perip_rst_en0.reg_uart1_rst = 0; + break; + case 2: + SYSTEM.perip_rst_en1.reg_uart2_rst = 1; + SYSTEM.perip_rst_en1.reg_uart2_rst = 0; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_rst_enx are shared registers, 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 Set the UART source clock. * diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index 531cfafa3d..b990cf7df5 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -229,6 +229,51 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) } } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_clk_en = enable; + break; + case 1: + PCR.uart1_conf.uart1_clk_en = enable; + break; + default: + // LP_UART + abort(); + break; + } +} + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_rst_en = 1; + PCR.uart0_conf.uart0_rst_en = 0; + break; + case 1: + PCR.uart1_conf.uart1_rst_en = 1; + PCR.uart1_conf.uart1_rst_en = 0; + break; + default: + // LP_UART + abort(); + break; + } +} + /** * @brief Set the UART source clock. * diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index ee7e5ab2fc..b25782d952 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -130,6 +130,49 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_en, 0); } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_clk_en = enable; + break; + case 1: + PCR.uart1_conf.uart1_clk_en = enable; + break; + default: + abort(); + break; + } +} + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_rst_en = 1; + PCR.uart0_conf.uart0_rst_en = 0; + break; + case 1: + PCR.uart1_conf.uart1_rst_en = 1; + PCR.uart1_conf.uart1_rst_en = 0; + break; + default: + abort(); + break; + } +} + /** * @brief Set the UART source clock. * diff --git a/components/hal/esp32p4/include/hal/clk_gate_ll.h b/components/hal/esp32p4/include/hal/clk_gate_ll.h index 8b21f7dfbb..4494544135 100644 --- a/components/hal/esp32p4/include/hal/clk_gate_ll.h +++ b/components/hal/esp32p4/include/hal/clk_gate_ll.h @@ -38,16 +38,6 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph) return HP_SYS_CLKRST_REG_I2C1_APB_CLK_EN; case PERIPH_LCD_MODULE: return HP_SYS_CLKRST_REG_LCD_CLK_EN; - case PERIPH_UART0_MODULE: - return HP_SYS_CLKRST_REG_UART0_CLK_EN; - case PERIPH_UART1_MODULE: - return HP_SYS_CLKRST_REG_UART1_CLK_EN; - case PERIPH_UART2_MODULE: - return HP_SYS_CLKRST_REG_UART2_CLK_EN; - case PERIPH_UART3_MODULE: - return HP_SYS_CLKRST_REG_UART3_CLK_EN; - case PERIPH_UART4_MODULE: - return HP_SYS_CLKRST_REG_UART4_CLK_EN; case PERIPH_TWAI0_MODULE: return HP_SYS_CLKRST_REG_TWAI0_CLK_EN; case PERIPH_TWAI1_MODULE: @@ -119,16 +109,6 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en return HP_SYS_CLKRST_REG_RST_EN_PPA; case PERIPH_SYSTIMER_MODULE: return HP_SYS_CLKRST_REG_RST_EN_STIMER; - case PERIPH_UART0_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_UART0_CORE; - case PERIPH_UART1_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_UART1_CORE; - case PERIPH_UART2_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_UART2_CORE; - case PERIPH_UART3_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_UART3_CORE; - case PERIPH_UART4_MODULE: - return HP_SYS_CLKRST_REG_RST_EN_UART4_CORE; case PERIPH_UHCI_MODULE: return HP_SYS_CLKRST_REG_RST_EN_UHCI; case PERIPH_I3C_MODULE: @@ -210,16 +190,6 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph) return HP_SYS_CLKRST_SOC_CLK_CTRL2_REG; case PERIPH_LCD_MODULE: return HP_SYS_CLKRST_PERI_CLK_CTRL110_REG; - case PERIPH_UART0_MODULE: - return HP_SYS_CLKRST_PERI_CLK_CTRL111_REG; - case PERIPH_UART1_MODULE: - return HP_SYS_CLKRST_PERI_CLK_CTRL112_REG; - case PERIPH_UART2_MODULE: - return HP_SYS_CLKRST_PERI_CLK_CTRL113_REG; - case PERIPH_UART3_MODULE: - return HP_SYS_CLKRST_PERI_CLK_CTRL114_REG; - case PERIPH_UART4_MODULE: - return HP_SYS_CLKRST_PERI_CLK_CTRL115_REG; case PERIPH_TWAI0_MODULE: case PERIPH_TWAI1_MODULE: case PERIPH_TWAI2_MODULE: @@ -268,11 +238,6 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph) return HP_SYS_CLKRST_HP_RST_EN0_REG; case PERIPH_PPA_MODULE: case PERIPH_SYSTIMER_MODULE: - case PERIPH_UART0_MODULE: - case PERIPH_UART1_MODULE: - case PERIPH_UART2_MODULE: - case PERIPH_UART3_MODULE: - case PERIPH_UART4_MODULE: case PERIPH_UHCI_MODULE: case PERIPH_I3C_MODULE: case PERIPH_I2C0_MODULE: diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index 1607febcc3..4a7c68f360 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -87,6 +87,9 @@ FORCE_INLINE_ATTR void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *sou case 1: *source_clk = (soc_module_clk_t)LP_UART_SCLK_XTAL_D2; break; + case 2: + *source_clk = (soc_module_clk_t)LP_UART_SCLK_LP_PLL; + break; } } @@ -96,7 +99,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 */ -static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_clk_src_t src_clk) +FORCE_INLINE_ATTR 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) { @@ -106,13 +109,16 @@ static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_ case LP_UART_SCLK_XTAL_D2: LPPERI.core_clk_sel.lp_uart_clk_sel = 1; break; + case LP_UART_SCLK_LP_PLL: + LPPERI.core_clk_sel.lp_uart_clk_sel = 2; + break; default: // Invalid LP_UART clock source HAL_ASSERT(false); } } -/// LPPERI.core_clk_sel is a shared register, so this function must be used in an atomic way +// 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__) /** @@ -121,13 +127,13 @@ static inline void lp_uart_ll_set_source_clk(uart_dev_t *hw, soc_periph_lp_uart_ * @param hw_id LP UART instance ID * @param enable True to enable, False to disable */ -static inline void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) +FORCE_INLINE_ATTR void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) { (void)hw_id; LPPERI.clk_en.ck_en_lp_uart = enable; } -/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way +// LPPERI.clk_en is a shared register, so this function must be used in an atomic way #define lp_uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_enable_bus_clock(__VA_ARGS__) /** @@ -135,17 +141,18 @@ static inline void lp_uart_ll_enable_bus_clock(int hw_id, bool enable) * * @param hw_id LP UART instance ID */ -static inline void lp_uart_ll_reset_register(int hw_id) +FORCE_INLINE_ATTR void lp_uart_ll_reset_register(int hw_id) { (void)hw_id; LPPERI.reset_en.rst_en_lp_uart = 1; LPPERI.reset_en.rst_en_lp_uart = 0; } -/// LPPERI.reset_en is a shared register, so this function must be used in an atomic way +// LPPERI.reset_en is a shared register, so this function must be used in an atomic way #define lp_uart_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_reset_register(__VA_ARGS__) /*************************************** General LL functions ******************************************/ + /** * @brief Sync the update to UART core clock domain * @@ -186,6 +193,8 @@ FORCE_INLINE_ATTR void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) abort(); } } +// HP_SYS_CLKRST.hp_rst_en1 is a shared register, so this function must be used in an atomic way +#define uart_ll_set_reset_core(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_set_reset_core(__VA_ARGS__) /** * @brief Enable the UART clock. @@ -199,35 +208,22 @@ FORCE_INLINE_ATTR void uart_ll_sclk_enable(uart_dev_t *hw) { if ((hw) == &UART0) { HP_SYS_CLKRST.peri_clk_ctrl110.reg_uart0_clk_en = 1; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart0_sys_clk_en = 1; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart0_apb_clk_en = 1; } else if ((hw) == &UART1) { HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart1_clk_en = 1; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = 1; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = 1; } else if ((hw) == &UART2) { HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart2_clk_en = 1; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = 1; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = 1; } else if ((hw) == &UART3) { HP_SYS_CLKRST.peri_clk_ctrl113.reg_uart3_clk_en = 1; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = 1; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = 1; } else if ((hw) == &UART4) { HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_en = 1; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = 1; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = 1; } else { // LP_UART reset shares the same register with other LP peripherals // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c abort(); } } +// HP_SYS_CLKRST.peri_clk_ctrlxxx are shared registers, so this function must be used in an atomic way +#define uart_ll_sclk_enable(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_sclk_enable(__VA_ARGS__) /** * @brief Disable the UART clock. @@ -240,35 +236,97 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) { if ((hw) == &UART0) { HP_SYS_CLKRST.peri_clk_ctrl110.reg_uart0_clk_en = 0; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart0_sys_clk_en = 0; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart0_apb_clk_en = 0; } else if ((hw) == &UART1) { HP_SYS_CLKRST.peri_clk_ctrl111.reg_uart1_clk_en = 0; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = 0; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = 0; } else if ((hw) == &UART2) { HP_SYS_CLKRST.peri_clk_ctrl112.reg_uart2_clk_en = 0; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = 0; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = 0; } else if ((hw) == &UART3) { HP_SYS_CLKRST.peri_clk_ctrl113.reg_uart3_clk_en = 0; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = 0; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = 0; } else if ((hw) == &UART4) { HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_en = 0; - //To do: call these two in clk_gate_ll.h - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = 0; - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = 0; } else { // LP_UART reset shares the same register with other LP peripherals // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c abort(); } } +// HP_SYS_CLKRST.peri_clk_ctrlxxx are shared registers, so this function must be used in an atomic way +#define uart_ll_sclk_disable(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_sclk_disable(__VA_ARGS__) + +/** + * @brief Enable the bus clock for uart + * @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) +{ + 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; + break; + case 1: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = enable; + break; + case 2: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = enable; + break; + case 3: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = enable; + break; + case 4: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = enable; + break; + default: + // LP_UART + abort(); + break; + } +} +// HP_SYS_CLKRST.soc_clk_ctrlx are shared registers, so this function must be used in an atomic way +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @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) +{ + 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; + break; + case 1: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb = 0; + break; + case 2: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb = 0; + break; + case 3: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb = 0; + break; + case 4: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 0; + break; + default: + // LP_UART + abort(); + break; + } +} +// 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 Set the UART source clock. @@ -307,11 +365,11 @@ FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_ } else if ((hw) == &UART4) { HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_src_sel = sel_value; } else { - // LP_UART reset shares the same register with other LP peripherals - // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c abort(); } } +//HP_SYS_CLKRST.peri_clk_ctrlxxx are shared registers, so this function must be used in an atomic way +#define uart_ll_set_sclk(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_set_sclk(__VA_ARGS__) /** * @brief Get the UART source clock type. @@ -364,36 +422,36 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source */ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint32_t sclk_freq) { - if ((hw) == &LP_UART){ - uint32_t clk_div = ((sclk_freq) << 4) / (baud); - hw->clkdiv_sync.clkdiv = clk_div >> 4; - hw->clkdiv_sync.clkdiv_frag = clk_div & 0xf; - } else { #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 - int sclk_div = DIV_UP(sclk_freq, max_div * baud); - - 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 - if ((hw) == &UART0) { - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl111, reg_uart0_sclk_div_num, sclk_div - 1); - } else if ((hw) == &UART1){ - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl112, reg_uart1_sclk_div_num, sclk_div - 1); - } else if ((hw) == &UART2){ - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl113, reg_uart2_sclk_div_num, sclk_div - 1); - } else if ((hw) == &UART3){ - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl114, reg_uart3_sclk_div_num, sclk_div - 1); - } else { - HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num, sclk_div - 1); - } - } + const uint32_t max_div = BIT(12) - 1; // UART divider integer part only has 12 bits + int sclk_div = DIV_UP(sclk_freq, max_div * baud); + 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 + if ((hw) == &UART0) { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl111, reg_uart0_sclk_div_num, sclk_div - 1); + } else if ((hw) == &UART1) { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl112, reg_uart1_sclk_div_num, sclk_div - 1); + } else if ((hw) == &UART2) { + HAL_FORCE_MODIFY_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl113, reg_uart2_sclk_div_num, sclk_div - 1); + } else if ((hw) == &UART3) { + 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 { + //LP UART + HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); + } #undef DIV_UP uart_ll_update(hw); } +#if !BOOTLOADER_BUILD +//HP_SYS_CLKRST.peri_clk_ctrlxxx are shared registers, so this function must be used in an atomic way +#define uart_ll_set_baudrate(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_set_baudrate(__VA_ARGS__) +#endif /** * @brief Get the current baud-rate. @@ -410,13 +468,13 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_fr int sclk_div = 0; if ((hw) == &UART0) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl111, reg_uart0_sclk_div_num) + 1; - } else if ((hw) == &UART1){ + } else if ((hw) == &UART1) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl112, reg_uart1_sclk_div_num) + 1; - } else if ((hw) == &UART2){ + } else if ((hw) == &UART2) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl113, reg_uart2_sclk_div_num) + 1; - } else if ((hw) == &UART3){ + } else if ((hw) == &UART3) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl114, reg_uart3_sclk_div_num) + 1; - } else if ((hw) == &UART4){ + } else if ((hw) == &UART4) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num) + 1; } else { return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag)); diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index d33fd2fb25..ef707f0b3f 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,8 @@ #include "hal/uart_types.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" +#include "soc/system_reg.h" +#include "soc/dport_reg.h" #include "esp_attr.h" #ifdef __cplusplus @@ -53,6 +55,56 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +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) + { + case 0: + reg_val = reg_val & (~DPORT_UART_CLK_EN); + reg_val = reg_val | (enable << DPORT_UART_CLK_EN_S); + break; + case 1: + reg_val = reg_val & (~DPORT_UART1_CLK_EN); + reg_val = reg_val | (enable << DPORT_UART1_CLK_EN_S); + break; + default: + abort(); + break; + } + WRITE_PERI_REG(DPORT_PERIP_CLK_EN0_REG, reg_val); +} +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t 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); + break; + case 1: + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_UART1_RST); + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_rst_enx are shared registers, 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 Set the UART source clock. * diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index b807110a29..363f5471ab 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -15,6 +15,7 @@ #include "hal/uart_types.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" +#include "soc/system_struct.h" #include "esp_attr.h" #ifdef __cplusplus @@ -69,6 +70,60 @@ static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) hw->clk_conf.rst_core = core_rst_en; } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_clk_en0.uart_clk_en = enable; + break; + case 1: + SYSTEM.perip_clk_en0.uart1_clk_en = enable; + break; + case 2: + SYSTEM.perip_clk_en1.uart2_clk_en = enable; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_rst_en0.uart_rst = 1; + SYSTEM.perip_rst_en0.uart_rst = 0; + break; + case 1: + SYSTEM.perip_rst_en0.uart1_rst = 1; + SYSTEM.perip_rst_en0.uart1_rst = 0; + break; + case 2: + SYSTEM.perip_rst_en1.uart2_rst = 1; + SYSTEM.perip_rst_en1.uart2_rst = 0; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_rst_enx are shared registers, 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 Set the UART source clock. * diff --git a/components/hal/include/hal/uart_hal.h b/components/hal/include/hal/uart_hal.h index 1682994023..193eedcd67 100644 --- a/components/hal/include/hal/uart_hal.h +++ b/components/hal/include/hal/uart_hal.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +29,26 @@ typedef struct { uart_dev_t *dev; } uart_hal_context_t; +/** + * @brief Configure the UART baud-rate and select the source clock + * + * @param hal Context of the HAL layer + * @param baud_rate The baud-rate to be set + * @param sclk_freq Frequency of the clock source of UART, in Hz. + * + * @return None + */ +#define uart_hal_set_baudrate(hal, baud_rate, sclk_freq) uart_ll_set_baudrate((hal)->dev, baud_rate, sclk_freq) + +/** + * @brief Set the UART source clock type + * @param hal Context of the HAL layer + * @param sclk The UART source clock type. + * + * @return None + */ +#define uart_hal_set_sclk(hal, sclk) uart_ll_set_sclk((hal)->dev, sclk); + /** * @brief Clear the UART interrupt status * @@ -188,15 +208,6 @@ void uart_hal_rxfifo_rst(uart_hal_context_t *hal); */ void uart_hal_init(uart_hal_context_t *hal, uart_port_t uart_num); -/** - * @brief Set the UART source clock type - * @param hal Context of the HAL layer - * @param sclk The UART source clock type. - * - * @return None - */ -void uart_hal_set_sclk(uart_hal_context_t *hal, soc_module_clk_t sclk); - /** * @brief Get the UART source clock type * @@ -207,17 +218,6 @@ void uart_hal_set_sclk(uart_hal_context_t *hal, soc_module_clk_t sclk); */ void uart_hal_get_sclk(uart_hal_context_t *hal, soc_module_clk_t *sclk); -/** - * @brief Configure the UART baud-rate and select the source clock - * - * @param hal Context of the HAL layer - * @param baud_rate The baud-rate to be set - * @param sclk_freq Frequency of the clock source of UART, in Hz. - * - * @return None - */ -void uart_hal_set_baudrate(uart_hal_context_t *hal, uint32_t baud_rate, uint32_t sclk_freq); - /** * @brief Configure the UART stop bit * diff --git a/components/hal/uart_hal.c b/components/hal/uart_hal.c index 9ca2bc289e..305bec872c 100644 --- a/components/hal/uart_hal.c +++ b/components/hal/uart_hal.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,21 +8,11 @@ #include "hal/uart_hal.h" #include "soc/soc_caps.h" -void uart_hal_set_sclk(uart_hal_context_t *hal, soc_module_clk_t sclk) -{ - uart_ll_set_sclk(hal->dev, sclk); -} - void uart_hal_get_sclk(uart_hal_context_t *hal, soc_module_clk_t *sclk) { uart_ll_get_sclk(hal->dev, sclk); } -void uart_hal_set_baudrate(uart_hal_context_t *hal, uint32_t baud_rate, uint32_t sclk_freq) -{ - uart_ll_set_baudrate(hal->dev, baud_rate, sclk_freq); -} - void uart_hal_get_baudrate(uart_hal_context_t *hal, uint32_t *baud_rate, uint32_t sclk_freq) { *baud_rate = uart_ll_get_baudrate(hal->dev, sclk_freq); diff --git a/components/soc/esp32p4/include/soc/uart_struct.h b/components/soc/esp32p4/include/soc/uart_struct.h index 6c8375d5c1..0756a2ad85 100644 --- a/components/soc/esp32p4/include/soc/uart_struct.h +++ b/components/soc/esp32p4/include/soc/uart_struct.h @@ -880,7 +880,21 @@ typedef union { */ typedef union { struct { - uint32_t reserved_0:24; + /** sclk_div_b : R/W; bitpos: [5:0]; default: 0; + * The denominator of the frequency divider factor. + */ + uint32_t sclk_div_b:6; + /** sclk_div_a : R/W; bitpos: [11:6]; default: 0; + * The numerator of the frequency divider factor. + */ + uint32_t sclk_div_a:6; + /** sclk_div_num : R/W; bitpos: [19:12]; default: 1; + * The integral part of the frequency divider factor. + * It is only used by LP UART + * HP UART's sclk_div_num is in hp_sys_clkrst_struct.h + */ + uint32_t sclk_div_num:8; + uint32_t reserved_20:4; /** tx_sclk_en : R/W; bitpos: [24]; default: 1; * Set this bit to enable UART Tx clock. */ diff --git a/components/ulp/lp_core/lp_core_uart.c b/components/ulp/lp_core/lp_core_uart.c index ade460a699..9fee3a0907 100644 --- a/components/ulp/lp_core/lp_core_uart.c +++ b/components/ulp/lp_core/lp_core_uart.c @@ -13,6 +13,7 @@ #include "hal/rtc_io_types.h" #include "esp_clk_tree.h" #include "esp_private/periph_ctrl.h" +#include "esp_private/uart_private.h" #define LP_UART_PORT_NUM LP_UART_NUM_0 #define LP_UART_TX_IDLE_NUM_DEFAULT (0U) @@ -52,7 +53,9 @@ static esp_err_t lp_core_uart_param_config(const lp_core_uart_cfg_t *cfg) } /* Override protocol parameters from the configuration */ - uart_hal_set_baudrate(&hal, cfg->uart_proto_cfg.baud_rate, sclk_freq); + UART_CLK_ATOMIC() { + uart_hal_set_baudrate(&hal, 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); From 3e3e9282098805c69d11295c31eed64421a05a2f Mon Sep 17 00:00:00 2001 From: gaoxu Date: Fri, 15 Sep 2023 11:09:52 +0800 Subject: [PATCH 3/5] feat(uart): move periph_ll_uart_enabled to uart_ll.h --- components/esp_hw_support/sleep_modes.c | 4 +- .../hal/esp32/include/hal/clk_gate_ll.h | 13 ---- components/hal/esp32/include/hal/uart_ll.h | 21 ++++++ .../hal/esp32c2/include/hal/clk_gate_ll.h | 11 --- components/hal/esp32c2/include/hal/uart_ll.h | 21 ++++++ .../hal/esp32c3/include/hal/clk_gate_ll.h | 11 --- components/hal/esp32c3/include/hal/uart_ll.h | 21 ++++++ .../hal/esp32c6/include/hal/clk_gate_ll.h | 13 ---- components/hal/esp32c6/include/hal/uart_ll.h | 22 ++++++ .../hal/esp32h2/include/hal/clk_gate_ll.h | 13 ---- components/hal/esp32h2/include/hal/uart_ll.h | 22 ++++++ components/hal/esp32p4/include/hal/uart_ll.h | 71 ++++++++++++++++--- .../hal/esp32s2/include/hal/clk_gate_ll.h | 11 --- components/hal/esp32s2/include/hal/uart_ll.h | 19 +++++ .../hal/esp32s3/include/hal/clk_gate_ll.h | 13 ---- components/hal/esp32s3/include/hal/uart_ll.h | 23 ++++++ components/soc/esp32p4/include/soc/soc_caps.h | 3 +- .../soc/esp32p4/include/soc/uart_struct.h | 7 +- components/ulp/lp_core/lp_core_uart.c | 2 +- 19 files changed, 217 insertions(+), 104 deletions(-) diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b112109005..8fbf4444c4 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -424,7 +424,7 @@ static void IRAM_ATTR flush_uarts(void) #ifdef CONFIG_IDF_TARGET_ESP32 esp_rom_uart_tx_wait_idle(i); #else - if (periph_ll_uart_enabled(i)) { + if (uart_ll_is_enabled(i)) { esp_rom_uart_tx_wait_idle(i); } #endif @@ -442,7 +442,7 @@ FORCE_INLINE_ATTR void suspend_uarts(void) s_suspended_uarts_bmap = 0; for (int i = 0; i < SOC_UART_HP_NUM; ++i) { #ifndef CONFIG_IDF_TARGET_ESP32 - if (!periph_ll_uart_enabled(i)) { + if (!uart_ll_is_enabled(i)) { continue; } #endif diff --git a/components/hal/esp32/include/hal/clk_gate_ll.h b/components/hal/esp32/include/hal/clk_gate_ll.h index 6455a04431..4ab3a9aceb 100644 --- a/components/hal/esp32/include/hal/clk_gate_ll.h +++ b/components/hal/esp32/include/hal/clk_gate_ll.h @@ -266,19 +266,6 @@ static inline void periph_ll_wifi_module_disable_clk_set_rst(void) DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); } -FORCE_INLINE_ATTR bool periph_ll_uart_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); - uint32_t uart_en_bit = ((uart_num == 0) ? DPORT_UART_CLK_EN : - (uart_num == 1) ? DPORT_UART1_CLK_EN : - (uart_num == 2) ? DPORT_UART2_CLK_EN : 0); - return DPORT_REG_GET_BIT(DPORT_PERIP_RST_EN_REG, uart_rst_bit) == 0 && - DPORT_REG_GET_BIT(DPORT_PERIP_CLK_EN_REG, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32/include/hal/uart_ll.h b/components/hal/esp32/include/hal/uart_ll.h index fbd970c9f2..45ce8b8e9c 100644 --- a/components/hal/esp32/include/hal/uart_ll.h +++ b/components/hal/esp32/include/hal/uart_ll.h @@ -11,6 +11,7 @@ #pragma once #include +#include "hal/assert.h" #include "hal/misc.h" #include "esp_attr.h" #include "soc/uart_reg.h" @@ -56,6 +57,26 @@ typedef enum { UART_INTR_CMD_CHAR_DET = (0x1<<18), } uart_intr_t; +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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); + uint32_t uart_en_bit = ((uart_num == 0) ? DPORT_UART_CLK_EN : + (uart_num == 1) ? DPORT_UART1_CLK_EN : + (uart_num == 2) ? DPORT_UART2_CLK_EN : 0); + return DPORT_REG_GET_BIT(DPORT_PERIP_RST_EN_REG, uart_rst_bit) == 0 && + DPORT_REG_GET_BIT(DPORT_PERIP_CLK_EN_REG, uart_en_bit) != 0; +} + /** * @brief Enable the bus clock for uart * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). diff --git a/components/hal/esp32c2/include/hal/clk_gate_ll.h b/components/hal/esp32c2/include/hal/clk_gate_ll.h index 69355f34f5..a832b86c9c 100644 --- a/components/hal/esp32c2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c2/include/hal/clk_gate_ll.h @@ -216,17 +216,6 @@ static inline void periph_ll_wifi_module_disable_clk_set_rst(void) DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); } -FORCE_INLINE_ATTR bool periph_ll_uart_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 : - (uart_num == 1) ? SYSTEM_UART1_CLK_EN : 0); - return DPORT_REG_GET_BIT(SYSTEM_PERIP_RST_EN0_REG, uart_rst_bit) == 0 && - DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c2/include/hal/uart_ll.h b/components/hal/esp32c2/include/hal/uart_ll.h index 46bea10726..4b65f064f7 100644 --- a/components/hal/esp32c2/include/hal/uart_ll.h +++ b/components/hal/esp32c2/include/hal/uart_ll.h @@ -12,10 +12,13 @@ #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" #include "soc/system_struct.h" +#include "soc/system_reg.h" +#include "soc/dport_access.h" #include "esp_attr.h" #ifdef __cplusplus @@ -57,6 +60,24 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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 : + (uart_num == 1) ? SYSTEM_UART1_CLK_EN : 0); + return DPORT_REG_GET_BIT(SYSTEM_PERIP_RST_EN0_REG, uart_rst_bit) == 0 && + DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; +} + /** * @brief Configure the UART core reset. * diff --git a/components/hal/esp32c3/include/hal/clk_gate_ll.h b/components/hal/esp32c3/include/hal/clk_gate_ll.h index 3222449055..b76993c048 100644 --- a/components/hal/esp32c3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c3/include/hal/clk_gate_ll.h @@ -265,17 +265,6 @@ static inline void periph_ll_wifi_module_disable_clk_set_rst(void) DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); } -FORCE_INLINE_ATTR bool periph_ll_uart_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 : - (uart_num == 1) ? SYSTEM_UART1_CLK_EN : 0); - return DPORT_REG_GET_BIT(SYSTEM_PERIP_RST_EN0_REG, uart_rst_bit) == 0 && - DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 3a19a9a6da..03217562f4 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -11,11 +11,14 @@ #pragma once #include +#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/system_struct.h" +#include "soc/system_reg.h" +#include "soc/dport_access.h" #include "esp_attr.h" #ifdef __cplusplus @@ -57,6 +60,24 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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 : + (uart_num == 1) ? SYSTEM_UART1_CLK_EN : 0); + return DPORT_REG_GET_BIT(SYSTEM_PERIP_RST_EN0_REG, uart_rst_bit) == 0 && + DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; +} + /** * @brief Configure the UART core reset. * diff --git a/components/hal/esp32c6/include/hal/clk_gate_ll.h b/components/hal/esp32c6/include/hal/clk_gate_ll.h index 3df27b2616..237c10d645 100644 --- a/components/hal/esp32c6/include/hal/clk_gate_ll.h +++ b/components/hal/esp32c6/include/hal/clk_gate_ll.h @@ -330,19 +330,6 @@ static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph) REG_GET_BIT(periph_ll_get_clk_en_reg(periph), periph_ll_get_clk_en_mask(periph)) != 0; } -FORCE_INLINE_ATTR bool periph_ll_uart_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 : - (uart_num == 1) ? PCR_UART1_RST_EN : 0); - uint32_t uart_en_bit = ((uart_num == 0) ? PCR_UART0_CLK_EN : - (uart_num == 1) ? PCR_UART1_CLK_EN : 0); - return REG_GET_BIT(uart_clk_config_reg, uart_rst_bit) == 0 && - REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index b990cf7df5..1927bbae1b 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -16,6 +16,7 @@ #include "soc/uart_struct.h" #include "soc/lp_uart_reg.h" #include "soc/pcr_struct.h" +#include "soc/pcr_reg.h" #include "soc/lp_clkrst_struct.h" #include "soc/lpperi_struct.h" #include "hal/assert.h" @@ -161,6 +162,27 @@ static inline void lp_uart_ll_reset_register(int hw_id) #define lp_uart_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_uart_ll_reset_register(__VA_ARGS__) /*************************************** General LL functions ******************************************/ + +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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 : + (uart_num == 1) ? PCR_UART1_RST_EN : 0); + uint32_t uart_en_bit = ((uart_num == 0) ? PCR_UART0_CLK_EN : + (uart_num == 1) ? PCR_UART1_CLK_EN : 0); + return REG_GET_BIT(uart_clk_config_reg, uart_rst_bit) == 0 && + REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; +} + /** * @brief Sync the update to UART core clock domain * diff --git a/components/hal/esp32h2/include/hal/clk_gate_ll.h b/components/hal/esp32h2/include/hal/clk_gate_ll.h index 19ba4c2aff..c0549ffdab 100644 --- a/components/hal/esp32h2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32h2/include/hal/clk_gate_ll.h @@ -394,19 +394,6 @@ static inline void periph_ll_wifi_module_disable_clk_set_rst(void) // DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); } -FORCE_INLINE_ATTR bool periph_ll_uart_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 : - (uart_num == 1) ? PCR_UART1_RST_EN : 0); - uint32_t uart_en_bit = ((uart_num == 0) ? PCR_UART0_CLK_EN : - (uart_num == 1) ? PCR_UART1_CLK_EN : 0); - return REG_GET_BIT(uart_clk_config_reg, uart_rst_bit) == 0 && - REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index b25782d952..dce5c6be1d 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -12,11 +12,13 @@ #include #include "esp_attr.h" +#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/pcr_struct.h" +#include "soc/pcr_reg.h" #include "esp_attr.h" #ifdef __cplusplus @@ -80,6 +82,26 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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 : + (uart_num == 1) ? PCR_UART1_RST_EN : 0); + uint32_t uart_en_bit = ((uart_num == 0) ? PCR_UART0_CLK_EN : + (uart_num == 1) ? PCR_UART1_CLK_EN : 0); + return REG_GET_BIT(uart_clk_config_reg, uart_rst_bit) == 0 && + REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; +} + /** * @brief Sync the update to UART core clock domain * diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index 4a7c68f360..ae9418991a 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -153,6 +153,52 @@ FORCE_INLINE_ATTR void lp_uart_ll_reset_register(int hw_id) /*************************************** General LL functions ******************************************/ +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) +{ + HAL_ASSERT(uart_num < SOC_UART_HP_NUM); + bool uart_rst_en = false; + bool uart_apb_en = false; + bool uart_sys_en = false; + 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; + uart_sys_en = HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart0_sys_clk_en; + break; + case 1: + uart_rst_en = HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb; + uart_apb_en = HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en; + uart_sys_en = HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en; + break; + case 2: + uart_rst_en = HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb; + uart_apb_en = HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en; + uart_sys_en = HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en; + break; + case 3: + uart_rst_en = HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb; + uart_apb_en = HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en; + uart_sys_en = HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en; + break; + case 4: + uart_rst_en = HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb; + uart_apb_en = HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en; + uart_sys_en = HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en; + break; + default: + break; + } + return (!uart_rst_en && uart_apb_en && uart_sys_en); +} + /** * @brief Sync the update to UART core clock domain * @@ -176,7 +222,6 @@ FORCE_INLINE_ATTR void uart_ll_update(uart_dev_t *hw) */ FORCE_INLINE_ATTR void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) { - if ((hw) == &UART0) { HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart0_core = core_rst_en; } else if ((hw) == &UART1) { @@ -188,8 +233,7 @@ FORCE_INLINE_ATTR void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) } else if ((hw) == &UART4) { HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_core = core_rst_en; } else { - // LP_UART reset shares the same register with other LP peripherals - // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + // Not going to implement LP_UART reset in this function, it will have its own LL function abort(); } } @@ -217,8 +261,7 @@ FORCE_INLINE_ATTR void uart_ll_sclk_enable(uart_dev_t *hw) } else if ((hw) == &UART4) { HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_en = 1; } else { - // LP_UART reset shares the same register with other LP peripherals - // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + // Not going to implement LP_UART reset in this function, it will have its own LL function abort(); } } @@ -245,8 +288,7 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) } else if ((hw) == &UART4) { HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_en = 0; } else { - // LP_UART reset shares the same register with other LP peripherals - // Needs to be protected with a lock, therefore, it has its unique LL function, and must be called from lp_periph_ctrl.c + // Not going to implement LP_UART reset in this function, it will have its own LL function abort(); } } @@ -282,8 +324,10 @@ FORCE_INLINE_ATTR void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enabl HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = enable; HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = enable; break; + case 5: + // LP_UART port having its own enable_bus_clock function: lp_uart_ll_enable_bus_clock + break;; default: - // LP_UART abort(); break; } @@ -319,8 +363,10 @@ FORCE_INLINE_ATTR void uart_ll_reset_register(uart_port_t uart_num) HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 1; HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 0; break; + case 5: + // LP_UART port having its own enable_bus_clock function: lp_uart_ll_reset_register + break;; default: - // LP_UART abort(); break; } @@ -365,6 +411,7 @@ FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_ } else if ((hw) == &UART4) { HP_SYS_CLKRST.peri_clk_ctrl114.reg_uart4_clk_src_sel = sel_value; } else { + // LP_UART port having its own enable_bus_clock function: lp_uart_ll_set_source_clk abort(); } } @@ -424,7 +471,9 @@ FORCE_INLINE_ATTR void uart_ll_set_baudrate(uart_dev_t *hw, uint32_t baud, uint3 { #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 - int sclk_div = DIV_UP(sclk_freq, max_div * baud); + 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. @@ -477,7 +526,7 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_fr } else if ((hw) == &UART4) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num) + 1; } else { - return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag)); + sclk_div = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1; } return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * sclk_div); } diff --git a/components/hal/esp32s2/include/hal/clk_gate_ll.h b/components/hal/esp32s2/include/hal/clk_gate_ll.h index 28c9787f13..32ee2c457b 100644 --- a/components/hal/esp32s2/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s2/include/hal/clk_gate_ll.h @@ -279,17 +279,6 @@ static inline void periph_ll_wifi_module_disable_clk_set_rst(void) DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG, 0); } -FORCE_INLINE_ATTR bool periph_ll_uart_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 : - (uart_num == 1) ? DPORT_UART1_CLK_EN : 0); - return DPORT_REG_GET_BIT(DPORT_PERIP_RST_EN_REG, uart_rst_bit) == 0 && - DPORT_REG_GET_BIT(DPORT_PERIP_CLK_EN_REG, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s2/include/hal/uart_ll.h b/components/hal/esp32s2/include/hal/uart_ll.h index ef707f0b3f..ab7d4941be 100644 --- a/components/hal/esp32s2/include/hal/uart_ll.h +++ b/components/hal/esp32s2/include/hal/uart_ll.h @@ -11,6 +11,7 @@ #pragma once #include +#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" @@ -55,6 +56,24 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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 : + (uart_num == 1) ? DPORT_UART1_CLK_EN : 0); + return DPORT_REG_GET_BIT(DPORT_PERIP_RST_EN_REG, uart_rst_bit) == 0 && + DPORT_REG_GET_BIT(DPORT_PERIP_CLK_EN_REG, uart_en_bit) != 0; +} + /** * @brief Enable the bus clock for uart * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). diff --git a/components/hal/esp32s3/include/hal/clk_gate_ll.h b/components/hal/esp32s3/include/hal/clk_gate_ll.h index 0d2a2b1872..dfc15c868b 100644 --- a/components/hal/esp32s3/include/hal/clk_gate_ll.h +++ b/components/hal/esp32s3/include/hal/clk_gate_ll.h @@ -300,19 +300,6 @@ static inline void periph_ll_wifi_module_disable_clk_set_rst(void) DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0); } -FORCE_INLINE_ATTR bool periph_ll_uart_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); - uint32_t uart_en_bit = ((uart_num == 0) ? SYSTEM_UART_CLK_EN : - (uart_num == 1) ? SYSTEM_UART1_CLK_EN : - (uart_num == 2) ? SYSTEM_UART2_CLK_EN : 0); - return DPORT_REG_GET_BIT(SYSTEM_PERIP_RST_EN0_REG, uart_rst_bit) == 0 && - DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; -} - #ifdef __cplusplus } #endif diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 363f5471ab..324f88f6e3 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -11,11 +11,14 @@ #pragma once #include +#include "hal/assert.h" #include "hal/misc.h" #include "hal/uart_types.h" #include "soc/uart_reg.h" #include "soc/uart_struct.h" #include "soc/system_struct.h" +#include "soc/system_reg.h" +#include "soc/dport_access.h" #include "esp_attr.h" #ifdef __cplusplus @@ -57,6 +60,26 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; +/** + * @brief Check if UART is enabled or disabled. + * + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * + * @return true: enabled; false: disabled + */ +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); + uint32_t uart_en_bit = ((uart_num == 0) ? SYSTEM_UART_CLK_EN : + (uart_num == 1) ? SYSTEM_UART1_CLK_EN : + (uart_num == 2) ? SYSTEM_UART2_CLK_EN : 0); + return DPORT_REG_GET_BIT(SYSTEM_PERIP_RST_EN0_REG, uart_rst_bit) == 0 && + DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; +} + /** * @brief Configure the UART core reset. * diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index a3d1d0a665..628b0ba9ac 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -472,9 +472,10 @@ /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-P4 has 6 UARTs (5 HP UART, and 1 LP UART) -// The RTC GPIO and sigmap is not supported yet, so make SOC_UART_NUM->5 to avoid lp-uart build errors #define SOC_UART_NUM (5) #define SOC_UART_HP_NUM (5) +// TODO: 7815 +// The RTC GPIO and sigmap is not supported yet, so make SOC_UART_NUM->5 to avoid lp-uart build errors // #define SOC_UART_LP_NUM (1U) #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */ diff --git a/components/soc/esp32p4/include/soc/uart_struct.h b/components/soc/esp32p4/include/soc/uart_struct.h index 0756a2ad85..b23e6db930 100644 --- a/components/soc/esp32p4/include/soc/uart_struct.h +++ b/components/soc/esp32p4/include/soc/uart_struct.h @@ -883,17 +883,16 @@ typedef union { /** sclk_div_b : R/W; bitpos: [5:0]; default: 0; * The denominator of the frequency divider factor. */ - uint32_t sclk_div_b:6; + uint32_t sclk_div_b:6; //HP UART's sclk_div_b is in hp_sys_clkrst_struct.h /** sclk_div_a : R/W; bitpos: [11:6]; default: 0; * The numerator of the frequency divider factor. */ - uint32_t sclk_div_a:6; + uint32_t sclk_div_a:6; //HP UART's sclk_div_a is in hp_sys_clkrst_struct.h /** sclk_div_num : R/W; bitpos: [19:12]; default: 1; * The integral part of the frequency divider factor. * It is only used by LP UART - * HP UART's sclk_div_num is in hp_sys_clkrst_struct.h */ - uint32_t sclk_div_num:8; + uint32_t sclk_div_num:8; //HP UART's sclk_div_num is in hp_sys_clkrst_struct.h uint32_t reserved_20:4; /** tx_sclk_en : R/W; bitpos: [24]; default: 1; * Set this bit to enable UART Tx clock. diff --git a/components/ulp/lp_core/lp_core_uart.c b/components/ulp/lp_core/lp_core_uart.c index 9fee3a0907..94e22e85d6 100644 --- a/components/ulp/lp_core/lp_core_uart.c +++ b/components/ulp/lp_core/lp_core_uart.c @@ -53,7 +53,7 @@ static esp_err_t lp_core_uart_param_config(const lp_core_uart_cfg_t *cfg) } /* Override protocol parameters from the configuration */ - UART_CLK_ATOMIC() { + UART_SCLK_ATOMIC() { uart_hal_set_baudrate(&hal, cfg->uart_proto_cfg.baud_rate, sclk_freq); } uart_hal_set_parity(&hal, cfg->uart_proto_cfg.parity); From 4f24f805cccc088be6e8b488c24d4b91596a8a4e Mon Sep 17 00:00:00 2001 From: gaoxu Date: Mon, 25 Sep 2023 11:12:09 +0800 Subject: [PATCH 4/5] feat(uart): add LP-UART GPIO support --- .../driver/include/esp_private/uart_private.h | 2 +- components/driver/uart/uart.c | 30 ++-- components/esp_pm/pm_impl.c | 2 +- components/esp_rom/include/esp_rom_uart.h | 3 +- components/esp_rom/patches/esp_rom_uart.c | 9 - components/esp_system/port/cpu_start.c | 15 +- components/hal/esp32c2/include/hal/uart_ll.h | 83 ++++----- components/hal/esp32c3/include/hal/uart_ll.h | 101 +++++------ components/hal/esp32c6/include/hal/uart_ll.h | 90 +++++----- components/hal/esp32h2/include/hal/uart_ll.h | 86 ++++----- components/hal/esp32p4/include/hal/uart_ll.h | 163 +++++++++--------- components/hal/esp32s3/include/hal/uart_ll.h | 26 +-- .../soc/esp32c3/include/soc/system_reg.h | 30 +--- .../soc/esp32c3/include/soc/system_struct.h | 22 +-- .../esp32c6/include/soc/Kconfig.soc_caps.in | 4 + components/soc/esp32c6/include/soc/soc_caps.h | 1 + .../esp32p4/include/soc/Kconfig.soc_caps.in | 6 +- .../soc/esp32p4/include/soc/clk_tree_defs.h | 2 +- components/soc/esp32p4/include/soc/soc_caps.h | 8 +- components/soc/esp32p4/uart_periph.c | 61 ++++--- examples/system/.build-test-rules.yml | 4 +- tools/ci/check_copyright_ignore.txt | 2 - 22 files changed, 353 insertions(+), 397 deletions(-) diff --git a/components/driver/include/esp_private/uart_private.h b/components/driver/include/esp_private/uart_private.h index 8d96de2624..863ed73472 100644 --- a/components/driver/include/esp_private/uart_private.h +++ b/components/driver/include/esp_private/uart_private.h @@ -18,7 +18,7 @@ extern "C" { #define LP_UART_CLK_ATOMIC() PERIPH_RCC_ATOMIC() #endif -#if CONFIG_IDF_TARGET_ESP32P4 +#if SOC_PERIPH_CLK_CTRL_SHARED #define UART_SCLK_ATOMIC() PERIPH_RCC_ATOMIC() #else #define UART_SCLK_ATOMIC() diff --git a/components/driver/uart/uart.c b/components/driver/uart/uart.c index bf4609a435..31cc1e8de9 100644 --- a/components/driver/uart/uart.c +++ b/components/driver/uart/uart.c @@ -26,6 +26,7 @@ #include "driver/gpio.h" #include "driver/rtc_io.h" #include "driver/uart_select.h" +#include "driver/lp_io.h" #include "esp_private/uart_private.h" #include "esp_private/periph_ctrl.h" #include "esp_clk_tree.h" @@ -666,17 +667,21 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #if (SOC_UART_LP_NUM >= 1) else { // LP_UART IO check - const uart_periph_sig_t *pins = uart_periph_signal[uart_num].pins; + #if !SOC_LP_GPIO_MATRIX_SUPPORTED + const uart_periph_sig_t *pins = uart_periph_signal[uart_num].pins; // LP_UART has its fixed IOs ESP_RETURN_ON_FALSE((tx_io_num < 0 || (tx_io_num == pins[SOC_UART_TX_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "tx_io_num error"); ESP_RETURN_ON_FALSE((rx_io_num < 0 || (rx_io_num == pins[SOC_UART_RX_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "rx_io_num error"); ESP_RETURN_ON_FALSE((rts_io_num < 0 || (rts_io_num == pins[SOC_UART_RTS_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "rts_io_num error"); ESP_RETURN_ON_FALSE((cts_io_num < 0 || (cts_io_num == pins[SOC_UART_CTS_PIN_IDX].default_gpio)), ESP_FAIL, UART_TAG, "cts_io_num error"); +#else + // LP_UART signals can be routed to any LP_IOs + ESP_RETURN_ON_FALSE((tx_io_num < 0 || rtc_gpio_is_valid_gpio(tx_io_num)), ESP_FAIL, UART_TAG, "tx_io_num error"); + ESP_RETURN_ON_FALSE((rx_io_num < 0 || rtc_gpio_is_valid_gpio(rx_io_num)), ESP_FAIL, UART_TAG, "rx_io_num error"); + ESP_RETURN_ON_FALSE((rts_io_num < 0 || rtc_gpio_is_valid_gpio(rts_io_num)), ESP_FAIL, UART_TAG, "rts_io_num error"); + ESP_RETURN_ON_FALSE((cts_io_num < 0 || rtc_gpio_is_valid_gpio(cts_io_num)), ESP_FAIL, UART_TAG, "cts_io_num error"); -#else // SOC_LP_GPIO_MATRIX_SUPPORTED - // LP_UART IOs can be routed any LP_IOs - //TODO: IDF-7815, check for LP_IO 0~15 #endif // SOC_LP_GPIO_MATRIX_SUPPORTED } #endif @@ -690,11 +695,11 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #if SOC_LP_GPIO_MATRIX_SUPPORTED else { - //TODO:IDF-7815 rtc_gpio_set_direction(tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); rtc_gpio_init(tx_io_num); rtc_gpio_iomux_func_sel(tx_io_num, 1); - LP_GPIO.func10_out_sel_cfg.reg_gpio_func10_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_TX_PIN_IDX].signal; + + lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); } #endif } @@ -708,12 +713,11 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #if SOC_LP_GPIO_MATRIX_SUPPORTED else { - //TODO:IDF-7815 rtc_gpio_set_direction(rx_io_num, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_init(rx_io_num); rtc_gpio_iomux_func_sel(rx_io_num, 1); - LP_GPIO.func2_in_sel_cfg.reg_gpio_sig2_in_sel = 1; - LP_GPIO.func2_in_sel_cfg.reg_gpio_func2_in_sel = 11; + + lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); } #endif } @@ -726,11 +730,10 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #if SOC_LP_GPIO_MATRIX_SUPPORTED else { - //TODO:IDF-7815 rtc_gpio_set_direction(rts_io_num, RTC_GPIO_MODE_OUTPUT_ONLY); rtc_gpio_init(rts_io_num); rtc_gpio_iomux_func_sel(rts_io_num, 1); - LP_GPIO.func10_out_sel_cfg.reg_gpio_func12_out_sel = uart_periph_signal[uart_num].pins[SOC_UART_RTS_PIN_IDX].signal; + lp_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); } #endif } @@ -744,12 +747,11 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #if SOC_LP_GPIO_MATRIX_SUPPORTED else { - //TODO:IDF-7815 rtc_gpio_set_direction(cts_io_num, RTC_GPIO_MODE_INPUT_ONLY); rtc_gpio_init(cts_io_num); rtc_gpio_iomux_func_sel(cts_io_num, 1); - LP_GPIO.func2_in_sel_cfg.reg_gpio_sig3_in_sel = 1; - LP_GPIO.func2_in_sel_cfg.reg_gpio_func3_in_sel = 13; + + lp_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0); } #endif } diff --git a/components/esp_pm/pm_impl.c b/components/esp_pm/pm_impl.c index e3d39d17d8..50f4772788 100644 --- a/components/esp_pm/pm_impl.c +++ b/components/esp_pm/pm_impl.c @@ -738,7 +738,7 @@ void esp_pm_impl_init(void) #else #error "No UART clock source is aware of DFS" #endif // SOC_UART_SUPPORT_xxx - while(!uart_ll_is_tx_idle(UART_LL_GET_HW(CONFIG_ESP_CONSOLE_UART_NUM))) { + 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 */ diff --git a/components/esp_rom/include/esp_rom_uart.h b/components/esp_rom/include/esp_rom_uart.h index 4d01172cbd..2e2904d573 100644 --- a/components/esp_rom/include/esp_rom_uart.h +++ b/components/esp_rom/include/esp_rom_uart.h @@ -11,6 +11,7 @@ extern "C" { #endif #include +#include "hal/uart_ll.h" #define ESP_ROM_CDC_ACM_WORK_BUF_MIN 128 @@ -34,7 +35,7 @@ void esp_rom_uart_tx_wait_idle(uint8_t uart_no); * @param clock_hz Source clock (in Hz) * @param baud_rate Baud rate to set */ -void esp_rom_uart_set_clock_baudrate(uint8_t uart_no, uint32_t clock_hz, uint32_t baud_rate); +#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) /** * @brief Wait until UART TX FIFO is empty (i.e. flush TX FIFO) diff --git a/components/esp_rom/patches/esp_rom_uart.c b/components/esp_rom/patches/esp_rom_uart.c index 743d1c9d0b..7e868b4b88 100644 --- a/components/esp_rom/patches/esp_rom_uart.c +++ b/components/esp_rom/patches/esp_rom_uart.c @@ -23,15 +23,6 @@ IRAM_ATTR void esp_rom_uart_tx_wait_idle(uint8_t uart_no) } #endif -IRAM_ATTR void esp_rom_uart_set_clock_baudrate(uint8_t uart_no, uint32_t clock_hz, uint32_t baud_rate) -{ -// To avoid build errors about __DECLARE_RCC_ATOMIC_ENV -#if !BOOTLOADER_BUILD - int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused)); -#endif - uart_ll_set_baudrate(UART_LL_GET_HW(uart_no), baud_rate, clock_hz); -} - #if CONFIG_IDF_TARGET_ESP32C3 /** * The ESP32-C3 ROM has released two versions, one is the ECO3 version, diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index cf7b749083..459632e01a 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -144,13 +144,6 @@ static volatile bool s_cpu_inited[SOC_CPU_CORES_NUM] = { false }; static volatile bool s_resume_cores; #endif -#if CONFIG_IDF_TARGET_ESP32P4 -#define UART_START_SCLK_ATOMIC() PERIPH_RCC_ATOMIC() -#else -// #define UART_START_SCLK_ATOMIC() for(int i = 1, __DECLARE_RCC_ATOMIC_ENV; i < 1; i--) -#define UART_START_SCLK_ATOMIC() int __DECLARE_RCC_ATOMIC_ENV; -#endif - static void core_intr_matrix_clear(void) { uint32_t core_id = esp_cpu_get_core_id(); @@ -690,10 +683,10 @@ void IRAM_ATTR call_start_cpu0(void) clock_hz = esp_clk_xtal_freq(); // From esp32-s3 on, UART clock source is selected to XTAL in ROM #endif esp_rom_uart_tx_wait_idle(CONFIG_ESP_CONSOLE_UART_NUM); - UART_START_SCLK_ATOMIC() { - (void) __DECLARE_RCC_ATOMIC_ENV; // To avoid build warning about __DECLARE_RCC_ATOMIC_ENV defined but not used on P4 - esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_UART_NUM, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); - } + + // In a single thread mode, the freertos is not started yet. So don't have to use a critical section. + int __DECLARE_RCC_ATOMIC_ENV __attribute__ ((unused)); // To avoid build errors about spinlock's __DECLARE_RCC_ATOMIC_ENV + esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_UART_NUM, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE); #endif #endif diff --git a/components/hal/esp32c2/include/hal/uart_ll.h b/components/hal/esp32c2/include/hal/uart_ll.h index 4b65f064f7..8e5d1a24a1 100644 --- a/components/hal/esp32c2/include/hal/uart_ll.h +++ b/components/hal/esp32c2/include/hal/uart_ll.h @@ -78,47 +78,6 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; } -/** - * @brief Configure the UART core reset. - * - * @param hw Beginning address of the peripheral registers. - * @param core_rst_en True to enable the core reset, otherwise set it false. - * - * @return None. - */ -FORCE_INLINE_ATTR void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) -{ - hw->clk_conf.rst_core = core_rst_en; -} - -/** - * @brief Enable the UART clock. - * - * @param hw Beginning address of the peripheral registers. - * - * @return None. - */ -FORCE_INLINE_ATTR void uart_ll_sclk_enable(uart_dev_t *hw) -{ - hw->clk_conf.sclk_en = 1; - hw->clk_conf.rx_sclk_en = 1; - hw->clk_conf.tx_sclk_en = 1; -} - -/** - * @brief Disable the UART clock. - * - * @param hw Beginning address of the peripheral registers. - * - * @return None. - */ -FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) -{ - hw->clk_conf.sclk_en = 0; - hw->clk_conf.rx_sclk_en = 0; - hw->clk_conf.tx_sclk_en = 0; -} - /** * @brief Enable the bus clock for uart * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). @@ -166,6 +125,48 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) // SYSTEM.perip_rst_en0 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 Configure the UART core reset. + * + * @param hw Beginning address of the peripheral registers. + * @param core_rst_en True to enable the core reset, otherwise set it false. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) +{ + hw->clk_conf.rst_core = core_rst_en; +} + +/** + * @brief Enable the UART clock. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_sclk_enable(uart_dev_t *hw) +{ + hw->clk_conf.sclk_en = 1; + hw->clk_conf.rx_sclk_en = 1; + hw->clk_conf.tx_sclk_en = 1; +} + +/** + * @brief Disable the UART clock. + * + * @param hw Beginning address of the peripheral registers. + * + * @return None. + */ +FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) +{ + hw->clk_conf.sclk_en = 0; + hw->clk_conf.rx_sclk_en = 0; + hw->clk_conf.tx_sclk_en = 0; +} + + /** * @brief Set the UART source clock. * diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 03217562f4..d9148d5de7 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -78,6 +78,53 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_clk_en0.reg_uart_clk_en = enable; + break; + case 1: + SYSTEM.perip_clk_en0.reg_uart1_clk_en = enable; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + SYSTEM.perip_rst_en0.reg_uart_rst = 1; + SYSTEM.perip_rst_en0.reg_uart_rst = 0; + break; + case 1: + SYSTEM.perip_rst_en0.reg_uart1_rst = 1; + SYSTEM.perip_rst_en0.reg_uart1_rst = 0; + break; + default: + abort(); + break; + } +} +// SYSTEM.perip_rst_enx are shared registers, 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 Configure the UART core reset. * @@ -119,60 +166,6 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) hw->clk_conf.tx_sclk_en = 0; } -/** - * @brief Enable the bus clock for uart - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - * @param enable true to enable, false to disable - */ -static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) -{ - switch (uart_num) - { - case 0: - SYSTEM.perip_clk_en0.reg_uart_clk_en = enable; - break; - case 1: - SYSTEM.perip_clk_en0.reg_uart1_clk_en = enable; - break; - case 2: - SYSTEM.perip_clk_en1.reg_uart2_clk_en = enable; - break; - default: - abort(); - break; - } -} -// SYSTEM.perip_clk_enx are shared registers, so this function must be used in an atomic way -#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) - -/** - * @brief Reset UART module - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - */ -static inline void uart_ll_reset_register(uart_port_t uart_num) -{ - switch (uart_num) - { - case 0: - SYSTEM.perip_rst_en0.reg_uart_rst = 1; - SYSTEM.perip_rst_en0.reg_uart_rst = 0; - break; - case 1: - SYSTEM.perip_rst_en0.reg_uart1_rst = 1; - SYSTEM.perip_rst_en0.reg_uart1_rst = 0; - break; - case 2: - SYSTEM.perip_rst_en1.reg_uart2_rst = 1; - SYSTEM.perip_rst_en1.reg_uart2_rst = 0; - break; - default: - abort(); - break; - } -} -// SYSTEM.perip_rst_enx are shared registers, 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 Set the UART source clock. * diff --git a/components/hal/esp32c6/include/hal/uart_ll.h b/components/hal/esp32c6/include/hal/uart_ll.h index 1927bbae1b..6468eb3b46 100644 --- a/components/hal/esp32c6/include/hal/uart_ll.h +++ b/components/hal/esp32c6/include/hal/uart_ll.h @@ -183,6 +183,51 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_clk_en = enable; + break; + case 1: + PCR.uart1_conf.uart1_clk_en = enable; + break; + default: + // LP_UART + abort(); + break; + } +} + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_rst_en = 1; + PCR.uart0_conf.uart0_rst_en = 0; + break; + case 1: + PCR.uart1_conf.uart1_rst_en = 1; + PCR.uart1_conf.uart1_rst_en = 0; + break; + default: + // LP_UART + abort(); + break; + } +} + /** * @brief Sync the update to UART core clock domain * @@ -251,51 +296,6 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) } } -/** - * @brief Enable the bus clock for uart - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - * @param enable true to enable, false to disable - */ -static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) -{ - switch (uart_num) - { - case 0: - PCR.uart0_conf.uart0_clk_en = enable; - break; - case 1: - PCR.uart1_conf.uart1_clk_en = enable; - break; - default: - // LP_UART - abort(); - break; - } -} - -/** - * @brief Reset UART module - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - */ -static inline void uart_ll_reset_register(uart_port_t uart_num) -{ - switch (uart_num) - { - case 0: - PCR.uart0_conf.uart0_rst_en = 1; - PCR.uart0_conf.uart0_rst_en = 0; - break; - case 1: - PCR.uart1_conf.uart1_rst_en = 1; - PCR.uart1_conf.uart1_rst_en = 0; - break; - default: - // LP_UART - abort(); - break; - } -} - /** * @brief Set the UART source clock. * diff --git a/components/hal/esp32h2/include/hal/uart_ll.h b/components/hal/esp32h2/include/hal/uart_ll.h index dce5c6be1d..4927bc2559 100644 --- a/components/hal/esp32h2/include/hal/uart_ll.h +++ b/components/hal/esp32h2/include/hal/uart_ll.h @@ -102,6 +102,49 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) REG_GET_BIT(uart_clk_config_reg, uart_en_bit) != 0; } +/** + * @brief Enable the bus clock for uart + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + * @param enable true to enable, false to disable + */ +static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_clk_en = enable; + break; + case 1: + PCR.uart1_conf.uart1_clk_en = enable; + break; + default: + abort(); + break; + } +} + +/** + * @brief Reset UART module + * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). + */ +static inline void uart_ll_reset_register(uart_port_t uart_num) +{ + switch (uart_num) + { + case 0: + PCR.uart0_conf.uart0_rst_en = 1; + PCR.uart0_conf.uart0_rst_en = 0; + break; + case 1: + PCR.uart1_conf.uart1_rst_en = 1; + PCR.uart1_conf.uart1_rst_en = 0; + break; + default: + abort(); + break; + } +} + /** * @brief Sync the update to UART core clock domain * @@ -152,49 +195,6 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) UART_LL_PCR_REG_SET(hw, sclk_conf, sclk_en, 0); } -/** - * @brief Enable the bus clock for uart - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - * @param enable true to enable, false to disable - */ -static inline void uart_ll_enable_bus_clock(uart_port_t uart_num, bool enable) -{ - switch (uart_num) - { - case 0: - PCR.uart0_conf.uart0_clk_en = enable; - break; - case 1: - PCR.uart1_conf.uart1_clk_en = enable; - break; - default: - abort(); - break; - } -} - -/** - * @brief Reset UART module - * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). - */ -static inline void uart_ll_reset_register(uart_port_t uart_num) -{ - switch (uart_num) - { - case 0: - PCR.uart0_conf.uart0_rst_en = 1; - PCR.uart0_conf.uart0_rst_en = 0; - break; - case 1: - PCR.uart1_conf.uart1_rst_en = 1; - PCR.uart1_conf.uart1_rst_en = 0; - break; - default: - abort(); - break; - } -} - /** * @brief Set the UART source clock. * diff --git a/components/hal/esp32p4/include/hal/uart_ll.h b/components/hal/esp32p4/include/hal/uart_ll.h index ae9418991a..383836b2c5 100644 --- a/components/hal/esp32p4/include/hal/uart_ll.h +++ b/components/hal/esp32p4/include/hal/uart_ll.h @@ -199,6 +199,85 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) return (!uart_rst_en && uart_apb_en && uart_sys_en); } +/** + * @brief Enable the bus clock for uart + * @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) +{ + 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; + break; + case 1: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = enable; + break; + case 2: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = enable; + break; + case 3: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = enable; + break; + case 4: + HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = enable; + HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = enable; + break; + case 5: + // LP_UART port having its own enable_bus_clock function: lp_uart_ll_enable_bus_clock + break;; + default: + abort(); + break; + } +} +// HP_SYS_CLKRST.soc_clk_ctrlx are shared registers, so this function must be used in an atomic way +#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) + +/** + * @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) +{ + 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; + break; + case 1: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb = 0; + break; + case 2: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb = 0; + break; + case 3: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb = 0; + break; + case 4: + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 1; + HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 0; + break; + case 5: + // LP_UART port having its own enable_bus_clock function: lp_uart_ll_reset_register + break;; + default: + abort(); + break; + } +} +// 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 * @@ -295,85 +374,6 @@ FORCE_INLINE_ATTR void uart_ll_sclk_disable(uart_dev_t *hw) // HP_SYS_CLKRST.peri_clk_ctrlxxx are shared registers, so this function must be used in an atomic way #define uart_ll_sclk_disable(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_sclk_disable(__VA_ARGS__) -/** - * @brief Enable the bus clock for uart - * @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) -{ - 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; - break; - case 1: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart1_apb_clk_en = enable; - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart1_sys_clk_en = enable; - break; - case 2: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart2_apb_clk_en = enable; - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart2_sys_clk_en = enable; - break; - case 3: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart3_apb_clk_en = enable; - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart3_sys_clk_en = enable; - break; - case 4: - HP_SYS_CLKRST.soc_clk_ctrl2.reg_uart4_apb_clk_en = enable; - HP_SYS_CLKRST.soc_clk_ctrl1.reg_uart4_sys_clk_en = enable; - break; - case 5: - // LP_UART port having its own enable_bus_clock function: lp_uart_ll_enable_bus_clock - break;; - default: - abort(); - break; - } -} -// HP_SYS_CLKRST.soc_clk_ctrlx are shared registers, so this function must be used in an atomic way -#define uart_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; uart_ll_enable_bus_clock(__VA_ARGS__) - -/** - * @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) -{ - 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; - break; - case 1: - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb = 1; - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart1_apb = 0; - break; - case 2: - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb = 1; - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart2_apb = 0; - break; - case 3: - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb = 1; - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart3_apb = 0; - break; - case 4: - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 1; - HP_SYS_CLKRST.hp_rst_en1.reg_rst_en_uart4_apb = 0; - break; - case 5: - // LP_UART port having its own enable_bus_clock function: lp_uart_ll_reset_register - break;; - default: - abort(); - break; - } -} -// 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 Set the UART source clock. * @@ -490,8 +490,7 @@ 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 { - //LP UART + } else if ((hw) == &LP_UART) { HAL_FORCE_MODIFY_U32_REG_FIELD(hw->clk_conf, sclk_div_num, sclk_div - 1); } #undef DIV_UP @@ -525,7 +524,7 @@ FORCE_INLINE_ATTR uint32_t uart_ll_get_baudrate(uart_dev_t *hw, uint32_t sclk_fr sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl114, reg_uart3_sclk_div_num) + 1; } else if ((hw) == &UART4) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(HP_SYS_CLKRST.peri_clk_ctrl115, reg_uart4_sclk_div_num) + 1; - } else { + } else if ((hw) == &LP_UART) { sclk_div = HAL_FORCE_READ_U32_REG_FIELD(hw->clk_conf, sclk_div_num) + 1; } return ((sclk_freq << 4)) / (((div_reg.clkdiv << 4) | div_reg.clkdiv_frag) * sclk_div); diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 324f88f6e3..37af33b240 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -80,19 +80,6 @@ FORCE_INLINE_ATTR bool uart_ll_is_enabled(uint32_t uart_num) DPORT_REG_GET_BIT(SYSTEM_PERIP_CLK_EN0_REG, uart_en_bit) != 0; } -/** - * @brief Configure the UART core reset. - * - * @param hw Beginning address of the peripheral registers. - * @param core_rst_en True to enable the core reset, otherwise set it false. - * - * @return None. - */ -static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) -{ - hw->clk_conf.rst_core = core_rst_en; -} - /** * @brief Enable the bus clock for uart * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). @@ -147,6 +134,19 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) // SYSTEM.perip_rst_enx are shared registers, 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 Configure the UART core reset. + * + * @param hw Beginning address of the peripheral registers. + * @param core_rst_en True to enable the core reset, otherwise set it false. + * + * @return None. + */ +static inline void uart_ll_set_reset_core(uart_dev_t *hw, bool core_rst_en) +{ + hw->clk_conf.rst_core = core_rst_en; +} + /** * @brief Set the UART source clock. * diff --git a/components/soc/esp32c3/include/soc/system_reg.h b/components/soc/esp32c3/include/soc/system_reg.h index 3a67cb4606..7bcb904214 100644 --- a/components/soc/esp32c3/include/soc/system_reg.h +++ b/components/soc/esp32c3/include/soc/system_reg.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SYSTEM_REG_H_ #define _SOC_SYSTEM_REG_H_ @@ -282,12 +274,6 @@ extern "C" { #define SYSTEM_TSENS_CLK_EN_M (BIT(10)) #define SYSTEM_TSENS_CLK_EN_V 0x1 #define SYSTEM_TSENS_CLK_EN_S 10 -/* SYSTEM_UART2_CLK_EN : R/W ;bitpos:[9] ;default: 1'b1 ; */ -/*description: */ -#define SYSTEM_UART2_CLK_EN (BIT(9)) -#define SYSTEM_UART2_CLK_EN_M (BIT(9)) -#define SYSTEM_UART2_CLK_EN_V 0x1 -#define SYSTEM_UART2_CLK_EN_S 9 /* SYSTEM_LCD_CAM_CLK_EN : R/W ;bitpos:[8] ;default: 1'b0 ; */ /*description: */ #define SYSTEM_LCD_CAM_CLK_EN (BIT(8)) @@ -538,12 +524,6 @@ extern "C" { #define SYSTEM_TSENS_RST_M (BIT(10)) #define SYSTEM_TSENS_RST_V 0x1 #define SYSTEM_TSENS_RST_S 10 -/* SYSTEM_UART2_RST : R/W ;bitpos:[9] ;default: 1'b0 ; */ -/*description: */ -#define SYSTEM_UART2_RST (BIT(9)) -#define SYSTEM_UART2_RST_M (BIT(9)) -#define SYSTEM_UART2_RST_V 0x1 -#define SYSTEM_UART2_RST_S 9 /* SYSTEM_LCD_CAM_RST : R/W ;bitpos:[8] ;default: 1'b1 ; */ /*description: */ #define SYSTEM_LCD_CAM_RST (BIT(8)) diff --git a/components/soc/esp32c3/include/soc/system_struct.h b/components/soc/esp32c3/include/soc/system_struct.h index 5e04cec828..f4cb995aa2 100644 --- a/components/soc/esp32c3/include/soc/system_struct.h +++ b/components/soc/esp32c3/include/soc/system_struct.h @@ -1,16 +1,8 @@ -// Copyright 2020 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. +/* + * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #ifndef _SOC_SYSTEM_STRUCT_H_ #define _SOC_SYSTEM_STRUCT_H_ @@ -104,7 +96,7 @@ typedef volatile struct system_dev_s { uint32_t reg_dma_clk_en : 1; /*reg_dma_clk_en*/ uint32_t reg_sdio_host_clk_en : 1; /*reg_sdio_host_clk_en*/ uint32_t reg_lcd_cam_clk_en : 1; /*reg_lcd_cam_clk_en*/ - uint32_t reg_uart2_clk_en : 1; /*reg_uart2_clk_en*/ + uint32_t reserved9 : 1; /*reserved*/ uint32_t reg_tsens_clk_en : 1; /*reg_tsens_clk_en*/ uint32_t reserved11 : 21; /*reserved*/ }; @@ -158,7 +150,7 @@ typedef volatile struct system_dev_s { uint32_t reg_dma_rst : 1; /*reg_dma_rst*/ uint32_t reg_sdio_host_rst : 1; /*reg_sdio_host_rst*/ uint32_t reg_lcd_cam_rst : 1; /*reg_lcd_cam_rst*/ - uint32_t reg_uart2_rst : 1; /*reg_uart2_rst*/ + uint32_t reserved9 : 1; /*reserved*/ uint32_t reg_tsens_rst : 1; /*reg_tsens_rst*/ uint32_t reserved11 : 21; /*reserved*/ }; diff --git a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in index fb87ce8dc2..5cbb3be3bb 100644 --- a/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c6/include/soc/Kconfig.soc_caps.in @@ -203,6 +203,10 @@ config SOC_LP_I2C_SUPPORTED bool default y +config SOC_ULP_LP_UART_SUPPORTED + bool + default y + config SOC_CLK_TREE_SUPPORTED bool default y diff --git a/components/soc/esp32c6/include/soc/soc_caps.h b/components/soc/esp32c6/include/soc/soc_caps.h index 0e2aec367a..b05238b3a9 100644 --- a/components/soc/esp32c6/include/soc/soc_caps.h +++ b/components/soc/esp32c6/include/soc/soc_caps.h @@ -75,6 +75,7 @@ #define SOC_LP_AON_SUPPORTED 1 #define SOC_LP_PERIPHERALS_SUPPORTED 1 #define SOC_LP_I2C_SUPPORTED 1 +#define SOC_ULP_LP_UART_SUPPORTED 1 #define SOC_CLK_TREE_SUPPORTED 1 #define SOC_ASSIST_DEBUG_SUPPORTED 1 diff --git a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in index ca2952ae5a..58a223ffda 100644 --- a/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32p4/include/soc/Kconfig.soc_caps.in @@ -1037,12 +1037,16 @@ config SOC_FLASH_ENCRYPTION_XTS_AES_128 config SOC_UART_NUM int - default 5 + default 6 config SOC_UART_HP_NUM int default 5 +config SOC_UART_LP_NUM + int + default 1 + config SOC_UART_FIFO_LEN int default 128 diff --git a/components/soc/esp32p4/include/soc/clk_tree_defs.h b/components/soc/esp32p4/include/soc/clk_tree_defs.h index 9fb5ec412b..0a8bec16fc 100644 --- a/components/soc/esp32p4/include/soc/clk_tree_defs.h +++ b/components/soc/esp32p4/include/soc/clk_tree_defs.h @@ -153,8 +153,8 @@ typedef enum { SOC_MOD_CLK_APLL, /*!< Audio PLL is sourced from PLL, and its frequency is configurable through APLL configuration registers */ // For LP peripherals SOC_MOD_CLK_XTAL_D2, /*!< XTAL_D2_CLK comes from the external 40MHz crystal, passing a div of 2 to the LP peripherals */ + SOC_MOD_CLK_LP_PLL, /*!< LP_PLL is from 32kHz XTAL oscillator frequency multipliers, it has a fixed frequency of 8MHz */ SOC_MOD_CLK_INVALID, /*!< Indication of the end of the available module clock sources */ - SOC_MOD_CLK_LP_PLL, } soc_module_clk_t; //////////////////////////////////////////////////SYSTIMER////////////////////////////////////////////////////////////// diff --git a/components/soc/esp32p4/include/soc/soc_caps.h b/components/soc/esp32p4/include/soc/soc_caps.h index 628b0ba9ac..4859f77986 100644 --- a/components/soc/esp32p4/include/soc/soc_caps.h +++ b/components/soc/esp32p4/include/soc/soc_caps.h @@ -72,6 +72,7 @@ // #define SOC_PMU_SUPPORTED 1 //TODO: IDF-7531 // #define SOC_PAU_SUPPORTED 1 //TODO: IDF-7531 // #define SOC_LP_TIMER_SUPPORTED 1 //TODO: IDF-7532 +// #define SOC_ULP_LP_UART_SUPPORTED 1 //TODO: IDF-7533 #define SOC_LP_GPIO_MATRIX_SUPPORTED 1 #define SOC_LP_PERIPHERALS_SUPPORTED 1 #define SOC_SPIRAM_SUPPORTED 1 @@ -208,7 +209,6 @@ // Support to hold a single digital I/O when the digital domain is powered off #define SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP (1) -// #define SOC_LP_GPIO_MATRIX_SUPPORTED (1) /*-------------------------- RTCIO CAPS --------------------------------------*/ #define SOC_RTCIO_PIN_COUNT 16 #define SOC_RTCIO_INPUT_OUTPUT_SUPPORTED 1 /* This macro indicates that the target has separate RTC IOMUX hardware feature, @@ -472,11 +472,9 @@ /*-------------------------- UART CAPS ---------------------------------------*/ // ESP32-P4 has 6 UARTs (5 HP UART, and 1 LP UART) -#define SOC_UART_NUM (5) +#define SOC_UART_NUM (6) #define SOC_UART_HP_NUM (5) -// TODO: 7815 -// The RTC GPIO and sigmap is not supported yet, so make SOC_UART_NUM->5 to avoid lp-uart build errors -// #define SOC_UART_LP_NUM (1U) +#define SOC_UART_LP_NUM (1U) #define SOC_UART_FIFO_LEN (128) /*!< The UART hardware FIFO length */ #define SOC_LP_UART_FIFO_LEN (16) /*!< The LP UART hardware FIFO length */ #define SOC_UART_BITRATE_MAX (5000000) /*!< Max bit rate supported by UART */ diff --git a/components/soc/esp32p4/uart_periph.c b/components/soc/esp32p4/uart_periph.c index 76047b25a1..76e12d5c9c 100644 --- a/components/soc/esp32p4/uart_periph.c +++ b/components/soc/esp32p4/uart_periph.c @@ -180,38 +180,37 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = { .irq = ETS_UART4_INTR_SOURCE, .module = PERIPH_UART4_MODULE, }, - //TODO:IDF-7815 - // { // LP UART0 - // .pins = { - // [SOC_UART_TX_PIN_IDX] = { - // .default_gpio = LP_U0TXD_GPIO_NUM, - // .iomux_func = LP_U0TXD_MUX_FUNC, - // .input = 0, - // .signal = LP_UART_TXD_PAD_OUT_IDX, - // }, + { // LP UART0 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = LP_U0TXD_GPIO_NUM, + .iomux_func = LP_U0TXD_MUX_FUNC, + .input = 0, + .signal = LP_UART_TXD_PAD_OUT_IDX, + }, - // [SOC_UART_RX_PIN_IDX] = { - // .default_gpio = LP_U0RXD_GPIO_NUM, - // .iomux_func = LP_U0RXD_MUX_FUNC, - // .input = 1, - // .signal = LP_UART_RXD_PAD_IN_IDX, - // }, + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = LP_U0RXD_GPIO_NUM, + .iomux_func = LP_U0RXD_MUX_FUNC, + .input = 1, + .signal = LP_UART_RXD_PAD_IN_IDX, + }, - // [SOC_UART_RTS_PIN_IDX] = { - // .default_gpio = LP_U0RTS_GPIO_NUM, - // .iomux_func = LP_U0RTS_MUX_FUNC, - // .input = 0, - // .signal = LP_UART_RTSN_PAD_OUT_IDX, - // }, + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = LP_U0RTS_GPIO_NUM, + .iomux_func = LP_U0RTS_MUX_FUNC, + .input = 0, + .signal = LP_UART_RTSN_PAD_OUT_IDX, + }, - // [SOC_UART_CTS_PIN_IDX] = { - // .default_gpio = LP_U0CTS_GPIO_NUM, - // .iomux_func = LP_U0CTS_MUX_FUNC, - // .input = 1, - // .signal = LP_UART_CTSN_PAD_IN_IDX, - // }, - // }, - // .irq = ETS_LP_UART_INTR_SOURCE, - // .module = PERIPH_LP_UART0_MODULE, - // }, + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = LP_U0CTS_GPIO_NUM, + .iomux_func = LP_U0CTS_MUX_FUNC, + .input = 1, + .signal = LP_UART_CTSN_PAD_IN_IDX, + }, + }, + .irq = ETS_LP_UART_INTR_SOURCE, + .module = PERIPH_LP_UART0_MODULE, + }, }; diff --git a/examples/system/.build-test-rules.yml b/examples/system/.build-test-rules.yml index 8d4f8c4a09..c0ac2807a0 100644 --- a/examples/system/.build-test-rules.yml +++ b/examples/system/.build-test-rules.yml @@ -205,11 +205,11 @@ examples/system/ulp/lp_core/lp_i2c: examples/system/ulp/lp_core/lp_uart/lp_uart_echo: enable: - - if: SOC_UART_LP_NUM > 0 + - if: SOC_ULP_LP_UART_SUPPORTED == 1 examples/system/ulp/lp_core/lp_uart/lp_uart_print: enable: - - if: SOC_UART_LP_NUM > 0 + - if: SOC_ULP_LP_UART_SUPPORTED == 1 examples/system/ulp/ulp_fsm/ulp: disable: diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index d362986e16..119fcf9629 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -687,8 +687,6 @@ components/soc/esp32c3/include/soc/soc_pins.h components/soc/esp32c3/include/soc/spi_mem_reg.h components/soc/esp32c3/include/soc/spi_pins.h components/soc/esp32c3/include/soc/spi_reg.h -components/soc/esp32c3/include/soc/system_reg.h -components/soc/esp32c3/include/soc/system_struct.h components/soc/esp32c3/include/soc/systimer_reg.h components/soc/esp32c3/include/soc/systimer_struct.h components/soc/esp32c3/include/soc/uart_pins.h From bc2a6bd73006846bb8f896e05995013c5df01c07 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Tue, 26 Sep 2023 17:42:03 +0800 Subject: [PATCH 5/5] 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: