Event Task Matrix (ETM)
Introduction
Normally, if a peripheral X needs to notify peripheral Y of a particular event, this could only be done via a CPU interrupt from peripheral X (where the CPU notifies peripheral Y on behalf of peripheral X). However, in time critical applications, the latency introduced by CPU interrupts is non-negligible. The Event Task Matrix (ETM) module allows subset of peripherals to notify each other of events directly (i.e., without CPU intervention). This allows precise (and low latency) synchronization between peripherals, and lessens the CPU’s work load (as the CPU no longer needs handle these events).
The ETM module has multiple programmable channels, they’re used to connect a particular Event to a particular Task. When an event is activated, the ETM channel will trigger the corresponding task automatically. Peripherals that support ETM functionality will provide their or unique set of events and tasks to be connected by the ETM. An ETM channel can connect any event to any task (even looping back an event to a task of on the same peripheral). However, an ETM channel can only connect one event to one task any time (i.e., 1 to 1 relation). If you want to use different events to trigger the same task, you can set up more ETM channels.
Typically, with the help of ETM module, you can implement features like:
Toggle the GPIO when a timer alarm event happens
Start an ADC conversion when a pulse edge is detected on a GPIO
Functional Overview
The following sections of this document cover the typical steps to configure and use the ETM module.
ETM Channel Allocation - describes how to install and uninstall ETM channel
ETM Event - describes how to allocate a new ETM event handle or fetch an existing handle from various peripherals
ETM Task - describes how to allocate a new ETM task handle or fetch an existing handle from various peripherals
ETM Channel Control - describes common ETM channel control functions
Thread Safety - lists which APIs are guaranteed to be thread safe by the driver.
Kconfig Options - lists the supported Kconfig options that can be used to make a different effect on driver behavior
ETM Channel Allocation
There’re many identical ETM channels in ESP32-C6 1, each channel is represented by esp_etm_channel_handle_t
in the software. The ETM core driver manages all available hardware resources in a pool, so that you don’t need to care about which channel is in use and which is not. The ETM core driver will allocate a channel for you when you call esp_etm_new_channel()
and delete it when you call esp_etm_del_channel()
. All requirements needed for allocating a channel are provided in esp_etm_channel_config_t
.
Before deleting an ETM channel, please disable it by esp_etm_channel_disable()
in advance or make sure it has not been enabled yet by esp_etm_channel_enable()
.
ETM Event
ETM Event abstracts the event source and is represented by esp_etm_event_handle_t
in the software. ETM event can be generated from a variety of peripherals, thus the way to get the event handle differs from peripherals. When an ETM event is no longer used, you should call esp_etm_channel_connect()
with a NULL
event handle to disconnect it and then call esp_etm_del_event()
to free the event resource.
GPIO Events
GPIO edge event is the most common event type, it can be generated by any GPIO pin. You can call gpio_new_etm_event()
to create a GPIO event handle, with the configurations provided in gpio_etm_event_config_t
:
gpio_etm_event_config_t::edge
decides which edge will trigger the event, supported edge types are listed in thegpio_etm_event_edge_t
.
You need to build a connection between the GPIO ETM event handle and the GPIO number. So you should call gpio_etm_event_bind_gpio()
afterwards. Please note, only the ETM event handle that created by gpio_new_etm_event()
can set a GPIO number. Calling this function with other kind of ETM event will return ESP_ERR_INVALID_ARG
error. Needless to say, this function won’t help do the GPIO initialization, you still need to call gpio_config()
to set the property like direction, pull up/down mode separately.
Other Peripheral Events
You can call
esp_systick_new_etm_alarm_event()
to get the ETM event from RTOS Systick, one per CPU core.Refer to ESP Timer for how to get the ETM event handle from esp_timer.
Refer to GPTimer for how to get the ETM event handle from GPTimer.
Refer to Async Memory Copy for how to get the ETM event handle from async memcpy.
ETM Task
ETM Task abstracts the task action and is represented by esp_etm_task_handle_t
in the software. ETM task can be assigned to a variety of peripherals, thus the way to get the task handle differs from peripherals. When an ETM task is no longer used, you should call esp_etm_channel_connect()
with a NULL
task handle to disconnect it and then call esp_etm_del_task()
to free the task resource.
GPIO Tasks
GPIO task is the most common task type, one GPIO task can even manage multiple GPIOs. When tha task gets activated by the ETM channel, all managed GPIOs can set/clear/toggle at the same time. You can call gpio_new_etm_task()
to create a GPIO task handle, with the configurations provided in gpio_etm_task_config_t
:
gpio_etm_task_config_t::action
decides what the GPIO action would be taken by the ETM task. Supported actions are listed in thegpio_etm_task_action_t
.
To build a connection between the GPIO ETM task and the GPIO number, you should call gpio_etm_task_add_gpio()
. You can call this function by several times if you want the task handle to manage more GPIOs. Please note, only the ETM task handle that created by gpio_new_etm_task()
can manage a GPIO. Calling this function with other kind of ETM task will return ESP_ERR_INVALID_ARG
error. Needless to say, this function won’t help do the GPIO initialization, you still need to call gpio_config()
to set the property like direction, pull up/down mode separately.
Before you call esp_etm_del_task()
to delete the GPIO ETM task, make sure that all previously added GPIOs are removed by gpio_etm_task_rm_gpio()
in advance.
Other Peripheral Tasks
Refer to GPTimer for how to get the ETM task handle from GPTimer.
ETM Channel Control
Connect Event and Task
An ETM event has no association with an ETM task, until they’re connected to the same ETM channel by calling esp_etm_channel_connect()
. Specially, calling the function with a NULL
task/event handle, means to disconnect the channel from any task or event. Note that, this function can be called either before or after the channel is enabled. But calling this function at runtime to change the connection can be dangerous, because the channel may be in the middle of a cycle, and the new connection may not take effect immediately.
Enable and Disable Channel
You can call esp_etm_channel_enable()
and esp_etm_channel_disable()
to enable and disable the ETM channel from working.
ETM Channel Profiling
To check if the ETM channels are set with proper events and tasks, you can call esp_etm_dump()
to dump all working ETM channels with their associated events and tasks. The dumping format is like:
===========ETM Dump Start==========
channel 0: event 48 ==> task 17
channel 1: event 48 ==> task 90
channel 2: event 48 ==> task 94
===========ETM Dump End============
The digital ID printed in the dump information is defined in the soc/soc_etm_source.h
file.
Thread Safety
The factory functions like esp_etm_new_channel()
and gpio_new_etm_task()
are guaranteed to be thread safe by the driver, which means, you can call it from different RTOS tasks without protection by extra locks.
No functions are allowed to run within ISR environment.
Other functions that take esp_etm_channel_handle_t
, esp_etm_task_handle_t
and esp_etm_event_handle_t
as the first positional parameter, are not treated as thread safe, which means you should avoid calling them from multiple tasks.
Kconfig Options
CONFIG_ETM_ENABLE_DEBUG_LOG is used to enabled the debug log output. Enable this option will increase the firmware binary size as well.
API Reference
Header File
Functions
-
esp_err_t esp_etm_new_channel(const esp_etm_channel_config_t *config, esp_etm_channel_handle_t *ret_chan)
Allocate an ETM channel.
备注
The channel can later be freed by
esp_etm_del_channel
- 参数
config – [in] ETM channel configuration
ret_chan – [out] Returned ETM channel handle
- 返回
ESP_OK: Allocate ETM channel successfully
ESP_ERR_INVALID_ARG: Allocate ETM channel failed because of invalid argument
ESP_ERR_NO_MEM: Allocate ETM channel failed because of out of memory
ESP_ERR_NOT_FOUND: Allocate ETM channel failed because all channels are used up and no more free one
ESP_FAIL: Allocate ETM channel failed because of other reasons
-
esp_err_t esp_etm_del_channel(esp_etm_channel_handle_t chan)
Delete an ETM channel.
- 参数
chan – [in] ETM channel handle that created by
esp_etm_new_channel
- 返回
ESP_OK: Delete ETM channel successfully
ESP_ERR_INVALID_ARG: Delete ETM channel failed because of invalid argument
ESP_FAIL: Delete ETM channel failed because of other reasons
-
esp_err_t esp_etm_channel_enable(esp_etm_channel_handle_t chan)
Enable ETM channel.
备注
This function will transit the channel state from init to enable.
- 参数
chan – [in] ETM channel handle that created by
esp_etm_new_channel
- 返回
ESP_OK: Enable ETM channel successfully
ESP_ERR_INVALID_ARG: Enable ETM channel failed because of invalid argument
ESP_ERR_INVALID_STATE: Enable ETM channel failed because the channel has been enabled already
ESP_FAIL: Enable ETM channel failed because of other reasons
-
esp_err_t esp_etm_channel_disable(esp_etm_channel_handle_t chan)
Disable ETM channel.
备注
This function will transit the channel state from enable to init.
- 参数
chan – [in] ETM channel handle that created by
esp_etm_new_channel
- 返回
ESP_OK: Disable ETM channel successfully
ESP_ERR_INVALID_ARG: Disable ETM channel failed because of invalid argument
ESP_ERR_INVALID_STATE: Disable ETM channel failed because the channel is not enabled yet
ESP_FAIL: Disable ETM channel failed because of other reasons
-
esp_err_t esp_etm_channel_connect(esp_etm_channel_handle_t chan, esp_etm_event_handle_t event, esp_etm_task_handle_t task)
Connect an ETM event to an ETM task via a previously allocated ETM channel.
备注
Setting the ETM event/task handle to NULL means to disconnect the channel from any event/task
- 参数
chan – [in] ETM channel handle that created by
esp_etm_new_channel
event – [in] ETM event handle obtained from a driver/peripheral, e.g.
xxx_new_etm_event
task – [in] ETM task handle obtained from a driver/peripheral, e.g.
xxx_new_etm_task
- 返回
ESP_OK: Connect ETM event and task to the channel successfully
ESP_ERR_INVALID_ARG: Connect ETM event and task to the channel failed because of invalid argument
ESP_FAIL: Connect ETM event and task to the channel failed because of other reasons
-
esp_err_t esp_etm_del_event(esp_etm_event_handle_t event)
Delete ETM event.
备注
Although the ETM event comes from various peripherals, we provide the same user API to delete the event handle seamlessly.
- 参数
event – [in] ETM event handle obtained from a driver/peripheral, e.g.
xxx_new_etm_event
- 返回
ESP_OK: Delete ETM event successfully
ESP_ERR_INVALID_ARG: Delete ETM event failed because of invalid argument
ESP_FAIL: Delete ETM event failed because of other reasons
-
esp_err_t esp_etm_del_task(esp_etm_task_handle_t task)
Delete ETM task.
备注
Although the ETM task comes from various peripherals, we provide the same user API to delete the task handle seamlessly.
- 参数
task – [in] ETM task handle obtained from a driver/peripheral, e.g.
xxx_new_etm_task
- 返回
ESP_OK: Delete ETM task successfully
ESP_ERR_INVALID_ARG: Delete ETM task failed because of invalid argument
ESP_FAIL: Delete ETM task failed because of other reasons
-
esp_err_t esp_etm_dump(FILE *out_stream)
Dump ETM channel usages to the given IO stream.
- 参数
out_stream – [in] IO stream (e.g. stdout)
- 返回
ESP_OK: Dump ETM channel usages successfully
ESP_ERR_INVALID_ARG: Dump ETM channel usages failed because of invalid argument
ESP_FAIL: Dump ETM channel usages failed because of other reasons
Structures
-
struct esp_etm_channel_config_t
ETM channel configuration.
Type Definitions
-
typedef struct esp_etm_channel_t *esp_etm_channel_handle_t
ETM channel handle.
-
typedef struct esp_etm_event_t *esp_etm_event_handle_t
ETM event handle.
-
typedef struct esp_etm_task_t *esp_etm_task_handle_t
ETM task handle.
Header File
Functions
-
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event)
Create an ETM event object for the GPIO peripheral.
备注
The created ETM event object can be deleted later by calling
esp_etm_del_event
备注
The newly created ETM event object is not bind to any GPIO, you need to call
gpio_etm_event_bind_gpio
to bind the wanted GPIO- 参数
config – [in] GPIO ETM event configuration
ret_event – [out] Returned ETM event handle
- 返回
ESP_OK: Create ETM event successfully
ESP_ERR_INVALID_ARG: Create ETM event failed because of invalid argument
ESP_ERR_NO_MEM: Create ETM event failed because of out of memory
ESP_ERR_NOT_FOUND: Create ETM event failed because all events are used up and no more free one
ESP_FAIL: Create ETM event failed because of other reasons
-
esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num)
Bind the GPIO with the ETM event.
备注
Calling this function multiple times with different GPIO number can override the previous setting immediately.
备注
Only GPIO ETM object can call this function
- 参数
event – [in] ETM event handle that created by
gpio_new_etm_event
gpio_num – [in] GPIO number that can trigger the ETM event
- 返回
ESP_OK: Set the GPIO for ETM event successfully
ESP_ERR_INVALID_ARG: Set the GPIO for ETM event failed because of invalid argument, e.g. GPIO is not input capable, ETM event is not of GPIO type
ESP_FAIL: Set the GPIO for ETM event failed because of other reasons
-
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task)
Create an ETM task object for the GPIO peripheral.
备注
The created ETM task object can be deleted later by calling
esp_etm_del_task
备注
The GPIO ETM task works like a container, a newly created ETM task object doesn’t have GPIO members to be managed. You need to call
gpio_etm_task_add_gpio
to put one or more GPIOs to the container.- 参数
config – [in] GPIO ETM task configuration
ret_task – [out] Returned ETM task handle
- 返回
ESP_OK: Create ETM task successfully
ESP_ERR_INVALID_ARG: Create ETM task failed because of invalid argument
ESP_ERR_NO_MEM: Create ETM task failed because of out of memory
ESP_ERR_NOT_FOUND: Create ETM task failed because all tasks are used up and no more free one
ESP_FAIL: Create ETM task failed because of other reasons
-
esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num)
Add GPIO to the ETM task.
备注
You can call this function multiple times to add more GPIOs
备注
Only GPIO ETM object can call this function
- 参数
task – [in] ETM task handle that created by
gpio_new_etm_task
gpio_num – [in] GPIO number that can be controlled by the ETM task
- 返回
ESP_OK: Add GPIO to the ETM task successfully
ESP_ERR_INVALID_ARG: Add GPIO to the ETM task failed because of invalid argument, e.g. GPIO is not output capable, ETM task is not of GPIO type
ESP_ERR_INVALID_STATE: Add GPIO to the ETM task failed because the GPIO is used by other ETM task already
ESP_FAIL: Add GPIO to the ETM task failed because of other reasons
-
esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num)
Remove the GPIO from the ETM task.
备注
Before deleting the ETM task, you need to remove all the GPIOs from the ETM task by this function
备注
Only GPIO ETM object can call this function
- 参数
task – [in] ETM task handle that created by
gpio_new_etm_task
gpio_num – [in] GPIO number that to be remove from the ETM task
- 返回
ESP_OK: Remove the GPIO from the ETM task successfully
ESP_ERR_INVALID_ARG: Remove the GPIO from the ETM task failed because of invalid argument
ESP_ERR_INVALID_STATE: Remove the GPIO from the ETM task failed because the GPIO is not controlled by this ETM task
ESP_FAIL: Remove the GPIO from the ETM task failed because of other reasons
Structures
-
struct gpio_etm_event_config_t
GPIO ETM event configuration.
Public Members
-
gpio_etm_event_edge_t edge
Which kind of edge can trigger the ETM event module
-
gpio_etm_event_edge_t edge
-
struct gpio_etm_task_config_t
GPIO ETM task configuration.
Public Members
-
gpio_etm_task_action_t action
Which action to take by the ETM task module
-
gpio_etm_task_action_t action
Enumerations
-
enum gpio_etm_event_edge_t
GPIO edges that can be used as ETM event.
Values:
-
enumerator GPIO_ETM_EVENT_EDGE_POS
A rising edge on the GPIO will generate an ETM event signal
-
enumerator GPIO_ETM_EVENT_EDGE_NEG
A falling edge on the GPIO will generate an ETM event signal
-
enumerator GPIO_ETM_EVENT_EDGE_ANY
Any edge on the GPIO can generate an ETM event signal
-
enumerator GPIO_ETM_EVENT_EDGE_POS
Header File
Functions
-
esp_err_t esp_systick_new_etm_alarm_event(int core_id, esp_etm_event_handle_t *out_event)
Get the ETM event handle of systick hardware’s alarm/heartbeat event.
备注
The created ETM event object can be deleted later by calling
esp_etm_del_event
- 参数
core_id – [in] CPU core ID
out_event – [out] Returned ETM event handle
- 返回
ESP_OK Success
ESP_ERR_INVALID_ARG Parameter error
- 1
Different ESP chip series might have different numbers of ETM channels. For more details, please refer to ESP32-C6 Technical Reference Manual > Chapter Event Task Matrix (ETM) [PDF]. The driver will not forbid you from applying for more channels, but it will return error when all available hardware resources are used up. Please always check the return value when doing channel allocation (i.e.
esp_etm_new_channel()
).