LOCAL_INLINE FUNC(void, COM_CODE) Com_RxProcessing_RxPduSigEvent(PduIdType comRxPduInfoIdx, P2CONST(PduInfoType, AUTOMATIC, COM_APPL_DATA) PduInfoPtr,
P2VAR(FctPtrCacheStrct, AUTOMATIC, COM_APPL_DATA) fctPtrCacheStrctPtr)
这个函数的作用是解包PDU(对应一帧CAN MSG)->SDU(对应这帧MSG中包含的信号), 那么它在何时被调用呢?
Com_RxIndication->PDU->Deffered or Immediate 处理
如果是该PDU被配置为Deffered(推后处理) 则只将该PDU数据和DLC缓存起来, 不立即解包, 解包是在
Com_MainFunctionRx->(Mapping 到Task中周期调用, Polling)
Com_RxDeferredPduProcessing->
Com_RxDeferredPduProcessing_IterateOverAllRxPdus->
Com_RxProcessDeferredPDU->
Com_RxProcessing_RxPduSigEvent
如果是Immediate 则立即解包, 比如sig1是一个uint8信号, 则在Pduinfo->SduPtr 中将数据提取到sig1自己的buffer中, 这样Com_ReadSignal(sigid, void * dataptr)就能从sig1<->sigid1中拷贝出数据
note: Deffered/Immediate 是针对PDU的配置, 而不是SDU
下面分析下解包过程
Com_RxSigInfoIterType idxRxSigInfo = Com_GetRxSigInfoStartIdxOfRxPduInfo(comRxPduInfoIdx);
for(; idxRxSigInfo < Com_GetRxSigInfoEndIdxOfRxPduInfo(comRxPduInfoIdx); idxRxSigInfo++)
{
迭代一个PDU中包含的SDU
# if (COM_UBMASKUSEDOFRXSIGINFO == STD_ON)
/* #30 Check if the ComSignal was updated */
boolean process = Com_RxProcessing_CheckSigUB(idxRxSigInfo, PduInfoPtr); /* SBSW_COM_FCTCALL_WITH_P2CONST */
if(process == TRUE)
# endif
检查一下这个SIG中的UpdateBit是否有效(如果配置了的话)
->有效 ,认为该信号已经更新 -> 重置timeout_counter(如果配置了DeadLineMonitoring)(即超时检测可以配置到具体的SDU)
->无效,啥也不做,处理完成,信号没有更新,timeout_counter–在Com_RxDlMon_MainFunctionRx(Mapping 到Task中周期调用), timeout_counter == 0则表明该SDU接收超时, 触发配置的action和notifications(注意这里的s)
->如果没配置或者说不需要UpdateBit机制, 那么只要接收到这帧PDU, 它包含的所有SDU 都认为是被更新了, timeout_counter全部重置, 感觉UpdateBit+timeout_counter配合使用, 可以确保能检测到一个关键的信号是否被更新。
那么如何判断一个Signal 是否有效呢? 可以为每个信号预先配置一个Invalid value(或者使用DBC中定义的无效值) 然后将接收到的value 与之对比。(比如Speed == 0x1fff is invalid)。