【OS基础】符合AUTOSAR标准的RTAOS-Alarms详解

目录

前言

正文

7.报警Alarms

7.1配置Alarms

7.1.1激活一个任务

7.1.2 设置一个事件

7.1.3报警回调Alarm Callback

7.1.4 增加计数器值

7.2设置Alarms

7.2.1 绝对Alarms

7.2.2 相对Alarm

7.3自启动Alarms

7.4 删除Alarms

7.5确认何时会发生Alarm

7.6非周期Alarms

7.7 小结


前言

本系列文章将以RTA-OS为例详细介绍AUTOSAR OS标准及概念,并分享实际使用的一些案例,本文为符合AUTOSAR标准的RTA-OS--Alarm介绍。

OS相关文章

4.1 【OS基础】符合AUTOSAR标准的RTA-OS-功能简介

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

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

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

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

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

2.1 【OS】AUTOSAR架构下的OS错误处理

2.2 【OS】AUTOSAR架构下QM Application如何访问ASIL Application

2.3 【OS】AUTOSAR架构下多核启动

2.4 【OS】AUTOSAR架构下多核Shutdown

2.5 【OS】AUTOSAR架构下多核通信

2.6 【OS】RH850U2A芯片平台Spinlock的底层实现

2.7 【OS】AUTOSAR架构下MCAL Modules软件分区问题分析

2.8 【OS】AUTOSAR架构下的中断和异常向量表

2.9 【OS】AUTOSAR Os是如何启动第一个Task的

2.10 【OS】AUTOSAR OS系统调用产生Trap的过程详解

2.11 【OS】AUTOSAR OS如何实现Task抢占

2.12 【OS】AUTOSAR OS调度器实现原理


注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!

正文

7.报警Alarms

可以使用ISR构建以不同速率激活任务的系统。然而,对于复杂的系统,这可能会变得低效和不切实际。警报器(Alarms)提供了一种更方便、更便携的调度系统方式。

该报警机构由以下两部分组成:

1.一个计数器counter.

2.一个或多个报警器连接到计数器上。

报警(Alarm)指定在达到特定计数器值时要执行的操作。系统中的每个计数器都可以附加任意数量的报警(Alarm)。

当计数器的值等于附加到计数器的警报的值时,就说警报已经过期。在到期时,RTA-OS将执行与告警相关联的操作。该操作可以是激活任务(OsAlarmActiveTask)、执行警报回调例程(OsAlarmCallback)、设置事件(OsAlarmSetEvent)或增加计数器值(OsAlarmIncrementCounter)。

报警到期值可以相对于实际计数器值或定义为绝对值。如果报警失效定义为相对于实际计数器,则称为相对报警(Relative alarm)。如果将其定义为绝对值,则称为绝对警报(Absolute Alarm)。

警报可以配置为过期一次。一旦过期的警报被称为单次警报(Single-shot Alarm)。

还可以将警报指定为定期过期。这种类型的警报被称为循环警报(cyclic alarm)。您可以在第7.2节中找到更多关于循环警报的信息。

7.1配置Alarms

一个Alarm需要配置三个配置项:

1.名字 - 系统中的每个报警都需要分配一个唯一的名称。对于其他操作系统对象,这是将代码中在运行时引用警报的名称。

2.关联的计数器counter - 报警在配置时静态绑定到计数器。警报的任何设置都是根据相关计数器的滴答(ticks)数来完成的。

3.报警到期后的动作。

创建的每个报警最多包含4个动作:

1.激活一个任务

Figure 7.1: Activating a Task with an Alarm

2.触发一个事件(event)。

3.执行一个callback函数。

4.增加一个计数器(counter)的值。

如果需要激活多个任务、设置多个事件、进行多个回调或在到期时增加多个计数器,则需要具有相同到期值的多个警报。(调度表提供了一种替代机制,允许同时激活多个任务和/或设置多个事件。后面将在在调度表章节中阅读关于调度表的内容)。

7.1.1激活一个任务

警报最常见的动作是激活一个任务。这是构建具有定期激活任务的系统的基础——可以为每个任务创建一个警报,然后通过软件代码将警报设置为在所需的时间段内发生。图7.1显示了如何配置告警以激活任务。

7.1.2 设置一个事件

报警可以为指定的任务设置一个事件。当事件设置为警报时,它具有与使用SetEvent() API调用设置时相同的属性。这意味着用户需要同时指定事件和要为其设置事件的任务。图7.2显示了如何为告警设置事件操作。

Figure 7.2: Setting an Event for a Task with an Alarm

7.1.3报警回调Alarm Callback

每个报警都可以有一个关联的回调函数。回调只是一个C函数,在告警到期时被调用。

集成指导:根据AUTOSAR操作系统标准,报警回调只允许在可伸缩性级别1(Scalability Class 1)中进行。这是因为这些回调在操作系统级别上运行,因此可能会干扰定时保护,并在内存保护方案中出现一个漏洞。

Portability Note: RTA-OS允许放松这个限制,允许在General➔Optimizations➔RTA-OS中使用配置选项在所有可伸缩性类中允许警报回调。

图7.3显示了如何为报警配置回调函数。

Figure 7.3: Configuring a Callback Routine for an Alarm

每个回调函数都必须使用ALARMCALLBACK() 宏来编写,如示例7.1所示。

ALARMCALLBACK(UserProvidedAlarmCallback) {
/* Callback code. */
}

集成指导:回调例程在操作系统级别运行,这意味着2类中断被禁用。因此,应该是尽可能保持回调例程的精简,以最小化任务和ISR在运行时遭受的阻塞量。

用户可以在回调中进行的唯一使用的RTA-OS API调用是SuspendAllInterrupts() and ResumeAllInterrupts().

7.1.4 增加计数器值

警报增加软件计数器允许您从单个ISR级联多个计数器。由Alarm驱动(Ticked)的计数器Counter继承了警报的周期。所以,如果你有一个每5毫秒发生一次的警报,你可以使用警报来驱动一个秒级的Counter, 这个Counter的一个tick是5ms. 图7.4显示了在RTA-OS中是如何配置的。

Figure 7.4: Cascading counter increments from an alarm

示例7.2显示了如何从中断中驱动1毫秒计数器。在1毫秒计数器上注册的每五次中断将导致告警过期,并增加级联计数器5秒:

#include <Os.h>
ISR(MillisecondInterrupt){CLEAR_PENDING_INTERRUPT();Os_IncrementCounter(Counter1ms);
/* Every 5th call internally performs Os_IncrementCounter(Counter5ms) */
}

Example 7.2: Cascading Counters

级联计数器的滴答率(tick rate)必须是驱动报警的计数器的整数倍。用户可以使用多级级别的级联来配置系统。但是,如果您试在级联中配置一个循环系统或尝试增加硬件计数器,RTA-OS将生成错误。

集成指导:级联计数器的定时特性是相对于级联中第一个计数器的定时特性来定义的。因此,级联中最早的计数器决定了定义所有其他计数器的基本滴答率。如果您更改了最早计数器的标记率,则应用程序的整个计时行为将相应地缩放。

7.2设置Alarms

OS提供两个API用来设置Alarms:

SetAbsAlarm(AlarmID, start, cycle);

将报警设置为在计数器值下次到达时开始时失效。如果底层计数器在调用SetAbsAlarm时已经开始,那么在本次计数器周期内不会发生警报。

SetRelAlarm(AlarmID, increment, cycle);

增量式Alarm,即设置该Alarm后计数满足就执行该Alarm.

在这两个API调用中,周期值设置为0表示警报是单次触发警报,这意味着它在被取消之前只会过期一次。循环值大于零定义循环报警。这意味着在第一次到期后,它将继续使每个周期过期。设置非零周期值可以轻松地配置具有周期变化周期的周期性警报。

参数选着

如果被激活的任务是BCC1或ECC1/2,则将不会有排队的激活。这意味着,如果开始值或增量值非常短,或者开始值非常接近当前的计数器值,那么这可能会导致不希望产生的副作用。当先前激活的实例仍在执行时,警报将尝试激活该任务。激活将会丢失,并将引发一个E_OS_LIMIT错误。必须确保有足够的时间完成任务,然后才能导致任务重新触发任务。

7.2.1 绝对Alarms

单次触发

绝对报警指定报警失效的底层计数器的绝对值。单次触发绝对警报用于监控预定义的阈值非常有用——警报可以配置为在超过阈值时过期。用户可能希望计算在运行时获取的数据采样中发生的错误数量,然后在错误数量达到危险级别时触发恢复操作。这一点如示例7.3所示。

/* Expire when counter value reaches 42. */
SetAbsAlarm(DangerLevelReached, 42, 0);

Example 7.3: Absolute single shot alarm

示例7.3如图7.5所示。

Figure 7.5: Illustration of an Absolute Single Shot Alarm

当我们需要设置一个超时,然后等待一个固定的超时时间,然后在超时发生时采取动作时,单次触发报警很有用。

循环触发

如果绝对告报警指定了一个非零周期值,则它将首先在指定的起始点终止,然后在此后的每个周期终止。这一点如示例7.4所示。

Figure 7.6: Illustration of the Absolute Cyclic Alarm

/* Expire when counter value reaches 10 and then every 20 ticks thereafter
*/
SetAbsAlarm(Alarm1, 10, 20);

Example 7.4: Absolute cyclic alarm

对于绝对告警,零刻度的绝对起始值与任何其他值相同——这意味着当计数器达到零值时告警失效。

例如,如果当前计数器值为零,则将不会看到警报过期,直到计数器值的最大值+1数量发生。另一方面,如果计数器的值已经处于最大等值,那么就会看到警报在计数器的下一个tick上过期。

设置Alarm为过去值

设置为过去式Alarm时,需要等待MAXALLOWEDVALUE+1个Tick后才能到期。

注意:一个常见的错误是设置绝对Alarm在OS 起动后Counter为0时发生,这样的Alarm不会发生,因为0已经是过去发生的。

Figure 7.7: Setting an alarm in the past

将绝对循环Alarm同步到计数器包装

将Alarm设置为在已知的同步点定期发生对于实时系统非常重要。但是,在AUTOSAR操作系统中,不可能将绝对Alarm设置为每次基线计数器环绕时定期发生。

如果需要此类功能,则必须提供每次Alarm过期时重置绝对单次Alarm的代码。例如,如果Task1连接到Alarm1,则Task1的主体将需要在激活任务时重置Alarm,如下示例所示。

TASK(Task1) {/* Single-shot alarm reset at top dead center = 0 = 360 degrees. */SetAbsAlarm(Alarm1, 0, 0);/* User code. */TerminateTask();
}

Example 7.5: Resetting an Alarm when a Task is Activated

7.2.2 相对Alarm

单次触发

相对报警指定报警失效的底层计数器的绝对值。当用户想在运行时超时某些活动时,单次触发相对报警很有用。例如,用户可能希望等待一个外部事件,然后在该事件未发生时激活该任务。

Figure 7.8: Illustration of a Relative Single Shot Alarm

示例7.6显示了如何设置绝对单枪报警。

/* Timeout 42 ticks from now */
SetRelAlarm(Timeout, 42, 0);

Example 7.6: Relative single shot alarm

当用户需要设置一个超时,等待一个固定的超时时间,然后在超时发生时采取行动时,单次触发报警我们很有用。

在AUTOSAR操作系统中,禁止在SetRelAlarm()中使用零作为增量。如果您使用零作为增量,则将返回一个E_OS_VALUE错误。

循环触发

示例7.7显示了一个相对警报,在10次响后响一次,然后每20次响一次。

/* Expire after 10 ticks, then every 20 ticks. */
SetRelAlarm(Alarm1, 10, 20);

Example 7.7: Relative cyclic alarm

在图7.9中,可以看到如何可视化此报警。

Figure 7.9: Illustration of a Relative Cyclic Alarm

7.3自启动Alarms

虽然可通过在主函数中调用SetRelAlarm() 或 SetAbsAlarm() API来起动Alarm,但最简单的调用周期Alarms方式是在STARTOS()后自启动Alarm。

自启动Alarm需声明其为绝对还是相对Alarm,counter及周期值。

Figure 7.10: Auto-starting Alarms

RTA-OS确保软件计数器在StartOS()期间初始化为零(硬件计数器将设置为您自己的应用程序初始化代码配置的值)。因此,如果对绝对Alarm使用零刻度开始时间,则必须小心,因为在Alarm启动时,零刻度已经发生。虽然Alarm将启动,但在相关计数器变为零之前,Alarm不会过期。在一个16位计数器上,每毫秒Tick增加一次,你需要等待超过65秒,然后在一个32位计数器上等待不到48天。指定Alarm在第一次(或以后)勾选时开始表示初始到期将在计数器的下一次勾选时发生。如果需要Alarm彼此同步(即Alarm之间的相对过期时间必须间隔预先设定的刻度数),则自动启动绝对Alarm非常有用。

7.4 删除Alarms

可以通过调用CancelAlarm() API来删除Alarm,例如,可能需要取消Alarm以停止正在执行的特定任务。可以使用SetAbsAlarm()或SetRelAlarm() API调用重新启动Alarm。

7.5确认何时会发生Alarm

当用户需要确认Alarm何时会发生,如对于绝对Alarm,为了避免已经达到的值被设置时可以通过调用Get Alarm() API获取。该调用返回指定Alarm到期前剩余的Tick数。如果未设置Alarm,则API调用将返回值E_OS_NOFUNC,到期的刻度数未定义。建议在使用结果之前检查调用的返回值。示例7.8显示了API调用的使用情况。

TickType TimeToExpiry;TickType SafetyMargin = 100;StatusType IsValid;IsValid = GetAlarm(Alarm1, &TimeToExpiry);if (IsValid != E_OS_NOFUNC) {    if (TimeToExpiry <= SafetyMargin) {      Log(InsideSafetyMargin);  }}

Example 7.8: Getting the time to expiry

在根据调用返回的Tick值出运行时决策时,尤其是在底层计数器具有高分辨率的情况下,应特别小心。与使用GetCounterValue() 读取计数器值一样,在获取该值和使用该值进行计算之间可能会发生抢占。这意味着可能会读取(很长)到期时间,但随后会被抢占,以便在Alarm到期前不久(甚至在Alarm到期后)恢复。

7.6非周期Alarms

周期报警只对循环行为有用。在许多系统中,例如那些需要定期执行任务来轮询数据源的系统中,这是非常理想的。但是,用户可能需要对在运行时需要更改的系统进行编程。例如,正在计算一个发动机轴转速,并使用它来编程火花或喷射定时的持续时间。

需要使用单次触发警报对具有警报的非周期行为进行编程,并由激活的任务设置为下一个到期值。

在示例7.9中,一个任务每毫秒运行一次,并轮询一个记录曲轴旋转度的计数器。该任务将计算曲柄的位置和速度。速度用于确定火花定时的持续时间。火花启动,警报设置为在SparkTiming ticks到期后。

TASK(MillisecondTask) {...GetElapsedCounterValue(ShaftEncoder,&Position,&DegreesRotation);RevsPerMinute = (DegreesRotation/360) * 1000 * 60;SparkTiming = Lookup(RevsPerMinute);if (Position == 90) {StartSpark();SetRelAlarm(TimeCounter, SparkTiming, 0); /* Activates SparkOff onexpiry */ }
}
...
TerminateTask()
}
​
TASK(SparkOff){StopSpark();TerminateTask();
}
Example 7.9: Aperiodic Alarm Example

7.7 

  • Alarms是基于counter设置的,同一个Counter可设置多个Alarms;

  • 每个Alarm执行的操作可能为:执行某个Task、设置个Event、执行某回调函数或增加一个计数器;

  • Alarm可设置绝对或相对counter值;

  • Alarm可配置为自启动模式。

  • 实际应用中一般采用调度表来调度,Alarms应用相对比较少。

参考文档:

[1] RTA-OS V6.1.3 User Guide

[2] Specification of Operating System AUTOSAR Release 4.2.2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/357170.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Golang | Leetcode Golang题解之第179题最大数

题目&#xff1a; 题解&#xff1a; func largestNumber(nums []int) string {sort.Slice(nums, func(i, j int) bool {x, y : nums[i], nums[j]sx, sy : 10, 10for sx < x {sx * 10}for sy < y {sy * 10}return sy*xy > sx*yx})if nums[0] 0 {return "0"…

网络安全-如何设计一个安全的API(安全角度)

目录 API安全概述设计一个安全的API一个基本的API主要代码调用API的一些问题 BasicAuth认证流程主要代码问题 API Key流程主要代码问题 Bearer auth/Token auth流程 Digest Auth流程主要代码问题 JWT Token流程代码问题 Hmac流程主要代码问题 OAuth比较自定义请求签名身份认证&…

Golang | Leetcode Golang题解之第167题两数之和II-输入有序数组

题目&#xff1a; 题解&#xff1a; func twoSum(numbers []int, target int) []int {low, high : 0, len(numbers) - 1for low < high {sum : numbers[low] numbers[high]if sum target {return []int{low 1, high 1}} else if sum < target {low} else {high--}}r…

示例:WPF中应用Grid的SharedSizeGroup设置整齐的布局

一、目的&#xff1a;应用Grid的SharedSizeGroup设置整齐的布局 二、实现 <ItemsControl ItemsSource"{local:GetStudents Count5}"><ItemsControl.ItemTemplate><DataTemplate><Grid ShowGridLines"True"><Grid.ColumnDefinit…

51单片机STC89C52RC——3.1 数码管静态展示

目的 让数码管在指定位置显示指定数字 一&#xff0c;STC单片机模块 二&#xff0c;数码管 2.1 数码管位置 2.2 生活中用到的数目管 红绿灯 LED数码管在生活中随处可见&#xff0c;洗衣机、电饭煲、热水器、微波炉、冰箱、这些最基本的家用电器上基本都用到了这种7段LED数…

[手机Linux PostmarketOS]一,1加6T真正的手机Linux系统

前面用Linux deploy软件安装了Linux系统在手机&#xff0c;实则不是真正的手机刷成了linux系统&#xff0c;而是通过Linux deploy软件在容器里安装了Linux系统&#xff0c;在使用方面会有诸多限制&#xff0c;并不能发挥Linux的真实强大之处&#xff0c;于是我又百度又谷歌(真不…

51单片机STC89C52RC——5.1 LCD1602液晶显示屏

目录 目的 一&#xff0c;STC单片机模块 二&#xff0c;LCD1602 2.1 模块简介 2.2 针脚 2.3 DDRAM地址与显示器对应关系 2.4 标准字库表 2.5 常用指令 2.6 读写操作 三&#xff0c;创建Keil项目 四&#xff0c;代码 五&#xff0c;代码编译、下载到51单片机 六&a…

掌握Three.js:学习路线,成为3D可视化开发的高手!

学习Three.js可以按照以下路线进行&#xff1a; 基础知识&#xff1a; 首先要了解基本的Web开发知识&#xff0c;包括HTML、CSS和JavaScript。如果对这些知识已经比较熟悉&#xff0c;可以直接进入下一步。 Three.js文档&#xff1a; 阅读Three.js官方文档是学习的第一步。官…

【Flutter 专题】120 Flutter 腾讯移动通讯 TPNS~

1.2 方法使用 小菜按照官网的介绍尝试了一些常用的 API 方式&#xff0c;主要分为应用类&#xff0c;账号类和标签类三种 API&#xff0c;小菜业务中没有应用账号和标签模块&#xff0c;暂未深入研究&#xff1b; 应用接口 API a. 注册推送服务 对于服务的注册初始化&#x…

跟TED演讲学英文:How language shapes the way we think by Lera Boroditsky

How language shapes the way we think Link: https://www.ted.com/talks/lera_boroditsky_how_language_shapes_the_way_we_think? Speaker: Lera Boroditsky Date: November 2017 文章目录 How language shapes the way we thinkIntroductionVocabularySummaryTranscriptA…

目前哪个充电宝品牌比较好?四款优质充电宝分享

在电量成为现代生活不可或缺的生产资源的时代&#xff0c;选择一款优质的充电宝无疑是保证移动设备持续运作的关键。面对市场上众多品牌和型号的充电宝&#xff0c;消费者在选择时可能会感到困惑和迷茫。本文将为您揭示哪些品牌真正代表了耐用性和质量的典范&#xff0c;让自己…

贪心算法—

贪心算法是一种在每一步选择中都采取在当前状态下最好或最优&#xff08;即最有利&#xff09;的选择&#xff0c;从而希望导致结果是全局最好或最优的算法。这种算法并不总是能找到全局最优解&#xff0c;但在某些问题上能提供足够好的解决方案。贪心算法的关键特性包括&#…

51单片机STC89C52RC——6.1 中断系统

一&#xff0c;文字层面理解 反正我看下面的几段文字时脑壳没有正常运转。一个头几个大 中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。 当中央处理机CPU正在处理某件事的时候外界发生了紧急事件请求&#xff0c;要求CPU暂停当前的工作&#xff0c;转而去处理这…

华为---- RIP路由协议基本配置

08、RIP 8.1 RIP路由协议基本配置 8.1.1 原理概述 RIP(Routing Information Protocol,路由协议)作为最早的距离矢量IP路由协议&#xff0c;也是最先得到广泛使用的一种路由协议&#xff0c;采用了Bellman-Ford算法&#xff0c;其最大的特点就是配置简单。 RIP协议要求网络中…

使用Gradle查看Android项目中库的依赖关系

| | -- com.android.support:support-compat:25.3.1 | | | — com.android.support:support-annotations:25.3.1 | | -- com.android.support:support-media-compat:25.3.1 | | | -- com.android.support:support-annotations:25.3.1 | | | — com.android.support:support…

前端初学java

目录 java术语 JDK Javac Java Jdb Jhat JVM JRE JAR JDK下载 运行java文件 字面量 隐式转换 强制转换 注意 运算符 &&、||、&、| Switch 程序入口 String[] args 数组 静态初始化 动态初始化 变量初始化 Java内存 方法 重载 Final 包 …

如何解决代码中if…else-过多的问题,建议收藏

逻辑表达模式固定的 if…else 实现与示例 if (param.equals(value1)) { doAction1(someParams); } else if (param.equals(value2)) { doAction2(someParams); } else if (param.equals(value3)) { doAction3(someParams); } // … 可重构为 Map<?, Function<?>…

Hexo 搭建个人博客(ubuntu20.04)

1 安装 Nodejs 和 npm 首先登录NodeSource官网&#xff1a; Nodesource Node.js DEB 按照提示安装最新的 Node.js 及其配套版本的 npm。 &#xff08;1&#xff09;以 sudo 用户身份运行下面的命令&#xff0c;下载并执行 NodeSource 安装脚本&#xff1a; sudo curl -fsSL…

qt 简单实验 一个可以向右侧拖拽缩放的矩形

1.概要 目的是设置一个可以拖拽缩放的矩形&#xff0c;这里仅用右侧的一个边模拟这个过程。就是为了抓住核心&#xff0c;这个便解决了&#xff0c;其他的边也是一样的。而这个更能体现原理。 2.代码 2.1 resizablerectangle.h #ifndef RESIZABLERECTANGLE_H #define RESIZ…

c++中string的用法

STL的简介 一.什么是STL二.STL的六大组件2.1仿函数2.2空间配置器2.3 算法2.4 迭代器2.5容器2.6配置器 三.string类3.1string类3.2string类的常用接口说明代码示例运行结果 3.3string类对象的容量操作代码示例sizelengthcapcityempty resizereverse 3.4string类对象的访问及遍历…