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