IOW56 SPI transmission: not all bytes are read

This is the English forum for all topics related to IO-Warrior. Please post in English only

Moderator: Guido Körber

lgzco
Posts: 10
Joined: Tue Mar 13, 2007 10:23 am

IOW56 SPI transmission: not all bytes are read

Post by lgzco »

Hi,

I am using IOW56 SPI to transmit data. Sometimes not all bytes are read during the transmission. This information is returned from IowKitRead(). The GetLastError() returns sometimes 0 and sometimes 5. What does it mean ? Has anyone the similar situation ?

By the way I use Python script to control the transmission.

Thank you very much in advance !

kind regards
Ligang
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Re: IOW56 SPI transmission: not all bytes are read

Post by wayoda »

Hi Ligang,
definitly more input reqired!
lgzco wrote: I am using IOW56 SPI to transmit data.
What kind of device are you adressing? transmit in or out, what speed, ...
Sometimes not all bytes are read during the transmission.
This information is returned from IowKitRead().
How many bytes do you write/read? How many bytes did you expect to read. What does IowKitRead() return ?
The GetLastError() returns sometimes 0 and sometimes 5. What does it mean ?
0=NO-ERROR
5=IO-ERROR
Google for "errno" or search microsoft.com for constants returned by GetLastError.
By the way I use Python script to control the transmission.
How does that fit in? Is that a python-layer on top of the iowkit-lib?
If there is an error in the python-bindings, you are probably on your own.

Eberhard
lgzco
Posts: 10
Joined: Tue Mar 13, 2007 10:23 am

Post by lgzco »

Hi Eberhard,

thank you for your quick reply.

The device that I address is a FPGA with SPI slave interface. And the problem i reported happens with almost all possible transmission rate from 12 MHz down to 94 KHz.

Through this interface more than 100 kbytes are transferred but through many SPI transactions. By each SPI transaction about 20 bytes are transfered.

Python script calls the IoWarrior dll function. From Python I haven't found relative bug by using dll.

Best Regards,
Ligang
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Hi Ligang,

still need more input.
For a question like yours one needs to know:
The exact producer and partnumber of device you are talking about , so I could have a look at the Datasheet. (If it is abvailable somewhere on the internet:

The list of commands you send to the device:
How do you init the SPI-Mode?
How many bytes exactly do you send to the device?
What does IowkitWrite() return.
How many bytes did you expect to be written by the command.
Does you're program also read some data back from the device?

You need to be more explicit in your description of the error that occurs.

Eberhard
lgzco
Posts: 10
Joined: Tue Mar 13, 2007 10:23 am

Post by lgzco »

Hello Eberhard,

thank you for your kind answer. Because I was busy doing something else, I haven't the chance to visit this forum. Now there are relatively detailed info from my side.

The exact producer and partnumber of device you are talking about , so I could have a look at the Datasheet. (If it is abvailable somewhere on the internet:
The device is designedby ourselves and we have checked there are no conflicts with IOWorrior. Further more, the same error happens, even when IoWarrior does not connect to my device.
How do you init the SPI-Mode?
Clock Divider is within the range defined in IOWarrior Datasheet.
CPHA = 0
CPOL = 0
How many bytes exactly do you send to the device?
I send a SRecord file to the device, it amouts 110 KByte totally. I send the whole file through many SPI transfers one after another. By each transfer I send one line of the file. So each line does not necessarily have the same length, about 20 bytes.
You need to be more explicit in your description of the error that occurs.
Following is part of my python code:

Code: Select all

        f = open('Test.S', 'r')
        line = f.readline()
        while ((len(line) != 0) and (line[0:2] != 'S7')):
            DataWrite = []
            DataRead = []
            ReadResult = []
            
            DataWrite.append(int(line[2:4], 16))     #append number of bytes to transfer
            DataWrite.append(0)      #append the 'flag' field
            DataWrite.append(1)      #append 'write memory' command

            DataRead.append(int(line[2:4], 16)+1) #append number of bytes to transfer
            DataRead.append(0) #append 'flag' field
            DataRead.append(2) #append 'read memory' command
            DataRead.append(int(line[4:6], 16)) #append 1st address byte
            DataRead.append(int(line[6:8], 16)) #append 2ed address byte
            DataRead.append(int(line[8:10], 16)) #append 3rd address byte
            DataRead.append(int(line[10:12], 16)) #append 4th address byte
            DataRead.append(0)      #append dummy byte
            
            for i in range(4, len(line)-4, 2):
               DataWrite.append(int(line[i:i+2], 16))        #append address, DataWrite

            for i in range(12, len(line)-4, 2):
                DataRead.append(0)

            a.SPITransfer(DataWrite)
            ReadResult = a.SPITransfer(DataRead)
            .......
            line = f.readline()

The python source code of SPITransfer(..) function:

Code: Select all

  def SPITransfer(self, Data):
      BytesWritten = windll.IowKit.IowKitWrite(self.DeviceHandle, 1, pointer(Data), sizeof(IowReadResult56))
      if BytesWritten != sizeof(IowReadResult56):
        raise "IoWarrior: Not all bytes written!"
    
      ReturnLength = windll.Iowkit.IowKitRead(self.DeviceHandle, 1, pointer(Data), sizeof(IowReadResult56))
      if ReturnLength != sizeof(IowReadResult56):
        raise "IoWarrior: Not all bytes read!"

      ReturnList = []
      for k in range(1, datac.IowReadResult[0]+1):
        ReturnList.append(datac.IowReadResult[k])
      
      return ReturnList
What does IowkitWrite() return.
Does you're program also read some data back from the device?
Following is part of output, if the transfer finished correctly, the transferred line was just printed out.:

Code: Select all

S31540000070C82140000B2000008A1160A0090000162C
S31540000080C82140000B2000008A1160A40900002A04
.........
.........
S3154000009088112200C82140008A10200088102000C4
S315400000A003100004821060009FC040000100000061
S315400000B00000C1ED64000000400000000000C219CD

Traceback (most recent call last):
  File "C:\Test\Download.py", line 62, in ?
    a.SPITransfer(DataWrite)
    raise "IoWarrior: Not all bytes read!"
IoWarrior: Not all bytes read!
It seems there is error in the "read" function. The read results are all '0'.

Further more I also observed: The error happens more frequently when another windows application starts during the SPI transfer. It seems that the start of the another application interferes the transfer. The error does not always happen at the same position, i.e. the transfer of first several k bytes may be totally correct.

best regards,

Ligang
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Hello Ligang, now I was busy so this took a while...
lgzco wrote: It seems there is error in the "read" function. The read results are all '0'.

Further more I also observed: The error happens more frequently when another windows application starts during the SPI transfer. It seems that the start of the another application interferes the transfer. The error does not always happen at the same position, i.e. the transfer of first several k bytes may be totally correct.
Did you set a timeout for the read()-call in the SPITransfer()?
If the timeout is too short the windll.IowKit.IowKitRead() method does not wait long enough for the report to be returned by the IOWarrior.

If the timeout expires before any data can be read ReturnLength is 0, and the error in your code is raised.

Eberhard
lgzco
Posts: 10
Joined: Tue Mar 13, 2007 10:23 am

Post by lgzco »

Hi Eberhard,

Thanks a lot for your kind reply !

I haven't set any timeout for the read() call. Further the same error occurs even when no target is connected with IO-Warrior. Therefore I think the error condition is independent from which SPI slave that IO-Warrior is connected with. I hope this will help us to narrow down the error cause.

Best regards,
Ligang
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

lgzco wrote:...the same error occurs even when no target is connected with IO-Warrior.
By target you mean your external device?
If the error really occurs without your device attached we can at least forget about hardware issues.

Sadly the iowkit-library is not very good at communicating errors, but inside your application you could request details about the error in read with GetLastError(). I'm not very familiar with Python on Windows, but calling

Code: Select all

//In SPITransfer
ReturnLength = windll.Iowkit.IowKitRead(self.DeviceHandle, 1, pointer(Data), sizeof(IowReadResult56)) 
if ReturnLength != sizeof(IowReadResult56): 
    print windll.kernel32.GetLastError() 
could help to find out more about the error.

Eberhard
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

Failing IowKit functions when no device is connected is of course completely correct. What else should the functions do?
The next error is not reaching the chip over SPI. You get an error report for that.
Guido Körber
Site Admin
Posts: 2856
Joined: Tue Nov 25, 2003 10:25 pm
Location: Germany/Berlin
Contact:

Post by Guido Körber »

SPI has no handshaking that would allow to detect if there is a device on the other end.
lgzco
Posts: 10
Joined: Tue Mar 13, 2007 10:23 am

Post by lgzco »

Hi Eberhard,

finally I found there is really a 500 ms timeout configuration, which is set somewhere else as my SPITransfer() function by another colleague in team. And the error code (1460) returned from GetLastError (as you recommended in your last post) is also timeout error. Sorry for my false post ! After I increase the timeout to be 5000 ms, the same timeout error occured. After I comment the IowKitSetTimeout(..) function, my programm is blocked for ever. What can the reason be?

By the way,
By target you mean your external device?
If the error really occurs without your device attached we can at least forget about hardware issues.
yes, even when no external device is attached.

best regards,
Ligang
wayoda
Posts: 362
Joined: Fri Dec 19, 2003 12:00 pm
Location: Wuppertal/Germany

Post by wayoda »

Hi Ligang,

Lets check a few topics:
1. The Read-Timeout
If you call IowKitRead() you should (must?) set a timeout. Otherwise you application might lock up waiting for a report from the iowarrior that never arrives. 5 seconds seems to be a good choice here. When you expect an report to be returned for some command you send to the IOWarrior, it is a safe guess you have an error-condition after waiting for 5 seconds.

2. Why does the read in your programm timeout?
I have no idea. The IOWarrior56 does return a SPI-report for every report you send to it. Even without any SPI-Hardware attached to the IOWarrior your application should never fail to read a report with ReportId=0x09 after writing one .

3. Anything more you could check?
Are you using an IOWarrior56-Starterkit or a selfmade PCB?
Is there a hub inbetween the IOWarrior and you computer?
Are you using a bad or very long cable?

You should write a small test-app that, after initializing the SPI-mode with some defaults, simply sends of the 64 bytes of an SPI-report to the IOWarrior, and then waits for the 64 bytes to be returned from the device. If you do not connect you SPI-hardware, this test should never fail to read back a report after writing one.

Code: Select all

ReturnLength = windll.Iowkit.IowKitRead(self.DeviceHandle, 1, pointer(Data), sizeof(IowReadResult56)) 
I assume sizeof(IowReadResult56) does default to 64 in the above code?

Can you rule out a problem with the python windll module?
I possible, write the test-app from above in "C" to check wether you problem is Python related.

That's about all I can think of for now.

Eberhard
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

You should also use SimpleHIDWrite.exe (included in the SDK) for the experiment Wayoda proposed. If it succeeds with SimpleHIDWrite but not through Python then we know that the bug is in the Python program.
lgzco
Posts: 10
Joined: Tue Mar 13, 2007 10:23 am

Post by lgzco »

Hi Eberhard, Hi Robert,

many thanks for you kind reply again!
Are you using an IOWarrior56-Starterkit or a selfmade PCB?
I am using IOWarrior56-Starterkit.
Is there a hub inbetween the IOWarrior and you computer?
No.
Are you using a bad or very long cable?
It is just a very normal USB cable with about 1.5 m.

Furthermore, I have tried with your advice to send 64 bytes reports to IoWarrior. The problem is, the error is not so easily reproduced. I must wrap this send statement in a loop with long enough (e.g serveral thousand) iterations. During its running I start another programm like Eclipse, then the error is reproduced. And sometimes the GetLastError() returns also 5 (access denied) other than 1460 (time out), the later is of course the most often error message.
However I donot know how to simulate the same situation using SimpleHIDWrite.exe. Because with SimpleHIDWrite.exe I can only write the reports by pressing the "write" button manually. It seems that writing a text file automatically is not possible. What about the "playback" function? If it is the right one, can you explain me more about it? Is the following format the correct one ?

first line: WR 09 3D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
second line: RD 09 3D 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
...

best wishes,
Ligang
Robert Marquardt
Posts: 543
Joined: Mon Dec 01, 2003 6:09 pm

Post by Robert Marquardt »

"Save As..." saves the log to a text file.
"Playback..." allows to play back a saved log. Only device selections and actions which write to the device are executed.
If you doubleclick an entry in the log list box it is executed if possible.

Between writes SimpleHIDWrite sleeps for 50 msecs and handles Windows messages to allow the IOWarrior some time to execute commands.

It is rather easy to create long command lists simply by editing a saved log file.

BTW can you post your source here (if it is not too long)?
Post Reply