【SYS/BIOS】4.2节同步模块之事件模块

本文介绍了SYS/BIOS中的事件模块,用于线程间的通信和同步。事件类似于信号量,但允许等待多个条件。事件实例通过'pend'和'post'操作进行管理,其中Event_pend()调用指定等待的事件,Event_post()指定传递的事件。事件对象支持最多32个事件,每个事件由事件ID表示。一些SYS/BIOS对象如邮箱和信号量支持隐式发布事件,当资源可用时自动发布相关事件。
摘要由CSDN通过智能技术生成

4.2节 事件模块(Event Module)

本章介绍用于同步访问共享资源的模块
目录列表如下:

4.1 信号量(Semaphores)

4.2 事件模块(Event Module)

4.3门(Gates)

4.4 邮箱(Mailboxes)

4.5 队列(Queues)

事件为线程之间的通信和同步提供了一种方法。他们类似于信号量(参见【SYS/BIOS】4.1节同步模块之信号量)只是它们允许您指定在等待线程返回之前必须发梢的多个条件(“事件”)。

事件实例的使用与信号量一样,也是调用"pend"和"post"。但是,对Event_pend()的调用还指定要等待哪些事件,对Event_post()的调用指定要传递哪些事件。

注意:一次只有1个任务可以挂起在事件对象上。

单个事件实例最多可以管理32个事件,每个事件由一个事件ID表示。事件ID是对应于事件对象管理的唯一事件的位掩码。

每个事件的行为都像一个二进制信号量。但是,有关从信号量或邮箱隐式传递(post)的事件的详细信息,请参见第4.2.1节。

有关此模块实例的参数结构和单个参数的信息,请参阅第1.6.1节中描述的API参考帮助系统.

调用Event_pend()需要一个“andMask”和一个“orMask”。andMask由所有必须发生的事件的事件ID组成,orMask由任何只有一个必须发生的事件的事件ID组成。

与信号量一样,对Event_pend()的调用采用超时值,如果调用超时,则返回0。如果对Event_pend()的调用成功,它将返回“已消耗”事件的掩码,即满足对Event_pend()调用的事件。然后,任务负责处理所有消耗的事件。

只有任务可以调用Event_pend(),而Hwis、Swis和其他任务都可以调用Event_post()。

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_post()可能会导致在特定情况下重新启用硬件中断(Hwi)。有关详细信息,请参见第8.2.4节,启用和禁用中断。

配置示例:这些配置语句静态创建事件。事件对象有1个名为“myEvent”的事件句柄类型的事件对象。

var Event = xdc.useModule("ti.sysbios.knl.Event");
Program.global.myEvent = Event.create();

运行时示例:下面的C代码创建了一个名为“myEvent”的Event_Handle类型的事件对象。

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代码在事件上阻塞。只有当事件0和6都发生时,它才会唤醒任务。它将andMask设置为同时启用Event_Id_00 和 Event_Id_06。它将orMask设置为Event_Id_NONE.

Event_pend(myEvent, (Event_Id_00 + Event_Id_06), Event_Id_NONE,
           BIOS_WAIT_FOREVER);

运行时示例:下面的C代码调用Event_post()来指示发生了哪些事件。eventMask应该包含正在传递(post)的事件的ID。

Event_post(myEvent, Event_Id_00);

运行时示例:下面的C代码示例显示了一个任务,该任务提供三个中断服务例程所需的后台处理。

在这里插入图片描述

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);
    ...
}

4.2.1 隐式发布事件

除了支持通过Event_post()API显式发布事件外,一些SYS/BIOS对象还支持隐式发布与其对象关联的事件。例如,可以将邮箱配置为每当消息可用时(即每当调用Mailbox_post()时)发布关联事件,从而允许任务在等待邮箱消息和/或某个其他事件发生时阻塞。

邮箱和信号量对象当前支持发布与其资源可用相关的事件。要启用从邮箱和信号量对象发布事件的功能,必须将信号量模块的supportsEvents属性设置为True。例如,配置可能包括以下语句:

Semaphore.supportsEvents = true;

支持隐式事件发布的SYS/BIOS对象在创建时必须配置事件对象和事件ID。您可以决定将哪个事件ID与特定的资源可用性信号(即邮箱中可用的邮件、邮箱中可用的房间或可用的信号量)关联。

注意:如前所述,一次只能在事件对象上挂起一个任务。因此,配置为隐式事件发布的SYS/BIOS对象一次只能由单个任务等待。

当使用Event_pend()从隐式发布对象获取资源是,应使用BIOS_NO_WAIT timeout参数,以便随后从该对象检索资源。

回想以下,事件是二进制的,因此从Event_pend()返回时,所有匹配的事件都会被消耗。如果任务在从信号量隐式发布的事件上被阻止,则会使用相应的事件ID。在同一个事件ID上再次立即调用Event_pend()将导致阻塞。

但是,如果在调用 Event_pend() 之前对相应的信号量调用了Semaphore_pend(sem, BIOS_NO_WAIT),对象事件中匹配的事件ID将在从Semaphore_pend()返回之前在内部刷新以匹配新更新的信号量“count”。如果调用Semaphore_pend()后,信号量计数非零,在事件对象中设置相应的事件ID。如果调用Semaphore_pend()后,计数为零,事件对象中相应的事件ID被清除。通过这种方式,事件对象与隐式调用Event_post()的信号量对象保持同步。但是为了使同步发生,应用程序必须调用 Semaphore_pend(sem, BIOS_NO_WAIT)。

由于邮箱是基于信号量构建的,所以相同的逻辑适用于想邮箱注册的事件对象。在Mailbox_post()或 Mailbox_pend()从 Event_pend() 返回隐式发布的事件之后,通过对Mailbox_pend(mbx, mbuf, BIOS_NO_WAIT) 或 Mailbox_post(mbx, mbuf, BIOS_NO_WAIT)的中间调用刷新相应的事件对象。

运行时示例:下面的C代码示例显示了一个任务,该任务处理发送到邮箱的消息,并执行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");
   }

以上内容翻译自TI官方文档 TI-RTOS Kernel (SYS/BIOS) User’s Guide Literature Number: SPRUEX3U February 2018

翻译原文链接:https://www.ti.com.cn/cn/lit/ug/spruex3v/spruex3v.pdf
转载请注明出处

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值