Using ISO TP send and recive messages in one PCAN

A free API for the transfer of data packages according to ISO-TP (ISO 15765-2)
Post Reply
jerry.lee
Posts: 4
Joined: Tue 19. Oct 2021, 09:56

Using ISO TP send and recive messages in one PCAN

Post by jerry.lee » Mon 1. Aug 2022, 07:05

Hi

We want to try to use one of PCAN to complete the send and recive of ISOTP(API from PCAN-ISO-TP_2016.cs), so we called the following C# function, we can send the first message and recive the feedback message, but when we call the 2nd MsgDataInit_2016, it will be failed.

Could you help to point out the cause of the error or where it needs to be corrected? The following is our code flow.

Thx

Code: Select all

	   // Initialize channels: CAN2.0 - 500Kbit/s
	   res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter : {0}", STATUS_OK_KO(res));

            // Allocate tx CAN message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx CAN message : {0}", STATUS_OK_KO(res));

            // Allocate rx message
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_NONE);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Initialize Tx message containing "SartDownload"
            uint can_id = 0x700;
            byte[] dataSartDownload = { 0x81, 0x27, 0x72, 0xd7, 0x68, 0xfa, 0x81, 0xed };

            res = CanTpApi.MsgDataInit_2016(out tx_msg, can_id, cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED, 8, dataSartDownload);
            Console.WriteLine("Initialize tx message : {0}", STATUS_OK_KO(res));

            // Write "dataSartDownload" message
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write \"SartDownload\" message : {0}", STATUS_OK_KO(res));

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter : {0}", STATUS_OK_KO(res));

            // Initialize channels: CAN2.0 - 500Kbit/s
            res = CanTpApi.Initialize_2016(receiver_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize receiver : {0}", STATUS_OK_KO(res));

            // Allocate rx message
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_NONE);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Create and set a receive event on receiver
            System.Threading.AutoResetEvent receive_event = new System.Threading.AutoResetEvent(false);
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = Convert.ToUInt32(receive_event.SafeWaitHandle.DangerousGetHandle().ToInt32());
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = receive_event.SafeWaitHandle.DangerousGetHandle().ToInt64();
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(receiver_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Set receive event on receiver : {0}", STATUS_OK_KO(res));
            // Wait a receive event on receiver
            bool wait_result = receive_event.WaitOne(100000);
            Console.WriteLine("Wait a message on receiver : {0}", OK_KO(wait_result));

            // If we receive something on the receiver, read the message
            if (wait_result)
            {
                res = CanTpApi.Read_2016(receiver_handle, out rx_msg);
                Console.WriteLine("Read message on receiver : {0}", ByteArrayToString(rx_msg.Msgdata_can_Copy.data_max));
                String valSartDownload = "0000000000000000";
                var rx_result = ByteArrayToString(rx_msg.Msgdata_can_Copy.data_max);
                byte val = 0;
                if (CanTpApi.getData_2016(ref rx_msg, 0, out val))
                    Console.WriteLine("Check if the message is \"SartDownload\" : {0}", OK_KO(ByteArrayToString(rx_msg.Msgdata_can_Copy.data_max) == valSartDownload));
                else
                    Console.WriteLine("Check if the message is \"SartDownload\" : NOK");
            }

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref rx_msg);
            Console.WriteLine("Free rx message : {0}", STATUS_OK_KO(res));

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(receiver_handle);
            Console.WriteLine("Uninitialize receiver : {0}", STATUS_OK_KO(res));

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter : {0}", STATUS_OK_KO(res));
					
	   // Initialize channels: CAN2.0 - 500Kbit/s
            res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter : {0}", STATUS_OK_KO(res));

            // Allocate tx CAN message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx CAN message : {0}", STATUS_OK_KO(res));

            // Allocate rx message
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_NONE);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            uint can_id = 0x700;
            byte[] dataSartDownload = { 0x81, 0x27, 0x72, 0xd7, 0x68, 0xfa, 0x81, 0xed };

 ---------// the 2nd MsgDataInit will fail-------------------------
            res = CanTpApi.MsgDataInit_2016(out tx_msg, can_id, cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED, 8, dataSartDownload);
            Console.WriteLine("Initialize tx message : {0}", STATUS_OK_KO(res));

            // Write "dataSart2nd" message
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write \"SartDownload\" message : {0}", STATUS_OK_KO(res));


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

Re: Using ISO TP send and recive messages in one PCAN

Post by F.Vergnaud » Mon 1. Aug 2022, 10:00

Hello,

I've tried your sample but there was no issue with the 2nd MsgDataInit_2016 call... What error code do you get?

Your code is alright, just be careful on the workflow:
- you should not uninitialize your Tx channel right after writing a message. It may still be in the processing queue as the Write function is asynchronous.
- you should initialize the Rx channel and the receive event before writing your message. Otherwise you will not receive anything as the CAN frame is already transmitted on the bus.

Here is your code with the above modifications.

Code: Select all

        /// <summary>Entry point of the program, start a small CAN ISO TP read/write example</summary>
        static void Main(string[] args)
        {
            // Local variables
            int MSG_SIZE = MSG.Length;
            cantp_status res = new cantp_status();
            StringBuilder buffer = new StringBuilder(500);
            UInt32 STmin;
            cantp_msg tx_msg = new cantp_msg();
            cantp_msg rx_msg = new cantp_msg();
            cantp_mapping mapping = new cantp_mapping();
            cantp_handle transmitter_handle = new cantp_handle();
            cantp_handle receiver_handle = new cantp_handle();

            // Initialize variables
            transmitter_handle = cantp_handle.PCANTP_HANDLE_USBBUS2;  // TODO: modify the value according to your available PCAN devices.
            receiver_handle = cantp_handle.PCANTP_HANDLE_USBBUS1;  // TODO: modify the value according to your available PCAN devices.

            // Print version informations
            CanTpApi.GetValue_2016(cantp_handle.PCANTP_HANDLE_NONEBUS, cantp_parameter.PCANTP_PARAMETER_API_VERSION, buffer, 500);
            Console.WriteLine("PCAN-ISO-TP API Version : {0}", buffer);

            // Initialize channels: CAN2.0 - 500Kbit/s
            res = CanTpApi.Initialize_2016(transmitter_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize transmitter : {0}", STATUS_OK_KO(res));


            // Initialize channels: CAN2.0 - 500Kbit/s
            res = CanTpApi.Initialize_2016(receiver_handle, cantp_baudrate.PCANTP_BAUDRATE_500K);
            Console.WriteLine("Initialize receiver : {0}", STATUS_OK_KO(res));

            // Allocate rx message
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_NONE);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Create and set a receive event on receiver
            System.Threading.AutoResetEvent receive_event = new System.Threading.AutoResetEvent(false);
            if (IntPtr.Size == 4)
            {
                UInt32 iBuffer = Convert.ToUInt32(receive_event.SafeWaitHandle.DangerousGetHandle().ToInt32());
                res = CanTpApi.SetValue_2016(transmitter_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, ref iBuffer, sizeof(UInt32));
            }
            else if (IntPtr.Size == 8)
            {
                Int64 iBuffer = receive_event.SafeWaitHandle.DangerousGetHandle().ToInt64();
                byte[] byteArray = BitConverter.GetBytes(iBuffer);
                res = CanTpApi.SetValue_2016(receiver_handle, cantp_parameter.PCANTP_PARAMETER_RECEIVE_EVENT, byteArray, sizeof(UInt64));
            }
            Console.WriteLine("Set receive event on receiver : {0}", STATUS_OK_KO(res));



            // Allocate tx CAN message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx CAN message : {0}", STATUS_OK_KO(res));

            // Allocate rx message
            res = CanTpApi.MsgDataAlloc_2016(out rx_msg, cantp_msgtype.PCANTP_MSGTYPE_NONE);
            Console.WriteLine("Allocate rx message : {0}", STATUS_OK_KO(res));

            // Initialize Tx message containing "SartDownload"
            uint can_id = 0x700;
            byte[] dataSartDownload = { 0x81, 0x27, 0x72, 0xd7, 0x68, 0xfa, 0x81, 0xed };

            res = CanTpApi.MsgDataInit_2016(out tx_msg, can_id, cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED, 8, dataSartDownload);
            Console.WriteLine("Initialize tx message : {0}", STATUS_OK_KO(res));

            // Write "dataSartDownload" message
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write \"SartDownload\" message : {0}", STATUS_OK_KO(res));

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));


            // Wait a receive event on receiver
            bool wait_result = receive_event.WaitOne(100000);
            Console.WriteLine("Wait a message on receiver : {0}", OK_KO(wait_result));

            // If we receive something on the receiver, read the message
            if (wait_result)
            {
                res = CanTpApi.Read_2016(receiver_handle, out rx_msg);
                Console.WriteLine("Read message on receiver : {0}", ByteArrayToString(rx_msg.Msgdata_can_Copy.data_max));
                String valSartDownload = "0000000000000000";
                var rx_result = ByteArrayToString(rx_msg.Msgdata_can_Copy.data_max);
                byte val = 0;
                if (CanTpApi.getData_2016(ref rx_msg, 0, out val))
                    Console.WriteLine("Check if the message is \"SartDownload\" : {0}", OK_KO(ByteArrayToString(rx_msg.Msgdata_can_Copy.data_max) == valSartDownload));
                else
                    Console.WriteLine("Check if the message is \"SartDownload\" : NOK");
            }

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref rx_msg);
            Console.WriteLine("Free rx message : {0}", STATUS_OK_KO(res));




            // Allocate tx CAN message
            res = CanTpApi.MsgDataAlloc_2016(out tx_msg, cantp_msgtype.PCANTP_MSGTYPE_CAN);
            Console.WriteLine("Allocate tx CAN message : {0}", STATUS_OK_KO(res));

            // the 2nd MsgDataInit 
            
            res = CanTpApi.MsgDataInit_2016(out tx_msg, can_id, cantp_can_msgtype.PCANTP_CAN_MSGTYPE_EXTENDED, 8, dataSartDownload);
            Console.WriteLine("Initialize tx message : {0}", STATUS_OK_KO(res));

            // Write "dataSart2nd" message
            res = CanTpApi.Write_2016(transmitter_handle, ref tx_msg);
            Console.WriteLine("Write \"SartDownload\" message : {0}", STATUS_OK_KO(res));

            // Free messages space
            res = CanTpApi.MsgDataFree_2016(ref tx_msg);
            Console.WriteLine("Free tx message : {0}", STATUS_OK_KO(res));

            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(transmitter_handle);
            Console.WriteLine("Uninitialize transmitter : {0}", STATUS_OK_KO(res));
            // Uninitialize channels
            res = CanTpApi.Uninitialize_2016(receiver_handle);
            Console.WriteLine("Uninitialize receiver : {0}", STATUS_OK_KO(res));

            // Exit

            Console.WriteLine("Press any key to exit...");
            Console.In.Read();
        }
Best regards,
Fabrice

jerry.lee
Posts: 4
Joined: Tue 19. Oct 2021, 09:56

Re: Using ISO TP send and recive messages in one PCAN

Post by jerry.lee » Mon 1. Aug 2022, 11:02

Hi Vergnaud

Thanks for your quick reply

Sorry I didn't clearly express the content of the question. My setting is to use one set of PCAN to send and receive, and another set of CAN devices to receive and feedback. The Initialize settings are as follows:

// Initialize handles
transmitter_handle = cantp_handle.PCANTP_HANDLE_USBBUS1; // TODO: modify the value according to your available PCAN devices.
receiver_handle = cantp_handle.PCANTP_HANDLE_USBBUS1; // TODO: modify the value according to your available PCAN devices.

Thx

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

Re: Using ISO TP send and recive messages in one PCAN

Post by F.Vergnaud » Mon 1. Aug 2022, 11:29

If you use the same channel to transmit and receive, you only need to initialize that channel once: just use your variable "transmitter_handle" and remove "receiver_handle".

Also note that if you want to transmit an ISOTP message, you need to configure the Networking Addressing Information of your message.
Currently you're only configuring a CAN frame (as the NAI is not provided).

Please check "02_client_ISO15765-2_normal_addressing" for a complete sample.
Best regards,
Fabrice

Post Reply