本篇文章续接上篇文章【ETAS CP AUTOSAR工具链】基本概念与开发流程,继续按上篇文章描述的ETAS CP工具链进行开发的基本框架,讲述了“RTE集成与配置”这部分的基本概念与开发流程。
RTE(Runtime Environment)处于应用层与基础软件层的中间,基于OS提供的接口完成不同周期任务的调度和各个组件之间信号的传递工作,文章较为详细的描述了整个RTE的配置以及代码生成过程。
目录
BSW:OS
BSW:RTE
RTE运行时环境配置与代码生成
RTE配置
ECU级模块配置信息收集
运行实体到操作系统任务的映射
RTE Generation阶段生成
RTE时应用层软件和基础软件的桥梁,所以RTE的开发一般在ECU级开发末期以及系统级的设计(应用层软件组件导入与系统/内部信号连接等)完成之后,具体完整的开发框架和流程详见【ETAS CP AUTOSAR工具链】基本概念与开发流程。所以在介绍具体的RTE之前我们先介绍一下与之相关的RTE与OS这两个基础组件。
这两个基础组件与其他基础组件不同之处在于,他们在生成BSW CodeGen之后并没没有生成对应的静态与配置代码(.c/.h文件),而是只有对应的arxml文件,可以从这点看出,这些配置需要被OS和RTE引用,它们影响的对应代码都生成在了OS CodeGen以及RTE Generation阶段。引用关系如下。
它们在基础软件组件中的位置如下。
BSW:OS
基础软件中的OS组件创建方式如下图。
我们需要配置的地方如下图为三个地方,其中OSTasks是我们在后边RTE配置中主要引用的配置。其余的配置会在别的组件中被引用。
OsAppModes我们配置为OSDEFAULTAPPMODE。
EcuM模块在启动OS的时候,会通过函数EcuM_Prv_StartOS传递OS的application mode,最终完成OS提供的启动OS的API:FUNC(boolean, OS_CODE) Os_StartOS(AppModeType Mode)调用。
下面定义系统Tick的名称。
他在需要使用Tick的别的基础组件中被使用。
最后,我们还需要配置所有的Task信息,这个是RTE引用的主要信息。
其中一下三个最基本的任务属性含义如下:
- OsTaskActivation:此属性定义任务的排队激活请求的最大数量。‘1’值等于表示在任何时候,此任务只允许一次激活。注意,该值必须是从1开始的自然数。
- OsTaskPriority:任务优先级,数字越大,优先级越高。
- OsTaskSchedule:任务可抢占属性,NON为非抢占式,FULL为可抢占式。
BSW:RTE
基础软件中的RTE组件创建方式如下。
这个组件我们需要配置的地方不多,大部分配置是在RTE配置的过程中自动引入的,在引入的基础上我们配置更多的信息。我们一开始主要需要配置的地方为RteGeneration。
其中是RTE生成的一些参数,包含RteIocInteractionReturnValue(RTE返回值基于多核还是正常)以及RteOptimizationMode(RTE代码生成器优化器模式,上图为速度优先)等配置。
剩下那两个配置项我们在RTE的具体配置时再进行交叉介绍。
RTE运行时环境配置与代码生成
RTE生成器一般可工作在两个阶段:合同阶段(Contract Phase)和生成阶段(Generate Phase)。
合同阶段主要用于应用层软件开发阶段,此时完整的ECU定义可能还没有完成,这样可以便于多方合作先行把相关的接口和数据流向梳理清晰,提前解决一些连接方面的问题。所以其输出文件仅为一些“.h”文件,主要包含类型定义和接口定义信息。RTE Contract生成示意图如下。
点击下图所示摁扭完成合同阶段的生成。
RTE配置
ECU级模块配置信息收集
首先,我们需要完成ECU级模块配置信息的收集(Ecuc Value Collection),通过下图完成对应的AR Element创建。
然后双击新建的Ecuc Value Collection,选择关联对应的ECU Extract和之前建立好的基础模块(Rte,Os等)。
下面我们就可以向其中添加各个模块的配置信息,添加方式如下。
然后,就可以向新建的Ecuc Value Collection中添加各个模块的信息,最终添加完成的界面如下。
因为我们提前建立了BSW:OS以及BSW:RTE等RTE相关的基础软件组件,我能可以在新建Ecuc Value Collection之后直接选择,我们同时也可以在RTE Configuration界面,点击Generate即可创建Rte模块,切换至OS Task Properties,点击Creat OSAppMode即可创建Os模块。
运行实体到操作系统任务的映射
切换到OS Task Properties,可以看到之前定义好的Task。
下面我们完成任务到系统Task的映射,我们如下图将右侧没有完成映射的任务拖拽到定义好的任务下即可, 《【ETAS CP AUTOSAR工具链】基本概念与开发流程》文中应用层组件设计的Runnables也在这里完成拖拽。其中Runables executed in callers contexts中添加的任务属于事件触发型(模式切换调用等)。
映射完成之后,即可在BSW:RTE组件中看到相关的信息生成,我们可以在这个基础上补充一些信息帮助RTE与其余的模块正常通信。
正如这个模块,我们需要补充RteBswRequiredModeGroupConnection,来连接RTE与BswM静态代码中定义好的不同模式下诸如BswM_Cfg_DfrdBswNotification_BswM_MRP_BswM_MDG_ECUM_STATE_SHUTDOWN()ECU模式通知函数,可以供给BswM等模块通知BswM模块进入不同ECU状态,执行对应的Action List。
应用层组件的Runnable映射添加会在下图的位置形成相应的配置信息。
RTE Generation阶段生成
在完成了RTE配置之后,就可以进行RTE生成阶段(Generation Phase)的生成,该阶段将主要生成如下配置文件。
- Rte_Types.h:通用的Type定义。
- Rte_<SWC Name>.h:应用API声明。
- Rte_<SWC Name>_Type.h:软件组件特定的Type定义。
- Rte.c::运行时环境函数定义、数据结构定义。
- Rte_Lib.c:静态RTE库函数。
- <Task Name>.c:Task函数实体。
- osNeeds.arxml::Os配置描述文件。
下图为RTE Generation阶段生成示意图。
点击ISOLAR-A主界面Generated RTE code,如下图所示。
在弹出的窗口选择RTA-RTE工具、文件生成路径,并选择General阶段(区别合同阶段),选择一个ECU Instance,然后输入Additional Commands,点击Finish即可完成代码生成。
下面展示一些RTE生成的代码。下面时软件组件向外发送系统信号,直接调用标准接口Com_SendSignal()。
FUNC(Std_ReturnType, RTE_CODE)
Rte_ImplWrite_SelfTest_CANSingle17(VAR(UInt8, AUTOMATIC) data) /* 1 */
{
VAR(Std_ReturnType, AUTOMATIC) rtn = RTE_E_OK;
Rte_Ms_000084 = data;
/* SpecReq: Send signal begin */
/* The signal is SelfTest */
if ( ((VAR(StatusType, AUTOMATIC))E_OK) != Com_SendSignal(((VAR(Com_SignalIdType, AUTOMATIC))134), &data) )
{
rtn = ((VAR(Std_ReturnType, AUTOMATIC))RTE_E_COM_STOPPED);
}
/* SpecReq: Send signal end */
/* Send complete */
return rtn;
}
其次,展示以下C/S接口的调用。因为是同步模式,可以看到直接调用了组件的Runnable:RE_SelfTest_func。
FUNC(Std_ReturnType, RTE_CODE)
Rte_Call_SlefTest_client_SetActiveFlg(VAR(Boolean, AUTOMATIC) SelfTest_ActiveFlg) /* 2 */
{
VAR(Std_ReturnType, AUTOMATIC) rtn;
/* SpecReq: Activate RE via Queue begin */
/* Parameter SelfTest_ActiveFlg has direction IN */
RE_SelfTest_func(SelfTest_ActiveFlg);
rtn = ((VAR(Std_ReturnType, AUTOMATIC))RTE_E_OK);
/* SpecReq: Measurement point CS begin */
/* SpecReq: Measurement point CS end */
/* SpecReq: Activate RE via Queue end */
return rtn;
}
最后,我们展示一个Task主体函数对应整个.c代码。可见名为ASW_OsTask_1ms的Task主体函数调用了先前映射到它上面的两个运行实体函数。
/** @file ASW_OsTask_1ms.c
*
* @brief Task ASW_OsTask_1ms body
*
* @note AUTOMATICALLY GENERATED FILE! DO NOT EDIT!
*
* @note Generated by ETAS RTA-RTE
* @note Version 6.6.0
*/
#define RTE_CORE
#include "Rte_Const.h"
#if !defined(RTE_VENDOR_MODE)
#pragma message "Compiling an individual task file but RTE_VENDOR_MODE not defined. Compiling a stale file?"
#endif /* !defined(RTE_VENDOR_MODE) */
#if defined(RTE_USE_TASK_HEADER)
#include "ASW_OsTask_1ms.h"
#else /* !defined(RTE_USE_TASK_HEADER) */
#include "Os.h"
#endif /* !defined(RTE_USE_TASK_HEADER) */
#if defined(RTE_REQUIRES_IOC)
#include "Ioc.h"
#endif /* defined(RTE_REQUIRES_IOC) */
#include "Rte.h"
#include "Rte_Intl.h"
#include "Rte_Type.h"
#include "Rte_DataHandleType.h"
/* Runnable entity prototypes */
#define Base_SWC_START_SEC_CODE
#include "Base_SWC_MemMap.h" /*lint !e537 permit multiple inclusion */
FUNC(void, Base_SWC_CODE) RE_Base_SWC_func(void);
#define Base_SWC_STOP_SEC_CODE
#include "Base_SWC_MemMap.h" /*lint !e537 permit multiple inclusion */
#define Os_SWC_START_SEC_CODE
#include "Os_SWC_MemMap.h" /*lint !e537 permit multiple inclusion */
FUNC(void, Os_SWC_CODE) RE_Os_SWC_OsTask_1ms_func(void);
#define Os_SWC_STOP_SEC_CODE
#include "Os_SWC_MemMap.h" /*lint !e537 permit multiple inclusion */
#define RTE_ASW_OSTASK_1MS_START_SEC_CODE
#include "Rte_MemMap.h" /*lint !e537 permit multiple inclusion */
TASK(ASW_OsTask_1ms)
{
/* Box: Implicit Buffer Initialization begin */
/* Box: Implicit Buffer Initialization end */
/* Box: Implicit Buffer Fill begin */
/* Box: Implicit Buffer Fill end */
{
/* Box: CPT_Os_SWC begin */
RE_Os_SWC_OsTask_1ms_func();
/* Box: CPT_Os_SWC end */
}
{
/* Box: CPT_Base_SWC begin */
RE_Base_SWC_func();
/* Box: CPT_Base_SWC end */
}
/* Box: Implicit Buffer Flush begin */
/* Box: Implicit Buffer Flush end */
TerminateTask();
} /* ASW_OsTask_1ms */
#define RTE_ASW_OSTASK_1MS_STOP_SEC_CODE
#include "Rte_MemMap.h" /*lint !e537 permit multiple inclusion */
RTE生成的代码中还会在跨任务的数据访问之间添加RTE_ATOMIC宏定义,在访问数据的时候调用Rte_SuspendOSInterrupts挂起中断,访问结束后使用Rte_ResumeOSInterrupts打开中断。
细心的读者可能会发现我们在配置RTE的过程中并没有配置具体任务的周期,这部分配置会在RTA-OS中Schedule Table中来配置。后边我们将OS的过程中再详细介绍。
十六宿舍 原创作品,转载必须标注原文链接。
©2023 Yang Li. All rights reserved.
欢迎关注 『十六宿舍』,大家喜欢的话,给个👍,更多关于嵌入式相关技术的内容持续更新中。