As of 2011-09-06, I've stopped working on my VNC2 projects. This page will remain with my latest findings on the various issues I discovered.
This page documents the issues I have come across while trying to develop software for the FTDI VNC2 family and my interactions with FTDI technical support.
If you have other reproducable issues, or need some help to diagnose a problem, sent me a note at jjp@pobox.com and I can incorporate new issues or provide some insight into diagnosis.
See my main page for updates.
Issue # | Name | Status | Firmware Version | Last Updated |
1 | USBSlave interrupt becomes stuck on | Sent to FTDI - no resolution | 1.4.0 | 2011-03-04 |
2 | USBHost limits interrupt in requests to no more often than 32ms | Sent to FTDI - no resolution | 1.4.0 | 2011-03-05 |
4 | USBHost driver provides no mechanism for determining the actual number of bytes read from a SETUP token | Sent to FTDI - no resolution | 1.4.0 | 2011-03-05 |
5 | USBSlave driver provides no mechanism to recover if a host times out a SETUP request | Sent to FTDI - no resolution | 1.4.0 | 2011-03-05 |
Not yet triaged. | ||||
Leaving the local variables or thread manager window open makes single stepping extremely slow | ||||
VIDE does not update disassembly tab when a new version is flashed | ||||
The "memory" window does not update as the scroll bar is dragged, just when the mouse is released | ||||
Opening a new disassembly window in VIDE resets the cursor of all other tabs to the top of the file | ||||
Often single stepping through assembly does not result in control returning to the IDE | ||||
Frequent VIDE hangs while editing text | ||||
Disassembly does not contain markup output from assember | ||||
Resolved. | ||||
3 | VinC cannot handle a function pointer as the first element of a structure | Resolved in 1.4.2 | 1.4.0 | 2011-09-05 |
6 | XOR-Equal "^=" does not work correctly on array elements | Resolved in 1.4.2 | 1.4.0 | 2011-09-05 |
7 | Linker optimizations appear to severely corrupt output | Obsoleted in V1.4.0 | 1.2.2-SP1 | 2011-03-01 |
8 | Reproducable compiler segfault | Resolved in 1.4.2 | 1.4.0 | 2011-09-05 |
9 | VIDE project wizard includes symbols that aren't defined in generated code | Resolved in 1.4.2 | 1.4.0 | 2011-09-05 |
10 | VIDE new project files encode absolute paths | Resolved in 1.4.2 | 1.4.0sp1 | 2011-09-05 |
11 | In 1.4.0 Firmware, writing to USBSlave interrupt in endpoint blocks forever | Resolved in 1.4.0sp1 | 1.4.0 | 2011-05-07 |
While developing an application using the USBSlave driver, I noticed odd timing behavior in user code. Namely, in some circumstances, user code can appear to run at 100x-300x slower than normal. On my linux host machine (2.6.35), the behavior trips 100% of the time after the host sends the SET_CONFIGURATION message. On my Windows host machine (Vista), it seems more sporadic, usually triggering after the first message or two from the host.
I was able to reproduce this with minimal modifications to one of the sample firmware applications and have attached a diff (ignoring whitespace), and a ZIP file of the entire project. In it, I toggle GPIO pins as fast as possible after receiving each SETUP message. The measured spacing varies from 18us when things are going well to 5ms when they are not.
I have done some followup investigation on this issue and have confirmed that it is indeed an interrupt firing very frequently.
My procedure for confirming this was to hex-edit the ROM file to modify all the interrupt vectors to instead point to unique bounce routines which incremented a counter before jumping to the original interrupt handler. My application only had 3 interrupts defined, one of which was obviously the reset handler. Then, in my user code, in a point where the slowdown was occurring, I sampled each counter, ran an empty for loop:
uint8 data; for (data = 0; data < 10; data++);
Then sampled it again. One of the interrupts fired on average 27 times during that simple busy loop, which seems to be comparable to the slowdown I am seeing. I am compiling with -O=1 so that the loop is not optimized away.
The interrupt vectors as they appear in my application:
03c0 - The reset vector 03c2 - This is the interrupt which is firing too frequently 03c4 - Appears to be unused 03c6 - Used, but is not repeatedly firing 03c8 - Unused 03ca - Unused 03cc - Unused 03ce - Unused
It is challenging for me to decipher much more than this, given that I am not sure what that interrupt vector is even driven by.
I have attached a ZIP file containing the modified USBSlaveHIDKbd application and a .diff file showing the changes from the FTDI umodified original. Note that in addition to changing the source, I modified the resulting .rom file in a hex editor to redirect the interrupt service routine. I have included both the original and modified binaries of the .rom file as .rom-original and .rom-modified. The one named .rom only is equal to .rom-modified in the ZIP file.
To observe the behavior, set a breakpoint inside the second critical section's if block. It will only be reached if the interrupt service routine fires more than 10 times in the above busy loop. For me, this happens every time I connect the slave port to a PC master.
When initiating interrupt in read requests to a HID device using the USBHost driver, the driver appears to be limited to at most one request per 32ms. Is there any driver configuration which can be used to reduce this interval? I am querying a HID device which updates every 10ms, and drops data if it is not queried at least that often.
A sample application is attached which demonstrates the problem when attached to a HID mouse when moved continuously, or other HID devices which always return data instead of stalls when queried. With an oscilloscope on pin 12, you can observe the total time for each read transfer request. Simultaneously analyzing the USB lines, the IN request is emitted on the same 32ms boundaries, with the transfer software request returning shortly after the device has responded. Regardless of the amount of delays in my application code, the flags I pass to the transfer, or the parameters I pass to initialize the USBHost driver, the reads appear to still complete only on even 32ms boundaries.
The VNC2 compiler produces a spurious error when a function pointer is the first element of a structure, that does not occur when a non-function pointer is the first element. The error occurs when trying to access the pointer in an instance of the structure, and has the form:
[VinC.exe] : compiler_fptr.c line 22: (error) C1000 syntax error, unexpected TYPE_NAME, expecting IDENTIFIER or CONSTANT
I have attached a C file demonstrating the problem. There is a commented out 'uint8' member of the structure, which if uncommented, causes the compiler to stop complaining.
The VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER ioctl issues a SETUP token across the host USB bus, and optionally sends or receives data from the remote device. However, when reading, the ioctl provides no mechanism for determining how many bytes were actually read from the device. The ioctl will return the USBHOST_CC_DATAUNDERRUN or USBHOST_CC_DATAOVERRUN flag, but from those, you would need to binary search to determine how many bytes a device actually returned, assuming that the result it returned was repeatable.
I am running into this when querying descriptors from devices in a generic way, and it is challenging in my application to perform a 'probe' query to first determine the size before making the real query. Even that is not robust, as the device need not return data commensurate with the reported descriptor size. It is also a problem in the case of HID report descriptors, where it is more difficult to determine what the appropriate size is.
It seems likely that the VOS_IOCTL_USBHOST_DEVICE_SETUP_TRANSFER is internally using the usbhost_xfer_t read/write mechanism that is exposed for IN or OUT pipes. That mechanism does report the actual number of bytes read, so I presume it would not be terribly difficult to expose that information for the SETUP API as well.
The VOS_IOCTL_USBSLAVE_SETUP_TRANSFER ioctl is used to respond to a SETUP token as issued by the host. If used to transmit from device to host, it blocks until the host polls the slave. If instead of polling for data, the host issues another SETUP token, the VOS_IOCTL_USBSLAVE_SETUP_TRANSFER continues to wait and responds to the next poll (associated with the new SETUP token) with the data as intended for the old one. It does not discard the new SETUP token, which is then received upon the next call to VOS_IOCTL_USBSLAVE_WAIT_SETUP_RCVD. Needless to say, this causes the x_WAIT_SETUP_RCVD to get out of phase with the x_SETUP_TRANSFER ioctl, from which I have found no reliable way to recover.
This can easily be triggered by setting the OS timeout on any individual setup transaction to be relatively short and forcing a delay in the VNC2 application before invoking x_SETUP_TRANSFER.
Ideally, x_SETUP_TRANSFER would return an error if a SETUP token had been received but had not yet been reported through x_WAIT_SETUP_RCVD, or if a SETUP token was received while it was waiting to transmit data.
The XOR-equal operator "^=" does not appear to work properly when operating on array elements, although it does when operating on scalar values. For example:
uint8 value = 0x43; value ^= 0x01;
Will result in value being equal to 0x42, as expected. However,
uint8 data[2]; data[1] = 0x43; data[1] ^= 0x01;
Will result in data[1] being equal to 0xc8, clearly not the correct XOR value.
If you enable optimizations for the linker, the output ROM file appears to have corrupted all libraries. From what I can tell, it looks like application code is unharmed, but as soon as a call is made into a system library, things go awry. I have demonstrated this by taking one of the sample applications, and the only change being to switch to a Release target and enable linker optimizations through:
Project | Options| VNC2 Linker | Enable optimizations = 1 (with optimization)
With linker optimizations disabled, the sample operates as expected.
[FROM FTDI] Using the USBHid example code with Compile options set for Release and Linker Optimizations set to 1, I was not able to replicate your problem.
That is most confusing. I have uploaded the resultant binary files from my compiler. Could you either compare them against yours, or send me yours? I did nothing but extract the original ZIP file; then in VIDE, select the "Build" ribbon, then click "Build". This is with 1.2.2-SP1 (I started with 1.2.2 then patched up to SP1).
USBSlaveHIDKbd-lto-20110228.zipThe md5sum of the .rom and .bin file are:
6a0f0c01d8932bcd2b620091694b71f9 *USBSlaveHIDKbd.rom 0bf14a6b408fcd0832bc5c117c470019 *USBSlaveHIDKbd.bin
I noticed this morning from the FTDI newsletter that version 1.4.0 of the toolchain has been released. Running it, I see that the option in the IDE to specify link time optimizations has been removed entirely. The option was not removed from the linker itself though, and can still be passed on the command line.
My old project file where I had it enabled still passes the -O=1 flag to the linker, although it shows up nowhere in the new IDE dialogs. When the -O=1 is passed, the output still appears to me to be corrupted. The checksums are different though due to the other changes in the toolchain and libraries though.
v1.4.0 02c2adc21c1d65cb16d789d6aa917895 USBSlaveHIDKbd.rom 8ab3047ee57bc3a46dc04b83a8c07e75 USBSlaveHIDKbd.bin
USBSlaveHIDKbd-lto-20110301.zip
I am guessing since the special purpose field for this option was removed from the IDE that it is no longer encouraged to be used, so I am not worrying about this too much. I am worried that my toolchain may be producing results which are not identical to yours.
After updating to toolchain version 1.4.0, some existing code I had started causing the compiler to segfault. I narrowed it down to the following construct:
#include "USBHost.h" uint8 status; if (status != USBHOST_OK) { if (status >= USBHOST_CC_ERROR) { } }
Upon attempting to compile this, the compiler segfaults. I attached Visual Studio to it and have included the backtrace below, although you'll need symbols or a .pdb file to make use of it:
> ntdll.dll!779f6356() [Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll] ntdll.dll!779f5cac() KernelBase.dll!75b86872() VinC.exe!0059cfee() ntdll.dll!779f6449() ntdll.dll!779f641b() ntdll.dll!779d8b7d() ntdll.dll!779f62a7() VinC.exe!00456f82() VinC.exe!0040b437() VinC.exe!0040cd1f() VinC.exe!00439074() VinC.exe!0040c8bc() VinC.exe!00439038() VinC.exe!0040ce03() VinC.exe!00439074() VinC.exe!0040c8bc() VinC.exe!00439038() VinC.exe!0040f34f() VinC.exe!00439128() VinC.exe!00402d07() VinC.exe!00405d11() VinC.exe!00409f7b() VinC.exe!00409874() VinC.exe!005a7184() kernel32.dll!76731194() ntdll.dll!77a0b429() ntdll.dll!77a0b3fc()
I have uploaded a sample application, trivially modified from the default 1.4.0 wizard generated code which demonstrates this problem.
I tried to create a sample application using the new wizard, the default generated code in my configuration does not compile with the following error:
"C:\Program Files\FTDI\Vinculum II Toolchain\tools\bin\VinC.exe" -c -o Debug\sample_wizard.obj \\ -d 1 C:\Users\josh\Documents\\sample_wizard\sample_wizard.c Compiling C:\Users\josh\Documents\\sample_wizard\sample_wizard.c 0 errors, 0 warnings and 0 informational messages "C:\Program Files\FTDI\Vinculum II Toolchain\tools\bin\VinC.exe" -c -o Debug\sample_wizard_iomux.obj \\ -d 1 C:\Users\josh\Documents\\sample_wizard\sample_wizard_iomux.c Compiling C:\Users\josh\Documents\\sample_wizard\sample_wizard_iomux.c 1 errors, 0 warnings and 0 informational messages [VinC.exe] : C:\Users\josh\Documents\\sample_wizard\sample_wizard_iomux.c \\ line 34: (error) C1100 undeclared identifier 'IOMUX_OUT_SPI_SLAVE_0_CLK' Vinc.exe failed with return code 4
It looks like the default generated IO mux configuration for the 32 pin package is using the incorrect symbol and probably intended to use the IOMUX_IN_SPI_SLAVE_0_CLK symbol instead.
For reference, I have uploaded the resulting code:
This problem appears to be new with the 1.4.0 toolchain:
Projects created using the new project wizard (I know of no other way to create new project files) encode absolute paths such that there is no easy way to move or rename a directory containing a project after the fact.
I am using toolchain version 1.4.0 and a V2DIP2-48.
In my application, after updating to 1.4.0, writing to an interrupt in endpoint with the USBSlave driver stopped working. Specifically, the VOS_IOCTL_USBSLAVE_TRANSFER ioctl would block, never returning, and when the host PC polled the interrupt endpoint, it would always return a stall. This behavior also appears for me in the sample USBHIDKbd application as delivered with the 1.4.0 firmware update. I had to slightly modify the source to choose a valid disconnect monitoring pin for the VNC2-48 on the V2DIP2-48:
The binary in that zip file is the direct result of compiling with the Debug profile.
When running this connected to a host PC, the device is detected correctly as a keyboard, but I see no key presses, and my software USB protocol analyzer shows every interrupt in request as a stall.
It should be noted, that in toolchain 1.2.2-SP1, this did work correctly as far as I could tell.
Home -> VNC2 Firmware and Toolchain Issues