文章目录
- 前言
- Autosar Nvm接口
- 设计模型及接口
- 生成代码及arxml
- RTE接口mapping
- RTE代码分析
- 总结
前言
之前介绍过Simulink开发Dem故障触发逻辑,本文接着介绍另外一个常用的功能-Nvm存储的实现。
Autosar Nvm接口
Autosar Nvm中一般在上电初始化的时调用Nvm_ReadAll获取Nvm block的数据到Ram中。对于block来说,可以通过Nvm_ReadBlock进行读取,通过Nvm_WriteBlock进行写入。Autosar Dem标准接口为NvMService,使用Simulink中自带的demo-autosar_bsw_sensor中的定义,如下所示:
需要注意的是:生成的package位置为/AUTOSAR/Services/Dem(暂时没找到怎么修改),而在使用时,导入对应Autosar工具(例如Etas)时可能会找不到对应的定义。此处我们后面是手动更改arxml中的package路径
设计模型及接口
配置Nvm的ClientPort,如下所示
Nvm需要使用到Simulink自带的Data Store Memory模块,如下所示
在初始化函数中进行Nvm读取
配置Nvm的Port及读取的函数
做了一个简单的存储逻辑:当输入值小于存储的值时,触发Nvm的存储
写入需要使用Data Store Write,然后使用Data Store Read调用WriteBlock进行写入,如下所示
配置Nvm的Port及写入的函数
Nvm的Functions Callers在刷新后会自动生成并mapping
生成代码及arxml
生成的代码中调用了RTE函数Rte_Call_S1LowSetPoint_ReadBlock用来读取Nvm,调用RTE函数Rte_Call_S1LowSetPoint_WriteBlock用来写入Nvm,示例如下:
/* Model step function */
void Runnable_Step(void)
{uint16 rtb_RelationalOperator_tmp;boolean rtb_RelationalOperator;/* Outport: '<Root>/Percent' incorporates:* DataTypeConversion: '<Root>/Data Type Conversion'* Inport: '<Root>/RawADC'* Lookup_n-D: '<Root>/TPS Lookup'*/Rte_IWrite_Runnable_Step_Percent_Percent(rtCP_TPSLookup_tableData[plook_u32f_linckan(Rte_IRead_Runnable_Step_RawADC_RawADC(), rtCP_TPSLookup_bp01Data, 10U)]);/* Outputs for Triggered SubSystem: '<Root>/Enabled Subsystem' incorporates:* TriggerPort: '<S1>/Trigger'*//* RelationalOperator: '<Root>/Relational Operator' incorporates:* DataStoreWrite: '<S1>/Data Store Write'* Inport: '<Root>/RawADC'*/rtb_RelationalOperator_tmp = Rte_IRead_Runnable_Step_RawADC_RawADC();/* End of Outputs for SubSystem: '<Root>/Enabled Subsystem' *//* RelationalOperator: '<Root>/Relational Operator' incorporates:* DataStoreRead: '<Root>/Data Store Read'* Inport: '<Root>/RawADC'*/rtb_RelationalOperator = (rtb_RelationalOperator_tmp < rtARID_DEF.LowSetPoint);/* Outputs for Triggered SubSystem: '<Root>/Enabled Subsystem' incorporates:* TriggerPort: '<S1>/Trigger'*/if (rtb_RelationalOperator && (rtARID_DEF.EnabledSubsystem_Trig_ZCE !=POS_ZCSIG)) {/* DataStoreWrite: '<S1>/Data Store Write' */rtARID_DEF.LowSetPoint = rtb_RelationalOperator_tmp;/* FunctionCaller: '<S1>/NvMServiceCaller1' */Rte_Call_S1LowSetPoint_WriteBlock(&rtARID_DEF.LowSetPoint);}rtARID_DEF.EnabledSubsystem_Trig_ZCE = rtb_RelationalOperator;/* End of Outputs for SubSystem: '<Root>/Enabled Subsystem' */
}/* Model initialize function */
void Runnable_Init(void)
{/* Start for DataStoreMemory: '<Root>/Data Store Memory' */rtARID_DEF.LowSetPoint = 50U;/* SystemInitialize for Triggered SubSystem: '<Root>/Enabled Subsystem' */rtARID_DEF.EnabledSubsystem_Trig_ZCE = ZERO_ZCSIG;/* End of SystemInitialize for SubSystem: '<Root>/Enabled Subsystem' *//* Outputs for Atomic SubSystem: '<Root>/Initialize_Function' *//* FunctionCaller: '<S2>/NvMServiceCaller' */Rte_Call_S1LowSetPoint_ReadBlock(&rtARID_DEF.LowSetPoint);/* End of Outputs for SubSystem: '<Root>/Initialize_Function' */
}
对应的arxml中也生成了对应的接口描述
此处对应的package路径不对,需要替换成ETAS Nvm对应路径(/AUTOSAR_NvM/PortInterfaces/),替换完后copy到ETAS工具链中
RTE接口mapping
如果是新增的SWC,还需要将SWC映射到对应的EcucPartition上,且对应的runnable也要映射到对应的task上,本文不介绍这部分内容,默认上述工作已经完成
注意:初始化的Runnable在SWC中没有对应的Event,原因是Simulink中未配置,需要配置如下:
此处默认对应的NVM block已经建立好了(Nvm block需要配置NvMRbGenRteServicePort为True)。在对应的Nvm ServiceSwComponent中已经有了对应的Pport
Simulink生成的Arxml中的SWC中已经有了对应的NVM接口(Rport,Client接口)
Runnable中也有了对应调用关系
注意:此处生成的Server Call Point是Async接口,会导致后面ETAS生成RTE时生成Alarm和其他无关的代码,我们不需要,此处需要手动修改为Sync接口,如下所示:
将SWC接口与NVM接口进行mapping
mapping好后进行ECU Extract,然后生成RTE代码即可
RTE代码分析
在生成的SWC RTE头文件中,有对应的接口调用宏定义
#if defined(RTE_PRV_ALL_API) || defined(RTE_RUNNABLEAPI_Runnable_Init)
/* Inline function call optimization; Rte_Call_S1LowSetPoint_ReadBlock to NvM_ReadBlock */
#define Rte_Call_S1LowSetPoint_ReadBlock( DstPtr ) NvM_ReadBlock(((VAR(NvM_BlockIdType, AUTOMATIC))43), DstPtr)#endif
#if defined(RTE_PRV_ALL_API) || defined(RTE_RUNNABLEAPI_Runnable_Step)
/* Inline function call optimization; Rte_Call_S1LowSetPoint_WriteBlock to NvM_WriteBlock */
#define Rte_Call_S1LowSetPoint_WriteBlock( SrcPtr ) NvM_WriteBlock(((VAR(NvM_BlockIdType, AUTOMATIC))43), SrcPtr)#endif
自动生成的宏中实际也是调用的对应Nvm的函数,只是加上了对应的Nvm id,这样的话,应用层也不需要关心是具体是哪个Nvm id了
总结
使用Simulink Nvm模块可以减少一部分Nvm相关的RTE接口,能够节省一部分存储交互的工作量。