esp_event.h 25 KB

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