From f9109beda2e08e4440203c1661c4d488fed45ca8 Mon Sep 17 00:00:00 2001 From: gaoxu Date: Wed, 28 Feb 2024 09:56:18 +0800 Subject: [PATCH] feat(uart): add HP/LP uart support on ESP32C5 --- components/esp_driver_uart/src/uart.c | 11 +- .../port/esp32c5/esp_clk_tree.c | 3 + components/hal/esp32c5/include/hal/uart_ll.h | 43 +++---- .../include/esp32c5/idf_performance_target.h | 7 ++ .../esp32c5/include/soc/Kconfig.soc_caps.in | 20 +++ .../soc/esp32c5/include/soc/clk_tree_defs.h | 14 ++- components/soc/esp32c5/include/soc/soc_caps.h | 14 +-- .../soc/esp32c5/include/soc/uart_channel.h | 2 - .../soc/esp32c5/include/soc/uart_pins.h | 8 +- .../soc/esp32c5/include/soc/uart_struct.h | 3 +- components/soc/esp32c5/uart_periph.c | 114 ++++++++++++++++++ 11 files changed, 195 insertions(+), 44 deletions(-) create mode 100644 components/idf_test/include/esp32c5/idf_performance_target.h diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index aae8e9d94b..78abcbca64 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -25,6 +25,7 @@ #include "driver/rtc_io.h" #include "driver/uart_select.h" #include "driver/lp_io.h" +#include "esp_private/gpio.h" #include "esp_private/uart_share_hw_ctrl.h" #include "esp_clk_tree.h" #include "sdkconfig.h" @@ -678,7 +679,7 @@ 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)) { if (uart_num < SOC_UART_HP_NUM) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[tx_io_num], PIN_FUNC_GPIO); + gpio_func_sel(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); } @@ -695,7 +696,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r if (rx_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { if (uart_num < SOC_UART_HP_NUM) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rx_io_num], PIN_FUNC_GPIO); + gpio_func_sel(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); @@ -713,7 +714,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) { if (uart_num < SOC_UART_HP_NUM) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[rts_io_num], PIN_FUNC_GPIO); + gpio_func_sel(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); } @@ -729,7 +730,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) { if (uart_num < SOC_UART_HP_NUM) { - gpio_hal_iomux_func_sel(GPIO_PIN_MUX_REG[cts_io_num], PIN_FUNC_GPIO); + gpio_func_sel(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); diff --git a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c index 74560e1eb4..f578ee3b15 100644 --- a/components/esp_hw_support/port/esp32c5/esp_clk_tree.c +++ b/components/esp_hw_support/port/esp32c5/esp_clk_tree.c @@ -38,6 +38,9 @@ uint32_t *freq_value) case SOC_MOD_CLK_PLL_F240M: clk_src_freq = CLK_LL_PLL_240M_FREQ_MHZ * MHZ; break; + case SOC_MOD_CLK_RTC_FAST: + clk_src_freq = 20 * MHZ; + break; case SOC_MOD_CLK_SPLL: clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ * MHZ; break; diff --git a/components/hal/esp32c5/include/hal/uart_ll.h b/components/hal/esp32c5/include/hal/uart_ll.h index 6112005b97..52e3d1cd11 100644 --- a/components/hal/esp32c5/include/hal/uart_ll.h +++ b/components/hal/esp32c5/include/hal/uart_ll.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,8 +85,6 @@ typedef enum { UART_INTR_WAKEUP = (0x1 << 19), } uart_intr_t; -// TODO: [ESP32C5] IDF-8722, IDF-8633 - /** * @brief Sync the update to UART core clock domain * @@ -213,15 +211,18 @@ static inline void lp_uart_ll_reset_register(int hw_id) */ 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; + switch (uart_num) { + case 0: + return PCR.uart0_conf.uart0_clk_en && !PCR.uart0_conf.uart0_rst_en; + case 1: + return PCR.uart1_conf.uart1_clk_en && !PCR.uart1_conf.uart1_rst_en; + case 2: // LP_UART + return LPPERI.clk_en.lp_uart_ck_en && !LPPERI.reset_en.lp_uart_reset_en; + default: + // Unknown uart port number + HAL_ASSERT(false); + return false; + } } /** @@ -336,14 +337,14 @@ FORCE_INLINE_ATTR void uart_ll_set_sclk(uart_dev_t *hw, soc_module_clk_t source_ if ((hw) != &LP_UART) { uint32_t sel_value = 0; switch (source_clk) { - case UART_SCLK_PLL_F80M: - sel_value = 2; + case UART_SCLK_XTAL: + sel_value = 0; break; case UART_SCLK_RTC: sel_value = 1; break; - case UART_SCLK_XTAL: - sel_value = 0; + case UART_SCLK_PLL_F80M: + sel_value = 2; break; default: // Invalid HP_UART clock source @@ -370,14 +371,14 @@ FORCE_INLINE_ATTR void uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *source if ((hw) != &LP_UART) { switch (UART_LL_PCR_REG_GET(hw, sclk_conf, sclk_sel)) { default: - case 1: - *source_clk = (soc_module_clk_t)UART_SCLK_PLL_F80M; + case 0: + *source_clk = (soc_module_clk_t)UART_SCLK_XTAL; break; - case 2: + case 1: *source_clk = (soc_module_clk_t)UART_SCLK_RTC; break; - case 3: - *source_clk = (soc_module_clk_t)UART_SCLK_XTAL; + case 2: + *source_clk = (soc_module_clk_t)UART_SCLK_PLL_F80M; break; } } else { diff --git a/components/idf_test/include/esp32c5/idf_performance_target.h b/components/idf_test/include/esp32c5/idf_performance_target.h new file mode 100644 index 0000000000..dd3f635e54 --- /dev/null +++ b/components/idf_test/include/esp32c5/idf_performance_target.h @@ -0,0 +1,7 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once diff --git a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in index 5f195f86ff..dadbeb8cc9 100644 --- a/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32c5/include/soc/Kconfig.soc_caps.in @@ -55,6 +55,10 @@ config SOC_FLASH_ENC_SUPPORTED bool default y +config SOC_LP_PERIPHERALS_SUPPORTED + bool + default y + config SOC_SPI_FLASH_SUPPORTED bool default y @@ -331,10 +335,26 @@ config SOC_LP_UART_FIFO_LEN int default 16 +config SOC_UART_BITRATE_MAX + int + default 5000000 + +config SOC_UART_SUPPORT_PLL_F80M_CLK + bool + default y + config SOC_UART_SUPPORT_XTAL_CLK bool default y +config SOC_UART_SUPPORT_WAKEUP_INT + bool + default y + +config SOC_UART_SUPPORT_FSM_TX_WAIT_SEND + bool + default y + config SOC_PM_SUPPORT_CPU_PD bool default y diff --git a/components/soc/esp32c5/include/soc/clk_tree_defs.h b/components/soc/esp32c5/include/soc/clk_tree_defs.h index 9eb3e85f2d..5b73764fa3 100644 --- a/components/soc/esp32c5/include/soc/clk_tree_defs.h +++ b/components/soc/esp32c5/include/soc/clk_tree_defs.h @@ -232,20 +232,30 @@ typedef enum { // TODO: [ESP32C5] IDF-8727 (inherit from C6) ///////////////////////////////////////////////////UART///////////////////////////////////////////////////////////////// +/** + * @brief Array initializer for all supported clock sources of UART + */ +#define SOC_UART_CLKS {SOC_MOD_CLK_PLL_F80M, SOC_MOD_CLK_XTAL, SOC_MOD_CLK_RC_FAST} + /** * @brief Type of UART clock source, reserved for the legacy UART driver */ -typedef enum { // TODO: [ESP32C5] IDF-8722 (inherit from C6) +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 */ UART_SCLK_DEFAULT = SOC_MOD_CLK_PLL_F80M, /*!< UART source clock default choice is PLL_F80M */ } soc_periph_uart_clk_src_legacy_t; +/** + * @brief Array initializer for all supported clock sources of LP_UART + */ +#define SOC_LP_UART_CLKS {SOC_MOD_CLK_RTC_FAST, SOC_MOD_CLK_XTAL_D2} + /** * @brief Type of LP_UART clock source */ -typedef enum { // TODO: [ESP32C5] IDF-8633 (inherit from C6) +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_DEFAULT = SOC_MOD_CLK_RTC_FAST, /*!< LP_UART source clock default choice is LP(RTC)_FAST */ diff --git a/components/soc/esp32c5/include/soc/soc_caps.h b/components/soc/esp32c5/include/soc/soc_caps.h index ec53f6e3bb..cde21d7f2d 100644 --- a/components/soc/esp32c5/include/soc/soc_caps.h +++ b/components/soc/esp32c5/include/soc/soc_caps.h @@ -19,7 +19,7 @@ /*-------------------------- COMMON CAPS ---------------------------------------*/ // #define SOC_ADC_SUPPORTED 1 // TODO: [ESP32C5] IDF-8701 // #define SOC_DEDICATED_GPIO_SUPPORTED 1 // TODO: [ESP32C5] IDF-8725 -#define SOC_UART_SUPPORTED 1 // TODO: [ESP32C5] IDF-8722 +#define SOC_UART_SUPPORTED 1 #define SOC_GDMA_SUPPORTED 1 #define SOC_AHB_GDMA_SUPPORTED 1 #define SOC_GPTIMER_SUPPORTED 1 @@ -61,7 +61,7 @@ // #define SOC_PAU_SUPPORTED 1 // TODO: [ESP32C5] IDF-8638, IDF-8640 // #define SOC_LP_TIMER_SUPPORTED 1 // TODO: [ESP32C5] IDF-8636 // #define SOC_LP_AON_SUPPORTED 1 // TODO: [ESP32C5] IDF-8638, IDF-8640 -// #define SOC_LP_PERIPHERALS_SUPPORTED 1 // TODO: [ESP32C5] IDF-8695, IDF-8723, IDF-8719 +#define SOC_LP_PERIPHERALS_SUPPORTED 1 // #define SOC_LP_I2C_SUPPORTED 1 // TODO: [ESP32C5] IDF-8634 // #define SOC_ULP_LP_UART_SUPPORTED 1 // TODO: [ESP32C5] IDF-8633 // #define SOC_CLK_TREE_SUPPORTED 1 // TODO: [ESP32C5] IDF-8642 @@ -475,14 +475,14 @@ #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 */ +#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) // TODO: [ESP32C5] IDF-8642 #define SOC_UART_SUPPORT_XTAL_CLK (1) /*!< Support XTAL clock as the clock source */ -// #define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ +#define SOC_UART_SUPPORT_WAKEUP_INT (1) /*!< Support UART wakeup interrupt */ // UART has an extra TX_WAIT_SEND state when the FIFO is not empty and XOFF is enabled -// #define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) +#define SOC_UART_SUPPORT_FSM_TX_WAIT_SEND (1) /*-------------------------- COEXISTENCE HARDWARE PTI CAPS -------------------------------*/ // #define SOC_COEX_HW_PTI (1) diff --git a/components/soc/esp32c5/include/soc/uart_channel.h b/components/soc/esp32c5/include/soc/uart_channel.h index 4f261aef74..a1fc15821c 100644 --- a/components/soc/esp32c5/include/soc/uart_channel.h +++ b/components/soc/esp32c5/include/soc/uart_channel.h @@ -8,8 +8,6 @@ #pragma once -// TODO: [ESP32C5] IDF-8722 - //UART channels #define UART_GPIO10_DIRECT_CHANNEL UART_NUM_0 #define UART_NUM_0_TXD_DIRECT_GPIO_NUM 10 diff --git a/components/soc/esp32c5/include/soc/uart_pins.h b/components/soc/esp32c5/include/soc/uart_pins.h index 6c63383284..fd0b0cc76d 100644 --- a/components/soc/esp32c5/include/soc/uart_pins.h +++ b/components/soc/esp32c5/include/soc/uart_pins.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -8,14 +8,12 @@ #include "soc/io_mux_reg.h" -// TODO: [ESP32C5] IDF-8722 - /* 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 17 -#define U0TXD_GPIO_NUM 16 +#define U0RXD_GPIO_NUM 11 +#define U0TXD_GPIO_NUM 10 #define U0RTS_GPIO_NUM (-1) #define U0CTS_GPIO_NUM (-1) diff --git a/components/soc/esp32c5/include/soc/uart_struct.h b/components/soc/esp32c5/include/soc/uart_struct.h index 04beb1d443..734f18d6b7 100644 --- a/components/soc/esp32c5/include/soc/uart_struct.h +++ b/components/soc/esp32c5/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; diff --git a/components/soc/esp32c5/uart_periph.c b/components/soc/esp32c5/uart_periph.c index e69de29bb2..154038a7b6 100644 --- a/components/soc/esp32c5/uart_periph.c +++ b/components/soc/esp32c5/uart_periph.c @@ -0,0 +1,114 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/uart_periph.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 = U0TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U0RXD_GPIO_NUM, + .iomux_func = U0RXD_MUX_FUNC, + .input = 1, + .signal = U0RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U0RTS_GPIO_NUM, + .iomux_func = U0RTS_MUX_FUNC, + .input = 0, + .signal = U0RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U0CTS_GPIO_NUM, + .iomux_func = U0CTS_MUX_FUNC, + .input = 1, + .signal = U0CTS_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 = U1TXD_OUT_IDX, + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = U1RXD_GPIO_NUM, + .iomux_func = U1RXD_MUX_FUNC, + .input = 1, + .signal = U1RXD_IN_IDX, + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = U1RTS_GPIO_NUM, + .iomux_func = U1RTS_MUX_FUNC, + .input = 0, + .signal = U1RTS_OUT_IDX, + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = U1CTS_GPIO_NUM, + .iomux_func = U1CTS_MUX_FUNC, + .input = 1, + .signal = U1CTS_IN_IDX, + }, + }, + .irq = ETS_UART1_INTR_SOURCE, + .module = PERIPH_UART1_MODULE, + }, + + { // LP UART0 + .pins = { + [SOC_UART_TX_PIN_IDX] = { + .default_gpio = LP_U0TXD_GPIO_NUM, + .iomux_func = LP_U0TXD_MUX_FUNC, + .input = 0, + .signal = UINT8_MAX, // Signal not available in signal map + }, + + [SOC_UART_RX_PIN_IDX] = { + .default_gpio = LP_U0RXD_GPIO_NUM, + .iomux_func = LP_U0RXD_MUX_FUNC, + .input = 1, + .signal = UINT8_MAX, // Signal not available in signal map + }, + + [SOC_UART_RTS_PIN_IDX] = { + .default_gpio = LP_U0RTS_GPIO_NUM, + .iomux_func = LP_U0RTS_MUX_FUNC, + .input = 0, + .signal = UINT8_MAX, // Signal not available in signal map + }, + + [SOC_UART_CTS_PIN_IDX] = { + .default_gpio = LP_U0CTS_GPIO_NUM, + .iomux_func = LP_U0CTS_MUX_FUNC, + .input = 1, + .signal = UINT8_MAX, // Signal not available in signal map + }, + }, + .irq = ETS_LP_UART_INTR_SOURCE, + .module = PERIPH_LP_UART0_MODULE, + }, +};