diff --git a/components/esp_event/esp_event.c b/components/esp_event/esp_event.c
index 0d9be71409..1e6fc99da6 100644
--- a/components/esp_event/esp_event.c
+++ b/components/esp_event/esp_event.c
@@ -22,7 +22,7 @@
/* ---------------------------- Definitions --------------------------------- */
#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
-// LOOP @
rx: dr:
+// LOOP @ rx: dr:
#define LOOP_DUMP_FORMAT "LOOP @%p,%s rx:%" PRIu32 " dr:%" PRIu32 "\n"
// handler @ ev: inv: time:
#define HANDLER_DUMP_FORMAT " HANDLER @%p ev:%s,%s inv:%" PRIu32 " time:%lld us\n"
@@ -146,14 +146,42 @@ static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_n
// This happens in "handler instance can unregister itself" test case.
// To prevent memory corruption error it's necessary to check if pointer is still valid.
esp_event_loop_node_t* loop_node;
- esp_event_handler_node_t* handler_node;
SLIST_FOREACH(loop_node, &(loop->loop_nodes), next) {
+ // try to find the handler amongst the list of handlers that are registered on the
+ // loop level (i.e., registered to be triggered for all events)
+ esp_event_handler_node_t* handler_node;
SLIST_FOREACH(handler_node, &(loop_node->handlers), next) {
if (handler_node == handler) {
handler->invoked++;
handler->time += diff;
}
}
+
+ // try to find the handler amongst the list of handlers that are registered on the
+ // base level (i.e., registered to be triggered for all events of a specific event base)
+ esp_event_base_node_t* base_node;
+ SLIST_FOREACH(base_node, &(loop_node->base_nodes), next) {
+ esp_event_handler_node_t* base_handler_node;
+ SLIST_FOREACH(base_handler_node, &(base_node->handlers), next) {
+ if (base_handler_node == handler) {
+ handler->invoked++;
+ handler->time += diff;
+ }
+ }
+
+ // try to find the handler amongst the list of handlers that are registered on the
+ // ID level (i.e., registered to be triggered for a specific event ID of a specific event base)
+ esp_event_id_node_t* id_node;
+ SLIST_FOREACH(id_node, &(base_node->id_nodes), next) {
+ esp_event_handler_node_t* id_handler_node;
+ SLIST_FOREACH(id_handler_node, &(id_node->handlers), next) {
+ if (id_handler_node == handler) {
+ handler->invoked++;
+ handler->time += diff;
+ }
+ }
+ }
+ }
}
xSemaphoreGive(loop->profiling_mutex);
@@ -885,7 +913,7 @@ esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t
}
#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
- atomic_fetch_add(&loop->events_recieved, 1);
+ atomic_fetch_add(&loop->events_received, 1);
#endif
return ESP_OK;
@@ -933,7 +961,7 @@ esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, esp_event_ba
}
#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
- atomic_fetch_add(&loop->events_recieved, 1);
+ atomic_fetch_add(&loop->events_received, 1);
#endif
return ESP_OK;
@@ -962,13 +990,13 @@ esp_err_t esp_event_dump(FILE* file)
portENTER_CRITICAL(&s_event_loops_spinlock);
SLIST_FOREACH(loop_it, &s_event_loops, next) {
- uint32_t events_recieved, events_dropped;
+ uint32_t events_received, events_dropped;
- events_recieved = atomic_load(&loop_it->events_recieved);
+ events_received = atomic_load(&loop_it->events_received);
events_dropped = atomic_load(&loop_it->events_dropped);
PRINT_DUMP_INFO(dst, sz, LOOP_DUMP_FORMAT, loop_it, loop_it->task != NULL ? loop_it->name : "none",
- events_recieved, events_dropped);
+ events_received, events_dropped);
int sz_bak = sz;
diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h
index caa0f1614b..f6c6e870c1 100644
--- a/components/esp_event/private_include/esp_event_internal.h
+++ b/components/esp_event/private_include/esp_event_internal.h
@@ -76,7 +76,7 @@ typedef struct esp_event_loop_instance {
esp_event_loop_nodes_t loop_nodes; /**< set of linked lists containing the
registered handlers for the loop */
#ifdef CONFIG_ESP_EVENT_LOOP_PROFILING
- atomic_uint_least32_t events_recieved; /**< number of events successfully posted to the loop */
+ atomic_uint_least32_t events_received; /**< number of events successfully posted to the loop */
atomic_uint_least32_t events_dropped; /**< number of events dropped due to queue being full */
SemaphoreHandle_t profiling_mutex; /**< mutex used for profiliing */
SLIST_ENTRY(esp_event_loop_instance) next; /**< next event loop in the list */
diff --git a/components/esp_event/test_apps/main/test_event_common.cpp b/components/esp_event/test_apps/main/test_event_common.cpp
index bbac3490f1..9666e5470b 100644
--- a/components/esp_event/test_apps/main/test_event_common.cpp
+++ b/components/esp_event/test_apps/main/test_event_common.cpp
@@ -1597,3 +1597,49 @@ TEST_CASE("default event loop: registering event handler instance without instan
TEST_ESP_OK(esp_event_loop_delete_default());
}
+
+#if CONFIG_ESP_EVENT_LOOP_PROFILING
+static void handler_all(void* arg, esp_event_base_t event_base, int32_t event_id, void* data)
+{
+ printf("Event received: base=%s, id=%" PRId32 ", data=%p\n", event_base, event_id, data);
+}
+
+static void handler_base(void* arg, esp_event_base_t event_base, int32_t event_id, void* data)
+{
+ printf("Event received: base=%s, id=%" PRId32 ", data=%p\n", event_base, event_id, data);
+}
+
+static void handler_id(void* arg, esp_event_base_t event_base, int32_t event_id, void* data)
+{
+ printf("Event received: base=%s, id=%" PRId32 ", data=%p\n", event_base, event_id, data);
+}
+
+TEST_CASE("profiling reports valid values", "[event][default]")
+{
+ TEST_ESP_OK(esp_event_loop_create_default());
+
+ /* register handler for event base 1 and event id 1 */
+ TEST_ESP_OK(esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1, handler_id, NULL));
+
+ /* register handler for event base 1 and all event ids */
+ TEST_ESP_OK(esp_event_handler_register(s_test_base1, ESP_EVENT_ANY_ID, handler_base, NULL));
+
+ /* register handler for all event bases and all event ids */
+ TEST_ESP_OK(esp_event_handler_register(ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, handler_all, NULL));
+
+ /* post an event on event base 1, event id 1 */
+ TEST_ESP_OK(esp_event_post(s_test_base1, TEST_EVENT_BASE1_EV1, NULL, 0, pdMS_TO_TICKS(1000)));
+
+ /* post an event 1 from base 1 and check the dump.
+ * - 3 handlers invoked, exec time is not 0 */
+ esp_event_dump(stdout);
+
+ /* unregister handlers */
+ TEST_ESP_OK(esp_event_handler_unregister(ESP_EVENT_ANY_BASE, ESP_EVENT_ANY_ID, handler_all));
+ TEST_ESP_OK(esp_event_handler_unregister(s_test_base1, ESP_EVENT_ANY_ID, handler_base));
+ TEST_ESP_OK(esp_event_handler_unregister(s_test_base1, TEST_EVENT_BASE1_EV1, handler_id));
+
+ /* delete loop */
+ TEST_ESP_OK(esp_event_loop_delete_default());
+}
+#endif // CONFIG_ESP_EVENT_LOOP_PROFILING
diff --git a/components/esp_event/test_apps/pytest_esp_event.py b/components/esp_event/test_apps/pytest_esp_event.py
index 9057e2ff9f..234382e176 100644
--- a/components/esp_event/test_apps/pytest_esp_event.py
+++ b/components/esp_event/test_apps/pytest_esp_event.py
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
+# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@@ -29,3 +29,15 @@ def test_esp_event_posix_simulator(dut: Dut) -> None:
dut.expect_exact('Press ENTER to see the list of tests.')
dut.write('*')
dut.expect(r'\d{2} Tests 0 Failures 0 Ignored', timeout=120)
+
+
+@pytest.mark.esp32
+@pytest.mark.generic
+def test_esp_event_profiling(dut: Dut) -> None:
+ dut.expect_exact('Press ENTER to see the list of tests.')
+ dut.write('"profiling reports valid values"')
+ # look for all references of handlers invoked at least 1 time
+ # with an execution time superior to 0 us
+ matches = dut.expect(r'HANDLER .+ inv:[1-9][0-9]{0,} time:[1-9][0-9]{0,} us', timeout=2)
+ matches_arr = matches.group().split(b'\r\n')
+ assert (len(matches_arr) == 3)