Menu

#7 Maybe error in Device.setBaudrate()

1.0
closed
None
2018-07-27
2018-07-13
Oliver Lenz
No

Hi Stephen

It seems that there is an error.
Device.setBaudrate throws an Exception.

Log:
net.sf.yad2xx.FTDIException: Exception in D2XX native library call. Function: FT_SetBaudRate, Status: FT_INVALID_BAUD_RATE.
at net.sf.yad2xx.FTDIInterface.setBaudRate(Native Method)
at net.sf.yad2xx.Device.setBaudRate(Device.java:341)
at commontests.NegotiatorHardwaretest.main(NegotiatorHardwaretest.java:90)

Exception in thread "main" java.lang.NullPointerException
at commontests.NegotiatorHardwaretest.main(NegotiatorHardwaretest.java:147)


Is something to do before calling setBaudrate? I tried a Device.open()-call before, but the result is same. I want to change spi clock, is this possible with this method?
Also, a getBaudrate()-method would be also nice.

It would be nice if you can fix it. :)

regards
Oliver

Discussion

  • Oliver Lenz

    Oliver Lenz - 2018-07-13

    PS: cause invalid baudrate - I've tried it with some different values, from 10kHz, 1MHz, 10MHz (the speed I want) and some values between. Always same result.

     
  • Stephen Davies

    Stephen Davies - 2018-07-14
    • assigned_to: Stephen Davies
     
  • Stephen Davies

    Stephen Davies - 2018-07-14

    Hi Oliver,
    a few questions to get the process started:
    1) Which OS are you using? e.g. Windows
    2) Which version?
    3) Which FTDI chip? e.g. FT232RL
    4) Are you using the MPSSE class Spi?

    Yad2xx provides a Java layer over the top of the D2XX library. In many places the Java method call passes straight through to the underlying D2XX function, setBaudRate is one of those places.

    When a D2XX function call returns a value other than FT_OK the function call has failed. When this happens yad2xx thows FTDIException to indicate which function failed and why. In your case a call was made to FT_SetBaudRate and it returned a status code of FT_INVALID_BAUD_RATE. I have no way of knowing what value you passed for the baud rate, simply that D2XX didn't like it. Standard baud rate values are coded in the interface FTDIConstants. 10MHz is well above any standard baud rate.

    As a general rule you need to read the FTDI D2XX Programmers Reference. Looking at the entry for FT_SetBaudRate I can see their sample code calling FT_Open before calling FT_SetBaudRate.

    Agree that a getBaudRate method would be nice to have. Unfortunately there is no FT_GetBaudRate method in the D2XX API.

    If you are trying to use SPI the first thing to check is if your FTDI chip provides MPSSE support. Assuming your chip supports MPSSE it is recommend that you look at the Spi class and the three SPI samples provided.

    The Spi class provides two constructors, one allows you to set the SPI clock rate. This can only be set at startup (for now). As a workaround you could try closing an existing Spi object, then creating a new Spi object wrapping the same Device with a different clock rate and then opening it. I would expect that to work.

    Regards,
    Stephen

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-14

    Hi

    1) Which OS are you using? e.g. Windows
    -Windows 7
    2) Which version?
    I can't look for this at the moment. Only on monday again.
    3) Which FTDI chip? e.g. FT232RL
    FT232H
    4) Are you using the MPSSE class Spi?
    Yes, and spi works fine, but I had it tested only with a couple of bytes.

    I have to send >2kB every 10ms. First tests with this task resulting in an exception after a short time, not immediatly. My first idea (and the only which I have investigated) are buffer overflow or some similar.

    I've written two IOStream-classes for using the spi (if you're interested i would make it available here), in a single test (with hand typed data) it works fine.

    Thanks for remembering with the seccond constructor-well, I've seen this in ide's code completing. I will test it first on monday.

    Is there an other way to log whats going wrong? Maybe I'm not the only user who had this problem which changing spi clock.

     
  • Stephen Davies

    Stephen Davies - 2018-07-15

    Hi Oliver,
    comments inline.

    I have to send >2kB every 10ms. First tests with this task resulting in an exception after a short
    time, not immediatly. My first idea (and the only which I have investigated) are buffer overflow or
    some similar.

    Which method(s) in Spi was(were) being called?
    What was the stack trace?

    Spi testing has been limited. It works with basic bytes, DotStar LEDs and serial EEPROMs. It has not been tested in a high bandwidth/high throughtput situation yet.

    Looking at the code, Spi.writeBits() has an obvious bug. It will send at most 2^16 bytes. This is the maximum size permitted by the underlying MPSSE protocol. If the data is larger than 2^16 then it will only send the first 2^16 bytes and ignore the rest.

    It should probably sit in a loop but this raises the possibility of buffer overflow. Need to work out how to flow control for large buffers.

    I've written two IOStream-classes for using the spi (if you're interested i would make it
    available here), in a single test (with hand typed data) it works fine.

    Cool. Hadn't given any thought to using streams but can't think of a reason why not. So long as the streams are treated as being pure byte streams (no Unicode).

    Is there an other way to log whats going wrong? Maybe I'm not the only user who had this
    problem which changing spi clock.

    SPI clock rate configuration is separate from FT_SetbaudRate. SPI uses MPSSE. Changing the clock rate involves sending a command to the MPSSE controller (using FT_Write). Have a look at Mpsse.configureClock().

    I strongly recommend reading these FTDI documents:
    AN135 - MPSSE Basics
    AN114 - Interfacing FT2232H Hi-Speed Devices To SPI Bus
    AN108 - Command Processor for MPSSE and MCU Host Bus Emulation Modes

    Regards,
    Stephen

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-15

    Hi Stephen
    I'm using your new spi.transactReadWrite()-method. You have it written for me last week, I'm sure you remember ;). I feed this method only with a single byte-array.
    To post the stack trace, I will look for it next time at work.

    I have to optmize some methods to the IOStreams, actual I've only overriden the write-method for single bytes, this is actual only possible with generating an array by new-operator. For a single byte ok, but calling this in a loop by other standard stream methods is poorly.
    I do this next week and then I will commit it.

    Thanks for information about the mpsse. Well, I know that the FTDI-chip accesses its spi in mpsse-mode, but the way to create an spi-object only with a device-object let me forgotten the mpsse. In fact, I've been wondering for what it is, now I know. ;)
    I try to do my test with it.

     
  • Stephen Davies

    Stephen Davies - 2018-07-15

    Hi,
    the framework is written in layers. The Spi layer wraps an Mpsse object which in turn wraps a Device.

    Mpsse has lots of commands, only a few are SPI specific. If you read through the FTDI application notes and then walk through Spi.open() and its calls into various Mpsse methods you will be able to match up the FTDI code samples with yad2xx.

    Remember that the Mpsse code is intended to be generic and is shared by the Spi, I2c and Jtag classes.

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-17

    Ok Stephen, here is the stacktrace from exception:

    SCHWERWIEGEND: null
    net.sf.yad2xx.FTDIException: Exception in D2XX native library call. Function: FT_Read, Status: FT_IO_ERROR.
    at net.sf.yad2xx.FTDIInterface.read(Native Method)
    at net.sf.yad2xx.Device.read(Device.java:302)
    at net.sf.yad2xx.mpsse.Mpsse.read(Mpsse.java:454)
    at net.sf.yad2xx.mpsse.Spi.readWriteBits(Spi.java:250)
    at net.sf.yad2xx.mpsse.Spi.transactReadWrite(Spi.java:324)
    at net.sf.yad2xx.mpsse.Spi.transactReadWrite(Spi.java:309)

    One other...please, could you also add an transactReadWrite-method for a single byte? IO-Streams needs an overwritten method to read/write a single byte. Creating an array with a single item is poorly...

    Oh...there happens something other: I've improved mit OutputStream-class: you I have only overwritten the obliged write(int i)-method for writing a single byte.

    I also overruled now the other methods which provide to write a byte-array. And see, I get an other exception:

    Exception in thread "Thread-3" java.lang.ArrayIndexOutOfBoundsException: 2048
    at net.sf.yad2xx.mpsse.Mpsse.enqueue(Mpsse.java:397)
    at net.sf.yad2xx.mpsse.Spi.readWriteBits(Spi.java:233)
    at net.sf.yad2xx.mpsse.Spi.transactReadWrite(Spi.java:324)
    at net.sf.yad2xx.mpsse.Spi.transactReadWrite(Spi.java:309)

    Seems there is a constraining, unobserved buffer array, but it is not in your java code. Maybe in the dll or in FTDI's API? Is it possible to fix it?

     
  • Stephen Davies

    Stephen Davies - 2018-07-18

    Hi Oliver,
    am unable to replicate the first exception. Some more information would be helpful:
    1) What is the byte[] length being passed in to transactReadWrite, i.e. the argument to call Spi.java:309?
    2) Is this the first time transactReadWrite has been called?
    3) Do you have a code sample you can share?

    Method signature for Spi.transactReadWrite has changed from (byte[]) to (byte...). This allows invocation with a single byte, a comma separated list of bytes or a byte[].

    The second exception I have fixed. The Mpsse class has an internal buffer and it was way too small.

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-18

    Hi Stephen
    I'm not at work now, so I can't provide a codesample yet. Anyway, it would be a big bunch of classes, and I'm sure that I cant post all the code here. But maybe I'm able to provide small problem model version.

    But some conditions I can give yet: I want to send a byte[] with 2200 bytes, every 10ms (so far possible under windows).
    This transfer must occurred every 10ms, also if there is nothing to send (maybe there is some to read). If there is nothing to send, 0x00 will send 2200 times. The exception is thrown at first userinput, when some other then 0x00 is to send.

    Next time, I will add a counter to the 10ms-loop and add this to the exception.

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-20

    Hi Stephen, here I'am again.

    Unfortunatly, I'm not able to count the loops, but in debugger it works until I write something other than 0x00.

    I don't want to post this code here, but I'm sending an email to you with some more informations and code samples

     
  • Stephen Davies

    Stephen Davies - 2018-07-22

    Hi Oliver,
    4 days ago your issue was transactReadWrite reporting a problem with FT_Read (FT_IO_ERROR).

    I suspect this may be caused by the way your code is implemented i.e. using multiple threads. Concurrent use of a single Device is centainly going to end in failure. Is there any chance that this may have occured? Did two (or more) threads try to make concurrent calls to Spi.transactReadWrite?

    Todays stack trace (private email) reports a call to FT_Write failed with FT_INVALID_HANDLE. The most likely cause of this is that Spi.close() was called whilst concurrent threads were still running. Looking at your code I suspect the hardware test thread has completed but the conversation runner thread is still active.

    Were it up to me I'd be making this much simpler for now. Try using a single main function that polls the system timer before allowing periodic calls to Spi.transactReadWrite. That is, do it all from a single thread. My guess is that this will work correctly.

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-22

    Hi Stephen

    I am extremely embarrassed, but it seems that the exception is really caused by my implementation. After I send the mail, I tried an other test under same condition (but much easier written) works fine.
    I'm really sure that there are no Spi.transactReadWrite-calls in different threads, a unit test with the complete class works fine and I'm sure, that such mistakes would be prevent a successfull test.
    But chaotic close-call(s) is possible, I will check this next time.

    Please, could you implement an isClosed-method for Spi (and other objects which offer an open-mehtod)? I will clear my implementation, but I think it would be fine to observe the state if it is changeable. And it could be helpfull for debugging.

     
  • Oliver Lenz

    Oliver Lenz - 2018-07-23

    Hi Stephen

    Now its fixed-it was a mistake in my implementation. Thanks for repairing the out-of-boundary-exception and changing method signature. I think you can close this ticket now.

    The promised IO-Streams are in attachement. There are two versions: one with synchronisation and one without. Both variants has so happened during my work here.

    There are also unit tests for both variants, which needs an connected device (see javadocs) and both working fine here.. I don't know which framework you are using for unit tests-I'm using jUnit-plugin in Netbeans. Maybe you could the test adapt to your test framework.

    And maybe you has some notes or suggestions for it. Its the first time that I publish some (small) code here and Im sure that there are some things which could be made better.

     
  • Stephen Davies

    Stephen Davies - 2018-07-27

    Hi Oliver,
    good to hear that you're up and running.

    Thanks for the IOStreams code. Will look into incorporating them into the project. Yad2xx is also using JUnit.

    Regards,
    Stephen

     
  • Stephen Davies

    Stephen Davies - 2018-07-27
    • status: open --> closed
     

Log in to post a comment.