【OS基础】符合AUTOSAR标准的RTA-OS-Event详解

目录

5.事件Event

5.1 配置事件Configuring Event

5.1.1 定义等待事件 Defining Waiting Tasks

5.2 等待事件 Waiting on Events

5.2.1 单个事件Single Events

5.2.2 多个事件Multiple Events

5.2.3 扩展任务的死锁 Deadlock with Extended Tasks

5.3 设置事件Setting Events

5.3.1 使用报警器设置事件Setting Events with an Alarm

5.3.2 通过调度表的Expiry Point设置事件Setting Events with a Schedule Table Expiry Point

5.4 清除事件Clearing Events

5.5 用基本任务模拟扩展任务 Simulating Extended Tasks with Basic Tasks

5.6 小结


5.事件Event

在AUTOSAR OS系统中,事件用于向任务发送信号信息。本节解释事件是什么,如何配置它们以及如何在运行时使用它们。

事件可用于为扩展任务提供多个同步点。同步的可视化如图5.1所示。

扩展任务可以等待事件,这将导致任务进入等待状态。当系统中的任务或ISR设置事件时,等待任务将进入就绪状态。当它成为最高优先级的就绪任务时,RTA-OS将选择它来运行。

事件由与其关联的扩展任务拥有。通常,扩展任务将作为一个无限循环运行,其中包含对其拥有的事件的一系列受保护的等待调用。因此,事件机制允许您构建事件驱动的状态机。

如果计时行为在您的系统中很重要,那么所有扩展任务(换句话说,等待事件的任何任务)的优先级必须低于基本任务。

图5.1 事件的可视化

5.1 配置事件Configuring Event

使用rtaoscfg配置事件。应用程序中可以存在的最大事件数由目标硬件决定。查阅目标/编译器端口指南,可以了解每个任务可以有多少个事件。

当声明事件时,它必须具有:

•名字。

名称仅用于在配置时指示事件的目的。

•至少有一个任务使用它。

•事件掩码。

这可以由RTA-OS自动分配。

在rtaoscfg中指定的事件名称在运行时用作事件掩码的符号名称。掩码是一个N位向量,其中N是一个任务可以等待的最大事件的最大数量。set位标识一个特定的事件。

事件名称在运行时用作掩码的符号名称。通过选择表示事件的位来配置掩码。图5.2显示了一个名为WakeUp的事件已经被声明,它将使用事件掩码中的第9位。除非确实需要分配一个特定的位位置,否则最好让RTA-OS来确定掩码值。这允许它优化bit的打包( optimize the packing of the bits),从而节省内存。

图5.2:配置事件掩码

如果一个事件由多个任务使用,则每个任务都有自己的单独副本。设置事件时,必须同时指定任务。因此,例如,如果您为一个名为t3的任务设置了一个名为Event2的事件,这对任务t4的Event2没有影响。

5.1.1 定义等待事件 Defining Waiting Tasks

使用rtaoscfg选择等待任务。如果声明一个等待事件的任务,则意味着该任务将自动被视为扩展任务。

图5.3显示了已经声明了一个事件WakeUp,并且任务TaskC和TaskD已经配置为等待该事件。

等待事件的扩展任务通常会自动启动,并且任务永远不会终止。当任务开始执行时,RTA-OS将清除它拥有的所有事件。

图5.3:选择等待事件的任务

5.2 等待事件 Waiting on Events

任务使用WaitEvent(EventMask) API调用等待事件。EventMask必须与rtaoscfg中声明的EventMask对应。

WaitEvent()将事件作为其唯一参数。当调用执行时有两种可能:

1) 该事件尚未发生。在这种情况下,任务将进入等待状态,RTA-OS将在就绪状态下运行最高优先级的任务。

2) 事件已发生。在这种情况下,任务保持在运行状态,并将在WaitEvent()调用之后的语句中继续执行。

5.2.1 单个事件Single Events

等待单个事件,只需将事件掩码名称传递给API调用。示例5.1显示了任务如何等待事件。

#include <Os.h>

TASK(ExtendedTask) {

    ...

    WaitEvent(Event1); /* Task enters waiting state in API call if Event1

    has not happened */

    /* When Event1 is set, ExtendedTask resumes here */

    ...

}

Example 5.1: Waiting on an Event

在AUTOSAR操作系统中,为处于挂起状态的任务设置事件是非法的。在实践中,这意味着等待事件的任务结构通常是一个等待事件的无限循环,如例5.2所示。

#include <Os.h>

TASK(ExtendedTask){

    /* Entry state */

    while(true){

    WaitEvent(Event1);

    /* State 1 */

    WaitEvent(Event2);

    /* State 2 */

    WaitEvent(Event3);

    /* State 3 */

    }

    /* Task never terminates */

}

Example 5.2: Simple 3-state State Machine with Events

5.2.2 多个事件Multiple Events

因为AUTOSAR OS事件只是一个位掩码,所以可以通过按位顺序排列一组位掩码来同时等待多个事件。

当任务等待多个事件时,当等待的任何一个事件发生时,它将被恢复。当从等待多个事件中恢复时,需要计算出发生了哪个(或多个)事件。

#include <Os.h>

TASK(ExtendedTask){

    EventMaskType WhatHappened;

    while(true){

        WaitEvent(Event1|Event2|Event3);

        GetEvent(Task1, &WhatHappened);

        if( WhatHappened & Event1 ) {
    
        /* Take action on Event1 */

        ...
    
    } else if( WhatHappened & Event2 ) {

        /* Take action on Event2 */

        ...

    } else if( WhatHappened & Event3 ) {

        /* Take action on Event3 */

    ...

        }

    }

}

Example 5.3: Waiting on Multiple Events

AUTOSAR OS提供了GetEvent() API调用,允许获取为任务设置的当前事件集。

例5.3展示了任务如何同时等待多个事件,然后在恢复时识别哪些事件已被设置。

5.2.3 扩展任务的死锁 Deadlock with Extended Tasks

虽然AUTOSAR OS在临界区互斥中提供了免于死锁的方法(参见第4章),但不能避免使用可能死锁的事件构建系统。如果有相互设置和等待事件集的扩展任务,那么可能会有两个(或更多)任务正在等待事件,而这些事件仅由正在等待的其他任务设置。当然,系统中的基本任务不可能死锁,即使存在死锁的扩展任务。

例5.4展示了两个任务,如果没有其他任务设置Ev1或Ev2,它们将死锁。

操作系统配置不捕获哪些任务/ ISR设置事件,只捕获哪些任务可以等待事件。因此,RTA-OS不可能静态地确定扩展任务是否会死锁。然而,以下设计方法可能会有所帮助:

•只使用基本任务

•分析代码,以显示在所有SetEvent()/WaitEvent()对的传递性闭包上没有循环等待事件

#include <Os.h>

TASK(Task1) {

    while (1) {

        WaitEvent(Ev1);

        /* Never reach here - DEADLOCKED with Task2! */

        SetEvent(Task2,Ev2)

    }

}

TASK(Task2) {

    while (1) {

        WaitEvent(Ev2);

        /* Never reach here - DEADLOCKED with Task1! */

        SetEvent(Task1,Ev1)

    }

}

Example 5.4: Deadlock with Extended Tasks

5.3 设置事件Setting Events

使用SetEvent() API设置事件。

SetEvent()调用有两个参数,一个任务和一个事件掩码。对于指定的任务,SetEvent()调用设置事件掩码中指定的事件。该调用不为共享事件的任何其他任务设置事件。可以在调用SetEvent()时按位或多个事件掩码,以同时为任务设置多个事件

无法为处于挂起状态的任务设置事件。因此,在设置事件之前,必须确保任务没有挂起。

可以使用GetTaskState() API调用来实现这一点,但请注意,当对比调用者优先级更高的任务调用此方法时,存在潜在的竞争条件。调用者可能在调用API和评估结果之间被抢占,并且被请求的任务的状态可能在这段时间内发生了变化。

当扩展任务正在等待的任何一个事件被设置时,扩展任务将从等待状态移动到就绪状态。

例5.5展示了任务如何设置事件。

多个任务可以等待一个事件。但是,从例5.5中可以看到,事件没有广播机制。换句话说,无法通过单个API调用向等待该事件的所有任务发出事件发生的信号。事件也可以通过闹钟和时间表来设置。

#include <Os.h>

TASK(Task1) {

    TaskStateType TaskState;

    /* Set a single event */

    SetEvent(Task2, Event1);

    /* Set multiple events */

    SetEvent(Task3, Event1 | Event2 | Event3);

    ...

   /* Checking for the suspended state */

    GetTaskState(Task2,&TaskState);

    if (TaskState != SUSPENDED) {

        SetEvent(Task2, Event1);

    }

    ...

    TerminateTask();

}

Example 5.5: Setting Events

5.3.1 使用报警器设置事件Setting Events with an Alarm

警报可用于定期激活不终止的扩展任务。每次告警过期,都会设置该事件。等待事件的任务将准备好运行。

5.3.2 通过调度表的Expiry Point设置事件Setting Events with a Schedule Table Expiry Point

调度表上的到期点可用于扩展任务的定期激活。每次处理过期点时,都会设置事件。等待事件的任务将准备好运行。

5.4 清除事件Clearing Events

事件可以由任何任务或ISR设置,但只能由事件所有者清除。

当一个任务等待一个事件时,事件发生了,那么对同一事件的WaitEvent()的后续调用将立即返回,因为事件仍然是设置的。

在等待事件再次发生之前,必须清除该事件最后一次发生的事件。

使用ClearEvent(EventMask) API调用清除事件。EventMask必须与声明的EventMask对应。

例5.6展示了任务通常如何使用ClearEvent()。

当任务终止时,它拥有的所有事件将自动清除。

#include <Os.h>

TASK(ExtendedTask){

    EventMaskType WhatHappened;

    ...

    while( WaitEvent(Event1|Event2|Event3)==E_OK ) {
    
        GetEvent(Task1, & WhatHappened);
    
        if(WhatHappened & Event1 ) {

        ClearEvent(Event1);

        /* Take action on Event1 */

        ...

    } else if( WhatHappened & (Event2 | Event3 ) {
    
        ClearEvent(Event2 | Event3);

        /* Take action on Event2 or Event3*/

    ...

        }

    }

}

Example 5.6: Clearing Events

5.5 用基本任务模拟扩展任务 Simulating Extended Tasks with Basic Tasks

基本任务只能在任务执行开始或结束时同步。

如果需要其他同步点,则事件机制提供了一种方法。然而,扩展任务通常比基本任务有更大的开销。在资源受限的系统上,只能使用基本任务来构建同步。

例如,如果将任务构建为状态机(例如使用C switch语句),则可以设置状态变量,发出TerminateTask()调用并等待重新激活。例5.7展示了如何实现这一点。

#include <Os.h>

/* Create a "State" variable that remains in scope between task

activations */

uint8 State;

TASK(Task1) {

    switch (State) {

    case 0:

    /* Synchronization point 0. */

    State = 1;

    break;

    case 1:

    /* Synchronization point 1. */

    State = 2;

    break;

    case 2:

    /* Synchronization point 2. */

    State = 0;

    break;

}

TerminateTask();

}

Example 5.7: Multiple Synchronization Points in a Basic Task

5.6 小结

•事件是可以由扩展任务等待的同步对象。

•一个事件可以被多个任务使用。

•设置一个事件不是一个广播机制来通知所有正在等待的任务。

•任务,ISR,闹钟和计划表可以设置事件。

参考文档:

[1] RTA-OS V6.1.3 User Guide

[2] Specification of Operating System AUTOSAR Release 4.2.2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

汽车电子嵌入式

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值