Classic AUTOSAR RTE

本文深入探讨了Classic AUTOSAR中的RTE(Runtime Environment)层,它是连接应用层(SWC)和基础软件层(BSW)的桥梁。RTE通过Sender/Receiver Port和Client/Server Port提供通信接口,确保数据完整性和解耦组件关系。此外,RTE作为运行时调度环境,支持Runnable的调度执行,并通过事件触发机制实现组件的并行开发和独立设计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       上一章节,我们介绍了Classic AUTOSAR三层架构中的Application层,主要讲解了Application中涉及到的相关元素(SWC,Port,Runnable等),下面我们来讲一下AUTOSAR三层架构中的RTE层。

       RTE是AUTOSAR中的一个重要的层次,在AUTOSAR中,RTE相当于1个虚拟功能总线一样,如上图,主要实现2种数据交互:

① 不同SWC之间的交互; 

       在不同SWC之间的交互过程中,RTE作为中间层,为SWC提供相应的接口,SWC之间不直接进行交互,当SWC需要发送相应的数据给其他SWC的时候,只需要调用RTE相应的接口,将数据发送给RTE即可,其他SWC读取数据时,从RTE里直接读取数据即可。

       在不同SWC之间交互时,SWC只需要通过Port接口对RTE负责即可,即RTE是作为不同SWC之间连接的桥梁;故在开发过程中,不同SWC只要约定好了和RTE之间的接口内容,不同SWC内部功能开发可以是独立的,相当于RTE解耦了不同SWC之间的关系。

② SWC和BSW之间的交互;

       在SWC和BSW之间的交互过程中,RTE作为中间层,分别为BSW和SWC提供接口,SWC和BSW只需要通过Port分别对RTE负责即可,即SWC和BSW内部开发内容是相互独立的,相当于RTE解耦了SWC和BSW之间的关系。

       SWCBSW的通信中,如BSW向上层提供的服务调用的时候,那么RTE会将BSW的服务以接口的形式提供给SWCSWC直接调用相应的接口即可完成相应的服务的调用。

1. RTE架构实现

       如下图,RTE是处于SWC与BSW之间的层次,主要的作用就是让SWC的设计和实现不依赖于底层BSW的实现,RTE为SWC和BSW提供了相应的接口,供他们进行使用和交互,这个交互可以是ECU内部的,也可以是ECU之间的。

       再进一步看,BSW层次里面也遵循了模块化、分层的原则,简单分成3层,分别为Service(服务层)、ECU Abstraction Layer(ECU抽象层)、Microcontroller Abstraction Layer(简称MCAL);

       Service层主要包括OS, Memory, ComM, CANSM, NM等的一些Service模块

       ECU抽象层主要包括一些Memory的硬件抽象层MemIf, 通信的硬件抽象层CanIf/LinIf/EthIf, 其他服务的一些抽象层等等,除此之外,还包含板载驱动和IOHWAB硬件抽象层;

       MCAL驱动层主要包含各种Driver驱动。

       对于APP、RTE、BSW三层架构而言,RTE解耦了APP和BSW,使得APP和BSW的设计和开发相关独立,为APP和BSW的并行开发提供了架构上的可能性。

 2. RTE作为通信接口

       RTE作为AUTOSAR软件架构下 “不同SWC之间” 以及 “SWC与BSW” 之间的通信媒介,它可以作为VFB(虚拟功能总线)的接口,提供了对应通信接口。

       在ECU内部,即 “不同SWC之间” ,可以走 “Sender/Receiver Port数据交互接口” 或 “Client/Server Port服务交互接口” 完成通信数据或服务交互,比如对应Rte_Read**/Read_Write**函数接口或Read_Call**接口;在ECU之间,即 “SWC和BSW之间”,也同样可以走这两种交互接口完成交互。

       RTE可以基于COM模块,比如CAN总线有数据接收更新时,COM模块会触发1个Callback函数,该Callback可以由RTE实现,然后SWC通过Port从RTE中获取最新的数据。

       除此之外,RTE作为通信接口,还可以支持如下特点;

① 支持简单和复杂数据结构;

       Rte作为通信接口进行数据或服务交互时,传输的数据结构可以是基本数据类型,也可以是根据需求定义的各种复杂数据类型。

② 保证数据完整性;

       比如,在使用Sender/Receive Port接口实现不同SWC之间数据交互时,如下图,SWC1在10ms的周期内调用接口写入数据,SWC2在5ms的周期内调用接口读取数据,如果数据类型是复杂数据类型,那么,当SWC2调用接口读取数据时,很可能出现SWC1也正在调用写入数据,这个时候,很容易出现数据一致性问题;针对这种情况,RTE层做了保护机制处理,即当调用Rte_Read或Rte_Write接口时,如果从设计调度上有数据不一致的风险,RTE会自动生成保护代码,避免数据不一致的情况。具体的细节保护内容,主要有终端锁等机制,后续章节中再进行详细介绍。

③ SWC支持1种类型的多个多实例化处理;

       对于有些功能组件SWC的设计而言,存在多个相同SWC组件多实例化的需求,比如说车身的左门和右门,除了方位的区别,在功能层面上是一摸一样的;在设计阶段,如果左门和右门作为2个SWC,相关的Port/Runnable等的设计都应该完全一样,RTE生成的相关内容也应该差不多。

       针对这种情况,存在1个SWC的多实例化处理选择,可以在创建SWC的时候选择多实例化选项,在实例化的时候,就可以创建多个一样操作的SWC了,当在1个SWC上面做相关设计操作时,其余SWC也会做同样设计操作。

2.1 Send/Receive Port

       对于Send/Receive Port接口,在数据传输时,如下图,主要分为 “SWC与SWC之间” 和 “SWC与BSW” 之间这2种交互方式。

① SWC与SWC之间的接口交互

       SWC与SWC之间的接口交互,主要应用于ECU内部的功能组件之间,如SWC1与SWC2之间的数据交互,SWC1或SWC2只需要对RTE进行负责即可。SWC1调用Rte_Write_<Port>_<Data>接口将数据写入到RTE的Buffer中,SWC2调用Rte_Read_<Port>_<Data>接口从RTE的Buffer中读取数据。

② SWC与BSW之间的接口交互

      SWC与BSW之间的接口交互,主要应用于ECU之间,如ECU1的SWC2与ECU2的SWC3之间的数据交互,SWC2或SWC3也只需要对RTE进行负责即可。ECU1的SWC2调用Rte_Write_<Port>_<Data>接口将数据写入到RTE的Buffer中,RTE进一步调用Com_SendSignal函数将数据写到Com的PDU中,再通过BSW将数据发送到总线上去;ECU2收到总线上的数据时,数据通过BSW传递到COM层的PDU中,ECU2的SWC3通过调用Rte_Read_<Port>_<Data>接口读取数据,RTE会调用Com_ReceiveSignal接口将数据从COM层的PDU读取出来。

 2.1.1 Explict显性接口

       Send/Receive Port在做数据传输时,通信双方只需要对RTE负责,对应的数据在RTE中会有对应的GlobalBuffer,如下图,在调用Send Port接口或Receive Port接口去写入或读取RTE GlobaoBuffer内容时,如果配置为 “Explict显性接口”,那么访问的GlobalBuffer内容始终是最新的,对应接口为Rte_Read_<Port>_<Data>或Rte_Write_<Port>_<Data>。

       比如说,数据发送方Send Port以1ms周期发送数据,数据接收方Receive Port以10ms周期接收数据,如下图,如果是 “Explict显性接口”,那么,数据接收方Receive Port始终获取的是RTE中GlobalBuffer的最新内容。

2.1.2 Implict隐性接口

       Send/Receive Port在做数据传输时,当发送方和接收方数据收发周期不一致时,收发数据方可能希望在1个任务周期内访问的数据是一致的,这种需求,就需要 “Implict隐性接口” 来实现了,对应接口为Rte_IRead_<Port>_<Data>或Rte_IWrite_<Port>_<Data>。

       如下图,在Runnable执行期间调用Receive Port接口获取数据,在这种情况下,Runnable执行之前,该Runnable中需要访问的Receive Port对应的RTE GlobalBuffer会先把内容拷贝到CopyBuffer中,在Runnable运行期间,无论何时调用Receive Port访问数据,都是获取的是CopyBuffer中的数据,保证该Runnable运行期间,得到的数据都是一致的。

2.1.3 Queue队列机制处理

        基于Send/Receive Port中的 “Explict显性接口”,当接收双方周期不一致时,比如说Send Port发送方周期为1ms,Receive Port接收方周期为5ms时,当Receive Port接收方读取数据时,只能够读取到RTE中GlobalBuffer的最新值,在上个5ms周期间隔期间,至少会丢失4次数据,但实际需求可能是需要所有接收到的数据。

        基于这种需求,RTE提供了Queue队列机制,如下图,GlobalBuffer中存在多个Buffer,可以起到缓存的作用,Receive Port接收方可以获取Queue里面所有缓存的值。

2.1.4 无效值处理

       在Send/Receive Port传输数据过程中,可能存在传输数据内容超出设定范围等情况,针对这种无效值的情况处理,RTE会生成RTE_Invalidate_...Rte_IInvalidate_...的接口,在发送到Invalid数据时,可以调用这种接口来进行Invalid无效值/非法值的设置。

       如果接收端接收到的数据是无效Invalid的,对于Explict显性接口,通过Rte_Read函数可得到函数返回值RTE_E_INVALID,否则是RTE_E_OK;对于Implict隐性接口,通过Rte_IStatus_...返回无效的结果RTE_E_INVALID同时,当有无效值/非法值得时候,这个错误事件本身可以作为1个DataReceiveErrorEvent,触发Runnable的执行。   

       在Send/Receive Port接口创建的时候可以进行无效值范围的设置,一般可通过InvalidData数据限制(DataConstraint)进行配置HandleInvalidReaction的配置。 

2.2 Client/Server Port

        Client/Server Port的交互主要侧重于服务调用,也包含数据传输的特性,在进行服务的请求调用时,ClientServer支持的是n:1的方式,就是你nclient可以调用一个服务。   

        Sever的实现操作在SWC中是以ServerRunnable的形式去实现,相当于1个功能服务函数,Client端调用执行时,会调用ServerOperation来执行相应的操作,Server端正常作为一个SWC的一个ServerRunnable来进行实现。

         Client/Server的调用方式支持同步和异步两种调用的方式,对于ServerRunnable,它主要运行在两个环境,一种是在客户端的逻辑中,即直接的函数调用,当Client端调用时,Server端直接嵌套执行完成;另一种是在Task任务中,当Client端调用时,对Server端下发一个触发执行请求,Server端一般运行在Task任务中,接收到这个触发请求之后,再触发执行,而Client端下发完成请求之后,继续直接执行Client端的后续内容的执行。

2.2.1 Synchronous同步处理接口

       同步调用的处理,当Client端调用Port的时候(Rte_Call_**),触发ServerServerRunnable的执行,Client端会Block在那里,等待ServerRunnable执行完成并返回结果给Client端。

      ServerRunnable在执行的时候,Client也不会一直Block在那里,会有一个Timeout的超时计时;如果在Timeout超时之前,Server端正常执行结束,结果会正常返回给Client端;如果Server端在Timeout超时之后还未执行完,发生超时,那么TimeoutError会报出来。

      Client/Server Port一般用的是同步的,也可以做异步的;同步的CSPort相当于嵌套函数的调用;异步的CSPort,需要将ServerRunnable Map到对应的Task上,可用于不同ASIL等级的OSApplication上,也可用于不同Core上的Task(不同Core上的CSPort需要采用IOC机制实现数据交互);当然,CSPort中的ServerRunnable也可MapTask上,此时,Client端调用相当于发送1Request请求(相当于给ServerRunable设置1SetEvent)ServerRunnableRTE调度。

2.2.2 Asynchronous异步处理接口

      异步调用的处理,Client端调用服务的客户端不会被BLOCK掉,不会等待执行结果的到来;异步调用中Client端可以采用 “Polling” 或者 “Waiting” 的方式来进行结果的检查(RTE会提供相应的接口给SWC来调用)。“Polling” 方式,Client端采用轮询访问的方式去查询结果;Waiting” 方式,Client端在调用接口查询结果时,会一直Hold在这边,等待Server端执行完成,这种有点类似于同步调用的机制了,区别在于Client端可以决定何时查询结果。

       CSPortAsynchronous调用,分为4种方式;

      如果配置成None的方式,Rte_Result**函数接口不生成(返回结果只返回Client端请求的结果,RTE_E_OK代表请求成功,RTE_E_LIMIT代表请求未成功,但不确定Server端是否执行正常)Client端与ServerOperation的执行,通过几个标志位实现(Complete,Active等,比如ServerOperation执行完之后,CompleteFlag重新置为True,然后Client端根据判断CompleteFlag是否True进行再次调用)

      如果配置成Polling方式,Rte_Result**函数接口生成,需要Client端自己周期性(周期自己决定)去调用Rte_Result**函数去Polling请求结果,Client端、ServerOperationRte_Result**函数之间的顺序调用,通过在Polling方式几个标志位的基础上再添加ClientFlag标志位;Client端根据判断ClientFlag标志位为1,执行进一步的调用操作,将ClientFlag标志位置为0CompleteFlag置为0Active置为1ServerOperation执行完之后,Active置为0Rte_Result**函数判断ClientFlag标志位为0CompleteFlag1,将ClientFlag置为1并返回函数结果(结果为RTE_E_OK/RTE_E_NO_DATA)

      如果配置成Waiting方式,Rte_Result**函数接口生成,Client端一旦调用Rte_Result**函数去请求结果时,会WaitEvent一直等Server端执行完,ServerRunnable执行完之后会SetEvent,然后Rte_Result**函数可以继续执行返回结果(结果为RTE_E_OK/RTE_E_TIMEOUT)Wait过程相当于进入IdleTask状态,故Waiting方式下Rte_Result**函数最好放在单独的Task或该Task中其他任务不重要;WaitTimeout机制代码会自动生成(Timeout0,相当于没配置Timeout,对应的Timeout机制不会生成)

      如果配置成以上三种方式,再重新配置1Runnable,选择OnOperationCallReturn的方式,在ServeRunnable执行完会SetEvent触发配置的Runnable的执行,相当于1Callback函数,在该Runnable中可以手动调用Rte_Result**函数去请求结果(结果为RTE_E_OK/RTE_E_NO_DATA)。

3. RTE作为运行时调度环境

       RTE是Runnable运行实体的运行时环境,它可以为Runnable执行调度提供触发机制,主要有以下特点:

① RTE主要是配置,没有静态代码,代码一般都是配置生成代码;对于不同的ECU,RTE的最终实现是不同的,因为每个ECU它实现的功能都是不同的,它的SWC不同,那么相对于的各种配置就是不同;

② RTE对OS和BSW进行了抽象,在设计上层SWC时,不需要关心底软BSW的服务机制和OS的运行机制,即SWC的设计只需要对RTE负责;

③ Runnable运行实体的调度是由RTE的事件来触发执行的,根据 “SWC的Runnable和TASK的映射关系” 配置生成RTE;

       那么,RTE作为运行时调度环境,是如何通过RTE的事件触发调度SWC的Runnable运行的呢?下图,OS作为底层调度,在满足RTE Event事件时,触发调度Runnable的执行,实际上来说,Runnable的触发和运行,是依赖于OS和RTE这两者一起的。

       除此之外,RTE还可以提供Rte_Start和Rte_Stop的接口,一般来说,Rte_Start在程序启动初始阶段Active相关的OS Task或Set相关的OS Alarm等,Rte_Stop在程序结束阶段Deactive相关的OS Task或Cancel相关的OS Alarm等。

       RTE Event触发事件支持的类型如下:

① Init,初始化触发事件,对应触发初始化Init Runnable,初始化执行一次;

② TimingEvent,时间触发事件,一般触发周期执行Runnable;

③ DataReceiveEvent,接收数据触发事件,一般接收到数据之后触发执行Runnable;

④ DataReceiveErrorEvent,接收数据错误事件,一般接收数据发生错误时触发执行Runnable;

       还有其他的Event类型,比如Background事件、Com模块的Notification事件等等,这里就不逐个列出了,后面具体应用时再逐渐体会。

4. 总结

       以上内容即为 “AUTOSAR RTE” 的整体内容了,后面我们将会持续更新AUTOSAR BSW相关内容、AUTOSAR方法论等内容,包含BSW层架构、典型协议栈模块的功能原理和开发内容示例。

       敬请期待......

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

AUTOSAR普及侠

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

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

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

打赏作者

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

抵扣说明:

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

余额充值