概念

可以定义任意数量的事件对象(仅受可用 RAM 的限制)。每个事件对象都由其内存地址引用。
一个或多个线程可以等待事件对象,直到将所需的事件集传递到事件对象。将新事件传递到事件对象时,所有已满足等待条件的线程将同时准备就绪。
事件对象具有以下关键属性:

  • 一个 32 位值,用于跟踪已向其传递的事件。

必须先初始化事件对象,然后才能使用它。
事件可以由线程或 ISR 传递。传递事件时,事件可能会覆盖现有的事件集或者以按位方式添加到这些事件集。

  • 覆盖现有事件集时,这称为设置。
  • 当以按位方式添加到它们时,这被称为发布。

发布和设置事件都有可能满足等待事件对象的多个线程的匹配条件。满足匹配条件的所有线程将同时变为活动状态。
线程可能会等待一个或多个事件。他们可以等待所有请求的事件,也可以等待其中任何一个事件。此外,发出等待请求的线程可以选择在等待之前重置事件对象跟踪的当前事件集。

定义事件对象

事件对象是使用k_event类型的变量定义的。然后必须通过调用k_event_init()对其进行初始化。

  1. struct k_event my_event;
  2. k_event_init(&my_event);

也可以通过调用K_EVENT_DEFINE在编译时定义和初始化事件对象。

  1. K_EVENT_DEFINE(my_event);

设置事件

事件对象中的事件是通过调用k_event_set()来设置的。

  1. void input_available_interrupt_handler(void *arg)
  2. {
  3. /* notify threads that data is available */
  4. k_event_set(&my_event, 0x001);
  5. ...
  6. }

发布事件

通过调用k_event_post()将事件发布到事件对象。

  1. void input_available_interrupt_handler(void *arg)
  2. {
  3. ...
  4. /* notify threads that more data is available */
  5. k_event_post(&my_event, 0x120);
  6. ...
  7. }

等待事件

线程通过调用k_event_wait()来等待事件。
以下代码最多等待 50 毫秒以发布任何指定的事件。如果未及时发布任何事件,则会发出警告。

  1. void consumer_thread(void)
  2. {
  3. uint32_t events;
  4. events = k_event_wait(&my_event, 0xFFF, false, K_MSEC(50));
  5. if (events == 0) {
  6. printk("No input devices are available!");
  7. } else {
  8. /* Access the desired input device(s) */
  9. ...
  10. }
  11. ...
  12. }

或者使用者线程可能希望等待所有事件,然后再继续。

  1. void consumer_thread(void)
  2. {
  3. uint32_t events;
  4. events = k_event_wait_all(&my_event, 0x121, false, K_MSEC(50));
  5. if (events == 0) {
  6. printk("At least one input device is not available!");
  7. } else {
  8. /* Access the desired input devices */
  9. ...
  10. }
  11. ...
  12. }

事件的Kconfig

Kconfig 描述
CONFIG_EVENTS 启用事件