About UDS_WaitForMultipleMessage and UDS_SvcTesterPresent

A free API for the communication with control devices according to UDS (ISO 14229-1)
Post Reply
luliily
Posts: 11
Joined: Sun 22. Jan 2017, 14:13

About UDS_WaitForMultipleMessage and UDS_SvcTesterPresent

Post by luliily » Thu 27. Apr 2017, 11:24

Hello,

In my case,the ECU's TesterPresent (0x3E) service is not standard.

Here is what I need:
搜狗截图20170427170118.png
搜狗截图20170427170118.png (10.26 KiB) Viewed 8838 times
But the PCAN UDS API does not match:
搜狗截图20170427170011.png
搜狗截图20170427170011.png (13.12 KiB) Viewed 8838 times
I want to disable the TesterPresent function,So I set to the default session:

Code: Select all

	TPUDSSessionInfo session;
	result = UDS_GetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));
	session.SESSION_TYPE = PUDS_SVC_PARAM_DSC_DS;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));
But when UDS_WaitForMultipleMessage is timeout,the API send TesterPresent messsage automatically:

Code: Select all

Line_Send_Again_1:
	MsgUDS_WRITE.LEN = 2;
	MsgUDS_WRITE.DATA.RAW[0] = 0x33;
	MsgUDS_WRITE.DATA.RAW[1] = 0x02;
	result = UDS_Write(PUDS_USBBUS1, &MsgUDS_WRITE);
	if (result == PUDS_ERROR_OK)
	{
		result = UDS_WaitForMultipleMessage(PUDS_USBBUS1, MsgUDS_READ, numECU, &count, &MsgUDS_WRITE, 5, 2000, 2000, FALSE);
		if (result != PUDS_ERROR_OK)
		{
			MessageBox(L"UDS_WaitForMultipleMessage 10");
			return;
		}
		else if (
			(MsgUDS_READ[0].DATA.RAW[0] == 0x7F &&
			MsgUDS_READ[0].DATA.RAW[1] == 0x33 &&
			MsgUDS_READ[0].DATA.RAW[2] == 0xFB) ||
			(MsgUDS_READ[1].DATA.RAW[0] == 0x7F &&
			MsgUDS_READ[1].DATA.RAW[1] == 0x33 &&
			MsgUDS_READ[1].DATA.RAW[2] == 0xFB))
		{
			goto Line_Send_Again_1;
			Sleep(20);
		}
	}
搜狗截图20170427171340.png
搜狗截图20170427171340.png (24.39 KiB) Viewed 8838 times
Question 1:When I use UDS_WaitForMultipleMessage function,is there any way to disable TesterPresent completely?
Question 2:Is there any way to set the TesterPresent function to send "0x3E" instead of "0x3E 0x80"?

Best regards.

K.Wagner
Software Development
Software Development
Posts: 1082
Joined: Wed 22. Sep 2010, 13:36

Re: About UDS_WaitForMultipleMessage and UDS_SvcTesterPresen

Post by K.Wagner » Thu 27. Apr 2017, 11:47

Hello,

please check the following Post.
Best regards,
Keneth

luliily
Posts: 11
Joined: Sun 22. Jan 2017, 14:13

Re: About UDS_WaitForMultipleMessage and UDS_SvcTesterPresen

Post by luliily » Fri 28. Apr 2017, 04:14

Hello,

I did read that Post.

Code: Select all

	TPUDSStatus result;
	TPUDSMsg MsgUDS_WRITE = {};
	TPUDSMsg MsgUDS_READ[2] = {};
	DWORD count;

	MsgUDS_WRITE.NETADDRINFO.SA = 0xFB;
	MsgUDS_WRITE.NETADDRINFO.TA = 0x00;
	MsgUDS_WRITE.NETADDRINFO.RA = 0x00;
	MsgUDS_WRITE.NETADDRINFO.PROTOCOL = PUDS_PROTOCOL_ISO_15765_2_11B;
	MsgUDS_WRITE.NETADDRINFO.TA_TYPE = PUDS_ADDRESSING_PHYSICAL;
	// 	request_UDS.MSGTYPE = PUDS_MESSAGE_TYPE_REQUEST;
	// 	request_UDS.NO_POSITIVE_RESPONSE_MSG = PUDS_KEEP_POS_RSP_MSG_INDICATION_BIT;

	result = UDS_Initialize(PUDS_USBBUS1, PUDS_BAUD_250K);
	if (result != PUDS_ERROR_OK)
	{
		MessageBox(L"UDS_Initialize Fail.");
	}

	WORD param = 0xFB;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_SERVER_ADDRESS, &param, sizeof(param));

	DWORD ulBuffer = 5000;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_TIMEOUT_REQUEST, &ulBuffer, sizeof(ulBuffer));
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_TIMEOUT_RESPONSE, &ulBuffer, sizeof(ulBuffer));

	TPUDSSessionInfo session;
	result = UDS_GetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));

	session.SESSION_TYPE = PUDS_SVC_PARAM_DSC_DS;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));

	CANTP_AddMapping(PUDS_USBBUS1,
		0x6F1,
		0x610,
		PCANTP_ID_CAN_11BIT,
		PCANTP_FORMAT_NORMAL,
		PCANTP_MESSAGE_DIAGNOSTIC,
		0xFB,
		0x00,
		PCANTP_ADDRESSING_PHYSICAL,
		0x00);

	CANTP_AddMapping(PUDS_USBBUS1,
		0x610,
		0x6F1,
		PCANTP_ID_CAN_11BIT,
		PCANTP_FORMAT_NORMAL,
		PCANTP_MESSAGE_DIAGNOSTIC,
		0x00,
		0xFB,
		PCANTP_ADDRESSING_PHYSICAL,
		0x00);

	result = CAN_FilterMessages(PCAN_USBBUS1, 0x610, 0x6F1, PCAN_MESSAGE_STANDARD);
But when UDS_WaitForMultipleMessage is timeout,TesterPresent is still triggered. :o

F.Vergnaud
Software Development
Software Development
Posts: 305
Joined: Mon 9. Sep 2013, 12:21

Re: About UDS_WaitForMultipleMessage and UDS_SvcTesterPresen

Post by F.Vergnaud » Tue 2. May 2017, 09:56

Hello Luliily,

I'm quoting the mentionned post :
You need to specify the Network Address Information you want to retrieve when you pass the session parameter to your GetValue function (as it is possible to have multiple sessions with different ECUs at the same time) :
Here is your code corrected:

Code: Select all

   TPUDSSessionInfo session;

// You MUST specify the Protocol, SA, TA, etc. to retrieve the corresponding Network Address Information
//
session.NETADDRINFO.PROTOCOL = PUDS_PROTOCOL_ISO_15765_2_11B;
session.NETADDRINFO.SA = 0xFB;
session.NETADDRINFO.TA = 0x00;
session.NETADDRINFO.TA_TYPE = PUDS_ADDRESSING_PHYSICAL;
session.NETADDRINFO.RA = 0x00;

// You SHOULD ALSO check the result value of this function, if you get PUDS_ERROR_NOT_INITIALIZED, it means that the corresponding session information was not found.
   result = UDS_GetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));

   session.SESSION_TYPE = PUDS_SVC_PARAM_DSC_DS;
   result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));
Best regards,
Fabrice

luliily
Posts: 11
Joined: Sun 22. Jan 2017, 14:13

Re: About UDS_WaitForMultipleMessage and UDS_SvcTesterPresen

Post by luliily » Wed 3. May 2017, 05:50

Hello Fabrice,

I updated my code:

Code: Select all

	TPUDSStatus result;
	TPUDSMsg MsgUDS_WRITE = {};
	TPUDSMsg MsgUDS_READ[2] = {};
	TPUDSMsg MsgUDS_READ_TEMP = {};
	DWORD count;

	MsgUDS_WRITE.NETADDRINFO.SA = 0xFB;
	MsgUDS_WRITE.NETADDRINFO.TA = 0x00;
	MsgUDS_WRITE.NETADDRINFO.RA = 0x00;
	MsgUDS_WRITE.NETADDRINFO.PROTOCOL = PUDS_PROTOCOL_ISO_15765_2_11B;
	MsgUDS_WRITE.NETADDRINFO.TA_TYPE = PUDS_ADDRESSING_PHYSICAL;
	// 	request_UDS.MSGTYPE = PUDS_MESSAGE_TYPE_REQUEST;
	// 	request_UDS.NO_POSITIVE_RESPONSE_MSG = PUDS_KEEP_POS_RSP_MSG_INDICATION_BIT;

	result = UDS_Initialize(PUDS_USBBUS1, PUDS_BAUD_250K);
	if (result != PUDS_ERROR_OK)
	{
		MessageBox(L"UDS_Initialize Fail.");
	}

	WORD param = 0xFB;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_SERVER_ADDRESS, &param, sizeof(param));

	DWORD ulBuffer = 5000;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_TIMEOUT_REQUEST, &ulBuffer, sizeof(ulBuffer));
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_TIMEOUT_RESPONSE, &ulBuffer, sizeof(ulBuffer));

	TPUDSSessionInfo session;

	// You MUST specify the Protocol, SA, TA, etc. to retrieve the corresponding Network Address Information
	session.NETADDRINFO.PROTOCOL = PUDS_PROTOCOL_ISO_15765_2_11B;
	session.NETADDRINFO.SA = 0xFB;
	session.NETADDRINFO.TA = 0x00;
	session.NETADDRINFO.TA_TYPE = PUDS_ADDRESSING_PHYSICAL;
	session.NETADDRINFO.RA = 0x00;

	// You SHOULD ALSO check the result value of this function, if you get PUDS_ERROR_NOT_INITIALIZED, it means that the corresponding session information was not found.
	result = UDS_GetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));

	session.SESSION_TYPE = PUDS_SVC_PARAM_DSC_DS;
	result = UDS_SetValue(PUDS_USBBUS1, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));

	CANTP_AddMapping(PUDS_USBBUS1,
		0x6F1,
		0x610,
		PCANTP_ID_CAN_11BIT,
		PCANTP_FORMAT_NORMAL,
		PCANTP_MESSAGE_DIAGNOSTIC,
		0xFB,
		0x00,
		PCANTP_ADDRESSING_PHYSICAL,
		0x00);

	CANTP_AddMapping(PUDS_USBBUS1,
		0x610,
		0x6F1,
		PCANTP_ID_CAN_11BIT,
		PCANTP_FORMAT_NORMAL,
		PCANTP_MESSAGE_DIAGNOSTIC,
		0x00,
		0xFB,
		PCANTP_ADDRESSING_PHYSICAL,
		0x00);

	result = CAN_FilterMessages(PCAN_USBBUS1, 0x610, 0x6F1, PCAN_MESSAGE_STANDARD);
	.
	.
	.
	.
	.
	.
	WORD len = 0xFF;
	int i = 0, j = 0;
	for (i = 0; i < 0x606; i++)
	{
		MsgUDS_WRITE.LEN = len + 1;
		MsgUDS_WRITE.DATA.RAW[0] = 0x36;

		for (j = 0; j < len; j++)
		{
			MsgUDS_WRITE.DATA.RAW[j + 1] = arrSrc.GetAt(i*len + j);
		}

		result = UDS_Write(PUDS_USBBUS1, &MsgUDS_WRITE);
		if (result == PUDS_ERROR_OK)
		{
			result = UDS_WaitForMultipleMessage(PUDS_USBBUS1, MsgUDS_READ, 2, &count, &MsgUDS_WRITE, 5, 5000, 10000, FALSE);
			if (result != PUDS_ERROR_OK)
			{
				CString str;
				str.Format(L"i=%d,j=%d", i, j);
				MessageBox(str);
				return;
			}
		}
	}
	.
	.
	.
	.
	.
But TesterPresent is still active:
搜狗截图20170503113026.png
搜狗截图20170503113026.png (40.87 KiB) Viewed 8816 times
Am I still missing something :?:

Best regards.
Luliily.

F.Vergnaud
Software Development
Software Development
Posts: 305
Joined: Mon 9. Sep 2013, 12:21

Re: About UDS_WaitForMultipleMessage and UDS_SvcTesterPresen

Post by F.Vergnaud » Thu 4. May 2017, 12:25

All right, I see there may be a misunderstanding in the way UDS session is working:
  • Sessions are defined when a call to the corresponding service is made (UDS_SvcDiagnosticSessionControl), only after reading the response(s) from this service will the UDS API know that a specific session was set up (and may then start sending automatic tester present messages to the ECU(s) if it is a non-default session).
  • If you switch from an unknown session (which is the case after the UDS initialization) or default diagnostic session to "an ECU programming" session then the current state of the session with that specific ECU will be updated. To disable automatic tester present messages, the corresponding code must be called after receiving the diagnostic session response from that ECU.
To sum up:
1. After UDS_Initialize, no session are defined so you cannot modify any.
2. After a call to the service UDS_SvcDiagnosticSessionControl and having received a valid response from an ECU, a session information is registered in the API.
3. If you want to disable the default tester present mechanism, you can only do it after processing that response. The processing is handled internally in our high level function like UDS_WaitForXXX, but if needed (for instance you do not use those functions) the corresponding function to call is UDS_ProcessResponse.
4. Keep in mind that if the service UDS_SvcDiagnosticSessionControl is called again, the received response will overwrite your customized session information.

You can assert my first statement by checking in your code the call to :

Code: Select all

result = UDS_GetValue(Channel, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));
It returns a PUDS_ERROR_NOT_INITIALIZED.. which means that this session is not defined.

Here is a glimpse of how things should be handled:

Code: Select all

// keep your existing initialization process...
[...]
	result = CAN_FilterMessages(PCAN_USBBUS1, 0x610, 0x6F1, PCAN_MESSAGE_STANDARD);
[...]
	// At some point in your code, you must be changing session. For instance like so:
	result = UDS_SvcDiagnosticSessionControl(Channel, &MsgUDS_WRITE, PUDS_SVC_PARAM_DSC_ECUPS);
	if (result == PUDS_ERROR_OK)
		result = UDS_WaitForService(Channel, &MsgUDS_READ[0], &MsgUDS_WRITE);
	printf("  UDS_SvcDiagnosticSessionControl: %i\n", (int)result);

	// Only then the API will send automatic TesterPrent messages !
	// Check that in your CAN viewer by sleeping  for 10s 
	Sleep(10000);

	// Only then, you can specify to disable the mechanism
	TPUDSSessionInfo session;

	// You MUST specify the Protocol, SA, TA, etc. to retrieve the corresponding Network Address Information
	session.NETADDRINFO.PROTOCOL = PUDS_PROTOCOL_ISO_15765_2_11B;
	session.NETADDRINFO.SA = 0xFB;
	session.NETADDRINFO.TA = 0x00;
	session.NETADDRINFO.TA_TYPE = PUDS_ADDRESSING_PHYSICAL;
	session.NETADDRINFO.RA = 0x00;

	// You SHOULD ALSO check the result value of this function, if you get PUDS_ERROR_NOT_INITIALIZED, it means that the corresponding session information was not found.
	result = UDS_GetValue(Channel, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));

	session.SESSION_TYPE = PUDS_SVC_PARAM_DSC_DS;
	result = UDS_SetValue(Channel, PUDS_PARAM_SESSION_INFO, &session, sizeof(TPUDSSessionInfo));
	
	// Check that the automatic TesterPresent is disabled, and no message is received
	Sleep(10000);
	
	// you can resume your code 
	WORD len = 0xFF;
	int i = 0, j = 0;
	for (i = 0; i < 0x606; i++)
	{
            [...]
        }
Best regards,
Fabrice

luliily
Posts: 11
Joined: Sun 22. Jan 2017, 14:13

Re: About UDS_WaitForMultipleMessage and UDS_SvcTesterPresen

Post by luliily » Mon 8. May 2017, 04:09

Great!
Now I understand how UDS session works!I admire very much! :D I rewrited my code.The TesterPresent was disable.Thank you! ;)

Post Reply