Adaptive AUTOSAR 平台接口使用指南

1 本文的介绍

1.1 内容

虽然FC的SWS 是ARA接口规范,但有些接口需要如何使用的“指南”。这份指南确实跟规范相关,但是有些是间接的,并且在每个SWS中都包含这些信息,因此读者很难理解其用法。另一个重要的角度是这些指南是AA 遵守的需求,但是FC的SWS是FC的需求规范。因此,在SWS中包含这些内容不太合适,这就是这本文档的目的。

如上所述背景,这份文档的主要内容是应用程序遵守的指南。不是所有的FC在这份文档中有内。当它认为有效时,它们将被添加。

内容是按照相关的话题组织的,但是一般情况下,按照FC组合一起,每个都有独立的章节。并且,请注意这些内容提供在单独的AUTOSAR AP 文档中。如果是这种情况,这种文档会被列出来或引用这份指南。

1.2 预读

这份文档是AP SWS的补充文档。因此,这份文档里的话题相关的SWS应该同步阅读。并且,应该阅读的第一份文档是Explanations of Adaptive Platform Design, AUTOSAR_EXP_PlatformDesign.pdf.,这份文档介绍了AP的架构

1.3 和其他AUTOSAR规范的关系

参考内容和预读

2. 核心类型

2.1 错误处理

错误处理对任何软件开发都是重要的话题。对于安全关键软件,它更重要,因为软件生命要依靠它。但是,目前的标准对安全关键软件的开发加了很多的限制,比如创建工具链,特别是关于C++异常。对ASIL应用程序,使用C++异常通常是不可能的因为缺乏对asil认证的c++编译器的异常支持。

Adaptive平台介绍了一个概念使没有C++异常的错误处理成为可能并定义了大量的c++数据类型来辅助这个概念。

从应用程序编码者的观点来看,核心类型实现这个概念的是 ara::core::ErrorCode和ara::core::Result.

2.1.1 ErrorCode

ara::core::ErrorCode的实例表示软件内的一个特定的错误条件。和std::error_code类似,但是在很多方面都不相同。

ErrorCode一直包含一个枚举值(类型擦除为整型)和一个错误域的引用。这个枚举值描述了错误的特定类型。错误域引用定义了错误应用的上下文。其他可选的成员一个是用户定义的消息字符串,一个是厂商定义的补充错误描述值。

2.1.2 Result

类ara::core::Result遵守来自C++建议 p0786中“ValueOrError”的概念。它包含一个value或一个error。由于模板特性,value和error可以是任何类型。但是,错误类型默认为ara::core::ErrorCode,而且希望整个Adaptive平台都能保持这个分配。

因为ErrorType默认为ara::core::ErrorCode,ara::core::Result的大部分声明仅需要给一个ValueType,比如对Result类型ara::core::Result<int>包含一个int变量或一个ErrorCode.

ARA接口使用ara::core::Result作为可恢复错误函数的返回类型。这个类型或者用来从对象中生成C++异常,或通过未使用异常的观察者方法中提取错误信息。

这部分指导你在应用程序代码中如何处理从ARA接口中返回Result对象。并且指导你如何在自己的Adaptive应用程序中创建新的Result对象。

2.1.2.1 Result的创建

使用嵌入值创建Result,有构造函数允许从ValueType隐式转换。这样用value来定义Result非常直接。

Result<int> res1(42);

Result<int> res2 = 42;

从声明返回Result的函数中返回一个value也是同样的直接。

Result<int> myfunction()

{

return 42;

}

把error放进Result中需要调用显示构造函数,比如:

ErrorCode ec = MyEnum::some_error;

Result<int> res2(ec);

另外,在静态成员函数中构造Result对象也是可能的。比如:

Result<int> res1 = Result<int>::FromValue(42);

Result<int> res2 = Result<int>::FromError(ec);

当Value Type或ErrorType Copy 代价非常昂贵的时候,这些形式是非常有益的。比如,返回的Reslut包换一个BigClass的实例。这个BigClass有两个构造参数"a1"和"a2"构建。像这样:

return Result<BigClass>::FromValue(a1, a2);

对于ErrorType,也允许ErrorCode实例的隐式构建,包含一个自定义错误消息和/或一个支持数据值。

return Result<BigClass>::FromError(

MyEnum::some_error, // ErrorCode enum value

"this operation did not work", // custom error message

0x12345678 // support data value

);

这种形式构建,只需要 执行一次构造函数。不像普通的构造函数调用,至少要执行两次构造操作,因为预先创建的值必须copy或move到Result实例中。

2.1.2.2 提取value和error

当试图从Result中提取value和error的时候,首先要考虑的是value或error是否真实可用。通常情况下,这是未知的,所以必须小心处理者两种情况。

当没有使用异常工作的时候, 要先查询Result对象是否包含value或error.

Result<int> some_function() { … }

Result<int> res = some_function();

if (res.HasValue()) {

int theValue = res.Value();

} else {

ErrorCode const& ec = res.Error();

}

这段代码在没有异常的环境中也可以完全工作,包括编译器完全不支持异常操作。

当处理异常工作流是,查询代码看起来更像普通的异常代码:

Result<int> some_function() { … }

int theValue = some_function().ValueOrThrow();

由some_function()返回的Result对象通过调用它的ValueOrThrow()成员函数快速归到它的ValueType(int)。事实上,如果Result确实包含一个ErrorCode,会立刻抛出一个对应到嵌入的ErrorCode对象的异常类型。自然,try...catch快应该添加到代码中一个合适的位置。

2.1.2.3 高级话题

提取嵌入的value或error两个借本的方法是Result::Value()和Result::Error()。但是,在调用任何这些函数时,必须确定Result对象确实包含调用这些函数之一所隐含的内容。在前面的部分,首先调用Result::HasValue(), Value()或Error()的调用依赖这个调用的输出。

另外一个访问嵌入value更方便的方式,之前的部分已经提过,通过调用Result::ValueOrThrow, 不需要if语句,整个调用只需要单行语句(不包含try...catch块,这个块可能在其他地方存在)。

其他方便的方法,比如Result::ValueOr提取value, 如果不存在就取默认值。比如:

int res = some_function().ValueOr(42);

Result :: ValueOr的一般化称为Result :: Resolve,它不使用默认值作为参数,而是一个Callable,它可按需创建默认值:

int res = some_function().Resolve([](ErrorCode const& ec){ return 42; });

对这种特殊的例子,使用Result::Resolve而不是Result::ValueOr没有意义。但是当常见默认值代价很昂贵的时候,可能是有意的。通过使用Result::Resolve,只有当确实需要的时候才会创建默认值。

另外一个方便的方法是Result::Bind,允许将包含的value转成另外一个value,甚至是另外一个类型,比如:

Result<String> res = some_function().Bind([](int v){ return v + 1; }).Bind([](int v){ return std::to_string(v); }).Bind([](String const& s) { return "'" + s + "'"); });

第一次调用Result::Bind()获取包含在Result对象中的value,加1之后,放入一个新的Result对象中并返回。

第二次调用Result::Bind()获取包含在Result对象中的value,将它转换成String,返回新的带有此字符串的Result<String>。

最后一次调用Result::Bind()获取包含在新的Result对象中的String对象,加上引号,放入其中并返回新的Result对象。

如果Result没有包含value, 那么这些可调用项都没有,Result对象仅进行类型转换,但保留原始的ErrorCode。

传递给Result :: Bind的Callables必须采用合适的类型作为参数,并且可以直接返回ValueType(如之前所说,或者和前面ValueType相同,或者一个新的,不同的ValueType),或Result<ValueType>。

3 执行管理

3.1 执行状态

执行状态描述了任何进程的内部生命周期。每个进程都需要给执行管理报告执行状态的变化,使用ExecutionClient::ReportExecutionState()接口。

一旦进程启动,当报告了KRunning状态,执行管理就认为进程初始化完成(见[SWS_EM_01053])。请注意Service Discovery会引入不确定性的延迟,因此建议在报告kRunning状态后进行;因此进程有可能在报告KRunning状态时初始化还没有完成。

执行管理通过向进程发送SIGTERM信号来启动进程终止。一旦收到SIGTERM,进程通过向执行管理报告kTerminating状态确认状态变化请求(见SWS_EM_01070)。

如果是自终止进程,进程会通过想执行管理报告kTerminating状态来启动自终止(见[SWS_EM_01071)。

报告kTerminating之后,进程会保存持久数据并释放所有内部使用的资源。进程通过简单的推出表明Terminating状态的完成(伴随合适的退出码)。执行管理不需要进程本身明确的进程终止的通知。

3.2 确定性执行

执行管理支持完全确定的进程多线程执行,因此处理给定的输入数据会在限定的时间内产生一直的输出,比如行为是可重现的。

在AUTOSAR Adaptive平台中,要求这种确定性的用例包括在高安全目标系统的软件Lockstep框架中的冗余执行和重用已验证的软件。更多的细节可以见Specification of Execution Management, AUTOSAR_SWS_StateManagement.pdf,“Deterministic Execution”部分。

可以完全确定地执行的进程必须以某种方式设计,实施和集成,使其独立于其他功能和计算,零星无关事件,竞争条件,偏差随机数等导致的处理器负载。

不确定行为可能有不同的原因造成,比如,计算资源不足或数据的不协调访问,很可能是由多个处理器内核上运行的多个线程造成的。线程访问数据的顺序也会影响结果,是结果不确定。

完全确定的执行包括:

*时间确定。计算的输出一直在给定的最后期限前产生。进程的资源需求需要以标准的方式描述,所以集成者能给进程分配足够的资源。(见Specification of Execution Management, AUTOSAR_SWS_StateManagement.pdf,“Real-Time Resources”部分)。

*数据确定。给定相同的输入和内部状态,计算也一直会产生相同的输出。这个部分剩下的部分将会描述如何达到数据确定。

执行管理提供DeterministicClient库功能来支持确定执行。

* 通过等待点API控制流程内部周期WaitForNextActivation()([SWS_EM_01301])。当API返回时,进程应执行一个循环,然后再次调用API以等待下一次激活。这个API的返回值控制进程的内部生命周期(比如:初始化,运行,终止),必须对其进行相应的准备。([SWS_EM_01302], [SWS_EM_01303] and [SWS_EM_01304]).

* 阻塞确定性工作程序池API RunWorkerPool()([SWS_EM_01305]),用于执行一组容器元素([SWS_EM_01306]),这些容器元素由同一工作程序运行对象(即应用程序功能)并行或顺序处理。

* APIs GetActivationTime() ([SWS_EM_01310]) 和 GetNextActivationTime() ([SWS_EM_01311]) 提供激活时间戳。这个时间戳不会改变指导进程达到下一个等待点。

* API GetRandom()提供随机数([SWS_EM_01308])。如果从工作程序池中使用,则将随机数分配给特定的容器元素,以允许确定性的冗余执行。

为了保证确定行为,确定性用户进程只可使用只有所有可用API的“确定性”子集,包括工作程序运行对象:

* 进程不允许通过自己使用普通POSIX进程创建线程或直接访问任何其他POSIX APIs,以规避包含不确定行为的风险。

* 进程只允许使用所有可用的ara::com机制的“确定性子集”。稍后将提供此类API和机制的详细列表。

* 只有下面的ara::exec接口被使用:DeterministicClient和ExecutionClient。

* 用户进程不允许访问其他ARA接口。

如果使用工作程序池API RunWorkerPool(),处理容器元素的工作程序运行对象,比如计算工作,需要满足某些实现规则来确保数据确定性:

* 运行对象在它运行的时候不允许交换任何信息。比如,它不会访问可运行对象的其他实例可以更改的数据,以避免出现竞争情况。

原理:运行对象可以物理的并行运行或以任何顺序有序运行。不能保证单个工作程序的时间。操作系统单个调度线程。相同数据的同时影响会导致不确定的结果。

* 除了通过从RunWorkerPool()返回对于所有工作程序来说通用的联接,没有锁和同步点(例如,没有信号/互斥量,没有锁/阻塞)。

原理:锁定/阻止使Process运行时不确定。提供了工作程序以增加运行时的利用率。 如果需要同步,则必须从RunWorkerPool()返回。

工作程序池不能用来并行处理多个不同的任务。使用多个可能不同的显式函数(工作程序可运行的对象)可能会增加不必要的复杂性,并可能导致运行时间利用率极不相同,因为每个工作程序有不同的计算时间。这会使资源部署的计划复杂化,这对于黑盒集成来说是必需的。

工作程序池用户的实现例子。比如:工作程序运行对象的例子:

class MyWorker1

: public DeterministicClient::WorkerrunnableBase<myContainer::

value_type, MyWorker1>

{

public:

void worker_runnable(myContainer::value_type& container_element,

DeterministicClient::WorkerThread& t)

{

// Get a unique and deterministic pseudo-random number}

uint64_t random_number = t.GetRandom();

}

};

工作程序线程对象:

class DeterministicClient::WorkerThread

{

// returns a deterministic pseudo-random number}

// which is unique for each container element}

uint64_t GetRandom();

...

};

4 状态管理

4.1 AUTOSAR Adaptive(平台)应用程序的交互

4.1.1 基本的状态管理功能

状态管理通过ara :: com提供了一组“Trigger”和“Notifier”字段。状态管理本质上侦听“Trigger”,并在内部执行特定实现的状态机处理,并在“Notifier”字段(如果有)中提供效果。状态管理还通过它们提供的标准接口与其他FC进行交互。

使用这个机制还可以达到下面的效果:

* 可以要求将功能组设置为专用状态。

* (部分)可以请求取消/激活网络

* 可以请求机器关闭或重启。

* 其他Adaptive(平台)应用程序的行为可能会受到影响

* 可以执行项目特定的动作

其中一些功能至关重要。因此,集成者必须通过IAM管理适当地保护对“Trigger”字段的访问,以免意外更改状态管理的内部状态(并因此而改变相关影响)。

状态管理的内部状态通过其提供的“Notifier”字段通知到系统。对这些字段的读取访问权限不太重要,因此,每当状态管理的内部状态发生更改时,每个Adaptive(平台)应用程序都可以注册其事件以收到通知。

因此,当状态管理的状态发生变化时,每个Adaptive(平台)应用程序都可以执行操作(需要时)。

4.1.2 高级状态管理功能

AUTOSAR Adaptive中的一些用例需要在状态管理所管理的状态中支持同步行为。。比如低功耗模式:一个示例可能是低功耗模式:只有当所有参与此低功耗模式场景的Adaptive(平台)应用程序都最终准备好用于低功耗时,状态管理才能最终切换到低功耗状态(例如,持续存在 其信息)。

因此每个要求支持这种同步工作模式的Adaptive(平台)应用程序必须通过ara::com提供这个字段。状态管理器可以通过FindService找到这个字段,状态管理器可以在以后注册,以便在Adaptive(平台)应用程序执行其操作时收到通知。

Adaptive(平台)应用程序必须完成的三件事,才能支持同步方案:

* Adaptive(平台)应用程序应注册状态管理器的相应“触发”现场事件(在满足状态管理中的条件时通知)

* Adaptive(平台)应用程序应为最终状态做任何准备工作

* Adaptive(平台)应用程序应将先前操作的结果写入其提供的字段

为了使状态管理认识到一个Adaptive(平台)应用程序想要成为同步场景的一部分,Adaptive(平台)应用程序不得不尽可能的提供它的字段服务使非常有必要的。并且当Adaptive(平台)应用程序不想再成为其中的一部分时,它不得不停止提供服务(例如 申请将完成)。

Adaptive(平台)应用程序的接口应该遵循状态管理的“TriggerOut”接口的模式。

5. 参考文档

[1]Explanations of Adaptive Platform Design, AUTOSAR_EXP_PlatformDesign.pdf.

[2]Specification of Execution Management, AUTOSAR_SWS_StateManagement.pdf.

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自适应autosar平台先关的文档资料 为适应新用例的需求,AUTOSAR开发了自适应平台。 一个突出的例子是 高度自动化驾驶,在该环境中,驾驶员暂时和/或部分地将驾驶责任转移给车辆。 这种情况下需要与交通基础设施(例如交通标志、交通灯)、云服务器(例如访问最新的交通信息或地图数据)等进行通信,或使用微处理器和高性能计算硬件进行并行处理(例如GPU)。 此外,Car-2-X应用还需要与车辆和车外系统进行交互沟通。 这意味着该系统必须具备安全的车载通信功能、支持跨域计算平台、智能手机集成、非AUTOSAR系统集成等。 此外,还需要采取专门的措施,保证云服务的安全,例如安全云交互和应急车辆优先。 它们可支持远程和分布式服务,例如远程诊断、空中下载(OTA)更新、修复和交换处理。 AUTOSAR目前正在对AUTOSAR自适应平台进行标准化处理,使其支持客户应用的动态部署,并为需要高端计算能力的应用提供适宜的环境。 该平台的核心是基于 POSIX 标准的操作系统。 根据IEEE1003.13(即PSE51),操作系统可以通过POSIX的子集从应用中调用。 自适应平台的一个关键特性是面向服务的通信。 自适应平台可以使用两种类型的接口:服务和应用程序编程接口(API)。 该平台由分布在服务层中的功能聚类和AUTOSAR自适应平台基础组成。 功能聚类: 汇编自适应平台的功能2016 确定需求规格说明书的聚类2016 从应用和网络角度描述软件平台的行为2016 但是,不得限制实现自适应平台的架构的最终软件设计。2016 AUTOSAR自适应平台基础中的功能聚类在每台(虚拟)机器中必须至少有一个实例,而服务则可以分布在车内网络中。 自适应平台服务包括: - 更新和配置管理 - 状态管理 - 网络管理 - 诊断 AUTOSAR自适应平台包含规范和代码。 与经典平台相比,AUTOSAR开发的实现可缩短验证周期并说明基本概念。 该实现适用于所有AUTOSAR成员。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值