AP AUTOSAR & 确定性执行
-
- 发表于:2023-09-15 11:31 浏览量: 850 来源: 未知
摘要:确定性执行的概念主要包括三种:
1.时间确定性;
2.数据确定性;
3.完全确定性。
确定性执行是指:给定输入数据,在有限时间内产生一致的输出,也就是说行为是可再现的,这是确定执行的一个概念。时间确定性是指计算的输出始终在给定的某个时间点之前发生,即程序不能无限制地运行下去,需要有一个时间限制。数据确定性是指在给定相同的输入和内部状态下,计算将始终产生相同的输出,也就是说输出仅跟输入有关,与过程无关。先来看一下时间确定性,时间确定性的要求是每次开始计算时,需要保证在指定的时间内得到结果。为了满足这样的要求,要有一定的限制。为了保证时间确定性需要满足以下要求:1. 需要保证足够的计算资源,如处理器的时间、Memory、以及服务响应时间。2. 在违反确定性假设时,必须将它视为错误并启动恢复操作,如当超过了我们设定的时间时,必须去启动一个恢复操作,把它当成一个错误报告给这个 PHM。
数据确定性是指要保证输出的结果仅仅取决于输入数据。可以通过以下方式来满足数据确定性:1. 硬件锁步:通过两条不同的执行路径同时执行,然后比较它们的结果来验证一致性。完全确定性就是指必须同时保证时间和数据的确定性,需要说明的是当前 AP AUTOSAR 仅仅指定了一台 Machine 上的完全确定性。多台 Machine 上的确定性还没有指定,所以当前在使用完全确定性时,要局限在一台 Machine 上。如高度自动驾驶的系统需要满足 ASIL-D。为了满足 ASIL-D 的要求,高度自动驾驶系统需要采取特定的措施,特别是软件锁步,因为目前是没有 ASIL-B 以上的硬件。还有就是 HPC 的瞬态硬件错误率非常高,所以系统需支持可预测性和可靠性。利用确定性执行可以保证软件行为的可预测性和可重现性。所以,在对功能安全有一定要求以及它使用这种 HPC 的时候,我们需要考虑使用确定性执行。在 CP AUTOSAR 4.3 以及在 AP AUTOSAR 1810 之前,AUTOSAR 在概念设计和开发流程上是没有任何确定性相关的内容。为了实现安全上的一些要求,AUTOSAR标准在 CP 4.3 和 AP 1810 之后,加入了确定性相关的内容。接下来我们对 AP AUTOSAR 中的确定性进行一个深入解析。AP 中与确定性执行相关的模块只要是执行管理,下图为执行管理模块中的确定性执行交互概览图:上图中应用层中有用户进程,用户进程会调用确定性客户端的 API 实现确定性执行。确定性客户端 Class(在代码中是以 C++ Class 的形式存在) 是由执行管理来提供的。EM 中还有一些跟执行客户端相关的 Class,本文重点研究确定性客户端,执行客户端不做深入探讨。在 AP 中的实现确定执行主要也是通过确定性客户端这样的一个 Class 来实现。确定性客户端主要包括以下内容:2. 确定性的 Worker Pool(工作程序池)确定性客户端一般会跟软件锁步相互作用来确保冗余进程执行的相同行为。即当我们有一个用户进程时,还需要有另外一个用户进程(冗余执行进程),冗余执行进程和用户进程执行的内容需保持一样,此时需要由软件锁步框架来保障用户进程和冗余进程之间执行的一致性,软件锁步框架如下图所示:上图中最上面是用户进程,最下面是冗余用户进程。黑色线是数据流,进程之间的数据交互需要基于 ara::com 进行。然后 ara:: com 会跟软件锁步框架交互,来同步用户进程和冗余进程的数据输入。同时,用户进程以及冗余进程之间,也要与软件锁步框架进行交互,来去保证输出相同。最后将用户进程与冗余进程的输出的话它会进行比较,具体比较的过程以及同步的过程都是在软件锁步框架里面去做的。接下来分享一下周期性确定性执行,它其实就是确定性执行的一种。这里面我们会把冗余执行进程打开,去深入了解它的一个执行过程。前文有提到确定执行进程里面主要包括这几方面的内容:跟控制相关的;跟 Worker Pool 相关的;跟随机数相关的。跟控制相关的内容是一个 API ,控制触发和重复的一个 API ,让进程中主线程代码周期执行。控制 API 的作用是什么?它通过阻塞等待点来控制进程的执行,如下图所示:从图中可以看出首先是启动进程,然后去调用报告执行状态 API,这个 API 在执行 Client 的 Class 里 。需要说明的是,这里会有几个概念比较混淆:进程的状态、进程的执行状态、功能组的状态;这几个概念都是跟确定性执行相关的。我们在启动的时候报告的进程的执行状态,即用户进程给执行管理“我要执行了”,在当前 AP 版本中执行状态是一个枚举类型,当前只有一个值: kRunning 。报告完之后,用户进程会调用一个由确定性客户端提供的 API “WaitForActivation API”,这是一个等待点 API,就是上图中绿色的点,它描述的是一种状态的属性。改 API 会返回一个值,主线程会根据返回值,去执行不同的循环。循环执行完之后,如果再次调用 WaitForActivation API,意味着等待下一次激活。我们一直在说 WaitForActivation API,但是从上图可以看到,图中并没有WaitForActivation API,只有一个 WaitForNextActivation API。为什么?这是因为 AP 2011版本把 WaitForNextActivation 废弃了,改成了 WaitForActivation,我们以新版本进行的说明。再来看一下 WaitForActivation。刚才也提到了,主线程会根据 WaitForActivation的返回值去判断该怎么去执行循环,这个返回值其实控制的就是进程的执行模式,包括以下几种:
- kRegisterServices: 进程(通过ara::com)注册其通信服务
- kServiceDiscovery: 进程执行服务发现
kRun 是指周期性执行 kRun 的激活行为,包括两种:1. 定期激活:WaitForActivation 根据定义的周期,定期返回2. 事件触发激活:WaitForActivation 由外部 CommunicationEvent 触发返回。如由于数据到达后而产生的 Event 或 Timer 事件。在软件锁步中,我们是使用事件触发的激活行为来初始化和触发冗余执行进程的。需要注意的是,当它是冗余执行进程,而且它是事件触发周期激活的时候,它循环的一个 CycleTimeValue 是等于 0 的。Worker Pool 是一个锁定 API,它是在进程执行周期内使用的 ,它通过使用不同的线程,不同的工作池来加速软件的一个执行。Worker Pool 是由进程的主线程调用 API 触发的。 Worker Pool 调用完之后,它的一个呈现形式是进程池,进程池中有多个 Worker。它跟主线程之间是没有并行性。2. Worker Runnable Object需要说明的是 Worker 会有多个,多个Worker组成了 Worker Pool,Worker Pool下面是 Worker Runnable Object,它只有一个。需要注意的是多个 Worker 之间是不允许进行一个数据交换的。接下来分享一下确定性的随机数。这个随机数是根据确定性算法生成的,所以它生成的随机数是伪随机数。它有会提供一个 Get 随机数的函数,供用户调用。这就是随机数主要的作用,一是算法中可能会用到随机数粒子过滤器。另一个考虑确定性执行,我们需要将冗余进程以及用户进程之间的随机数种子进行同步。有两个地方会提供 Get Random 随机数 API,一个是确定性客户端 Class,一个是 Worker 线程 Class。当用户进程去调用 GetRandom 时,它使用的是确定性客户端提供的 API 。Worker 调用的是 Worker 提供的 Get Random,当 Worker 调用完 Get Random 后,它会使用 Container 迭代器,然后将随机数分配给特定的 Container 元素,Container 就是参数 Object,参数 Object 之间它会有迭代。Worker 调用 Get Random 之后,它会将随机数分配给特定的某一个元素,来去保证确定性冗余执行。至于我们的用户进程也是一样的,用户进程中的非冗余进程中的 Worker 调用 Get Random 随机数,拿到那个随机数也是需要给到特定的 Container 迭代,然后去把它的参数进行使用等这些。接下来是时间戳,时间戳是指当前周期被激活的时间点以及下一个周期被激活的时间点。当我们配置了下一个周期激活的时间时,它会返回这样的时间点。如果没配,就是仅返回当前周期被激活的时间点。确定性冗余执行需要同步时间戳:冗余进程和用户进程之间需要同步时间戳
这个时间戳是通过调用确定性客户端 API“获取激活时间戳”来获得的。 之前提到 WaitForActivation 它的返回值会传递到下一个周期,时间戳表示的就是 WaitForActivation 返回 kRun 触发激活的时间点,在返回 KRun 的时候,把这个时间点提供给进程。除此之外,还有一个就是获取下一个激活时间戳,就是表示下一个 KRun 周期的时间点,如果有的话就返回。需要注意的是冗余执行进程提供的时间戳,应该与主进程提供的时间戳相同。在 2011 更改了获取激活时间戳的传参类型以及返回值类型,在1911的时候,有个传参就是时间戳,但是在 2011 直接把这个传参给去掉了,然后多了个返回值,类型也不一样,在使用不同版本的工具的时需要注意一下。Deterministic Sync Master:同步控制点
接下来分享一下确定性同步 Master,它其实就是一个同步控制点,为WaitForActivation 中的定期激活与事件触发激活提供同步行为,举个例子下图所示:上图中有两个用户进程 APP1、APP 2 ;它俩都会去调用它们各自的执行管理的确定性客户端。如果它们之间要进行同步行为,就需要用到确定性同步 Master。首先确定性同步 Master 会等待一个请求,然后 APP1 要跟 APP2 同步,APP1 会调用 WaitForNextActivation,然后调用 ara::com 的Send 同步请求给到确定性同步 Master 。APP2 也是一样,它也会通过 ara::com 发送同步请求。同步请求完之后,确定性同步 Master 就会计算双方执行的下一个周期。比如说 APP1 先去触发了这样的一个执行,APP2 也先去触发了,要想把它俩同步,只能是在它们下一个周期去进行同步,所以 Master 需要计算它们之间的下一个时间。然后 Master 会将同步响应发送给它们,它们就会在下一个周期根据这个响应消息来激活时间,进行同步触发,APP1 和 APP2 就完成了同步触发的流程。1. 连接到 DeterministicSyncMaster 的 DeterministicClients 的数量2. 已连接的 DeterministicClients 所需同步请求的最小数量3. DeterministicClients 的 kRun 循环总数1. 对于单域同步, DeterministicClients 和 DeterministicSyncMaster 使用本地时间资源,如使用 std :: chrono API2. 对于多域同步, DeterministicClients 和 DeterministicSyncMaster 使用全局时间资源,如 GPS 时间Deterministic Sync Master:部署
怎么去部署我们这个确定性同步 Master?它有几种不同的部署方式:Deterministic Sync Master:同步控制消息
同步控制消息要指将请求和响应的消息进行一个同步于我们发送的同步请求是需要包含以下数据:1. Service ID:发送同步请求的Service ID2. Instance ID:发送同步请求的进程 Instance ID3. 前一周期的激活时间戳:用于计算下一个周期激活时间4. 当前周期的 Code:kServiceDiscovery; kInit; kRun5. 当前周期数:用于指定何时返回 kTerminate1. Service ID:发送同步响应的 Service ID2. Instance ID:发送同步响应的进程 Instance ID4. 下一周期的 Code:kRun; kServiceDiscovery; kTerminate接下来分享一下 CP AUTOSAR 中的一些确定性执行,跟 CP AUTOSAR 相关的确定性执行主要是 Timing 扩展(时序扩展)和逻辑执行时间。
时序扩展的目的就是为了提供指导构建系统的时间相关的需求,这是时序扩展的一个目的。另外一个目的是提供足够的时间信息来分析和验证整个系统行为。关于时序扩展里面比较重要的概念就是时序视图,它包括 VFB 时序视图,是包含与VFB 视图相关的时序信息、时序描述、时序约束等等。同理,还有 SWC 时序,包括的就是跟 SWC 相关的时序信息、时序描述和时序约束以及跟系统视图相关的这些时序信息、时序描述、时序约束。除此之外呢?还有 BSW Module Timing、BSW 组建 Timing、ECU Timing 。ECU Timing 其实就是指包含与 ECU 视图相关的时序信息、时序描述、时序约束。逻辑执行时间就是 LET,它是确定了从读入程序输入到写入程序输出所花费的时间,如图所示:左边红色标注是读取程序输入的时间点,右边红色标注是写入程序输出的时间点。它其实与实际进程执行的时间无关,也就是说我们只确定两个输入输出两个点,与实际进程执行时间是没有关系的。它其实就是以形式化的一个描述函数运行和同步方式,与目标硬件没有关系。LET(逻辑执行时间) 如何在 CP 开发中使用,如下图所示:如上图所示,一开始的架构设计与 CP 传统流程一样,架构设计后就需要考虑使用 LET 模型进行一个计算,主要干的一件事情就是仿真 LET 的一个配置,这个跟 LET 相关的。
接下来就是使用工具产生调度结果:包括实时内核配置等等,然后去对调度结果进行一个验证等等这些。
文章来源:汽车电子与软件