pylessard / python-udsoncan

Python implementation of UDS (ISO-14229) standard.
MIT License
575 stars 199 forks source link

Swapped Sequence Numbers #147

Closed HussainMughal1 closed 1 year ago

HussainMughal1 commented 1 year ago

Hello,

Context: I'm using the IntelHex library to read from a .hex file, which I then use to flash a microcontroller. I'm also using UDSonCAN functions for the flashing sequence.

As you can appreciate, there are thousands of bytes contained in the .hex, and so I'm attempting to read and send the maximum number of bytes in one message at a time, which is 4095.

My code looks something like this:

startAddress = 0x00840000
maxFrameSize = 4095
data = []

"""  Send 100 blocks of data from hex file """
for blocks in range(100):

    """ Increment sequence number for every data block sent """
    for sequenceNumber in range(0x01, 0xFF):

          """ Read data from .hex and append to array """
           for i in range(maxFrameSize):

               data.append(int(IH[startAddress + I]))

           """ Send """
           client.transfer_data(sequence_number= sequenceNumber, data= bytes(data))

           """ Clear array """             
           data.clear()

           """ Update Start address for next block """
           startAddress += maxFrameSize

The issue I've encountered is that the sequence number of two bytes is swapped according to my trace, preventing me from finishing the data transfer.

The image is a diff containing my trace on the left, and a trace generated from another vendor-supplied microcontroller flashing tool, with the differences highlighted.

image

I hope I've provided enough information.

Any help would be appreciated!

HussainMughal1 commented 1 year ago

I think the image above may be blurry. Here's another screenshot from 2nd attempt.

image

pylessard commented 1 year ago

Interesting, Sounds like the underlying layer is failing you. I don't think it is the isotp layer. What is your hardware? Your hardware driver might be using multiple mailboxes which is bad for isotp. 1 mailbox per ID is required otherwise you are vulnerable to non-deterministic behavior.

Somebody else reported something similar a year ago and he fixed it by playing with the low level driver.

pylessard commented 1 year ago

See this : https://github.com/pylessard/python-can-isotp/issues/66

HussainMughal1 commented 1 year ago

Hello,

Thanks for getting back to me.

I'm using a PCAN-USB dongle to communicate with an NXP MPC57X device.

My python application is using only 1 Tx arbitration ID as 0x712.

For debugging purposes, is there a way for me to print all what the self.logger captures as shown in the screenshot below? (from connections.py)

image

pylessard commented 1 year ago

Yes, enable logging at the beginning of your script with

logging.basicConfig(level=logging.DEBUG)

You can also control specific logger like this logging.getLogger('isotp').setLevel(logging.DEBUG)

pylessard commented 1 year ago

From your answer, don't confuse arbitration ID with hardware mailboxes. I still think that you may have low level problems with mailbox handling

HussainMughal1 commented 1 year ago

Hello,

Thank you for getting back to me.

I've enabled the debug script and I can see the sending calls for the sequence number 2B. The red arrow in the screenshot below shows where sequence number 2B should be. Instead, it comes after sequence number 21.

Flash tool error

pylessard commented 1 year ago

Are you running the isotp stack across multiple threads by any means? This log is impossible in a single thread application.

pylessard commented 1 year ago

You can call send and receive safely across threads, but process must be called in a single thread.

pylessard commented 1 year ago

Is this issue still relevant?

HussainMughal1 commented 1 year ago

Hi,

My Python script was initially using multiple threads. It now runs on a single thread and that seems to have corrected the issue.

Thank you for your help.

pylessard commented 1 year ago

Good. Always transfer data with thread-safe containers when doing multi-threaded application. In python, a good old Queue from the queue module does the trick.

Cheers.