Jelajahi Sumber

etm: add basic driver on esp32h2

morris 3 tahun lalu
induk
melakukan
6f8ee89302

+ 2 - 2
components/esp_hw_support/test_apps/etm/README.md

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

+ 2 - 2
components/esp_hw_support/test_apps/etm/main/test_gptimer_etm.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -436,7 +436,7 @@ TEST_CASE("gptimer_start_stop_by_etm_task", "[etm]")
     uint64_t cur_count_val = 0;
     TEST_ESP_OK(gptimer_get_raw_count(gptimer, &cur_count_val));
     printf("cur_count_val: %llu\r\n", cur_count_val);
-    TEST_ASSERT_UINT_WITHIN(900, 500000, cur_count_val);
+    TEST_ASSERT_UINT_WITHIN(1000, 500000, cur_count_val);
 
     // trigger an neg-edge, this should stop the gptimer
     TEST_ESP_OK(gpio_set_level(input_gpio, 0));

+ 2 - 2
components/esp_hw_support/test_apps/etm/main/test_systimer_etm.c

@@ -1,5 +1,5 @@
 /*
- * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  *
  * SPDX-License-Identifier: Apache-2.0
  */
@@ -105,7 +105,7 @@ TEST_CASE("esp_timer_etm_event", "[etm]")
     TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, esp_timer_event, gpio_task));
     TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
 
-    printf("create a periodic esp_timer\r\b");
+    printf("create a periodic esp_timer\r\n");
     const esp_timer_create_args_t periodic_timer_args = {
         .callback = periodic_timer_callback,
         .name = "periodic"

+ 2 - 1
components/esp_hw_support/test_apps/etm/pytest_etm.py

@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
 # SPDX-License-Identifier: CC0-1.0
 
 import pytest
@@ -6,6 +6,7 @@ from pytest_embedded import Dut
 
 
 @pytest.mark.esp32c6
+@pytest.mark.esp32h2
 @pytest.mark.generic
 @pytest.mark.parametrize(
     'config',

+ 8 - 0
components/hal/esp32h2/include/hal/clk_gate_ll.h

@@ -55,6 +55,8 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
             return PCR_GDMA_CLK_EN;
         case PERIPH_MCPWM0_MODULE:
             return PCR_PWM_CLK_EN;
+        case PERIPH_ETM_MODULE:
+            return PCR_ETM_CLK_EN;
         case PERIPH_AES_MODULE:
             return PCR_AES_CLK_EN;
         case PERIPH_SHA_MODULE:
@@ -124,6 +126,8 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
             return PCR_GDMA_RST_EN;
         case PERIPH_MCPWM0_MODULE:
             return PCR_PWM_RST_EN;
+        case PERIPH_ETM_MODULE:
+            return PCR_ETM_RST_EN;
         case PERIPH_AES_MODULE:
         if (enable == true) {
             // Clear reset on digital signature, otherwise AES unit is held in reset also.
@@ -216,6 +220,8 @@ static uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
             return PCR_GDMA_CONF_REG;
         case PERIPH_MCPWM0_MODULE:
             return PCR_PWM_CONF_REG;
+        case PERIPH_ETM_MODULE:
+            return PCR_ETM_CONF_REG;
         case PERIPH_AES_MODULE:
             return PCR_AES_CONF_REG;
         case PERIPH_SHA_MODULE:
@@ -271,6 +277,8 @@ static uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
             return PCR_GDMA_CONF_REG;
         case PERIPH_MCPWM0_MODULE:
             return PCR_PWM_CONF_REG;
+        case PERIPH_ETM_MODULE:
+            return PCR_ETM_CONF_REG;
         case PERIPH_AES_MODULE:
             return PCR_AES_CONF_REG;
         case PERIPH_SHA_MODULE:

+ 103 - 0
components/hal/esp32h2/include/hal/etm_ll.h

@@ -0,0 +1,103 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// Note that most of the register operations in this layer are non-atomic operations.
+
+#pragma once
+
+#include <stdbool.h>
+#include "hal/assert.h"
+#include "hal/misc.h"
+#include "soc/soc_etm_struct.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Enable the clock for ETM module
+ *
+ * @param hw ETM register base address
+ * @param enable true to enable, false to disable
+ */
+static inline void etm_ll_enable_clock(soc_etm_dev_t *hw, bool enable)
+{
+    hw->clk_en.clk_en = enable;
+}
+
+/**
+ * @brief Enable ETM channel
+ *
+ * @param hw ETM register base address
+ * @param chan Channel ID
+ */
+static inline void etm_ll_enable_channel(soc_etm_dev_t *hw, uint32_t chan)
+{
+    if (chan < 32) {
+        hw->ch_ena_ad0_set.val = 1 << chan;
+    } else {
+        hw->ch_ena_ad1_set.val = 1 << (chan - 32);
+    }
+}
+
+/**
+ * @brief Disable ETM channel
+ *
+ * @param hw ETM register base address
+ * @param chan Channel ID
+ */
+static inline void etm_ll_disable_channel(soc_etm_dev_t *hw, uint32_t chan)
+{
+    if (chan < 32) {
+        hw->ch_ena_ad0_clr.val = 1 << chan;
+    } else {
+        hw->ch_ena_ad1_clr.val = 1 << (chan - 32);
+    }
+}
+
+/**
+ * @brief Check whether the ETM channel is enabled or not
+ *
+ * @param hw ETM register base address
+ * @param chan Channel ID
+ * @return true if the channel is enabled, false otherwise
+ */
+static inline bool etm_ll_is_channel_enabled(soc_etm_dev_t *hw, uint32_t chan)
+{
+    if (chan < 32) {
+        return hw->ch_ena_ad0.val & (1 << chan);
+    } else {
+        return hw->ch_ena_ad1.val & (1 << (chan - 32));
+    }
+}
+
+/**
+ * @brief Set the input event for the ETM channel
+ *
+ * @param hw ETM register base address
+ * @param chan Channel ID
+ * @param event Event ID
+ */
+static inline void etm_ll_channel_set_event(soc_etm_dev_t *hw, uint32_t chan, uint32_t event)
+{
+    hw->channel[chan].evt_id.evt_id = event;
+}
+
+/**
+ * @brief Set the output task for the ETM channel
+ *
+ * @param hw ETM register base address
+ * @param chan Channel ID
+ * @param task Task ID
+ */
+static inline void etm_ll_channel_set_task(soc_etm_dev_t *hw, uint32_t chan, uint32_t task)
+{
+    hw->channel[chan].task_id.task_id = task;
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 119 - 0
components/hal/esp32h2/include/hal/gpio_etm_ll.h

@@ -0,0 +1,119 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+// Note that most of the register operations in this layer are non-atomic operations.
+
+#pragma once
+
+#include <stdbool.h>
+#include "hal/assert.h"
+#include "hal/misc.h"
+#include "soc/gpio_ext_struct.h"
+#include "soc/soc_etm_source.h"
+
+#define GPIO_LL_ETM_EVENT_ID_POS_EDGE(ch) (GPIO_EVT_CH0_RISE_EDGE + (ch))
+#define GPIO_LL_ETM_EVENT_ID_NEG_EDGE(ch) (GPIO_EVT_CH0_FALL_EDGE + (ch))
+#define GPIO_LL_ETM_EVENT_ID_ANY_EDGE(ch) (GPIO_EVT_CH0_ANY_EDGE + (ch))
+
+#define GPIO_LL_ETM_TASK_ID_SET(ch) (GPIO_TASK_CH0_SET + (ch))
+#define GPIO_LL_ETM_TASK_ID_CLR(ch) (GPIO_TASK_CH0_CLEAR + (ch))
+#define GPIO_LL_ETM_TASK_ID_TOG(ch) (GPIO_TASK_CH0_TOGGLE + (ch))
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Set which GPIO to be bounded to the event channel
+ *
+ * @param dev Register base address
+ * @param chan Channel number
+ * @param gpio_num GPIO number
+ */
+static inline void gpio_ll_etm_event_channel_set_gpio(gpio_etm_dev_t *dev, uint32_t chan, uint32_t gpio_num)
+{
+    dev->etm_event_chn_cfg[chan].etm_ch0_event_sel = gpio_num;
+}
+
+/**
+ * @brief Wether to enable the event channel
+ *
+ * @param dev Register base address
+ * @param chan Channel number
+ * @param enable True to enable, false to disable
+ */
+static inline void gpio_ll_etm_enable_event_channel(gpio_etm_dev_t *dev, uint32_t chan, bool enable)
+{
+    dev->etm_event_chn_cfg[chan].etm_ch0_event_en = enable;
+}
+
+/**
+ * @brief Set which GPIO to be bounded to the task channel
+ *
+ * @note One channel can be bounded to multiple different GPIOs
+ *
+ * @param dev Register base address
+ * @param chan Channel number
+ * @param gpio_num GPIO number
+ */
+static inline void gpio_ll_etm_gpio_set_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num, uint32_t chan)
+{
+    int g_p = gpio_num / 4;
+    int g_idx = gpio_num % 4;
+    uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val;
+    reg_val &= ~(0x07 << (g_idx * 8 + 1));
+    reg_val |= ((chan & 0x07) << (g_idx * 8 + 1));
+    dev->etm_task_pn_cfg[g_p].val = reg_val;
+}
+
+/**
+ * @brief Wether to enable the GPIO to be managed by the task channel
+ *
+ * @param dev Register base address
+ * @param gpio_num GPIO number
+ * @param enable True to enable, false to disable
+ */
+static inline void gpio_ll_etm_enable_task_gpio(gpio_etm_dev_t *dev, uint32_t gpio_num, bool enable)
+{
+    int g_p = gpio_num / 4;
+    int g_idx = gpio_num % 4;
+    uint32_t reg_val = dev->etm_task_pn_cfg[g_p].val;
+    reg_val &= ~(0x01 << (g_idx * 8));
+    reg_val |= ((enable & 0x01) << (g_idx * 8));
+    dev->etm_task_pn_cfg[g_p].val = reg_val;
+}
+
+/**
+ * @brief Check whether a GPIO has been enabled and managed by a task channel
+ *
+ * @param dev Register base address
+ * @param gpio_num GPIO number
+ * @return True if enabled, false otherwise
+ */
+static inline bool gpio_ll_etm_is_task_gpio_enabled(gpio_etm_dev_t *dev, uint32_t gpio_num)
+{
+    int g_p = gpio_num / 4;
+    int g_idx = gpio_num % 4;
+    return dev->etm_task_pn_cfg[g_p].val & (0x01 << (g_idx * 8));
+}
+
+/**
+ * @brief Get the channel number that the GPIO is bounded to
+ *
+ * @param dev Register base address
+ * @param gpio_num GPIO number
+ * @return GPIO ETM Task channel number
+ */
+static inline uint32_t gpio_ll_etm_gpio_get_task_channel(gpio_etm_dev_t *dev, uint32_t gpio_num)
+{
+    int g_p = gpio_num / 4;
+    int g_idx = gpio_num % 4;
+    return (dev->etm_task_pn_cfg[g_p].val >> (g_idx * 8 + 1)) & 0x07;
+}
+
+#ifdef __cplusplus
+}
+#endif

+ 28 - 0
components/soc/esp32h2/include/soc/Kconfig.soc_caps.in

@@ -59,6 +59,10 @@ config SOC_SDM_SUPPORTED
     bool
     default y
 
+config SOC_ETM_SUPPORTED
+    bool
+    default y
+
 config SOC_RMT_SUPPORTED
     bool
     default y
@@ -247,6 +251,14 @@ config SOC_GDMA_SUPPORT_ETM
     bool
     default y
 
+config SOC_ETM_GROUPS
+    int
+    default 1
+
+config SOC_ETM_CHANNELS_PER_GROUP
+    int
+    default 50
+
 config SOC_GPIO_PORT
     int
     default 1
@@ -255,6 +267,18 @@ config SOC_GPIO_PIN_COUNT
     int
     default 28
 
+config SOC_GPIO_SUPPORT_ETM
+    bool
+    default y
+
+config SOC_GPIO_ETM_EVENTS_PER_GROUP
+    int
+    default 8
+
+config SOC_GPIO_ETM_TASKS_PER_GROUP
+    int
+    default 8
+
 config SOC_GPIO_SUPPORT_DEEPSLEEP_WAKEUP
     bool
     default y
@@ -703,6 +727,10 @@ config SOC_TIMER_GROUP_TOTAL_TIMERS
     int
     default 2
 
+config SOC_TIMER_SUPPORT_ETM
+    bool
+    default y
+
 config SOC_TWAI_CONTROLLER_NUM
     bool
     default y

+ 1 - 0
components/soc/esp32h2/include/soc/periph_defs.h

@@ -39,6 +39,7 @@ typedef enum {
     PERIPH_DS_MODULE,
     PERIPH_GDMA_MODULE,
     PERIPH_MCPWM0_MODULE,
+    PERIPH_ETM_MODULE,
     PERIPH_SYSTIMER_MODULE,
     PERIPH_SARADC_MODULE,
     PERIPH_MODULE_MAX

+ 11 - 1
components/soc/esp32h2/include/soc/soc_caps.h

@@ -47,6 +47,7 @@
 #define SOC_RTC_MEM_SUPPORTED           1
 #define SOC_I2S_SUPPORTED               1
 #define SOC_SDM_SUPPORTED               1
+#define SOC_ETM_SUPPORTED               1
 #define SOC_RMT_SUPPORTED               1
 // #define SOC_GPSPI_SUPPORTED             1 // TODO: IDF-6264
 #define SOC_LEDC_SUPPORTED              1
@@ -145,11 +146,20 @@
 #define SOC_GDMA_PAIRS_PER_GROUP        (3)  // Number of GDMA pairs in each group
 #define SOC_GDMA_SUPPORT_ETM            (1)  // Support ETM submodule
 
+/*-------------------------- ETM CAPS --------------------------------------*/
+#define SOC_ETM_GROUPS                  1U  // Number of ETM groups
+#define SOC_ETM_CHANNELS_PER_GROUP      50  // Number of ETM channels in the group
+
 /*-------------------------- GPIO CAPS ---------------------------------------*/
 // ESP32-H2 has 1 GPIO peripheral
 #define SOC_GPIO_PORT               (1U)
 #define SOC_GPIO_PIN_COUNT          (28)
 
+// GPIO peripheral has the ETM extension
+#define SOC_GPIO_SUPPORT_ETM          1
+#define SOC_GPIO_ETM_EVENTS_PER_GROUP 8
+#define SOC_GPIO_ETM_TASKS_PER_GROUP  8
+
 // Target has no full LP IO subsystem, GPIO7~14 remain LP function (powered by VDD3V3_LP, and can be used as deep-sleep wakeup pins)
 
 // GPIO7~14 on ESP32H2 can support chip deep sleep wakeup
@@ -346,7 +356,7 @@
 #define SOC_TIMER_GROUP_SUPPORT_PLL_F48M  (1)
 // #define SOC_TIMER_GROUP_SUPPORT_RC_FAST   (1) // TODO: IDF-6265
 #define SOC_TIMER_GROUP_TOTAL_TIMERS      (2)
-// #define SOC_TIMER_SUPPORT_ETM             (1)
+#define SOC_TIMER_SUPPORT_ETM             (1)
 
 // TODO: IDF-6217 (Copy from esp32c6, need check)
 /*-------------------------- TWAI CAPS ---------------------------------------*/

+ 6 - 4
components/soc/esp32h2/ld/esp32h2.peripherals.ld

@@ -41,10 +41,12 @@ PROVIDE ( ECC       = 0x6008B000 );
 PROVIDE ( DS        = 0x6008C000 );
 PROVIDE ( HMAC      = 0x6008D000 );
 
-PROVIDE ( IO_MUX    = 0x60090000 );
-PROVIDE ( GPIO      = 0x60091000 );
-PROVIDE ( GPIO_EXT  = 0x60091f00 );
-PROVIDE ( SDM       = 0x60091f00 ); /*ESP32H2-TODO*/
+PROVIDE ( IO_MUX         = 0x60090000 );
+PROVIDE ( GPIO           = 0x60091000 );
+PROVIDE ( GPIO_EXT       = 0x60091f00 );
+PROVIDE ( SDM            = 0x60091f00 );
+PROVIDE ( GLITCH_FILTER  = 0x60091f30 );
+PROVIDE ( GPIO_ETM       = 0x60091f60 );
 
 PROVIDE ( MEM_ACS_MONITOR   = 0x60092000 );
 PROVIDE ( PAU               = 0x60093000 );

+ 0 - 1
docs/docs_not_updated/esp32h2.txt

@@ -77,7 +77,6 @@ api-reference/peripherals/usb_device
 api-reference/peripherals/sdspi_host
 api-reference/peripherals/dac
 api-reference/peripherals/spi_slave
-api-reference/peripherals/etm
 api-reference/peripherals/i2s
 api-reference/peripherals/touch_element
 api-reference/peripherals/lcd

+ 2 - 2
examples/peripherals/timer_group/gptimer_capture_hc_sr04/README.md

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

+ 2 - 1
examples/peripherals/timer_group/gptimer_capture_hc_sr04/pytest_gptimer_capture_example.py

@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
 # SPDX-License-Identifier: CC0-1.0
 
 import pytest
@@ -6,6 +6,7 @@ from pytest_embedded import Dut
 
 
 @pytest.mark.esp32c6
+@pytest.mark.esp32h2
 @pytest.mark.generic
 def test_gptimer_capture(dut: Dut) -> None:
     dut.expect_exact('Configure trig gpio')