From c43a83596b8cd842444f25ca6b7be6194dc7c64a Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Wed, 10 Apr 2019 09:00:35 +0800 Subject: [PATCH 1/3] ci: add unit test job --- .gitlab-ci.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bc8bff3485..6eb2daf5cd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1521,6 +1521,13 @@ UT_004_16: - UT_T1_1 - psram +UT_004_17: + <<: *unit_test_template + tags: + - ESP32_IDF + - UT_T1_1 + - psram + UT_005_01: <<: *unit_test_template tags: From 2b914f2d2222b507bed0db65e1cdced13ee02589 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Fri, 15 Feb 2019 21:28:24 +0800 Subject: [PATCH 2/3] esp_event: allow posting events from ISRs --- components/esp_event/CMakeLists.txt | 7 + components/esp_event/Kconfig | 14 ++ components/esp_event/component.mk | 13 +- components/esp_event/default_event_loop.c | 14 ++ components/esp_event/esp_event.c | 136 ++++++++++++------ components/esp_event/include/esp_event.h | 74 ++++++++-- components/esp_event/linker.lf | 6 + .../private_include/esp_event_internal.h | 19 ++- components/esp_event/test/CMakeLists.txt | 2 +- 9 files changed, 229 insertions(+), 56 deletions(-) create mode 100644 components/esp_event/linker.lf diff --git a/components/esp_event/CMakeLists.txt b/components/esp_event/CMakeLists.txt index 999e7f2fdf..b30234c955 100644 --- a/components/esp_event/CMakeLists.txt +++ b/components/esp_event/CMakeLists.txt @@ -9,4 +9,11 @@ set(COMPONENT_PRIV_INCLUDEDIRS "private_include") set(COMPONENT_REQUIRES log tcpip_adapter) set(COMPONENT_PRIV_REQUIRES ethernet) +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) + register_component() + +if(GCC_NOT_5_2_0 AND CONFIG_EVENT_LOOP_PROFILING) + # uses C11 atomic feature + set_source_files_properties(esp_event.c PROPERTIES COMPILE_FLAGS -std=gnu11) +endif() \ No newline at end of file diff --git a/components/esp_event/Kconfig b/components/esp_event/Kconfig index e14e1e732c..f90f792f20 100644 --- a/components/esp_event/Kconfig +++ b/components/esp_event/Kconfig @@ -8,4 +8,18 @@ menu "Event Loop Library" to/recieved by an event loop, number of callbacks involved, number of events dropped to to a full event loop queue, run time of event handlers, and number of times/run time of each event handler. + config POST_EVENTS_FROM_ISR + bool "Support posting events from ISRs" + default y + help + Enable posting events from interrupt handlers. + + config POST_EVENTS_FROM_IRAM_ISR + bool "Support posting events from ISRs placed in IRAM" + default y + depends on POST_EVENTS_FROM_ISR + help + Enable posting events from interrupt handlers placed in IRAM. Enabling this option places API functions + esp_event_post and esp_event_post_to in IRAM. + endmenu diff --git a/components/esp_event/component.mk b/components/esp_event/component.mk index 05135a2750..fd3f6fa715 100644 --- a/components/esp_event/component.mk +++ b/components/esp_event/component.mk @@ -3,4 +3,15 @@ # COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := private_include -COMPONENT_SRCDIRS := . \ No newline at end of file +COMPONENT_SRCDIRS := . + +ifdef CONFIG_EVENT_LOOP_PROFILING + PROFILING_ENABLED := 1 +else + PROFILING_ENABLED := 0 +endif + +ifeq ($(and $(GCC_NOT_5_2_0),$(PROFILING_ENABLED)), 1) +# uses C11 atomic feature +esp_event.o: CFLAGS += -std=gnu11 +endif diff --git a/components/esp_event/default_event_loop.c b/components/esp_event/default_event_loop.c index 91fb789277..3daf5ab8d0 100644 --- a/components/esp_event/default_event_loop.c +++ b/components/esp_event/default_event_loop.c @@ -55,6 +55,20 @@ esp_err_t esp_event_post(esp_event_base_t event_base, int32_t event_id, } +#if CONFIG_POST_EVENTS_FROM_ISR +esp_err_t esp_event_isr_post(esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, BaseType_t* task_unblocked) +{ + if (s_default_loop == NULL) { + return ESP_ERR_INVALID_STATE; + } + + return esp_event_isr_post_to(s_default_loop, event_base, event_id, + event_data, event_data_size, task_unblocked); +} +#endif + + esp_err_t esp_event_loop_create_default() { if (s_default_loop) { diff --git a/components/esp_event/esp_event.c b/components/esp_event/esp_event.c index d9f65c4a2f..19bf1d8ccd 100644 --- a/components/esp_event/esp_event.c +++ b/components/esp_event/esp_event.c @@ -58,6 +58,8 @@ static portMUX_TYPE s_event_loops_spinlock = portMUX_INITIALIZER_UNLOCKED; /* ------------------------- Static Functions ------------------------------- */ #ifdef CONFIG_EVENT_LOOP_PROFILING + + static int esp_event_dump_prepare() { esp_event_loop_instance_t* loop_it; @@ -129,7 +131,11 @@ static void handler_execute(esp_event_loop_instance_t* loop, esp_event_handler_i start = esp_timer_get_time(); #endif // Execute the handler +#if CONFIG_POST_EVENTS_FROM_ISR + (*(handler->handler))(handler->arg, post.base, post.id, post.data_allocd ? post.data.ptr : &post.data.val); +#else (*(handler->handler))(handler->arg, post.base, post.id, post.data); +#endif #ifdef CONFIG_EVENT_LOOP_PROFILING diff = esp_timer_get_time() - start; @@ -371,34 +377,18 @@ static void loop_node_remove_all_handler(esp_event_loop_node_t* loop_node) } } -static esp_err_t post_instance_create(esp_event_base_t event_base, int32_t event_id, void* event_data, int32_t event_data_size, esp_event_post_instance_t* post) +static void inline __attribute__((always_inline)) post_instance_delete(esp_event_post_instance_t* post) { - void* event_data_copy = NULL; - - // Make persistent copy of event data on heap. - if (event_data != NULL && event_data_size != 0) { - event_data_copy = calloc(1, event_data_size); - - if (event_data_copy == NULL) { - ESP_LOGE(TAG, "alloc for post data to event %s:%d failed", event_base, event_id); - return ESP_ERR_NO_MEM; - } - - memcpy(event_data_copy, event_data, event_data_size); +#if CONFIG_POST_EVENTS_FROM_ISR + if (post->data_allocd && post->data.ptr) { + free(post->data.ptr); } - - post->base = event_base; - post->id = event_id; - post->data = event_data_copy; - - ESP_LOGD(TAG, "created post for event %s:%d", event_base, event_id); - - return ESP_OK; -} - -static void post_instance_delete(esp_event_post_instance_t* post) -{ - free(post->data); +#else + if (post->data) { + free(post->data); + } +#endif + memset(post, 0, sizeof(*post)); } /* ---------------------------- Public API --------------------------------- */ @@ -556,6 +546,9 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick } } + esp_event_base_t base = post.base; + int32_t id = post.id; + post_instance_delete(&post); if (ticks_to_run != portMAX_DELAY) { @@ -576,7 +569,7 @@ esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, TickType_t tick if (!exec) { // No handlers were registered, not even loop/base level handlers - ESP_LOGW(TAG, "no handlers have been registered for event %s:%d posted to loop %p", post.base, post.id, event_loop); + ESP_LOGW(TAG, "no handlers have been registered for event %s:%d posted to loop %p", base, id, event_loop); } } @@ -618,7 +611,7 @@ esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop) // Drop existing posts on the queue esp_event_post_instance_t post; while(xQueueReceive(loop->queue, &post, 0) == pdTRUE) { - free(post.data); + post_instance_delete(&post); } // Cleanup loop @@ -735,25 +728,38 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, return ESP_OK; } - esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, void* event_data, size_t event_data_size, TickType_t ticks_to_wait) { assert(event_loop); if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) { - ESP_LOGE(TAG, "posting nonspecific event base or id unsupported"); return ESP_ERR_INVALID_ARG; } esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; esp_event_post_instance_t post; - esp_err_t err = post_instance_create(event_base, event_id, event_data, event_data_size, &post); + memset((void*)(&(post.data)), 0, sizeof(post.data)); - if (err != ESP_OK) { - return err; + if (event_data != NULL && event_data_size != 0) { + // Make persistent copy of event data on heap. + void* event_data_copy = calloc(1, event_data_size); + + if (event_data_copy == NULL) { + return ESP_ERR_NO_MEM; + } + + memcpy(event_data_copy, event_data, event_data_size); +#if CONFIG_POST_EVENTS_FROM_ISR + post.data.ptr = event_data_copy; + post.data_allocd = true; +#else + post.data = event_data_copy; +#endif } + post.base = event_base; + post.id = event_id; BaseType_t result = pdFALSE; @@ -785,24 +791,65 @@ esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t post_instance_delete(&post); #ifdef CONFIG_EVENT_LOOP_PROFILING - xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY); - loop->events_dropped++; - xSemaphoreGive(loop->profiling_mutex); + atomic_fetch_add(&loop->events_dropped, 1); #endif return ESP_ERR_TIMEOUT; } #ifdef CONFIG_EVENT_LOOP_PROFILING - xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY); - loop->events_recieved++; - xSemaphoreGive(loop->profiling_mutex); + atomic_fetch_add(&loop->events_recieved, 1); #endif - ESP_LOGD(TAG, "posted %s:%d to loop %p", post.base, post.id, event_loop); - return ESP_OK; } +#if CONFIG_POST_EVENTS_FROM_ISR +esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, esp_event_base_t event_base, int32_t event_id, + void* event_data, size_t event_data_size, BaseType_t* task_unblocked) +{ + assert(event_loop); + + if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) { + return ESP_ERR_INVALID_ARG; + } + + esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop; + + esp_event_post_instance_t post; + memset((void*)(&(post.data)), 0, sizeof(post.data)); + + if (event_data_size > sizeof(post.data.val)) { + return ESP_ERR_INVALID_ARG; + } + + if (event_data != NULL && event_data_size != 0) { + memcpy((void*)(&(post.data.val)), event_data, event_data_size); + post.data_allocd = false; + } + post.base = event_base; + post.id = event_id; + + BaseType_t result = pdFALSE; + + // Post the event from an ISR, + result = xQueueSendToBackFromISR(loop->queue, &post, task_unblocked); + + if (result != pdTRUE) { + post_instance_delete(&post); + +#ifdef CONFIG_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_dropped, 1); +#endif + return ESP_FAIL; + } + +#ifdef CONFIG_EVENT_LOOP_PROFILING + atomic_fetch_add(&loop->events_recieved, 1); +#endif + + return ESP_OK; +} +#endif esp_err_t esp_event_dump(FILE* file) { @@ -826,8 +873,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; + + events_recieved = atomic_load(&loop_it->events_recieved); + 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" , - loop_it->events_recieved, loop_it->events_dropped); + events_recieved, events_dropped); int sz_bak = sz; diff --git a/components/esp_event/include/esp_event.h b/components/esp_event/include/esp_event.h index f97deaf8b4..824266512a 100644 --- a/components/esp_event/include/esp_event.h +++ b/components/esp_event/include/esp_event.h @@ -29,7 +29,6 @@ extern "C" { #endif - /// Configuration for creating event loops typedef struct { int32_t queue_size; /**< size of the event loop queue */ @@ -224,16 +223,15 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, * handler recieves is always valid. * * @param[in] event_base the event base that identifies the event - * @param[in] event_id the the event id that identifies the event + * @param[in] event_id the event id that identifies the event * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler * @param[in] event_data_size the size of the event data * @param[in] ticks_to_wait number of ticks to block on a full event queue * - * @note posting events from an ISR is not supported - * * @return * - ESP_OK: Success - * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * queue full when posting from ISR * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ @@ -253,16 +251,15 @@ esp_err_t esp_event_post(esp_event_base_t event_base, * * @param[in] event_loop the event loop to post to * @param[in] event_base the event base that identifies the event - * @param[in] event_id the the event id that identifies the event + * @param[in] event_id the event id that identifies the event * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler * @param[in] event_data_size the size of the event data * @param[in] ticks_to_wait number of ticks to block on a full event queue * - * @note posting events from an ISR is not supported - * * @return * - ESP_OK: Success - * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired + * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, + * queue full when posting from ISR * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id * - Others: Fail */ @@ -273,6 +270,65 @@ esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, size_t event_data_size, TickType_t ticks_to_wait); +#if CONFIG_POST_EVENTS_FROM_ISR +/** + * @brief Special variant of esp_event_post for posting events from interrupt handlers. + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data; max is 4 bytes + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * higher priority than currently running task has been unblocked by the posted event; + * a context switch should be requested before the interrupt is existed. + * + * @note this function is only available when CONFIG_POST_EVENTS_FROM_ISR is enabled + * @note when this function is called from an interrupt handler placed in IRAM, this function should + * be placed in IRAM as well by enabling CONFIG_POST_EVENTS_FROM_IRAM_ISR + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Event queue for the default event loop full + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, + * data size of more than 4 bytes + * - Others: Fail + */ +esp_err_t esp_event_isr_post(esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + BaseType_t* task_unblocked); + +/** + * @brief Special variant of esp_event_post_to for posting events from interrupt handlers + * + * @param[in] event_base the event base that identifies the event + * @param[in] event_id the event id that identifies the event + * @param[in] event_data the data, specific to the event occurence, that gets passed to the handler + * @param[in] event_data_size the size of the event data + * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with + * higher priority than currently running task has been unblocked by the posted event; + * a context switch should be requested before the interrupt is existed. + * + * @note this function is only available when CONFIG_POST_EVENTS_FROM_ISR is enabled + * @note when this function is called from an interrupt handler placed in IRAM, this function should + * be placed in IRAM as well by enabling CONFIG_POST_EVENTS_FROM_IRAM_ISR + * + * @return + * - ESP_OK: Success + * - ESP_FAIL: Event queue for the loop full + * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id, + * data size of more than 4 bytes + * - Others: Fail + */ +esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, + esp_event_base_t event_base, + int32_t event_id, + void* event_data, + size_t event_data_size, + BaseType_t* task_unblocked); +#endif + /** * @brief Dumps statistics of all event loops. * diff --git a/components/esp_event/linker.lf b/components/esp_event/linker.lf new file mode 100644 index 0000000000..fb02ff7a9d --- /dev/null +++ b/components/esp_event/linker.lf @@ -0,0 +1,6 @@ +if POST_EVENTS_FROM_IRAM_ISR = y: + [mapping:esp_event] + archive: libesp_event.a + entries: + esp_event:esp_event_isr_post_to (noflash) + default_event_loop:esp_event_isr_post (noflash) \ No newline at end of file diff --git a/components/esp_event/private_include/esp_event_internal.h b/components/esp_event/private_include/esp_event_internal.h index 734def5868..4566ae1bf8 100644 --- a/components/esp_event/private_include/esp_event_internal.h +++ b/components/esp_event/private_include/esp_event_internal.h @@ -16,6 +16,7 @@ #define ESP_EVENT_INTERNAL_H_ #include "esp_event.h" +#include "stdatomic.h" #ifdef __cplusplus extern "C" { @@ -77,18 +78,30 @@ 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_EVENT_LOOP_PROFILING - uint32_t events_recieved; /**< number of events successfully posted to the loop */ - uint32_t events_dropped; /**< number of events dropped due to queue being full */ + atomic_uint_least32_t events_recieved; /**< 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 */ #endif } esp_event_loop_instance_t; +#if CONFIG_POST_EVENTS_FROM_ISR +typedef union esp_event_post_data { + uint32_t val; + void *ptr; +} esp_event_post_data_t; +#else +typedef void* esp_event_post_data_t; +#endif + /// Event posted to the event queue typedef struct esp_event_post_instance { +#if CONFIG_POST_EVENTS_FROM_ISR + bool data_allocd; /**< indicates whether data is alloc'd */ +#endif esp_event_base_t base; /**< the event base */ int32_t id; /**< the event id */ - void* data; /**< data associated with the event */ + esp_event_post_data_t data; /**< data associated with the event */ } esp_event_post_instance_t; #ifdef __cplusplus diff --git a/components/esp_event/test/CMakeLists.txt b/components/esp_event/test/CMakeLists.txt index 96543b6215..287a2ba928 100644 --- a/components/esp_event/test/CMakeLists.txt +++ b/components/esp_event/test/CMakeLists.txt @@ -1,5 +1,5 @@ set(COMPONENT_SRCDIRS ".") set(COMPONENT_PRIV_INCLUDEDIRS "../private_include" ".") -set(COMPONENT_PRIV_REQUIRES unity test_utils esp_event) +set(COMPONENT_PRIV_REQUIRES unity test_utils esp_event driver) register_component() \ No newline at end of file From 659f1a12532132dd42046325d9451f09da38cd72 Mon Sep 17 00:00:00 2001 From: Renz Christian Bagaporo Date: Tue, 12 Mar 2019 21:53:39 +0800 Subject: [PATCH 3/3] esp_event: test posting from interrupt handler --- components/esp_event/test/test_event.c | 84 ++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/components/esp_event/test/test_event.c b/components/esp_event/test/test_event.c index 9805bd2e0b..b26877342a 100644 --- a/components/esp_event/test/test_event.c +++ b/components/esp_event/test/test_event.c @@ -7,7 +7,11 @@ #include "freertos/FreeRTOS.h" #include "esp_event_loop.h" #include "freertos/task.h" +#include "freertos/portmacro.h" #include "esp_log.h" +#include "soc/timer_group_struct.h" +#include "driver/periph_ctrl.h" +#include "driver/timer.h" #include "esp_event.h" #include "esp_event_private.h" @@ -268,6 +272,48 @@ static void test_teardown() TEST_ASSERT_EQUAL(ESP_OK, esp_event_loop_delete_default()); } +#define TIMER_DIVIDER 16 // Hardware timer clock divider +#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) // convert counter value to seconds +#define TIMER_INTERVAL0_SEC (2.0) // sample test interval for the first timer + +#if CONFIG_POST_EVENTS_FROM_ISR +static void test_handler_post_from_isr(void* event_handler_arg, esp_event_base_t event_base, int32_t event_id, void* event_data) +{ + SemaphoreHandle_t *sem = (SemaphoreHandle_t*) event_handler_arg; + // Event data is just the address value (maybe have been truncated due to casting). + int *data = (int*) event_data; + TEST_ASSERT_EQUAL(*data, (int) (*sem)); + xSemaphoreGive(*sem); +} +#endif + +#if CONFIG_POST_EVENTS_FROM_ISR +void IRAM_ATTR test_event_on_timer_alarm(void* para) +{ + /* Retrieve the interrupt status and the counter value + from the timer that reported the interrupt */ + TIMERG0.hw_timer[TIMER_0].update = 1; + uint64_t timer_counter_value = + ((uint64_t) TIMERG0.hw_timer[TIMER_0].cnt_high) << 32 + | TIMERG0.hw_timer[TIMER_0].cnt_low; + + TIMERG0.int_clr_timers.t0 = 1; + timer_counter_value += (uint64_t) (TIMER_INTERVAL0_SEC * TIMER_SCALE); + TIMERG0.hw_timer[TIMER_0].alarm_high = (uint32_t) (timer_counter_value >> 32); + TIMERG0.hw_timer[TIMER_0].alarm_low = (uint32_t) timer_counter_value; + + int data = (int) para; + // Posting events with data more than 4 bytes should fail. + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, 5, NULL)); + // This should succeedd, as data is int-sized. The handler for the event checks that the passed event data + // is correct. + BaseType_t task_unblocked; + TEST_ASSERT_EQUAL(ESP_OK, esp_event_isr_post(s_test_base1, TEST_EVENT_BASE1_EV1, &data, sizeof(data), &task_unblocked)); + if (task_unblocked == pdTRUE) { + portYIELD_FROM_ISR(); + } +} +#endif //CONFIG_POST_EVENTS_FROM_ISR TEST_CASE("can create and delete event loops", "[event]") { @@ -1102,6 +1148,44 @@ TEST_CASE("events are dispatched in the order they are registered", "[event]") TEST_TEARDOWN(); } +#if CONFIG_POST_EVENTS_FROM_ISR +TEST_CASE("can post events from interrupt handler", "[event]") +{ + SemaphoreHandle_t sem = xSemaphoreCreateBinary(); + + /* Select and initialize basic parameters of the timer */ + timer_config_t config; + config.divider = TIMER_DIVIDER; + config.counter_dir = TIMER_COUNT_UP; + config.counter_en = TIMER_PAUSE; + config.alarm_en = TIMER_ALARM_EN; + config.intr_type = TIMER_INTR_LEVEL; + config.auto_reload = false; + timer_init(TIMER_GROUP_0, TIMER_0, &config); + + /* Timer's counter will initially start from value below. + Also, if auto_reload is set, this value will be automatically reload on alarm */ + timer_set_counter_value(TIMER_GROUP_0, TIMER_0, 0x00000000ULL); + + /* Configure the alarm value and the interrupt on alarm. */ + timer_set_alarm_value(TIMER_GROUP_0, TIMER_0, TIMER_INTERVAL0_SEC * TIMER_SCALE); + timer_enable_intr(TIMER_GROUP_0, TIMER_0); + timer_isr_register(TIMER_GROUP_0, TIMER_0, test_event_on_timer_alarm, + (void *) sem, ESP_INTR_FLAG_IRAM, NULL); + + timer_start(TIMER_GROUP_0, TIMER_0); + + TEST_SETUP(); + + TEST_ASSERT_EQUAL(ESP_OK, esp_event_handler_register(s_test_base1, TEST_EVENT_BASE1_EV1, + test_handler_post_from_isr, &sem)); + + xSemaphoreTake(sem, portMAX_DELAY); + + TEST_TEARDOWN(); +} +#endif + #ifdef CONFIG_EVENT_LOOP_PROFILING TEST_CASE("can dump event loop profile", "[event]") {