From 0a110478ea4905ba1fde5a2680919738e8df51f3 Mon Sep 17 00:00:00 2001 From: laokaiyao Date: Tue, 17 Jun 2025 11:44:55 +0800 Subject: [PATCH] feat(modem_etm): support modem etm on h4 --- .../include/esp_private/etm_interface.h | 1 + .../modem/include/modem/modem_etm.h | 86 +++++++++++++++++++ components/esp_hw_support/modem/modem_etm.c | 69 +++++++++++++++ .../hal/esp32h4/include/hal/modem_etm_ll.h | 83 ++++++++++++++++++ .../esp32h4/include/soc/Kconfig.soc_caps.in | 4 + 5 files changed, 243 insertions(+) create mode 100644 components/esp_hw_support/modem/include/modem/modem_etm.h create mode 100644 components/esp_hw_support/modem/modem_etm.c create mode 100644 components/hal/esp32h4/include/hal/modem_etm_ll.h diff --git a/components/esp_hw_support/include/esp_private/etm_interface.h b/components/esp_hw_support/include/esp_private/etm_interface.h index 201ea67e4d..5b22a38dea 100644 --- a/components/esp_hw_support/include/esp_private/etm_interface.h +++ b/components/esp_hw_support/include/esp_private/etm_interface.h @@ -29,6 +29,7 @@ typedef enum { ETM_TRIG_PERIPH_TSENS, /*!< ETM trigger source: Temperature Sensor */ ETM_TRIG_PERIPH_I2S, /*!< ETM trigger source: I2S */ ETM_TRIG_PERIPH_LP_CORE, /*!< ETM trigger source: Low-Power Core */ + ETM_TRIG_PERIPH_MODEM, /*!< ETM trigger source: Modem */ } etm_trigger_peripheral_t; /** diff --git a/components/esp_hw_support/modem/include/modem/modem_etm.h b/components/esp_hw_support/modem/include/modem/modem_etm.h new file mode 100644 index 0000000000..517c706a9f --- /dev/null +++ b/components/esp_hw_support/modem/include/modem/modem_etm.h @@ -0,0 +1,86 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Modem ETM event type + * + * @note The event type is used to identify the event type. + */ +typedef enum { + MODEM_ETM_EVENT_G0 = 0, /*!< Modem ETM event group 0 */ + MODEM_ETM_EVENT_G1 = 1, /*!< Modem ETM event group 1 */ + MODEM_ETM_EVENT_G2 = 2, /*!< Modem ETM event group 2 */ + MODEM_ETM_EVENT_G3 = 3, /*!< Modem ETM event group 3 */ + MODEM_ETM_EVENT_MAX, +} modem_etm_event_type_t; + +/** + * @brief Modem ETM task type + * + * @note The task type is used to identify the task type. + */ +typedef enum { + MODEM_ETM_TASK_G0 = 0, /*!< Modem ETM task group 0 */ + MODEM_ETM_TASK_G1 = 1, /*!< Modem ETM task group 1 */ + MODEM_ETM_TASK_G2 = 2, /*!< Modem ETM task group 2 */ + MODEM_ETM_TASK_G3 = 3, /*!< Modem ETM task group 3 */ + MODEM_ETM_TASK_MAX, +} modem_etm_task_type_t; + +/** + * @brief Modem ETM event configuration + * + * @note The event configuration is used to configure the event. + */ +typedef struct { + modem_etm_event_type_t event_type; /*!< Modem ETM event type */ +} modem_etm_event_config_t; + +/** + * @brief Modem ETM task configuration + * + * @note The task configuration is used to configure the task. + */ +typedef struct { + modem_etm_task_type_t task_type; /*!< Modem ETM task type */ +} modem_etm_task_config_t; + + +/** + * @brief Create a new modem ETM event + * + * @param config The modem ETM event configuration + * @param out_event The output modem ETM event handle + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_NO_MEM: No memory + */ +esp_err_t modem_new_etm_event(const modem_etm_event_config_t *config, esp_etm_event_handle_t *out_event); + +/** + * @brief Create a new modem ETM task + * + * @param config The modem ETM task configuration + * @param out_task The output modem ETM task handle + * @return + * - ESP_OK: Success + * - ESP_ERR_INVALID_ARG: Invalid argument + * - ESP_ERR_NO_MEM: No memory + */ +esp_err_t modem_new_etm_task(const modem_etm_task_config_t *config, esp_etm_task_handle_t *out_task); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_hw_support/modem/modem_etm.c b/components/esp_hw_support/modem/modem_etm.c new file mode 100644 index 0000000000..23c8952b38 --- /dev/null +++ b/components/esp_hw_support/modem/modem_etm.c @@ -0,0 +1,69 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "sdkconfig.h" +#include "esp_log.h" +#include "esp_check.h" +#include "esp_heap_caps.h" +#include "modem/modem_etm.h" +#include "hal/modem_ll.h" +#include "esp_private/etm_interface.h" + +#define ETM_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT + +static const char *TAG = "modem-etm"; + +static esp_err_t s_modem_del_etm_event(esp_etm_event_t *event) +{ + free(event); + return ESP_OK; +} + +static esp_err_t s_modem_del_etm_task(esp_etm_task_t *task) +{ + free(task); + return ESP_OK; +} + +esp_err_t modem_new_etm_event(const modem_etm_event_config_t *config, esp_etm_event_handle_t *out_event) +{ + ESP_RETURN_ON_FALSE(config && out_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(config->event_type < MODEM_ETM_EVENT_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid event type"); + esp_etm_event_t *event = heap_caps_calloc(1, sizeof(esp_etm_event_t), ETM_MEM_ALLOC_CAPS); + ESP_RETURN_ON_FALSE(event, ESP_ERR_NO_MEM, TAG, "no memory for ETM event"); + + // Get the event id from the modem ETM event table + uint32_t event_id = MODEM_LL_ETM_EVENT_TABLE((uint32_t)config->event_type); + + // fill the ETM event object + event->event_id = event_id; + event->trig_periph = ETM_TRIG_PERIPH_MODEM; + event->del = s_modem_del_etm_event; + *out_event = event; + + return ESP_OK; +} + +esp_err_t modem_new_etm_task(const modem_etm_task_config_t *config, esp_etm_task_handle_t *out_task) +{ + ESP_RETURN_ON_FALSE(config && out_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument"); + ESP_RETURN_ON_FALSE(config->task_type < MODEM_ETM_TASK_MAX, ESP_ERR_INVALID_ARG, TAG, "invalid task type"); + esp_etm_task_t *task = heap_caps_calloc(1, sizeof(esp_etm_task_t), ETM_MEM_ALLOC_CAPS); + ESP_RETURN_ON_FALSE(task, ESP_ERR_NO_MEM, TAG, "no memory for ETM task"); + + // Get the task id from the modem ETM task table + uint32_t task_id = MODEM_LL_ETM_TASK_TABLE((uint32_t)config->task_type); + + // fill the ETM task object + task->task_id = task_id; + task->trig_periph = ETM_TRIG_PERIPH_MODEM; + task->del = s_modem_del_etm_task; + *out_task = task; + + return ESP_OK; +} diff --git a/components/hal/esp32h4/include/hal/modem_etm_ll.h b/components/hal/esp32h4/include/hal/modem_etm_ll.h new file mode 100644 index 0000000000..45790ebd03 --- /dev/null +++ b/components/hal/esp32h4/include/hal/modem_etm_ll.h @@ -0,0 +1,83 @@ +/* + * SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include +#include "soc/soc.h" +#include "hal/assert.h" +#include "soc/soc_etm_struct.h" +#include "soc/soc_etm_reg.h" +#include "soc/soc_etm_source.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MODEM_LL_ETM_EVENT_TABLE(event_type) \ + (uint32_t[4]){ \ + [0] = MODEM_EVT_G0, \ + [1] = MODEM_EVT_G1, \ + [2] = MODEM_EVT_G2, \ + [3] = MODEM_EVT_G3, \ + }[event_type] + +#define MODEM_LL_ETM_TASK_TABLE(task_type) \ + (uint32_t[4]){ \ + [0] = MODEM_TASK_G0, \ + [1] = MODEM_TASK_G1, \ + [2] = MODEM_TASK_G2, \ + [3] = MODEM_TASK_G3, \ + }[task_type] + +static inline bool modem_etm_ll_get_group_event_status(int group_id) +{ + switch (group_id) { + case 0: + return SOC_ETM.etm_evt_st6.etm_modem_evt_g0_st; + case 1: + return SOC_ETM.etm_evt_st6.etm_modem_evt_g1_st; + case 2: + return SOC_ETM.etm_evt_st6.etm_modem_evt_g2_st; + case 3: + return SOC_ETM.etm_evt_st6.etm_modem_evt_g3_st; + default: + HAL_ASSERT(false); + } + return false; +} + +static inline bool modem_etm_ll_get_group_task_status(int group_id) +{ + switch (group_id) { + case 0: + return SOC_ETM.etm_task_st5.etm_modem_task_g0_st; + case 1: + return SOC_ETM.etm_task_st5.etm_modem_task_g1_st; + case 2: + return SOC_ETM.etm_task_st5.etm_modem_task_g2_st; + case 3: + return SOC_ETM.etm_task_st5.etm_modem_task_g3_st; + default: + HAL_ASSERT(false); + } + return false; +} + +static inline void modem_etm_ll_clear_group_event_status(int group_id) +{ + SOC_ETM.etm_evt_st6_clr.val = SOC_ETM_MODEM_EVT_G0_ST_CLR << group_id; +} + +static inline void modem_etm_ll_clear_group_task_status(int group_id) +{ + SOC_ETM.etm_task_st5_clr.val = SOC_ETM_MODEM_TASK_G0_ST_CLR << group_id; +} + +#ifdef __cplusplus +} +#endif diff --git a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in index 4ba8aa3374..720f4839f0 100644 --- a/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32h4/include/soc/Kconfig.soc_caps.in @@ -491,6 +491,10 @@ config SOC_SYSTIMER_ALARM_MISS_COMPENSATE bool default y +config SOC_SYSTIMER_SUPPORT_ETM + bool + default y + config SOC_LP_TIMER_BIT_WIDTH_LO int default 32