前言
本系列文章将以RTA-OS为例详细介绍AUTOSAR OS标准及概念,并分享实际使用的一些案例,本文为符合AUTOSAR标准的RTA-OS--Schedule Tables介绍。
OS相关文章
符合AUTOSAR标准的RTA-OS --功能简介
符合AUTOSAR标准的RTA-OS --Task详解
符合AUTOSAR标准的RTA-OS --Interrupts详解
符合AUTOSAR标准的RTA-OS --Resources详解
符合AUTOSAR标准的RTAOS--Event详解
符合AUTOSAR标准的RTAOS--Counters详解
符合AUTOSAR标准的RTAOS-Alarms详解
【OS】AUTOSAR架构下的中断和异常向量表
【OS】AUTOSAR Os是如何启动第一个Task的
【OS】AUTOSAR OS如何实现Task抢占
【OS】AUTOSAR OS系统调用产生Trap的过程详解
【OS】AUTOSAR OS调度器实现原理
【OS】AUTOSAR OS Spinlock实现原理(下篇)
【OS】AUTOSAR OS Event实现原理
【OS】AUTOSAR OS Counter实现原理(下篇)
【OS】AUTOSAR OS Counter实现原理(上篇)
【OS】AUTOSAR OS Resource实现原理
AUTOSAR OsTask切换原理
AUTOSAR OS Alarm实现原理
AUTOSAR架构下多核启动
AUTOSAR架构下多核通信
AUTOSAR架构下多核Shutdown
RH850U2A芯片平台Spinlock的底层实现
注:本文章引用了一些第三方工具和文档,若有侵权,请联系作者删除!
正文
通过Alarms可以相对容易地构建需要周期性和非周期性行为的系统。但是,Alarm的一个限制是,每个Alarm只能执行一个操作。如果需要建立一个系统,其中有一个分阶段性的任务激活序列,并保证一些时间间隔,那么就需要非常小心如何启动和停止Alarm.
虽然可以用Alarm构建这样的系统,但除了代码审查之外,没有什么可以防止在运行时意外修改应用程序的定时属性。此外,如果想在一个时间点上定义多个任务激活,只能创建创建多个Alarm来实现这个需求。
AUTOSAR操作系统通过提供一个称为调度表的操作系统对象来解决警报的限制。
调度表包含一组到期点(expiry points),这些到期点发生在静态配置的名义零点的时间偏移点上。偏移量是用静态绑定计数器的滴度来指定的——就像警报的过期一样。调度表和警报之间的关键区别是调度表上的到期点保持相对分离(彼此之间)。在大多数情况下,这种分离在构建时是固定的。但是,对于显式同步的调度表,这种分离可以在预先配置的值范围内发生变化。调度表可以作为一个复合单元启动和停止,每当它重新启动时,到期日总是具有相同的相对执行行为:任何给定的点a都将始终跟着下一个点B。
调度表采用以下术语:
初始偏移量(Initial Offset)是对调度表上第一个到期日的偏移量。因此,它是已配置的最小偏移量。
持续时间(Duration)是在调度表停止之前从零开始的刻度数(Ticks)。
最终延迟(Final Delay)是指到最终终点的偏移量与持续时间之间的差值。因此,它等于持续时间的值减去最长的偏移量。
延迟(Delay)是相邻到期日之间的刻度数,它等于较长的偏移量减去较短的偏移量。如果计划表重复出现,则最后一个到期日和第一个到期日之间的延迟等于最终延迟加上初始偏移量。
重复定义(Repeating)调度表每次启动并自动停止时运行一次,还是使用OS API调用停止。
到期点(Expiry point)类似于告警,它指示RTA-OS需要采取一些操作的数量。然而,有效期不同于警报。下表显示了这些差异:
Figure 8.1: Visualizing a Schedule Table
图8.1显示了具有5个到期点和50个计数器持续时间的计划表的解剖。当计划表启动时,每个到期日每50次出现一次,从概念上的零点偏移一次。
集成指导8.1:我们使用术语“notional zero”来表示测量偏移量的点。概念上的零与底层计数器上的值无关。
当调度表启动时(参见第8.4节),概念上的零将被映射到基础计数器的适当的“现在”值上。
配置一个调度表,包括一下两个部分:
1.配置表本身的属性(8.1章节介绍)。
2.表上到期点(expiry point)的配置(8.2章节介绍)。
此外(由于进度表的配置可能是复杂的),rtaoscfg还提供了一个在第8.3节中描述的调度表助手。
需要为每个调度表分配一个唯一的名称,以便可以在API调用中引用它。
调度表,由操作系统计数器驱动。计数器为计划表提供一个滴答源(tick source),为到期点偏移提供参考。所有的偏移量都以操作系统计数器的刻度来指定。
Figure 8.2: Schedule Table Configuration
每个计划表都有一个静态配置的长度,称为持续时间(duration)。Duration由Counter计数器的ticks数指定,其范围值必须满足:MINCYCLE ≤ Duration ≤
MAXALLOWEDVALUE
调度表有两种操作模式:
Single shot: 调度表运行一次,并在最后自动停止。每个到期点都要处理一次。单某些触发事件时希望启动阶段性操作序列时,Single shot调度表非常有用。
Repeating: 调度表将连续运行。当到达表的末尾时,它再次从零开始运行。因此,到期点被定期处理,周期等于持续时间。
图8.2显示了一个名为MasterPlan的调度表的配置,它由毫秒计数器驱动,持续时间为50个ticks.
图8.3显示了图计数器8.1中的调度表在图8.2的计数器值0和42启动时如何运行。
在图8.3中,每次表重复时,到期点(expiry point)都与概念零(notional zero)的相对偏移量相同。但是,到期点的计数器ticks值取决于计划表的启动时间。
Figure 8.3 Visualizing a Schedule Table
其情况可能是,应用程序需要在特定的计数器值上出现到期日。例如,计数器可以计算曲轴上的旋转度,并且到期日必须出现在0°,90°等处。或者,您可能希望能够与全局时间信号同步地处理到期日。
其情况可能是,应用程序在特定的计数器值上需要到期点(expiry point)。例如,计数器可以计算曲轴上的旋转度,并且到期点必须出现在0°,90°等处。或者,用户可能希望能够与全局时间信号同步地处理到期点。
调度表支持使用同步的这些用例。支持以下三种同步策略:
None 没有使用策略。RTA-OS不做任何事情来确保同步。如果没有配置任何策略,则这是默认行为。
Implicit 假设用于驱动调度表的计数器是需要进行同步的计数器。第8.9节提供了关于隐式同步的附加信息。
Explicit 假设有两个计数器:
l一个驱动器计数器,它是用于处理调度表上的到期点的操作系统计数器
l一个位于操作系统外部的同步计数器(即,它不是第6章中描述的操作系统计数器对象),需要与之进行同步
RTA-OS被告知同步计数器的值,并使用它来同步调度表。
第8.10节更详细地描述了显式同步。
每个调度表都包含一个或多个到期点(expiry point)。到期点标记了需要执行操作的表上的偏移量。每个到期点都具有以下属性:
n从调度表开始的偏移量(概念上的零)
n零个或更多要激活的任务
n要为指定的任务设置的零个或多个事件
每个到期点必须激活至少一个任务或设置至少一个事件。如果不进行任何操作,就不可能有一个到期点。
偏移是用驱动调度表的操作系统计数器的ticks数定义的。这意味着计数器的属性对配置设置了限制。
偏移量可以为零,也可以在调度表持续时间的小周期范围内,并且在任何一对偏移量之间必须至少有MINCYCLE ticks差。
MINCYCLE ticks的限制是由于MINCYCLE ticks的延迟不能在计数器上编程。
例如,如果计数器的一个MINCYCLE ticks为10,那么:
n包括在1和9之间的偏移是无效的
n10和20的偏移量有效(20 - 10 = 10 >= MINCYCLE ticks)
n10和19的偏移量无效(19 - 10 = 9 < MINCYCLE ticks)
More formally, ∀x, y ∈ Offsets • abs(x − y) >= MINCYCLE
图8.4显示了如何指定过期点。
工作区的上部显示了到期点及其关联的偏移量。工作区的下部显示了所选到期点的操作,以及用于添加和删除到期日的控件。
Figure 8.4: Specifying Expiry Points
许多应用程序都是基于许多周期性任务进行的。由于设置一个具有多个(en)谐波周期的单一调度表可能会耗时且容易出错,因此rtaoscfg提供了一个辅助插件,它可以自动为这样的系统生成框架。
虽然调度表助手会根据需要创建必要的调度表、计数器、任务和事件容器,但最终用户仍然需要完成它们的定义(使用计数器频率、任务优先级等)。
周期系统的配置也可以保存到磁盘上,以备将来需要编辑时。
图8.5显示了进度表助手的初始视图。
数据输入条目(grid entry)要求周期和偏移量以“ticks”输入(由autosar指定)——ticks映射到实时单元是驱动调度表的计数器的功能,因此在计数器的配置页面中执行。
如果除了周期和偏移量之外,网格((grid entry))条目仅指定了任务名称,则该操作将配置为“激活任务(Activate Task)”。如果也指定了一个事件名称,则该操作将变为设置事件(Set Event)。
在输入配置时,数据输入网格下方的消息将显示要生成的调度表的长度和大小。
如果已经存在同名的调度表,则助手可以覆盖调度表,从而允许使用新的周期信息更新调度表。保存文件后文件➔保存定期配置可以重新加载和重新生成。
当按下生成按钮时,将生成调度表和支持容器——如果项目尚未打开,将弹出“新项目”对话框。
Figure 8.5: The Schedule Table Assistant
StartScheduleTableAbs(ScheduleTableID, Start)
API调用用于以绝对计数器值启动调度表,如示例8.1所示:
/* Start Schedule Table Tbl when the counter reaches tick 6 */
StartScheduleTableAbs(Tbl, 6);
Example 8.1: Using StartScheduleTableAbs()
当调用返回时,调度表处于SCHEDULETABLE_RUNNING状态,除非它是一个隐式同步的调度表,在这种情况下,它的状态为SCHEDULETABLE_RUNNING_AND_SYNCHRONOUS.
第一个到期点将在开始+初始偏移点过去时处理。图8.6显示了根据示例8.3启动时的图8.1中的进度表。
Figure 8.6: Starting a schedule table at an absolute count value
绝对启动对于构建与外部(硬件)计数器的特定值同步的进度表非常有用。实际上,如果一个调度表配置了隐式同步,那么这是启动调度表的唯一方法。
假设我们有与以前相同的调度表布局,但由一个计数器驱动,其模量等于调度表的持续时间。我们希望到期日偏移量来表示处理调度表时的实际计数值。这可以通过在0处进行绝对开始来实现,如示例8.2所示:
/* Start ImplicitlySynchronizedTable when the counter wraps to zero */
StartScheduleTableAbs(ImplicitlySynchronizedTable, 0);
Example 8.2: Starting an implicitly synchronized schedule tabl
图8.7(a)显示,调度表将等到计数器达到零时才开始,并且每个到期日都位于等于其偏移量的计数器值处。
Figure 8.7: Synchronizing a schedule table with an absolute count value
集成指导8.2: 当以绝对计数值启动调度表时,请注意该计数器可能已经传递了该值。直到计数器再次达到值(即结束后),调度表才开始。
当RTA-OS立即启动(甚至在Counter值为0时自动启动调度表)时,调度表最经常遇到这个问题,因为计数器值0已经在过去了。在处理第一个到期日之前,必须经过计数器的全模量包装(加上初始偏移量)。
注意:在运行在1 ms的32位计数器上,你需要等待大约50天才能发生这种情况。
图8.7(b)显示了如果图8.7(a)所示的计划表在计数器达到零之后启动会发生什么。
StartScheduleTableRel(ScheduleTableID, Offset)
API调用用于从现在开始以相对数量的刻度启动调度表。这与使用SetRelAlarm()相对启动警报的概念相同。
/* Start Schedule Table Tbl 6 ticks from now */
StartScheduleTableRel(Tbl, 6);
Example 8.3: Using StartScheduleTableRel()
StartScheduleTableRel()调用的偏移参数指定从现在开始RTA-OS将启动调度表的相对刻度数。
Figure 8.8: Starting a schedule table at a relative count value
当StartScheduleTableRel()函数调用返回时,调度表处于SCHEDULETABLE_RUNNING状态。当在计数器上经过偏移+初始偏移ticks时,将处理第一个到期日。图8.8显示了根据示例8.3启动时的图10.1中的调度表。
集成指导8.3: 如果底层计数器是一个硬件计数器,必须确保在StartScheduleTableRel()函数调用返回之前,传递给StartScheduleTableRel()的偏移量尚未过期。
对于由软件计数器驱动的调度表,在执行StartScheduleTableRel()时,计数器不能递增,因为这两个API调用都在操作系统级别执行,因此是序列化的。
对于使用隐式同步的计划表,禁止相对启动,因此以下代码将生成错误:
StartScheduleTableRel(ImplicitlySynchronizedTable, 6); /* returns E_OS_ID */
Example 8.4: Forbidden use of StartScheduleTableRel()
StartScheduleTableSynchron(ScheduleTableID) API调用用于在RTA-OS被告知同步化计数器的值后同步启动一个进度表。这个API只能用于具有显式同步的进度表。
Figure 8.9: Starting a schedule table synchronously
/* Start Schedule Table when the synchronization count is provided */
StartScheduleTableSynchron(ExplicitlySynchronizedTable);
/* Table now waits */
...
SyncScheduleTable(ExplicitlySynchronizedTable,42);
/* Table processes first expiry point Duration-42+InitialOffset ticks from
now */
Example 8.5: Using StartScheduleTableSynchron()
图8.9显示了当根据示例8.3启动调度表时所发生的情况。
当调用返回时,调度表处于SCHEDULETABLE_WAITING状态。
StartScheduleTableSynchron()假设调度表的名义零需要与同步计数器上的绝对值零同步。
当调度表通过调用StartScheduleTableSynchron()启动时,它将不会运行,直到随后调用SyncScheduleTable(ScheduleTableID, Value)。当持续时间-值+初始偏移刻度在驱动器计数器上经过时,将处理第一个到期点。
集成指导8.4: :如果SyncScheduleTable()从未被执行,那么表将不会离开SCHEDULETABLE_WAITING状态,除非使用StopScheduleTable()停止它。
过期点是在响应对驱动调度表的计数器进行的IncrementCounter()或Os_AdvanceCounter() API调用时处理的。
当计数器达到下一个到期点的值时,RTA-OS将:
•激活所有配置的任务,按优先级递减顺序;然后
•为任务设置所有事件,再次按优先级降序排列;然后
•在基础计数器上设置下一个到期点的匹配值。
可以通过调用StopScheduleTable(ScheduleID) API在任何点停止调度表。调度表处理立即停止。
一个重复的调度表将运行,直到通过调用StopScheduleTable()停止,或者通过调用NextScheduleTable()切换表。
配置为Single shot(重复属性为false)的调度表将在RTA-OS处理完最终过期点后,当Final Delay滴答流逝时自动停止,如图8.10所示。
Figure 8.10: Non-repeating schedule tables stop automatically
调用StartScheduleTable[Abs|Rel|Synchron]()可以重新启动已停止的调度表。调度表将从它的名义零点重新开始,如图8.11所示。没有机制可以在中途启动进度表。
Figure 8.11: Schedule tables always start at their notional zero
可以在运行时使用NextScheduleTable() API调用从一个调度表表切换到另一个调度表。调度表之间的切换总是发生在调度表的末尾——也就是在处理完最后的过期点之后且完成了最后的延迟滴答数。
/* Start To after From has finished */
NextScheduleTable(From, To);
例8.6展示了如何进行API调用。
只有在由相同计数器驱动的调度表之间切换才有效。切换的两个调度表不需要有相同数量的失效点、相同的持续时间、相同的初始偏移量等。
当调用NextScheduleTable()时,From上的最后一个到期点和to上的第一个到期点之间的延迟由以下公式决定:
Delay = From.FinalDelay + To.InitialOffset
集成指导8.5:如果当前调度表的最终延迟为0,而下一个调度表的初始偏移量为零,则到期日之间的延迟将为零。
图8.12显示了从一个持续50的计划表切换到持续30的计划表的过程。
Figure 8.12: Switching between schedule tables
如果在From运行时多次调用NextScheduleTable(),则下一个运行的表将是在最近调用中指定的表。
集成指导8.6:如果停止From调度表,那么To调度表将无限期地保持在SCHEDULETABLE_NEXT状态。
图8.13显示了效果,其中调度表From在转换到调度表To之前停止,使To处于SCHEDULETABLE_NEXT状态。
Figure 8.13: Leaving a schedule table in the SCHEDULETABLE_NEXT state
这个问题的一个副作用是,应用程序将无法运行调度表To,因为不可能启动不在SCHEDULETABLE_STOPPED中的调度表。这个问题可以在运行时通过检查表是否正在等待,然后调用StopScheduleTable(To)将其状态重置为scheduleable_stopped来修复。
例8.7展示了如何实现这一点。
ScheduleTableStatusType FromState,ToState;
GetScheduleTableStatus(From, &FromState);
GetScheduleTableStatus(To, &ToState);
if ( (ToState == SCHEDULETABLE_NEXT) &&
(FromState == SCHEDULETABLE_STOPPED) {
/* Reset state of To */
StopScheduleTable(To);
}
StartScheduleTableAbs(To,99);
Example 8.7: Resetting the state of a schedule table
请注意,为了避免读取和计算状态条件之间的竞争条件,任何类似的代码都必须以与操作两个调度表的最高优先级操作系统对象相同的优先级执行。
End
「汽车电子嵌入式在CSDN上同步推出AUTOSAR精进之路专栏,本专栏每个模块完全按实际项目中开发及维护过程来详细介绍。模块核心概念介绍、实际需求描述、实际工程配置、特殊需求介绍及背后原理、实际工程使用经验总结。目的是让读者看完每一个章节后能理解原理后根据需求完成一个模块的配置或者解决一个问题。」
点击文章最后左下角的阅读原文可以获取更多信息
或者复制如下链接到浏览器获取更多信息
https://blog.csdn.net/qq_36056498/article/details/132125693
文末福利
2.为便于技术交流,创建了汽车电子嵌入式技术交流群,可尽情探讨AP,CP,DDS,SOME/IP等前沿热点话题,后台回复“加群”即可加入;
注:本文引用了一些第三方工具和文档,若有侵权,请联系作者删除!
推荐阅读
汽车电子嵌入式精彩文章汇总第一期:20210530-20230703
汽车电子嵌入式精彩文章汇总第2期
汽车电子嵌入式精彩文章汇总第3期
【OS】AUTOSAR OS Event实现原理
【OS】AUTOSAR OS Spinlock实现原理(下篇)
【OS】AUTOSAR OS Spinlock实现原理(上篇)
CanNm处于PBS状态下接收到一帧诊断报文DCM会响应吗
TC3xx芯片CAN模块详解
AUTOSAR OS Alarm实现原理
AUTOSAR OsTask切换原理
TC3xx 芯片SPI模块详解
AUTSOAR ComStack如何实现PDU只收不发的
AUTOSAR OsStack监控原理
AUTOSAR架构下ICU唤醒详解
CanNm报文的触发发送详解
Can报文能发不能收问题分析
End
欢迎点赞,关注,转发,在看,您的每一次鼓励,都是我最大的动力!
汽车电子嵌入式
微信扫描二维码,关注我的公众号