Sending CAN FD frame error using UDSApi.SvcWriteDataByIdentifier_2013

A free API for the communication with control devices according to UDS (ISO 14229-1)
Post Reply
vddvss
Posts: 10
Joined: Wed 12. Jun 2019, 10:21

Sending CAN FD frame error using UDSApi.SvcWriteDataByIdentifier_2013

Post by vddvss » Wed 9. Feb 2022, 12:21

Hi,

I am writing a wrapper DLL in C# for UDS services. One of the services which I plan to use is the "Write Data by Identifier" service. I need to use CAN FD protocol, with varying length of data to be written to certain ID-s. If I have no more than 64 data bytes to be sent, then I would like to send them in one single CAN FD frame, if I have more data bytes to be sent then I would like to use segmented data transfer. I have an idea how this can be achieved, but so far it did not work. Here is my code (the init_FD and the WDBI functions):

Code: Select all

using cantp_bitrate = System.String;    // Alias' declaration for System.String

cantp_handle CAN_Channel;
uint CAN_request_ID;
uint CAN_response_ID;
uds_status result;
public const int OK = 0;

public int PEAK_UDS_init_FD(cantp_handle CAN_CH, cantp_bitrate CanBaudFD, uint CAN_Req_ID, uint CAN_Resp_ID, uint CAN_TO_Req, uint CAN_TO_Resp, ref string message)
{
	message = "UDSApi.InitializeFD_2013 OK.";
	uds_mapping UDS_Mapping_Request = new uds_mapping();
	uds_mapping UDS_Mapping_Response = new uds_mapping();

	CAN_Channel = CAN_CH;   // set the selected CAN channel to a globally applied CAN channel for the DLL instance
	try
	{
		// Initializing of the UDS Communication session
		result = UDSApi.InitializeFD_2013(CAN_Channel, CanBaudFD);
		if (!UDSApi.StatusIsOk_2013(result)) throw new Exception("UDSApi.InitializeFD_2013 failed.");

		// set timeout values
		result = UDSApi.SetValue_2013(CAN_Channel, uds_parameter.PUDS_PARAMETER_TIMEOUT_REQUEST, ref CAN_TO_Req, sizeof(UInt32));
		if (!UDSApi.StatusIsOk_2013(result)) throw new Exception("Set CAN_TO_Req failed.");
		result = UDSApi.SetValue_2013(CAN_Channel, uds_parameter.PUDS_PARAMETER_TIMEOUT_RESPONSE, ref CAN_TO_Resp, sizeof(UInt32));
		if (!UDSApi.StatusIsOk_2013(result)) throw new Exception("Set CAN_TO_Resp failed.");

		// Add mappings
		UDS_Mapping_Request.can_id = CAN_Req_ID;
		UDS_Mapping_Request.can_id_flow_ctrl = CAN_Resp_ID;
		UDS_Mapping_Request.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
		UDS_Mapping_Request.can_msgtype |= (cantp_can_msgtype.PCANTP_CAN_MSGTYPE_FD | cantp_can_msgtype.PCANTP_CAN_MSGTYPE_BRS);
		UDS_Mapping_Request.can_tx_dlc = 8;
		UDS_Mapping_Request.nai.extension_addr = 0;
		UDS_Mapping_Request.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_11B_NORMAL;
		UDS_Mapping_Request.nai.source_addr = (ushort) uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
		UDS_Mapping_Request.nai.target_addr = (ushort) uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
		UDS_Mapping_Request.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

		UDS_Mapping_Response.can_id = CAN_Resp_ID;
		UDS_Mapping_Response.can_id_flow_ctrl = CAN_Req_ID;
		UDS_Mapping_Response.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
		UDS_Mapping_Response.can_msgtype |= (cantp_can_msgtype.PCANTP_CAN_MSGTYPE_FD | cantp_can_msgtype.PCANTP_CAN_MSGTYPE_BRS);
		UDS_Mapping_Response.can_tx_dlc = 8;
		UDS_Mapping_Response.nai.extension_addr = 0;
		UDS_Mapping_Response.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_11B_NORMAL;
		UDS_Mapping_Response.nai.source_addr = (ushort) uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
		UDS_Mapping_Response.nai.target_addr = (ushort) uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
		UDS_Mapping_Response.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

		result = UDSApi.AddMapping_2013(CAN_Channel, ref UDS_Mapping_Request);
		if (!UDSApi.StatusIsOk_2013(result)) throw new Exception("Request mapping failed.");

		result = UDSApi.AddMapping_2013(CAN_Channel, ref UDS_Mapping_Response);
		if (!UDSApi.StatusIsOk_2013(result)) throw new Exception("Response mapping failed.");

		CAN_request_ID = CAN_Req_ID;
		CAN_response_ID = CAN_Resp_ID;
	}
	catch (Exception e)
	{
		message = e.Message + " Return code: " + ((int)result).ToString();

		return (int)result;
	}
	
	return OK;
}


public int PEAK_UDS_wdbi_FD(UDSApi.uds_svc_param_di di, byte[] dataBuffer, ref string message)
{
	uds_msg request = new uds_msg();
	uds_msg request_confirmation = new uds_msg();
	uds_msg response = new uds_msg();
	uds_msgconfig config = new uds_msgconfig();

	// Set request message configuration
	config.can_id = (UInt16)CAN_request_ID;
	config.can_msgtype = cantp_can_msgtype.PCANTP_CAN_MSGTYPE_STANDARD;
	config.can_msgtype |= (cantp_can_msgtype.PCANTP_CAN_MSGTYPE_FD | cantp_can_msgtype.PCANTP_CAN_MSGTYPE_BRS);
	config.nai.extension_addr = 0x0;
	config.nai.protocol = uds_msgprotocol.PUDS_MSGPROTOCOL_ISO_15765_2_11B_NORMAL;
	config.nai.source_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_TEST_EQUIPMENT;
	config.nai.target_addr = (UInt16)uds_address.PUDS_ADDRESS_ISO_15765_4_ADDR_ECU_1;
	config.nai.target_type = cantp_isotp_addressing.PCANTP_ISOTP_ADDRESSING_PHYSICAL;

	if (dataBuffer.Length < 65)
	{
		if (dataBuffer.Length < 9) config.can_tx_dlc = (byte)dataBuffer.Length;
		else if (dataBuffer.Length < 13) config.can_tx_dlc = 9;
		else if (dataBuffer.Length < 17) config.can_tx_dlc = 10;
		else if (dataBuffer.Length < 21) config.can_tx_dlc = 11;
		else if (dataBuffer.Length < 25) config.can_tx_dlc = 12;
		else if (dataBuffer.Length < 33) config.can_tx_dlc = 13;
		else if (dataBuffer.Length < 49) config.can_tx_dlc = 14;
		else config.can_tx_dlc = 15;
		config.type = uds_msgtype.PUDS_MSGTYPE_UUDT;
	}
	else config.type = uds_msgtype.PUDS_MSGTYPE_USDT;

	result = UDSApi.SvcWriteDataByIdentifier_2013(CAN_Channel, config, out request, di, dataBuffer, (uint)dataBuffer.Length);
	if (UDSApi.StatusIsOk_2013(result))
	{
		result = UDSApi.WaitForService_2013(CAN_Channel, ref request, out response, out request_confirmation);
		if (UDSApi.StatusIsOk_2013(result))
		{
			UDSApi.MsgFree_2013(ref request);
			UDSApi.MsgFree_2013(ref response);
			UDSApi.MsgFree_2013(ref request_confirmation);

			message = "UDSApi.SvcWriteDataByIdentifier_2013 OK.";
			return OK;
		}
		else
		{
			UDSApi.MsgFree_2013(ref request);
			UDSApi.MsgFree_2013(ref response);
			UDSApi.MsgFree_2013(ref request_confirmation);

			message = "UDSApi.SvcWriteDataByIdentifier_2013 failed. Return code: " + ((int)result).ToString();
			return -2;
		}
	}
	else
	{
		UDSApi.MsgFree_2013(ref request);
		UDSApi.MsgFree_2013(ref response);
		UDSApi.MsgFree_2013(ref request_confirmation);

		message = "UDSApi.SvcWriteDataByIdentifier_2013 failed. Return code: " + ((int)result).ToString();
		return -1;
	}
}
The CAN trace of the actual frame looks like the following:

reading out (using "Read Data By Identifier" service) the same ID looks like this:
Type=FD,BRS; Length=8, Data=03 22 F1 8C 55 55 55 55
Type=FD,BRS; Length=24, Data=00 13 62 F1 8C 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 CC CC CC

CAN capture of WDBI:
Type=FD,BRS; Length=20, Data=2E F1 8C 31 32 33 34 35 36 37 38 39 30 31 32 33 34 35 36 55

What am I doing wrong?
If that would work, as a next step:
Can I use UDS + ISO-TP APIs in a way where I need to send more than 64 bytes of data with WDBI, and still use segmented message type (uds_msgtype.PUDS_MSGTYPE_USDT)? Because this would be the most efficient way of sending lot of data bytes (to be able to use segmentation and also send the maximum amount of data bytes a single CAN FD frame can send = 64).

Thank you for your help,
Best Regards:
Balazs

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

Re: Sending CAN FD frame error using UDSApi.SvcWriteDataByIdentifier_2013

Post by F.Vergnaud » Wed 9. Feb 2022, 14:49

Hello,

The behaviour you want to achieve corresponds to PCAN-ISO-TP parameter : PCANTP_PARAMETER_CAN_TX_DL
Description: This parameter is used to define the default maximum Data Length Code (DLC) used when
transmitting ISO-TP messages with CAN FD enabled: the fragmented CAN FD frames composing the full
CAN ISO-TP message will have at most a length corresponding to that DLC (it depends if the data fit in a
lower DLC value). Note that member can_tx_dlc in cantp_mapping or message’s can_info.dlc can be used
to override this parameter locally.
Possible values: 8 (0x08) to 15 (0x0F).
Default value: 8 (0x08).
Be careful that CAN_TX_DL (and the corresponding cantp_mapping.can_tx_dlc) is a maximum value: the API will adapt the actual dlc based on the length of the ISO-TP message.
Just configure your mappings with:

Code: Select all

UDS_Mapping_Request.can_tx_dlc = 0xF; 
UDS_Mapping_Response.can_tx_dlc = 0xF;
In your WDBI code, remove the block "dataBuffer.Length < 65" and just use "config.type = uds_msgtype.PUDS_MSGTYPE_USDT;". The APIs will do the rest!

Let me know if this works for you.
Best regards,
Fabrice

vddvss
Posts: 10
Joined: Wed 12. Jun 2019, 10:21

Re: Sending CAN FD frame error using UDSApi.SvcWriteDataByIdentifier_2013

Post by vddvss » Wed 9. Feb 2022, 15:06

Hello Fabrice,

Thank you very much for the fast response!
Your suggestion helped a lot, and it works now as expected! I've had the feeling that I am only missing the solution by a little, however I did not see the full picture.

Thank you for your help,
Best Regards:
Balazs

Post Reply