事件为线程间的通信和同步提供了一种手段。它和Semaphores类似,除了它们允许你在等待线程返回之前可以指定必须发生的多个条件(“事件”)。
事件实例和Semaphore一样使用“pend”和“post”调用。然而调用Event_pend()需附加指定等待哪个事件,调用Event_post()需指定提交的事件是哪个。
注意:每次只有单个Task可以等待一个事件对象。
单个事件实例可管理最多32个事件,每个事件都用一个事件ID代表。事件ID是简单的比特掩码,对应着一个由事件对象管理的唯一事件。
事件的行为和二元semaphore类似。
Event_pend()有两个参数"andMask"和"orMask"。andMask由所有必须发生的事件的事件ID组成,orMask由所有事件中的必须发生的那个一个事件的事件ID组成。
和Semaphonres一样,调用Event_pend()时携带一个timeout参数,如果调用超时则返回0。如果调用 Event_pend()成功,则返回"消耗"掉的事件掩码-----也就是满足 Event_pend()的调用所发生的事件。然后该任务处理所有消耗掉的事件。
Event_pend()原型如下:
UInt Event_pend(Event_Handle event,
UInt andMask, UInt orMask, UInt timeout); |
Event_post()原型如下:
Void Event_post(Event_Handle event,
UInt eventIds); |
配置实例:以下配置声明静态地创建了一个事件。事件对象的Event_Handle名称为“myEvent”:
var Event = xdc.useModule(
"ti.sysbios.knl.Event");
Program.global.myEvent = Event.create(); |
运行时实例:以下C代码创建了一个事件对象,Event_Handle名称为“myEvent”:
Event_Handle myEvent;
Error_Block eb; Error_init(&eb); /* Default instance configuration params */ myEvent = Event_create( NULL, &eb); if (myEvent == NULL) { System_abort( "Event create failed"); } |
运行时实例:以下是一个事件的C代码。它仅在events 0和6都发生时才唤醒task。它设置andMash为Event_Id_00 和Event_Id_06,并设置orMash为Event_Id_NONE。
Event_pend(myEvent, (Event_Id_00 + Event_Id_06), Event_Id_NONE,
BIOS_WAIT_FOREVER); |
运行时实例:以下C代码调用Event_post()来表明发生哪个事件。eventMash应包含被提交的事件的IDs。
Event_post(myEvent, Event_Id_00);
|
运行时实例:以下C代码演示了task如何为三个中断服务程序提供后台运行的需要:
Event_Handle myEvent;
main() { ... /* create an Event object. All events are binary */ myEvent = Event_create( NULL, &eb); if (myEvent == NULL) { System_abort( "Event create failed"); } } isr0() { ... Event_post(myEvent, Event_Id_00); ... } isr1() { ... Event_post(myEvent, Event_Id_01); ... } isr2() { ... Event_post(myEvent, Event_Id_02); ... } task() { UInt events; while (TRUE) { /* Wait for ANY of the ISR events to be posted * events = Event_pend(myEvent, Event_Id_NONE, Event_Id_00 + Event_Id_01 + Event_Id_02, BIOS_WAIT_FOREVER); /* Process all the events that have occurred */ if (events & Event_Id_00) { processISR0(); } if (events & Event_Id_01) { processISR1(); } if (events & Event_Id_02) { processISR2(); } } } |
4.2.1 隐式提交事件
除了支持通过Event_post() API显示提交事件之外,一些SYS/BIOS对象还支持隐式提交它们所关联的事件。例如,Mailbox(邮箱)就可配置为
无论何时,只要获得信息(就是调用了Mailbox_post())都可
提交一个关联事件,这使得task可以阻塞以等待Mailbox信息或其它事件的发生。
Mailbox和Semaphore对象现在支持在所关联的资源可用时提交事件。
支持隐式事件提交的SYS/BIOS对象必须在创建时配置一个事件对象和事件ID。你可以决定将指定资源的可用信号关联到如一个事件ID之上(也就是Mailbox中的信息可用,Mailbox的room可用或Semaphore可用)。
注意:之前曾说过,同一时间只有一个Task可以等待一个事件对象。所以可以得出结论,为隐式提交的事件所配置的SYS/BIOS对象同一时间仅可以等待单个Task。
当Event_pend()用于从隐式提交的对象获取资源时,timeout参数BIOS_NO_WAIT将用于随后从对象接收资源。
运行时实例:以下C代码例程演示了一个task将消息提交到Mailbox消息以及执行一个ISR的提交处理需求。
Event_Handle myEvent;
Mailbox_Handle mbox; typedef struct msg { UInt id; Char buf[ 10]; } main() { Mailbox_Params mboxParams; Error_Block eb; Error_init(&eb); myEvent = Event_create( NULL, &eb); if (myEvent == NULL) { System_abort( "Event create failed"); } Mailbox_Params_init(&mboxParams); mboxParams.readerEvent = myEvent; /* Assign Event_Id_00 to Mailbox "not empty" event */ mboxParams.readerEventId = Event_Id_00; mbox = Mailbox_create( sizeof(msg), 50, &mboxParams, &eb); if (mbox == NULL) { System_abort( "Mailbox create failed"); } /* Mailbox_create() sets Mailbox's readerEvent to * counting mode and initial count = 50 */ } writerTask() { ... Mailbox_post(mbox, &msgA, BIOS_WAIT_FOREVER); /* implicitly posts Event_Id_00 to myEvent */ ... } isr() { Event_post(myEvent, Event_Id_01); } readerTask() { while (TRUE) /* Wait for either ISR or Mailbox message */ { events = Event_pend(myEvent, Event_Id_NONE, /* andMask = 0 */ Event_Id_00 + Event_Id_01, /* orMask */ BIOS_WAIT_FOREVER); /* timeout */ if (events & Event_Id_00) { /* Get the posted message. * Mailbox_pend() will not block since Event_pend() * has guaranteed that a message is available. * Notice that the special BIOS_NO_WAIT * parameter tells Mailbox that Event_pend() * was used to acquire the available message. */ Mailbox_pend(mbox, &msgB, BIOS_NO_WAIT); processMsg(&msgB); } if (events & Event_Id_01) { processISR(); } } } |