前言
Autosar Dem中一般使用两个函数来实现DTC的逻辑,一个是Dem_SetEventStatus,用来设置DTC故障状态,一个是Dem_GetEventFailed,用来获取当前的故障状态。Simulink中也提供了对应的模块,用来实现应用层中的故障DTC状态设置与获取,本文介绍其实现过程
Autosar Dem接口
Autosar Dem标准接口为DiagnosticMonitor和DiagnosticInfo,使用Simulink中自带的demo-autosar_bsw_monitor中的定义,如下所示:
DiagnosticMonitor中包含了SetEventStatus函数,DiagnosticInfo包含了GetEventFailed函数。
需要注意的是:生成的package位置为/AUTOSAR/Services/Dem(暂时没找到怎么修改),而在使用时,导入对应Autosar工具(例如Etas)时可能会找不到对应的定义。此处我们后面是手动更改arxml中的package路径,理论上来说应该有更好的方案
设计模型及接口
设置三个Client port,两个为DiagnosticInfo接口,一个为DiagnosticMonitor接口,名称参考ETAS Dem中生成的PPort名,DiagnosticInfo接口对应的名称为Event_DTC_0xXXXXXX_Event,DiagnosticInfo接口对应的名称为EvtInfo_DTC_0xXXXXXX_Event
也可以在Simulink模型中添加对应的Autosar模块,并配置其参数,然后点击刷新,可以自动生成对应的Client Port
添加对应模块,DiagnosticInfoCaller用来调用GetEventFailed,DiagnosticMonitorCaller用来调用SetEventStatus
配置对应的Client port名,及对应的使用的函数
点击刷新,可以自动创建对应的port
此处示例模型很简单,通过获取三个dtc状态,来触发另一个dtc,并没有什么实际意义
生成代码及arxml
生成的代码中调用了RTE函数Rte_Call_EvtInfo_DTC_0xXXXXX_Event_GetEventFailed用来获取故障状态,调用RTE函数Rte_Call_Event_DTC_0xXXXXXX_Event_SetEventStatus用来设置故障状态,示例如下:
/* Model step function */
void Runnable_Step(void)
{
float32 rtb_Switch1;
Dem_EventStatusType tmp;
boolean rtb_EvtInfo_DTC_0xffff11_Even_i;
boolean rtb_EvtInfo_DTC_0xffff12_Even_l;
boolean rtb_EvtInfo_DTC_0xffff15_Even_f;
/* FunctionCaller: '<Root>/EvtInfo_DTC_0xffff11_Event' */
Rte_Call_EvtInfo_DTC_0xffff11_Event_GetEventFailed
(&rtb_EvtInfo_DTC_0xffff11_Even_i);
/* FunctionCaller: '<Root>/EvtInfo_DTC_0xffff12_Event' */
Rte_Call_EvtInfo_DTC_0xffff12_Event_GetEventFailed
(&rtb_EvtInfo_DTC_0xffff12_Even_l);
/* FunctionCaller: '<Root>/EvtInfo_DTC_0xffff15_Event' */
Rte_Call_EvtInfo_DTC_0xffff15_Event_GetEventFailed
(&rtb_EvtInfo_DTC_0xffff15_Even_f);
/* Logic: '<Root>/Logical Operator' */
rtb_EvtInfo_DTC_0xffff11_Even_i = (rtb_EvtInfo_DTC_0xffff11_Even_i ||
rtb_EvtInfo_DTC_0xffff12_Even_l || rtb_EvtInfo_DTC_0xffff15_Even_f);
/* Switch: '<Root>/Switch1' */
if (rtb_EvtInfo_DTC_0xffff11_Even_i) {
/* Switch: '<Root>/Switch1' incorporates:
* Constant: '<Root>/Constant'
*/
rtb_Switch1 = 0.0F;
} else {
/* Switch: '<Root>/Switch1' incorporates:
* Inport: '<Root>/Sensor1_Percent'
* Switch: '<Root>/Switch'
*/
rtb_Switch1 = Rte_IRead_Runnable_Step_Sensor1_Percent_Percent();
}
/* End of Switch: '<Root>/Switch1' */
/* Outport: '<Root>/Percent' */
Rte_IWrite_Runnable_Step_Percent_Percent(rtb_Switch1);
/* Switch: '<S1>/Switch' incorporates:
* Constant: '<S1>/Constant'
* Constant: '<S1>/Constant1'
*/
if (rtb_EvtInfo_DTC_0xffff11_Even_i) {
tmp = DEM_EVENT_STATUS_FAILED;
} else {
tmp = DEM_EVENT_STATUS_PASSED;
}
/* End of Switch: '<S1>/Switch' */
/* FunctionCaller: '<Root>/Event_DTC_0xffff13_Event' */
Rte_Call_Event_DTC_0xffff13_Event_SetEventStatus(tmp);
}
对应的arxml中也生成了对应的接口描述
此处对应的package路径不对,需要替换成ETAS Dem对应路径,替换完后copy到ETAS工具链中
RTE接口mapping
如果是新增的SWC,还需要将SWC映射到对应的EcucPartition上,且对应的runnable也要映射到对应的task上,本文不介绍这部分内容,默认上述工作已经完成
SWC中已经有了对应的诊断接口(Rport,Client接口)
Runnable中也有了对应调用关系
将SWC接口与DEM接口进行mapping
mapping好后进行ECU Extract,然后生成RTE代码即可
RTE代码分析
在生成的SWC RTE头文件中,有对应的接口调用宏定义
#if defined(RTE_PRV_ALL_API) || defined(RTE_RUNNABLEAPI_Runnable_Step)
/* Inline function call optimization; Rte_Call_Event_DTC_0xffff13_Event_SetEventStatus to Dem_SetEventStatus */
#define Rte_Call_Event_DTC_0xffff13_Event_SetEventStatus( EventStatus ) Dem_SetEventStatus(((VAR(Dem_EventIdType, AUTOMATIC))60), EventStatus)
#endif
#if defined(RTE_PRV_ALL_API) || defined(RTE_RUNNABLEAPI_Runnable_Step)
/* Inline function call optimization; Rte_Call_EvtInfo_DTC_0xffff11_Event_GetEventFailed to Dem_GetEventFailed */
#define Rte_Call_EvtInfo_DTC_0xffff11_Event_GetEventFailed( EventFailed ) Dem_GetEventFailed(((VAR(Dem_EventIdType, AUTOMATIC))58), EventFailed)
#endif
#if defined(RTE_PRV_ALL_API) || defined(RTE_RUNNABLEAPI_Runnable_Step)
/* Inline function call optimization; Rte_Call_EvtInfo_DTC_0xffff12_Event_GetEventFailed to Dem_GetEventFailed */
#define Rte_Call_EvtInfo_DTC_0xffff12_Event_GetEventFailed( EventFailed ) Dem_GetEventFailed(((VAR(Dem_EventIdType, AUTOMATIC))59), EventFailed)
#endif
#if defined(RTE_PRV_ALL_API) || defined(RTE_RUNNABLEAPI_Runnable_Step)
/* Inline function call optimization; Rte_Call_EvtInfo_DTC_0xffff15_Event_GetEventFailed to Dem_GetEventFailed */
#define Rte_Call_EvtInfo_DTC_0xffff15_Event_GetEventFailed( EventFailed ) Dem_GetEventFailed(((VAR(Dem_EventIdType, AUTOMATIC))61), EventFailed)
自动生成的宏中实际也是调用的对应Dem的函数,只是加上了对应的Event id,这样的话,应用层也不需要关心是具体是哪个Event id了
总结
使用Simulink开发诊断,可以少一步应用层和底层的数据传递,逻辑开发也很简单。Simulink中除了Dem模块,还有Nvm的模块,有空可以再介绍。