1 /* 2 * SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #ifndef ESP_EVENT_H_ 8 #define ESP_EVENT_H_ 9 10 #include "esp_err.h" 11 12 13 #include "esp_event_base.h" 14 15 #ifdef __cplusplus 16 extern "C" { 17 #endif 18 19 /// Configuration for creating event loops 20 typedef struct { 21 int32_t queue_size; /**< size of the event loop queue */ 22 const char *task_name; /**< name of the event loop task; if NULL, 23 a dedicated task is not created for event loop*/ 24 unsigned int task_priority; /**< priority of the event loop task, ignored if task name is NULL */ 25 uint32_t task_stack_size; /**< stack size of the event loop task, ignored if task name is NULL */ 26 int task_core_id; /**< core to which the event loop task is pinned to, 27 ignored if task name is NULL */ 28 } esp_event_loop_args_t; 29 30 /** 31 * @brief Create a new event loop. 32 * 33 * @param[in] event_loop_args configuration structure for the event loop to create 34 * @param[out] event_loop handle to the created event loop 35 * 36 * @return 37 * - ESP_OK: Success 38 * - ESP_ERR_INVALID_ARG: event_loop_args or event_loop was NULL 39 * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list 40 * - ESP_FAIL: Failed to create task loop 41 * - Others: Fail 42 */ 43 esp_err_t esp_event_loop_create(const esp_event_loop_args_t *event_loop_args, esp_event_loop_handle_t *event_loop); 44 45 /** 46 * @brief Delete an existing event loop. 47 * 48 * @param[in] event_loop event loop to delete, must not be NULL 49 * 50 * @return 51 * - ESP_OK: Success 52 * - Others: Fail 53 */ 54 esp_err_t esp_event_loop_delete(esp_event_loop_handle_t event_loop); 55 56 /** 57 * @brief Create default event loop 58 * 59 * @return 60 * - ESP_OK: Success 61 * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list 62 * - ESP_ERR_INVALID_STATE: Default event loop has already been created 63 * - ESP_FAIL: Failed to create task loop 64 * - Others: Fail 65 */ 66 esp_err_t esp_event_loop_create_default(void); 67 68 /** 69 * @brief Delete the default event loop 70 * 71 * @return 72 * - ESP_OK: Success 73 * - Others: Fail 74 */ 75 esp_err_t esp_event_loop_delete_default(void); 76 77 /** 78 * @brief Dispatch events posted to an event loop. 79 * 80 * This function is used to dispatch events posted to a loop with no dedicated task, i.e. task name was set to NULL 81 * in event_loop_args argument during loop creation. This function includes an argument to limit the amount of time 82 * it runs, returning control to the caller when that time expires (or some time afterwards). There is no guarantee 83 * that a call to this function will exit at exactly the time of expiry. There is also no guarantee that events have 84 * been dispatched during the call, as the function might have spent all the allotted time waiting on the event queue. 85 * Once an event has been dequeued, however, it is guaranteed to be dispatched. This guarantee contributes to not being 86 * able to exit exactly at time of expiry as (1) blocking on internal mutexes is necessary for dispatching the dequeued 87 * event, and (2) during dispatch of the dequeued event there is no way to control the time occupied by handler code 88 * execution. The guaranteed time of exit is therefore the allotted time + amount of time required to dispatch 89 * the last dequeued event. 90 * 91 * In cases where waiting on the queue times out, ESP_OK is returned and not ESP_ERR_TIMEOUT, since it is 92 * normal behavior. 93 * 94 * @param[in] event_loop event loop to dispatch posted events from, must not be NULL 95 * @param[in] ticks_to_run number of ticks to run the loop 96 * 97 * @note encountering an unknown event that has been posted to the loop will only generate a warning, not an error. 98 * 99 * @return 100 * - ESP_OK: Success 101 * - Others: Fail 102 */ 103 esp_err_t esp_event_loop_run(esp_event_loop_handle_t event_loop, uint32_t ticks_to_run); 104 105 /** 106 * @brief Register an event handler to the system event loop (legacy). 107 * 108 * This function can be used to register a handler for either: (1) specific events, 109 * (2) all events of a certain event base, or (3) all events known by the system event loop. 110 * 111 * - specific events: specify exact event_base and event_id 112 * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id 113 * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id 114 * 115 * Registering multiple handlers to events is possible. Registering a single handler to multiple events is 116 * also possible. However, registering the same handler to the same event multiple times would cause the 117 * previous registrations to be overwritten. 118 * 119 * @param[in] event_base the base ID of the event to register the handler for 120 * @param[in] event_id the ID of the event to register the handler for 121 * @param[in] event_handler the handler function which gets called when the event is dispatched 122 * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called 123 * 124 * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should 125 * ensure that event_handler_arg still points to a valid location by the time the handler gets called 126 * 127 * @return 128 * - ESP_OK: Success 129 * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler 130 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 131 * - Others: Fail 132 */ 133 esp_err_t esp_event_handler_register(esp_event_base_t event_base, 134 int32_t event_id, 135 esp_event_handler_t event_handler, 136 void *event_handler_arg); 137 138 /** 139 * @brief Register an event handler to a specific loop (legacy). 140 * 141 * This function behaves in the same manner as esp_event_handler_register, except the additional 142 * specification of the event loop to register the handler to. 143 * 144 * @param[in] event_loop the event loop to register this handler function to, must not be NULL 145 * @param[in] event_base the base ID of the event to register the handler for 146 * @param[in] event_id the ID of the event to register the handler for 147 * @param[in] event_handler the handler function which gets called when the event is dispatched 148 * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called 149 * 150 * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should 151 * ensure that event_handler_arg still points to a valid location by the time the handler gets called 152 * 153 * @return 154 * - ESP_OK: Success 155 * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler 156 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 157 * - Others: Fail 158 */ 159 esp_err_t esp_event_handler_register_with(esp_event_loop_handle_t event_loop, 160 esp_event_base_t event_base, 161 int32_t event_id, 162 esp_event_handler_t event_handler, 163 void *event_handler_arg); 164 165 /** 166 * @brief Register an instance of event handler to a specific loop. 167 * 168 * This function can be used to register a handler for either: (1) specific events, 169 * (2) all events of a certain event base, or (3) all events known by the system event loop. 170 * 171 * - specific events: specify exact event_base and event_id 172 * - all events of a certain base: specify exact event_base and use ESP_EVENT_ANY_ID as the event_id 173 * - all events known by the loop: use ESP_EVENT_ANY_BASE for event_base and ESP_EVENT_ANY_ID as the event_id 174 * 175 * Besides the error, the function returns an instance object as output parameter to identify each registration. 176 * This is necessary to remove (unregister) the registration before the event loop is deleted. 177 * 178 * Registering multiple handlers to events, registering a single handler to multiple events as well as registering 179 * the same handler to the same event multiple times is possible. 180 * Each registration yields a distinct instance object which identifies it over the registration 181 * lifetime. 182 * 183 * @param[in] event_loop the event loop to register this handler function to, must not be NULL 184 * @param[in] event_base the base ID of the event to register the handler for 185 * @param[in] event_id the ID of the event to register the handler for 186 * @param[in] event_handler the handler function which gets called when the event is dispatched 187 * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called 188 * @param[out] instance An event handler instance object related to the registered event handler and data, can be NULL. 189 * This needs to be kept if the specific callback instance should be unregistered before deleting the whole 190 * event loop. Registering the same event handler multiple times is possible and yields distinct instance 191 * objects. The data can be the same for all registrations. 192 * If no unregistration is needed, but the handler should be deleted when the event loop is deleted, 193 * instance can be NULL. 194 * 195 * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should 196 * ensure that event_handler_arg still points to a valid location by the time the handler gets called 197 * 198 * @return 199 * - ESP_OK: Success 200 * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler 201 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID or instance is NULL 202 * - Others: Fail 203 */ 204 esp_err_t esp_event_handler_instance_register_with(esp_event_loop_handle_t event_loop, 205 esp_event_base_t event_base, 206 int32_t event_id, 207 esp_event_handler_t event_handler, 208 void *event_handler_arg, 209 esp_event_handler_instance_t *instance); 210 211 /** 212 * @brief Register an instance of event handler to the default loop. 213 * 214 * This function does the same as esp_event_handler_instance_register_with, except that it registers the 215 * handler to the default event loop. 216 * 217 * @param[in] event_base the base ID of the event to register the handler for 218 * @param[in] event_id the ID of the event to register the handler for 219 * @param[in] event_handler the handler function which gets called when the event is dispatched 220 * @param[in] event_handler_arg data, aside from event data, that is passed to the handler when it is called 221 * @param[out] instance An event handler instance object related to the registered event handler and data, can be NULL. 222 * This needs to be kept if the specific callback instance should be unregistered before deleting the whole 223 * event loop. Registering the same event handler multiple times is possible and yields distinct instance 224 * objects. The data can be the same for all registrations. 225 * If no unregistration is needed, but the handler should be deleted when the event loop is deleted, 226 * instance can be NULL. 227 * 228 * @note the event loop library does not maintain a copy of event_handler_arg, therefore the user should 229 * ensure that event_handler_arg still points to a valid location by the time the handler gets called 230 * 231 * @return 232 * - ESP_OK: Success 233 * - ESP_ERR_NO_MEM: Cannot allocate memory for the handler 234 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID or instance is NULL 235 * - Others: Fail 236 */ 237 esp_err_t esp_event_handler_instance_register(esp_event_base_t event_base, 238 int32_t event_id, 239 esp_event_handler_t event_handler, 240 void *event_handler_arg, 241 esp_event_handler_instance_t *instance); 242 243 /** 244 * @brief Unregister a handler with the system event loop (legacy). 245 * 246 * Unregisters a handler, so it will no longer be called during dispatch. 247 * Handlers can be unregistered for any combination of event_base and event_id which were previously registered. 248 * To unregister a handler, the event_base and event_id arguments must match exactly the arguments passed to 249 * esp_event_handler_register() when that handler was registered. Passing ESP_EVENT_ANY_BASE and/or ESP_EVENT_ANY_ID 250 * will only unregister handlers that were registered with the same wildcard arguments. 251 * 252 * @note When using ESP_EVENT_ANY_ID, handlers registered to specific event IDs using the same base will not be 253 * unregistered. When using ESP_EVENT_ANY_BASE, events registered to specific bases will also not be 254 * unregistered. This avoids accidental unregistration of handlers registered by other users or components. 255 * 256 * @param[in] event_base the base of the event with which to unregister the handler 257 * @param[in] event_id the ID of the event with which to unregister the handler 258 * @param[in] event_handler the handler to unregister 259 * 260 * @return ESP_OK success 261 * @return ESP_ERR_INVALID_ARG invalid combination of event base and event ID 262 * @return others fail 263 */ 264 esp_err_t esp_event_handler_unregister(esp_event_base_t event_base, 265 int32_t event_id, 266 esp_event_handler_t event_handler); 267 268 /** 269 * @brief Unregister a handler from a specific event loop (legacy). 270 * 271 * This function behaves in the same manner as esp_event_handler_unregister, except the additional specification of 272 * the event loop to unregister the handler with. 273 * 274 * @param[in] event_loop the event loop with which to unregister this handler function, must not be NULL 275 * @param[in] event_base the base of the event with which to unregister the handler 276 * @param[in] event_id the ID of the event with which to unregister the handler 277 * @param[in] event_handler the handler to unregister 278 * 279 * @return 280 * - ESP_OK: Success 281 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 282 * - Others: Fail 283 */ 284 esp_err_t esp_event_handler_unregister_with(esp_event_loop_handle_t event_loop, 285 esp_event_base_t event_base, 286 int32_t event_id, 287 esp_event_handler_t event_handler); 288 289 /** 290 * @brief Unregister a handler instance from a specific event loop. 291 * 292 * Unregisters a handler instance, so it will no longer be called during dispatch. 293 * Handler instances can be unregistered for any combination of event_base and event_id which were previously 294 * registered. To unregister a handler instance, the event_base and event_id arguments must match exactly the 295 * arguments passed to esp_event_handler_instance_register() when that handler instance was registered. 296 * Passing ESP_EVENT_ANY_BASE and/or ESP_EVENT_ANY_ID will only unregister handler instances that were registered 297 * with the same wildcard arguments. 298 * 299 * @note When using ESP_EVENT_ANY_ID, handlers registered to specific event IDs using the same base will not be 300 * unregistered. When using ESP_EVENT_ANY_BASE, events registered to specific bases will also not be 301 * unregistered. This avoids accidental unregistration of handlers registered by other users or components. 302 * 303 * @param[in] event_loop the event loop with which to unregister this handler function, must not be NULL 304 * @param[in] event_base the base of the event with which to unregister the handler 305 * @param[in] event_id the ID of the event with which to unregister the handler 306 * @param[in] instance the instance object of the registration to be unregistered 307 * 308 * @return 309 * - ESP_OK: Success 310 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 311 * - Others: Fail 312 */ 313 esp_err_t esp_event_handler_instance_unregister_with(esp_event_loop_handle_t event_loop, 314 esp_event_base_t event_base, 315 int32_t event_id, 316 esp_event_handler_instance_t instance); 317 318 /** 319 * @brief Unregister a handler from the system event loop. 320 * 321 * This function does the same as esp_event_handler_instance_unregister_with, except that it unregisters the 322 * handler instance from the default event loop. 323 * 324 * @param[in] event_base the base of the event with which to unregister the handler 325 * @param[in] event_id the ID of the event with which to unregister the handler 326 * @param[in] instance the instance object of the registration to be unregistered 327 * 328 * @return 329 * - ESP_OK: Success 330 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 331 * - Others: Fail 332 */ 333 esp_err_t esp_event_handler_instance_unregister(esp_event_base_t event_base, 334 int32_t event_id, 335 esp_event_handler_instance_t instance); 336 337 /** 338 * @brief Posts an event to the system default event loop. The event loop library keeps a copy of event_data and manages 339 * the copy's lifetime automatically (allocation + deletion); this ensures that the data the 340 * handler receives is always valid. 341 * 342 * @param[in] event_base the event base that identifies the event 343 * @param[in] event_id the event ID that identifies the event 344 * @param[in] event_data the data, specific to the event occurrence, that gets passed to the handler 345 * @param[in] event_data_size the size of the event data 346 * @param[in] ticks_to_wait number of ticks to block on a full event queue 347 * 348 * @return 349 * - ESP_OK: Success 350 * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, 351 * queue full when posting from ISR 352 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 353 * - Others: Fail 354 */ 355 esp_err_t esp_event_post(esp_event_base_t event_base, 356 int32_t event_id, 357 const void *event_data, 358 size_t event_data_size, 359 uint32_t ticks_to_wait); 360 361 /** 362 * @brief Posts an event to the specified event loop. The event loop library keeps a copy of event_data and manages 363 * the copy's lifetime automatically (allocation + deletion); this ensures that the data the 364 * handler receives is always valid. 365 * 366 * This function behaves in the same manner as esp_event_post, except the additional specification of the event loop 367 * to post the event to. 368 * 369 * @param[in] event_loop the event loop to post to, must not be NULL 370 * @param[in] event_base the event base that identifies the event 371 * @param[in] event_id the event ID that identifies the event 372 * @param[in] event_data the data, specific to the event occurrence, that gets passed to the handler 373 * @param[in] event_data_size the size of the event data 374 * @param[in] ticks_to_wait number of ticks to block on a full event queue 375 * 376 * @return 377 * - ESP_OK: Success 378 * - ESP_ERR_TIMEOUT: Time to wait for event queue to unblock expired, 379 * queue full when posting from ISR 380 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID 381 * - Others: Fail 382 */ 383 esp_err_t esp_event_post_to(esp_event_loop_handle_t event_loop, 384 esp_event_base_t event_base, 385 int32_t event_id, 386 const void *event_data, 387 size_t event_data_size, 388 uint32_t ticks_to_wait); 389 390 #if CONFIG_ESP_EVENT_POST_FROM_ISR 391 /** 392 * @brief Special variant of esp_event_post for posting events from interrupt handlers. 393 * 394 * @param[in] event_base the event base that identifies the event 395 * @param[in] event_id the event ID that identifies the event 396 * @param[in] event_data the data, specific to the event occurrence, that gets passed to the handler 397 * @param[in] event_data_size the size of the event data; max is 4 bytes 398 * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with 399 * higher priority than currently running task has been unblocked by the posted event; 400 * a context switch should be requested before the interrupt is existed. 401 * 402 * @note this function is only available when CONFIG_ESP_EVENT_POST_FROM_ISR is enabled 403 * @note when this function is called from an interrupt handler placed in IRAM, this function should 404 * be placed in IRAM as well by enabling CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 405 * 406 * @return 407 * - ESP_OK: Success 408 * - ESP_FAIL: Event queue for the default event loop full 409 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID, 410 * data size of more than 4 bytes 411 * - Others: Fail 412 */ 413 esp_err_t esp_event_isr_post(esp_event_base_t event_base, 414 int32_t event_id, 415 const void *event_data, 416 size_t event_data_size, 417 int *task_unblocked); 418 419 /** 420 * @brief Special variant of esp_event_post_to for posting events from interrupt handlers 421 * 422 * @param[in] event_loop the event loop to post to, must not be NULL 423 * @param[in] event_base the event base that identifies the event 424 * @param[in] event_id the event ID that identifies the event 425 * @param[in] event_data the data, specific to the event occurrence, that gets passed to the handler 426 * @param[in] event_data_size the size of the event data 427 * @param[out] task_unblocked an optional parameter (can be NULL) which indicates that an event task with 428 * higher priority than currently running task has been unblocked by the posted event; 429 * a context switch should be requested before the interrupt is existed. 430 * 431 * @note this function is only available when CONFIG_ESP_EVENT_POST_FROM_ISR is enabled 432 * @note when this function is called from an interrupt handler placed in IRAM, this function should 433 * be placed in IRAM as well by enabling CONFIG_ESP_EVENT_POST_FROM_IRAM_ISR 434 * 435 * @return 436 * - ESP_OK: Success 437 * - ESP_FAIL: Event queue for the loop full 438 * - ESP_ERR_INVALID_ARG: Invalid combination of event base and event ID, 439 * data size of more than 4 bytes 440 * - Others: Fail 441 */ 442 esp_err_t esp_event_isr_post_to(esp_event_loop_handle_t event_loop, 443 esp_event_base_t event_base, 444 int32_t event_id, 445 const void *event_data, 446 size_t event_data_size, 447 int *task_unblocked); 448 #endif 449 450 /** 451 * @brief Dumps statistics of all event loops. 452 * 453 * Dumps event loop info in the format: 454 * 455 @verbatim 456 event loop 457 handler 458 handler 459 ... 460 event loop 461 handler 462 handler 463 ... 464 465 where: 466 467 event loop 468 format: address,name rx:total_received dr:total_dropped 469 where: 470 address - memory address of the event loop 471 name - name of the event loop, 'none' if no dedicated task 472 total_received - number of successfully posted events 473 total_dropped - number of events unsuccessfully posted due to queue being full 474 475 handler 476 format: address ev:base,id inv:total_invoked run:total_runtime 477 where: 478 address - address of the handler function 479 base,id - the event specified by event base and ID this handler executes 480 total_invoked - number of times this handler has been invoked 481 total_runtime - total amount of time used for invoking this handler 482 483 @endverbatim 484 * 485 * @param[in] file the file stream to output to 486 * 487 * @note this function is a noop when CONFIG_ESP_EVENT_LOOP_PROFILING is disabled 488 * 489 * @return 490 * - ESP_OK: Success 491 * - ESP_ERR_NO_MEM: Cannot allocate memory for event loops list 492 * - Others: Fail 493 */ 494 esp_err_t esp_event_dump(FILE *file); 495 496 #ifdef __cplusplus 497 } // extern "C" 498 #endif 499 500 #endif // #ifndef ESP_EVENT_H_ 501