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