Merge branch 'refactor/rcc_critical_section_follow_up' into 'master'

refactor(lp_periph): move enable and reset control to LL driver

See merge request espressif/esp-idf!25498
This commit is contained in:
morris 2023-08-29 08:40:02 +08:00
commit cd9f48823d
15 changed files with 164 additions and 269 deletions

View File

@ -27,7 +27,6 @@
#include "driver/rtc_io.h"
#include "driver/uart_select.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/lp_periph_ctrl.h"
#include "esp_clk_tree.h"
#include "sdkconfig.h"
#include "esp_rom_gpio.h"
@ -77,7 +76,6 @@ static const char *UART_TAG = "uart";
| (UART_INTR_PARITY_ERR))
#endif
#define UART_ENTER_CRITICAL_SAFE(spinlock) esp_os_enter_critical_safe(spinlock)
#define UART_EXIT_CRITICAL_SAFE(spinlock) esp_os_exit_critical_safe(spinlock)
#define UART_ENTER_CRITICAL_ISR(spinlock) esp_os_enter_critical_isr(spinlock)
@ -85,7 +83,6 @@ static const char *UART_TAG = "uart";
#define UART_ENTER_CRITICAL(spinlock) esp_os_enter_critical(spinlock)
#define UART_EXIT_CRITICAL(spinlock) esp_os_exit_critical(spinlock)
// Check actual UART mode set
#define UART_IS_MODE_SET(uart_number, mode) ((p_uart_obj[uart_number]->uart_mode == mode))
@ -189,8 +186,10 @@ static void uart_module_enable(uart_port_t uart_num)
}
#if (SOC_UART_LP_NUM >= 1)
else {
lp_periph_module_enable(uart_periph_signal[uart_num].lp_module);
lp_periph_module_reset(uart_periph_signal[uart_num].lp_module);
PERIPH_RCC_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);
}
}
#endif
uart_context[uart_num].hw_enabled = true;
@ -207,7 +206,9 @@ static void uart_module_disable(uart_port_t uart_num)
}
#if (SOC_UART_LP_NUM >= 1)
else if (uart_num >= SOC_UART_HP_NUM) {
lp_periph_module_disable(uart_periph_signal[uart_num].lp_module);
PERIPH_RCC_ATOMIC() {
lp_uart_ll_enable_bus_clock(uart_num - SOC_UART_HP_NUM, false);
}
}
#endif
uart_context[uart_num].hw_enabled = false;
@ -561,7 +562,6 @@ esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_c
return ESP_OK;
}
esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num)
{
return uart_disable_intr_mask(uart_num, UART_INTR_CMD_CHAR_DET);
@ -747,7 +747,9 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
}
#if (SOC_UART_LP_NUM >= 1)
else {
lp_periph_set_clk_src(uart_periph_signal[uart_num].lp_module, uart_sclk_sel);
PERIPH_RCC_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);

View File

@ -36,10 +36,6 @@ if(NOT BOOTLOADER_BUILD)
"port/${target}/esp_clk_tree.c"
"port/esp_clk_tree_common.c")
if(CONFIG_SOC_LP_PERIPHERALS_SUPPORTED)
list(APPEND srcs "lp_periph_ctrl.c")
endif()
if(CONFIG_SOC_ADC_SUPPORTED)
list(APPEND srcs "adc_share_hw_ctrl.c")
endif()

View File

@ -1,59 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/periph_defs.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_LP_PERIPHERALS_SUPPORTED
/**
* @brief Enable LP peripheral module by un-gating the clock and de-asserting the reset signal.
*
* @param[in] lp_periph LP peripheral module
*
* @note If @c lp_periph_module_enable() is called a number of times,
* @c lp_periph_module_disable() has to be called the same number of times,
* in order to put the peripheral into disabled state.
*/
void lp_periph_module_enable(lp_periph_module_t lp_periph);
/**
* @brief Disable LP peripheral module by gating the clock and asserting the reset signal.
*
* @param[in] lp_periph LP peripheral module
*
* @note If @c lp_periph_module_enable() is called a number of times,
* @c lp_periph_module_disable() has to be called the same number of times,
* in order to put the peripheral into disabled state.
*/
void lp_periph_module_disable(lp_periph_module_t lp_periph);
/**
* @brief Reset LP peripheral module by asserting and de-asserting the reset signal.
*
* @param[in] lp_periph LP peripheral module
*
* @note Calling this function does not enable or disable the clock for the module.
*/
void lp_periph_module_reset(lp_periph_module_t lp_periph);
/**
* @brief Set LP peripheral module clock source.
*
* @param[in] lp_periph LP peripheral module
* @param[in] clk_src Module clock source, check soc/clk_tree_defs.h for the available clock sources for each LP peripheral
*/
void lp_periph_set_clk_src(lp_periph_module_t lp_periph, soc_module_clk_t clk_src);
#endif
#ifdef __cplusplus
}
#endif

View File

@ -1,49 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "freertos/FreeRTOS.h"
#include "esp_private/lp_periph_ctrl.h"
#include "hal/lp_periph_clk_ctrl_ll.h"
static portMUX_TYPE lp_periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
static uint8_t ref_counts[LP_PERIPH_MODULE_MAX] = {0};
void lp_periph_module_enable(lp_periph_module_t lp_periph)
{
portENTER_CRITICAL(&lp_periph_spinlock);
if (ref_counts[lp_periph] == 0) {
// Enable clock and clear reset
lp_periph_ll_enable_clk_clear_rst(lp_periph);
}
ref_counts[lp_periph]++;
portEXIT_CRITICAL(&lp_periph_spinlock);
}
void lp_periph_module_disable(lp_periph_module_t lp_periph)
{
portENTER_CRITICAL(&lp_periph_spinlock);
ref_counts[lp_periph]--;
if (ref_counts[lp_periph] == 0) {
// Disable clock and set reset
lp_periph_ll_disable_clk_set_rst(lp_periph);
}
portEXIT_CRITICAL(&lp_periph_spinlock);
}
void lp_periph_module_reset(lp_periph_module_t lp_periph)
{
portENTER_CRITICAL(&lp_periph_spinlock);
lp_periph_ll_reset(lp_periph);
portEXIT_CRITICAL(&lp_periph_spinlock);
}
void lp_periph_set_clk_src(lp_periph_module_t lp_periph, soc_module_clk_t clk_src)
{
portENTER_CRITICAL(&lp_periph_spinlock);
lp_periph_ll_set_clk_src(lp_periph, clk_src);
portEXIT_CRITICAL(&lp_periph_spinlock);
}

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32-C6 | ESP32-H2 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 |
| ----------------- | -------- | -------- | -------- |

View File

@ -18,6 +18,7 @@
#include "hal/i2c_types.h"
#include "soc/clk_tree_defs.h"
#include "soc/lp_clkrst_struct.h"
#include "soc/lpperi_struct.h"
#ifdef __cplusplus
extern "C" {
@ -739,6 +740,62 @@ static inline void i2c_ll_set_source_clk(i2c_dev_t *hw, i2c_clock_source_t src_c
PCR.i2c_sclk_conf.i2c_sclk_sel = (src_clk == I2C_CLK_SRC_RC_FAST) ? 1 : 0;
}
/**
* @brief Set LP I2C source clock
*
* @param hw Address offset of the LP I2C peripheral registers
* @param src_clk Source clock for the LP I2C peripheral
*/
static inline void lp_i2c_ll_set_source_clk(i2c_dev_t *hw, soc_periph_lp_i2c_clk_src_t src_clk)
{
(void)hw;
// src_clk : (0) for LP_FAST_CLK (RTC Fast), (1) for XTAL_D2_CLK
switch (src_clk) {
case LP_I2C_SCLK_LP_FAST:
LP_CLKRST.lpperi.lp_i2c_clk_sel = 0;
break;
case LP_I2C_SCLK_XTAL_D2:
LP_CLKRST.lpperi.lp_i2c_clk_sel = 1;
break;
default:
// Invalid source clock selected
HAL_ASSERT(false);
}
}
/// LP_CLKRST.lpperi is a shared register, so this function must be used in an atomic way
#define lp_i2c_ll_set_source_clk(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_i2c_ll_set_source_clk(__VA_ARGS__)
/**
* @brief Enable bus clock for the LP I2C module
*
* @param hw_id LP I2C instance ID
* @param enable True to enable, False to disable
*/
static inline void lp_i2c_ll_enable_bus_clock(int hw_id, bool enable)
{
(void)hw_id;
LPPERI.clk_en.lp_ext_i2c_ck_en = enable;
}
/// LPPERI.clk_en is a shared register, so this function must be used in an atomic way
#define lp_i2c_ll_enable_bus_clock(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_i2c_ll_enable_bus_clock(__VA_ARGS__)
/**
* @brief Reset LP I2C module
*
* @param hw_id LP I2C instance ID
*/
static inline void lp_i2c_ll_reset_register(int hw_id)
{
(void)hw_id;
LPPERI.reset_en.lp_ext_i2c_reset_en = 1;
LPPERI.reset_en.lp_ext_i2c_reset_en = 0;
}
/// LPPERI.reset_en is a shared register, so this function must be used in an atomic way
#define lp_i2c_ll_reset_register(...) (void)__DECLARE_RCC_ATOMIC_ENV; lp_i2c_ll_reset_register(__VA_ARGS__)
/**
* @brief Enable I2C peripheral controller clock
*
@ -808,7 +865,6 @@ static inline volatile void *i2c_ll_get_interrupt_status_reg(i2c_dev_t *dev)
return &dev->int_status;
}
/**
* @brief Enable I2C slave clock stretch.
*

View File

@ -1,105 +0,0 @@
/*
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdlib.h>
#include "soc/periph_defs.h"
#include "soc/clk_tree_defs.h"
#include "soc/soc.h"
#include "soc/lpperi_reg.h"
#include "soc/lp_clkrst_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
static inline uint32_t lp_periph_ll_get_clk_en_mask(lp_periph_module_t lp_periph)
{
switch (lp_periph) {
case LP_PERIPH_I2C0_MODULE:
return LPPERI_LP_EXT_I2C_CK_EN;
case LP_PERIPH_UART0_MODULE:
return LPPERI_LP_UART_CK_EN;
default:
// Unsupported LP peripherals
abort();
}
}
static inline uint32_t lp_periph_ll_get_rst_en_mask(lp_periph_module_t lp_periph)
{
switch (lp_periph) {
case LP_PERIPH_I2C0_MODULE:
return LPPERI_LP_EXT_I2C_RESET_EN;
case LP_PERIPH_UART0_MODULE:
return LPPERI_LP_UART_RESET_EN;
default:
// Unsupported LP peripherals
abort();
}
}
static inline void lp_periph_ll_enable_clk_clear_rst(lp_periph_module_t lp_periph)
{
SET_PERI_REG_MASK(LPPERI_CLK_EN_REG, lp_periph_ll_get_clk_en_mask(lp_periph));
CLEAR_PERI_REG_MASK(LPPERI_RESET_EN_REG, lp_periph_ll_get_rst_en_mask(lp_periph));
}
static inline void lp_periph_ll_disable_clk_set_rst(lp_periph_module_t lp_periph)
{
CLEAR_PERI_REG_MASK(LPPERI_CLK_EN_REG, lp_periph_ll_get_clk_en_mask(lp_periph));
SET_PERI_REG_MASK(LPPERI_RESET_EN_REG, lp_periph_ll_get_rst_en_mask(lp_periph));
}
static inline void lp_periph_ll_reset(lp_periph_module_t lp_periph)
{
uint32_t bit_mask = lp_periph_ll_get_rst_en_mask(lp_periph);
SET_PERI_REG_MASK(LPPERI_RESET_EN_REG, bit_mask);
CLEAR_PERI_REG_MASK(LPPERI_RESET_EN_REG, bit_mask);
}
static inline void lp_periph_ll_set_clk_src(lp_periph_module_t lp_periph, soc_module_clk_t clk_src)
{
uint32_t val;
switch (lp_periph) {
case LP_PERIPH_I2C0_MODULE:
switch (clk_src) {
case LP_I2C_SCLK_LP_FAST:
val = 0;
break;
case LP_I2C_SCLK_XTAL_D2:
val = 1;
break;
default:
// Invalid LP_I2C clock source
abort();
}
REG_SET_FIELD(LP_CLKRST_LPPERI_REG, LP_CLKRST_LP_I2C_CLK_SEL, val);
break;
case LP_PERIPH_UART0_MODULE:
switch (clk_src) {
case LP_UART_SCLK_LP_FAST:
val = 0;
break;
case LP_UART_SCLK_XTAL_D2:
val = 1;
break;
default:
// Invalid LP_UART clock source
abort();
}
REG_SET_FIELD(LP_CLKRST_LPPERI_REG, LP_CLKRST_LP_UART_CLK_SEL, val);
break;
default:
// Unsupported LP peripherals
abort();
}
}
#ifdef __cplusplus
}
#endif

View File

@ -7,7 +7,6 @@
// The LL layer for UART register operations.
// Note that most of the register operations in this layer are non-atomic operations.
#pragma once
#include "esp_attr.h"
@ -18,6 +17,7 @@
#include "soc/lp_uart_reg.h"
#include "soc/pcr_struct.h"
#include "soc/lp_clkrst_struct.h"
#include "soc/lpperi_struct.h"
#include "hal/assert.h"
#ifdef __cplusplus
@ -105,7 +105,60 @@ FORCE_INLINE_ATTR void lp_uart_ll_get_sclk(uart_dev_t *hw, soc_module_clk_t *sou
}
}
// LP_UART clock control LL functions are located in lp_periph_clk_ctrl_ll.h
/**
* @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:
LP_CLKRST.lpperi.lp_uart_clk_sel = 0;
break;
case LP_UART_SCLK_XTAL_D2:
LP_CLKRST.lpperi.lp_uart_clk_sel = 1;
break;
default:
// Invalid LP_UART clock source
HAL_ASSERT(false);
}
}
/// 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 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.lp_uart_ck_en = 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.lp_uart_reset_en = 1;
LPPERI.reset_en.lp_uart_reset_en = 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 ******************************************/
/**

View File

@ -13,6 +13,7 @@ extern "C" {
#endif
typedef enum {
/* HP peripherals */
PERIPH_LEDC_MODULE = 0,
PERIPH_UART0_MODULE,
PERIPH_UART1_MODULE,
@ -45,6 +46,9 @@ typedef enum {
PERIPH_TEMPSENSOR_MODULE,
PERIPH_REGDMA_MODULE,
PERIPH_ASSIST_DEBUG_MODULE,
/* LP peripherals */
PERIPH_LP_I2C0_MODULE,
PERIPH_LP_UART0_MODULE,
/* Peripherals clock managed by the modem_clock driver must be listed last in the enumeration */
PERIPH_WIFI_MODULE,
PERIPH_BT_MODULE,
@ -57,12 +61,6 @@ typedef enum {
/* !!! Don't append soc modules here !!! */
} periph_module_t;
typedef enum {
LP_PERIPH_I2C0_MODULE = 0,
LP_PERIPH_UART0_MODULE,
LP_PERIPH_MODULE_MAX,
} lp_periph_module_t;
#define PERIPH_MODEM_MODULE_MIN PERIPH_WIFI_MODULE
#define PERIPH_MODEM_MODULE_MAX PERIPH_MODEM_ETM_MODULE
#define PERIPH_MODEM_MODULE_NUM (PERIPH_MODEM_MODULE_MAX - PERIPH_MODEM_MODULE_MIN + 1)

View File

@ -109,6 +109,6 @@ const uart_signal_conn_t uart_periph_signal[SOC_UART_NUM] = {
},
},
.irq = ETS_LP_UART_INTR_SOURCE,
.lp_module = LP_PERIPH_UART0_MODULE,
.module = PERIPH_LP_UART0_MODULE,
},
};

View File

@ -70,16 +70,12 @@ typedef enum {
PERIPH_AXI_PDMA_MODULE,
PERIPH_UHCI_MODULE,
PERIPH_PCNT_MODULE,
/* LP peripherals */
PERIPH_LP_I2C0_MODULE,
PERIPH_LP_UART0_MODULE,
PERIPH_MODULE_MAX
} periph_module_t;
typedef enum {
LP_PERIPH_I2C0_MODULE = 0,
LP_PERIPH_UART0_MODULE,
LP_PERIPH_MODULE_MAX,
} lp_periph_module_t;
#ifdef __cplusplus
}
#endif

View File

@ -45,9 +45,6 @@ typedef struct {
const uint8_t irq;
union {
const periph_module_t module;
#if (SOC_UART_LP_NUM >= 1)
const lp_periph_module_t lp_module;
#endif
};
} uart_signal_conn_t;

View File

@ -11,7 +11,7 @@
#include "driver/rtc_io.h"
#include "soc/rtc_io_channel.h"
#include "esp_private/esp_clk_tree_common.h"
#include "esp_private/lp_periph_ctrl.h"
#include "esp_private/periph_ctrl.h"
static const char *LPI2C_TAG = "lp_core_i2c";
@ -108,8 +108,10 @@ static esp_err_t lp_i2c_config_clk(const lp_core_i2c_cfg_t *cfg)
/* Verify that the I2C_SCLK operates at a frequency 20 times larger than the requested SCL bus frequency */
ESP_RETURN_ON_FALSE(cfg->i2c_timing_cfg.clk_speed_hz * 20 <= source_freq, ESP_ERR_INVALID_ARG, LPI2C_TAG, "I2C_SCLK frequency (%"PRId32") should operate at a frequency at least 20 times larger than the I2C SCL bus frequency (%"PRId32")", source_freq, cfg->i2c_timing_cfg.clk_speed_hz);
/* Set LP I2C source clock */
lp_periph_set_clk_src(LP_PERIPH_I2C0_MODULE, (soc_module_clk_t)source_clk);
/* LP I2C clock source is mixed with other peripherals in the same register */
PERIPH_RCC_ATOMIC() {
lp_i2c_ll_set_source_clk(i2c_hal.dev, source_clk);
}
/* Configure LP I2C timing paramters. source_clk is ignored for LP_I2C in this call */
i2c_hal_set_bus_timing(&i2c_hal, cfg->i2c_timing_cfg.clk_speed_hz, (i2c_clock_source_t)source_clk, source_freq);
@ -128,12 +130,16 @@ esp_err_t lp_core_i2c_master_init(i2c_port_t lp_i2c_num, const lp_core_i2c_cfg_t
/* Configure LP I2C GPIOs */
ESP_RETURN_ON_ERROR(lp_i2c_set_pin(cfg), LPI2C_TAG, "Failed to configure LP I2C GPIOs");
PERIPH_RCC_ATOMIC() {
/* Enable LP I2C bus clock */
lp_i2c_ll_enable_bus_clock(lp_i2c_num - LP_I2C_NUM_0, true);
/* Reset LP I2C register */
lp_i2c_ll_reset_register(lp_i2c_num - LP_I2C_NUM_0);
}
/* Initialize LP I2C HAL */
i2c_hal_init(&i2c_hal, lp_i2c_num);
/* Enable LP I2C controller clock */
lp_periph_module_enable(LP_PERIPH_I2C0_MODULE);
/* Initialize LP I2C Master mode */
i2c_hal_master_init(&i2c_hal);

View File

@ -12,7 +12,7 @@
#include "hal/uart_hal.h"
#include "hal/rtc_io_types.h"
#include "esp_clk_tree.h"
#include "esp_private/lp_periph_ctrl.h"
#include "esp_private/periph_ctrl.h"
#define LP_UART_PORT_NUM LP_UART_NUM_0
#define LP_UART_TX_IDLE_NUM_DEFAULT (0U)
@ -39,15 +39,19 @@ static esp_err_t lp_core_uart_param_config(const lp_core_uart_cfg_t *cfg)
/* Get LP UART source clock frequency */
uint32_t sclk_freq = 0;
soc_module_clk_t clk_src = (soc_module_clk_t)(cfg->lp_uart_source_clk) ? (cfg->lp_uart_source_clk) : LP_UART_SCLK_DEFAULT;
ret = esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq);
soc_periph_lp_uart_clk_src_t clk_src = cfg->lp_uart_source_clk ? cfg->lp_uart_source_clk : LP_UART_SCLK_DEFAULT;
ret = esp_clk_tree_src_get_freq_hz((soc_module_clk_t)clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &sclk_freq);
if (ret != ESP_OK) {
// Unable to fetch LP UART source clock frequency
return ESP_FAIL;
}
// LP UART clock source is mixed with other peripherals in the same register
PERIPH_RCC_ATOMIC() {
lp_uart_ll_set_source_clk(hal.dev, clk_src);
}
/* Override protocol parameters from the configuration */
lp_periph_set_clk_src(LP_PERIPH_UART0_MODULE, clk_src);
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);

View File

@ -1,5 +1,5 @@
| Supported Targets | ESP32-C6 | ESP32-H2 |
| ----------------- | -------- | -------- |
| Supported Targets | ESP32-C6 | ESP32-H2 | ESP32-P4 |
| ----------------- | -------- | -------- | -------- |
# HC-SR04 Example based on GPTimer Capture and ETM