在之前的一篇文章中,介绍了RTE中的S/R接口,也是RTE中使用最多的接口。在Autosar定义的Interface中,分为Require Ports(需求接口,对应的S/R接口中的Receiver接口,C/S接口中的Client接口)和Provide Ports(提供接口,对应S/R接口中的Sender接口,C/S接口中的Server接口)。
S/R接口主要针对数据传输,而C/S接口主要是针对操作。一般C/S接口以函数调用和函数的形式存在。Client调用Server端的操作,一般以Runnable形式存在。
对于Server接口来说,实际就是一个功能函数的实现,在Autosar中,大部分时候都是通过Client接口调用对应的Server的函数。
此处演示在Simulink中如何创建一个Server接口,其他RTE设计工具中也是类似的选项
创建好一个Autosar类型的Model后,Ctrl+Shift+C打开Autosar SW Component,然后打开Autosar Dictionary
通过C/S Interface创建一个接口名为TestCSIf_server,然后创建对应的Operation, Operation即为对应的操作名称,Operation后面会关联到Runnable上。
此处操作名称为TestFunc_server.
接着通过Arguments配置操作的参数,此处示例配置两个输入和一个输出
此处只是定义了部分函数原型,具体的实现需要在Simulink中做,或者生成代码后自己再手动在Runnable中编写。
创建好接口后,需要创建serverPorts
将之前创建的C/S Interface与ServerPort映射
然后创建server对应的runnable,此处函数名称为TestFunc_server
Runnable选择Event为OperationInvokedEvent,且选择Event Trigger为之前创建的server的Operation,进行了Operation与Runnable的映射。
使用Simulink Function实现函数,示例如下
在Autosar SW Component中的Function界面进行Runnable和Function的mapping
生成的代码中关于server,只有一个对应的Runnable函数。关于Interface和Port的信息,都在Arxml中体现。
/* Output function */
void TestFunc_server(uint8 Input1, uint8 Input2, uint8 *Output)
{
/* Outputs for Function Call SubSystem: '/Simulink Function' */
/* SignalConversion generated from: '/Output' incorporates:
* SignalConversion generated from: '/Input1'
* SignalConversion generated from: '/Input2'
* Sum: '/Add'
*/
*Output = (uint8)((uint32)Input1 + Input2);
/* End of Outputs for SubSystem: '/Simulink Function' */
}
实际使用中,将Client接口与Server接口正确连接后,Client即可调用对应的Server函数了。C/S接口的map需要在Autosar RTE设计工具中配置。
标题中的synchronous和asynchronous都是针对Client接口的,表示调用Server的方式。在Simulink没有配置同步还是异步,默认都是同步。
此处演示在Simulink中如何创建一个Client接口
和Server接口一样,创建Client Interface,名为TestCSIf_client,然后创建Operation,接着创建参数,示例如下:
在Simulink中的10ms的Runnable中使用Function Caller模块实现Client,示例如下:
将刚刚建立的Function Caller和之前创建的Client Port进行map
生成的代码其实就是在10ms的Runnable中调用Client接口,此处默认是同步调用,接口为Rte_Call类型
/* Model step function for TID1 */
void Runable_10ms(void) /* Explicit Task: Runnable_10ms */
{
uint8 rtb_FunctionCaller;
/* RootInportFunctionCallGenerator generated from: '/Runnable_10ms' incorporates:
* SubSystem: '/Subsystem'
*/
/* FunctionCaller: '/Function Caller' incorporates:
* Inport: '/In1'
* Inport: '/In2'
*/
Rte_Call_cPort_TestFunc_client(Rte_IRead_Runable_10ms_Input1_Val(),
Rte_IRead_Runable_10ms_Input2_Val(), &rtb_FunctionCaller);
/* End of Outputs for RootInportFunctionCallGenerator generated from: '/Runnable_10ms' */
/* Outport: '/Out1' */
Rte_IWrite_Runable_10ms_Output_Val(rtb_FunctionCaller);
}
实际使用中,大部分应该都是同步调用。
该函数为标准中的API函数,原型如下:
Std_ReturnType
Rte_[Byps_]Call__([IN Rte_Instance ],
[IN|IN/OUT|OUT] ...
[IN|IN/OUT|OUT] ,
[OUT Std_TransformerError transformerError])
接口中
表示port名称,
假设Port名称为cPort,operation名称为TestFunc,则生成的Rte_Call接口名称示例如下:
Rte_Call_cPort_TestFunc
在同步通信中,输入和输出可以同时存在。而在异步通信中,调用Rte_Call时,输出参数应该被省略,需要使用Rte_Result来获取输出结果。
规范中解释如下:
在异步通信情况下:
•Rte_Call只包括IN和IN/OUT参数。
•Rte_Result只包含IN/OUT和OUT参数来收集服务器调用的结果。
•Rte_Call期间提供的IN/OUT参数可以是与Rte_Result期间传递的IN/OUT参数不同的地址。
标准中的同步通信过程:
实际Client调用Server时应该还有一个超时返回的功能,但是一般生成的代码中都没有体现(可能是我没有用对)
该函数为标准中的API函数,原型如下:
Std_ReturnType
Rte_[Byps_]Result__([IN Rte_Instance ],
[IN/OUT|OUT ]...
[IN/OUT|OUT ],
[OUT Std_TransformerError transformerError])
可以看出该函数中没有包含IN的参数,只有OUT或IN/OUT,也对应其名称Result,就是用来获取之前函数运行的结果的。
在异步通信中,Client调用Rte_Call函数后可以先返回,然后通过Rte_Result函数来获取结果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vOCV0QLE-1687527971221)(null)]
Polling:循环读取结果
Waiting:设置一个等待时间,时间到了之后读取结果
None:配置为事件触发,server运行完后会触发该事件,以触发client的响应,读取结果
实际使用中,还没有使用过异步通信,可能描述的不一定准确。
C/S接口一般在NVM或DEM中使用较多,SWC使用时一般都以Client的形式去调用BSW的API函数,后面有空会继续分享相关内容。