背景
在DCM开发过程中经常会遇到如下功能需求:
(1)某个UDS诊断服务不支持功能寻址的情况下,ECU接收到功能寻址的该UDS诊断服务,如何实现不响应该诊断服务。
- 举例:2E服务不支持功能寻址,ECU接收到2E服务请求,则不响应
(2)某个UDS诊断服务不支持抑制肯定响应的情况下,ECU接收到带有抑制肯定响应的SID诊断服务,如何实现上报否定响应NRC12。
- 举例:19服务不支持抑制肯定响应,ECU接收到19 8x xx请求,则响应NRC12
(3)如何实现ECU上报某些UDS诊断服务的NRC22否定响应。
- 举例:11服务需要NRC22条件(车速小于3km/h)检测,当车速大于3km/h时ECU接收到11 01请求,则响应NRC22
配置教程
Davinci Configurator Pro配置工具预留两个通知功能(manufacturer notification和supplier notification),可根据不同需求选择相应的功能,这边我们选择的是supplier notification。该功能是在DCM模块接收到诊断服务后会先调用相应的接口执行一些逻辑判定,若判定为成功进行下一步诊断逻辑,否则直接返回相应的NRC。
1.使能supplier notification功能
如下图所示,在Dcm–>DcmConfigSet–>DcmGeneral模块中,勾选DcmRequestSupplierNotificationEnabled功能。
2.创建Supplier notification容器
在/MICROSAR/Dcm/DcmConfigSet/DcmDsl/DcmDslServiceRequestSupplierNotification模块中,右击选择“create xxx container”。
3.创建Notification Indication 和Notification Confirmation函数
如下图所示,点击步骤2中生成的容器,填写Notification Indication 和Notification Confirmation函数名。
4.生成DCM代码
如下图所示,点击“generate”图标,选择“DCM”模块,点击“generate”即可生成代码。到这里Davinci 配置就已经完成了,接下来我们手动实现相应的功能即可。
5.查看生成代码
我们先来初略的查看下Davinci cfg工具生成的代码,对比代码可以看到,在Dcm_Lcfg.c中定义了一个Dcm_CfgDiagSysNotificationInfo结构体数组,包含两个函数(即步骤3中创建的函数名)。同时在Dcm_Lcfg.h文件中还定义这两个函数的参数和返回值。
/*! System supplier notification functions */
CONST(Dcm_CfgDiagNotificationInfoType, DCM_CONST) Dcm_CfgDiagSysNotificationInfo[2]=
{
{ ServiceRequestNotification_ConditionCheck_Indication,ServiceRequestNotification_Confirmation}
,{ NULL_PTR,NULL_PTR}
};
/***********************************************************************************************************************
* ServiceRequestNotification_ConditionCheck_Indication()
***********************************************************************************************************************/
/*! \brief Performs supplier specific validations on a diagnostic service request.
* \details This function is a request from the DCM to the application to validate the received diagnostic
* service, additionally to the DCM internal validation.
* \param[in] SID Contains the diagnostic service Id
* \param[in] RequestData Points to the request data. Points behind the service Id byte
* \param[in] DataSize Specifies the requested data length (without the SID byte)
* \param[in] ReqType Specifies the diagnostic request type:
* 0 - physical request
* 1 - functional request
* \param[in] SourceAddress Contains the diagnostic client source address
* \param[out] ErrorCode NRC to be sent in the negative response in case of failure (E_NOT_OK)
* \return E_OK The operation is finished
* \return DCM_E_REQUEST_NOT_ACCEPTED The diagnostic service shall not be processed.
* No response will be sent
* \return E_NOT_OK The operation has failed
* A concrete NRC shall be set, otherwise the DCM sends NRC 0x22
* \context TASK
* \reentrant FALSE
* \synchronous TRUE
* \pre -
***********************************************************************************************************************/
FUNC(Std_ReturnType, DCM_CALLOUT_CODE) ServiceRequestNotification_ConditionCheck_Indication(uint8 SID, P2CONST(uint8, AUTOMATIC, DCM_VAR_NOINIT) RequestData, uint16 DataSize, uint8 ReqType, uint16 SourceAddress, P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, DCM_VAR_NOINIT) ErrorCode);
/***********************************************************************************************************************
* ServiceRequestNotification_Confirmation()
***********************************************************************************************************************/
/*! \brief Finishes supplier specific actions on a diagnostic service request.
* \details This function is a notification from the DCM to the application that a diagnostic service processing
* is finished.
* \param[in] SID Contains the diagnostic service Id
* \param[in] ReqType Specifies the diagnostic request type:
* 0 - physical request
* 1 - functional request
* \param[in] SourceAddress Contains the diagnostic client source address
* \param[in] ConfirmationStatus Contains the response transmission resp. diagnostic response type
* \return E_OK The operation is finished
* \return E_NOT_OK The operation has failed. Has no effect on DCM.
* \context TASK
* \reentrant FALSE
* \synchronous TRUE
* \pre -
***********************************************************************************************************************/
FUNC(Std_ReturnType, DCM_CALLOUT_CODE) ServiceRequestNotification_Confirmation(uint8 SID, uint8 ReqType, uint16 SourceAddress, Dcm_ConfirmationStatusType ConfirmationStatus);
6.实现Notification Indication 和Notification Confirmation函数
根据上面三个功能需求,我们分别对2E/19/11服务进行相应的逻辑处理。
在2E服务中,若接收到功能寻址的指令,则不响应请求。
在19服务中,若SID的bit7为1,则响应NRC12。
在11服务中,先获取当前车速,判定车速是否满足要求,若不满足,则返回NRC22
#define DIA_NRC22_CONDITION_VEHSPEED_LIMIT (3.0f)
/***********************************************************************************************************************
* ServiceRequestNotification_ConditionCheck_Indication()
***********************************************************************************************************************/
/*! \brief Performs supplier specific validations on a diagnostic service request.
* \details This function is a request from the DCM to the application to validate the received diagnostic
* service, additionally to the DCM internal validation.
* \param[in] SID Contains the diagnostic service Id
* \param[in] RequestData Points to the request data. Points behind the service Id byte
* \param[in] DataSize Specifies the requested data length (without the SID byte)
* \param[in] ReqType Specifies the diagnostic request type:
* 0 - physical request
* 1 - functional request
* \param[in] SourceAddress Contains the diagnostic client source address
* \param[out] ErrorCode NRC to be sent in the negative response in case of failure (E_NOT_OK)
* \return E_OK The operation is finished
* \return DCM_E_REQUEST_NOT_ACCEPTED The diagnostic service shall not be processed.
* No response will be sent
* \return E_NOT_OK The operation has failed
* A concrete NRC shall be set, otherwise the DCM sends NRC 0x22
* \context TASK
* \reentrant FALSE
* \synchronous TRUE
* \pre -
***********************************************************************************************************************/
FUNC(Std_ReturnType, DCM_CALLOUT_CODE) ServiceRequestNotification_ConditionCheck_Indication(uint8 SID, P2CONST(uint8, AUTOMATIC, DCM_VAR_NOINIT) RequestData, uint16 DataSize, uint8 ReqType, uint16 SourceAddress, P2VAR(Dcm_NegativeResponseCodeType, AUTOMATIC, DCM_VAR_NOINIT) ErrorCode)
{
Std_ReturnType l_DcmReturn_e = DCM_E_OK;
vfc::float32_t l_vehicleVelocity = 0;
valin::EQualifierVehicleVelocity l_vehicleVelocityVaild = valin::EQualifierVehicleVelocity::Q_VEHICLE_VELOCITY_INVALID;
valin::CValInOutputPf l_ValInResponse;
if(true == ov_dia::Cov_diaRunnable::ov_dia_getInstance()->updateValInResponse(l_ValInResponse))
{
l_vehicleVelocity = vfc::abs(l_ValInResponse.m_pfOdometry.m_vehicleVelocityDisplay.value());
l_vehicleVelocityVaild = l_ValInResponse.m_pfOdometry.m_qualifierVehicleVelocity;
}
switch (SID)
{
case 0x10:
if(((*RequestData)&0x7F) == 0x02)
{
if(ReqType == DCM_FUNCTIONAL_REQUEST)
{
l_DcmReturn_e = DCM_E_REQUEST_NOT_ACCEPTED;
}
else
{
if((l_vehicleVelocityVaild == valin::EQualifierVehicleVelocity::Q_VEHICLE_VELOCITY_VALID)&& \
(l_vehicleVelocity > DIA_NRC22_CONDITION_VEHSPEED_LIMIT))
{
*ErrorCode = DCM_E_CONDITIONSNOTCORRECT;
l_DcmReturn_e = DCM_E_NOT_OK;
}
}
}
break;
case 0x11:
case 0x14:
case 0x28:
case 0x85:
if((l_vehicleVelocityVaild == valin::EQualifierVehicleVelocity::Q_VEHICLE_VELOCITY_VALID)&& \
(l_vehicleVelocity > DIA_NRC22_CONDITION_VEHSPEED_LIMIT))
{
*ErrorCode = DCM_E_CONDITIONSNOTCORRECT;
l_DcmReturn_e = DCM_E_NOT_OK;
}
break;
case 0x19:
if(((*RequestData)&0x80) != 0x00)
{
*ErrorCode = DCM_E_SUBFUNCTIONNOTSUPPORTED;
l_DcmReturn_e = DCM_E_NOT_OK;
}
break;
case 0x2E:
case 0x34:
case 0x36:
case 0x37:
if(ReqType == DCM_FUNCTIONAL_REQUEST)
{
l_DcmReturn_e = DCM_E_REQUEST_NOT_ACCEPTED;
}
break;
case 0x27:
case 0x31:
if(ReqType == DCM_FUNCTIONAL_REQUEST)
{
l_DcmReturn_e = DCM_E_REQUEST_NOT_ACCEPTED;
}
else if(((*RequestData)&0x80) != 0x00)
{
*ErrorCode = DCM_E_SUBFUNCTIONNOTSUPPORTED;
l_DcmReturn_e = DCM_E_NOT_OK;
}
break;
case 0x22:
case 0x35:
case 0x3E:
default:
break;
}
return l_DcmReturn_e;
}
/***********************************************************************************************************************
* ServiceRequestNotification_Confirmation()
***********************************************************************************************************************/
/*! \brief Finishes supplier specific actions on a diagnostic service request.
* \details This function is a notification from the DCM to the application that a diagnostic service processing
* is finished.
* \param[in] SID Contains the diagnostic service Id
* \param[in] ReqType Specifies the diagnostic request type:
* 0 - physical request
* 1 - functional request
* \param[in] SourceAddress Contains the diagnostic client source address
* \param[in] ConfirmationStatus Contains the response transmission resp. diagnostic response type
* \return E_OK The operation is finished
* \return E_NOT_OK The operation has failed. Has no effect on DCM.
* \context TASK
* \reentrant FALSE
* \synchronous TRUE
* \pre -
***********************************************************************************************************************/
FUNC(Std_ReturnType, DCM_CALLOUT_CODE) ServiceRequestNotification_Confirmation(uint8 SID, uint8 ReqType, uint16 SourceAddress, Dcm_ConfirmationStatusType ConfirmationStatus)
{
}
案例测试
1.案例1
2E服务不支持功能寻址,ECU接收到2E服务请求,则不响应
物理寻址2E服务,回复肯定响应
功能寻址2E服务,不响应
2.案例2
19服务不支持抑制肯定响应,ECU接收到19 8x xx请求,则响应NRC12
19 01 FF请求,回复肯定响应
19 81 FF请求,回复NRC12
3.案例3
11服务需要NRC22条件(车速小于3km/h)检测,当车速大于3km/h时ECU接收到11 01请求,则响应NRC22
在车速为0km/h时,11 01请求,回复肯定响应
在车速为5km/h时,11 01请求,回复NRC22