mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp_event: allow posting events from ISRs
This commit is contained in:
parent
c43a83596b
commit
2b914f2d22
@ -9,4 +9,11 @@ set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
|
|||||||
set(COMPONENT_REQUIRES log tcpip_adapter)
|
set(COMPONENT_REQUIRES log tcpip_adapter)
|
||||||
set(COMPONENT_PRIV_REQUIRES ethernet)
|
set(COMPONENT_PRIV_REQUIRES ethernet)
|
||||||
|
|
||||||
|
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
|
||||||
|
|
||||||
register_component()
|
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()
|
@ -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
|
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.
|
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
|
endmenu
|
||||||
|
@ -4,3 +4,14 @@
|
|||||||
COMPONENT_ADD_INCLUDEDIRS := include
|
COMPONENT_ADD_INCLUDEDIRS := include
|
||||||
COMPONENT_PRIV_INCLUDEDIRS := private_include
|
COMPONENT_PRIV_INCLUDEDIRS := private_include
|
||||||
COMPONENT_SRCDIRS := .
|
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
|
||||||
|
@ -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()
|
esp_err_t esp_event_loop_create_default()
|
||||||
{
|
{
|
||||||
if (s_default_loop) {
|
if (s_default_loop) {
|
||||||
|
@ -58,6 +58,8 @@ static portMUX_TYPE s_event_loops_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
|||||||
/* ------------------------- Static Functions ------------------------------- */
|
/* ------------------------- Static Functions ------------------------------- */
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
||||||
|
|
||||||
|
|
||||||
static int esp_event_dump_prepare()
|
static int esp_event_dump_prepare()
|
||||||
{
|
{
|
||||||
esp_event_loop_instance_t* loop_it;
|
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();
|
start = esp_timer_get_time();
|
||||||
#endif
|
#endif
|
||||||
// Execute the handler
|
// 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);
|
(*(handler->handler))(handler->arg, post.base, post.id, post.data);
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
||||||
diff = esp_timer_get_time() - start;
|
diff = esp_timer_get_time() - start;
|
||||||
@ -371,35 +377,19 @@ 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;
|
#if CONFIG_POST_EVENTS_FROM_ISR
|
||||||
|
if (post->data_allocd && post->data.ptr) {
|
||||||
// Make persistent copy of event data on heap.
|
free(post->data.ptr);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
memcpy(event_data_copy, event_data, event_data_size);
|
if (post->data) {
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
free(post->data);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
memset(post, 0, sizeof(*post));
|
||||||
|
}
|
||||||
|
|
||||||
/* ---------------------------- Public API --------------------------------- */
|
/* ---------------------------- 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);
|
post_instance_delete(&post);
|
||||||
|
|
||||||
if (ticks_to_run != portMAX_DELAY) {
|
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) {
|
if (!exec) {
|
||||||
// No handlers were registered, not even loop/base level handlers
|
// 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
|
// Drop existing posts on the queue
|
||||||
esp_event_post_instance_t post;
|
esp_event_post_instance_t post;
|
||||||
while(xQueueReceive(loop->queue, &post, 0) == pdTRUE) {
|
while(xQueueReceive(loop->queue, &post, 0) == pdTRUE) {
|
||||||
free(post.data);
|
post_instance_delete(&post);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup loop
|
// Cleanup loop
|
||||||
@ -735,26 +728,39 @@ esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop,
|
|||||||
return ESP_OK;
|
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,
|
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)
|
void* event_data, size_t event_data_size, TickType_t ticks_to_wait)
|
||||||
{
|
{
|
||||||
assert(event_loop);
|
assert(event_loop);
|
||||||
|
|
||||||
if (event_base == ESP_EVENT_ANY_BASE || event_id == ESP_EVENT_ANY_ID) {
|
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;
|
return ESP_ERR_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop;
|
esp_event_loop_instance_t* loop = (esp_event_loop_instance_t*) event_loop;
|
||||||
|
|
||||||
esp_event_post_instance_t post;
|
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) {
|
if (event_data != NULL && event_data_size != 0) {
|
||||||
return err;
|
// 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;
|
BaseType_t result = pdFALSE;
|
||||||
|
|
||||||
// Find the task that currently executes the loop. It is safe to query loop->task since it is
|
// Find the task that currently executes the loop. It is safe to query loop->task since it is
|
||||||
@ -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);
|
post_instance_delete(&post);
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
||||||
xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY);
|
atomic_fetch_add(&loop->events_dropped, 1);
|
||||||
loop->events_dropped++;
|
|
||||||
xSemaphoreGive(loop->profiling_mutex);
|
|
||||||
#endif
|
#endif
|
||||||
return ESP_ERR_TIMEOUT;
|
return ESP_ERR_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
||||||
xSemaphoreTake(loop->profiling_mutex, portMAX_DELAY);
|
atomic_fetch_add(&loop->events_recieved, 1);
|
||||||
loop->events_recieved++;
|
|
||||||
xSemaphoreGive(loop->profiling_mutex);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ESP_LOGD(TAG, "posted %s:%d to loop %p", post.base, post.id, event_loop);
|
|
||||||
|
|
||||||
return ESP_OK;
|
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)
|
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);
|
portENTER_CRITICAL(&s_event_loops_spinlock);
|
||||||
|
|
||||||
SLIST_FOREACH(loop_it, &s_event_loops, next) {
|
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" ,
|
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;
|
int sz_bak = sz;
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/// Configuration for creating event loops
|
/// Configuration for creating event loops
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int32_t queue_size; /**< size of the event loop queue */
|
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.
|
* handler recieves is always valid.
|
||||||
*
|
*
|
||||||
* @param[in] event_base the event base that identifies the event
|
* @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 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] event_data_size the size of the event data
|
||||||
* @param[in] ticks_to_wait number of ticks to block on a full event queue
|
* @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
|
* @return
|
||||||
* - ESP_OK: Success
|
* - 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
|
* - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
|
||||||
* - Others: Fail
|
* - 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_loop the event loop to post to
|
||||||
* @param[in] event_base the event base that identifies the event
|
* @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 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] event_data_size the size of the event data
|
||||||
* @param[in] ticks_to_wait number of ticks to block on a full event queue
|
* @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
|
* @return
|
||||||
* - ESP_OK: Success
|
* - 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
|
* - ESP_ERR_INVALID_ARG: Invalid combination of event base and event id
|
||||||
* - Others: Fail
|
* - 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,
|
size_t event_data_size,
|
||||||
TickType_t ticks_to_wait);
|
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.
|
* @brief Dumps statistics of all event loops.
|
||||||
*
|
*
|
||||||
|
6
components/esp_event/linker.lf
Normal file
6
components/esp_event/linker.lf
Normal file
@ -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)
|
@ -16,6 +16,7 @@
|
|||||||
#define ESP_EVENT_INTERNAL_H_
|
#define ESP_EVENT_INTERNAL_H_
|
||||||
|
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
|
#include "stdatomic.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
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
|
esp_event_loop_nodes_t loop_nodes; /**< set of linked lists containing the
|
||||||
registered handlers for the loop */
|
registered handlers for the loop */
|
||||||
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
#ifdef CONFIG_EVENT_LOOP_PROFILING
|
||||||
uint32_t events_recieved; /**< number of events successfully posted to the loop */
|
atomic_uint_least32_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_dropped; /**< number of events dropped due to queue being full */
|
||||||
SemaphoreHandle_t profiling_mutex; /**< mutex used for profiliing */
|
SemaphoreHandle_t profiling_mutex; /**< mutex used for profiliing */
|
||||||
SLIST_ENTRY(esp_event_loop_instance) next; /**< next event loop in the list */
|
SLIST_ENTRY(esp_event_loop_instance) next; /**< next event loop in the list */
|
||||||
#endif
|
#endif
|
||||||
} esp_event_loop_instance_t;
|
} 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
|
/// Event posted to the event queue
|
||||||
typedef struct esp_event_post_instance {
|
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 */
|
esp_event_base_t base; /**< the event base */
|
||||||
int32_t id; /**< the event id */
|
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;
|
} esp_event_post_instance_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
set(COMPONENT_SRCDIRS ".")
|
set(COMPONENT_SRCDIRS ".")
|
||||||
set(COMPONENT_PRIV_INCLUDEDIRS "../private_include" ".")
|
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()
|
register_component()
|
Loading…
x
Reference in New Issue
Block a user