2012-05-19

Rant: #pragma(pack) evilness

Wasting time on stuff like can ruin a otherwise great day:

#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
int main() 
{ 
  printf("size: %d\n", (int)sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION)); 
  return 0; 
}
cl test.cpp && test.exe
size: 44 (wrong)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
int main() 
{ 
  printf("size: %d\n", (int)sizeof(JOBOBJECT_BASIC_LIMIT_INFORMATION)); 
  return 0; 
}
cl test.cpp && test.exe
size: 48 (right)

I have just spent a few hours trying to figure out why SetInformationJobObject() kept failing in one of my projects.
And when it's because Microsoft can't decide if LARGE_INTEGER should be aligned to 4 or 8 bytes, I can't help but cursing their name.

The problem apears to be that winsock2.h does a "pragma pack(4)" before including windows.h, this will mess up some of the types defined in windows.h, including JOBOBJECT_BASIC_LIMIT_INFORMATION.

This was tested with VC2010 and the v7.0A sdk.

2012-03-04

FT232R BitBang mode is broken.


While trying to use a FTDI RT232RL in synchronous bitbang mode, I (like many others apparently) discovered that this feature is completely broken in most chips currently on the market.

The problem is described in the errata but not anywhere in the datasheet or appnode describing the bitbang modes.

It annoys me to no end that the bug is not described in the bitbang appnote, it would have saved me hours of frustration, and could possible save other people quite a bit of wasted time too.

When I was trying to find out what was wrong with my project, I ended up with this small repo case, that should have resulted in a 500 Hz square wave signal.

#include <stdio.h>
#include <string.h>
#include <ftdi.h>

int main()
{
  ftdi_context ftdic;
  ftdi_init(&ftdic);

  if(ftdi_usb_open_desc(&ftdic, 0x0403, 0x6001, NULL, NULL) < 0)
  {
    fprintf(stderr, "ftdi_usb_open_desc failed: %s\n", 
      ftdi_get_error_string(&ftdic));
    exit(1);
  }

  if(ftdi_set_baudrate(&ftdic, 1000) < 0)
  {
    fprintf(stderr, "ftdi_set_baudrate failed: %s\n", 
      ftdi_get_error_string(&ftdic));
    exit(1);
  }

  if(ftdi_set_bitmode(&ftdic, 0x01, BITMODE_SYNCBB) < 0)
  {
    fprintf(stderr, "ftdi_set_bitmode failed: %s\n", 
      ftdi_get_error_string(&ftdic));
    exit(1);
  }

  uint8_t data[256];
  for(int i=0; i<sizeof(data); i++)
    data[i] = i&1;

  for(;;)
  {
    ftdi_write_data(&ftdic, data, sizeof(data));
    uint8_t data2[256];
    ftdi_read_data(&ftdic, data2, sizeof(data2));
  }

  return 0;
}


But when hooking up a scope to the tx line of the FT232, it's easy to see that the output is a complete mess. The pulse widths are all over the place, from 60μs to 1ms.

In the errata, it's suggested that the fix is to run with a baudrate of 3000000, and just generate longer pulses to compensate. This might sound like a usable workaround, but FTDI neglected to tell that the chip is only running with 12.5MBit/s usb speed. Far from the needed ~65MBit/s needed for 3000000 baud (3000000baud * 10bits/byte (with bit stuffing) * 2 (we need to both send and recv) * 10% (usb header overhead).


Running the chip at 3000000 baud (changing 1000 to 3000000 in the ftdi_set_baudrate call), does not work either.
Not only do we not have enough usb bandwitdh (can be seen as the spratic blocks of data in the top part), but we only get 0.5μs long pulses. Not 0.33μs as expected.
The pulse widths are better than at lower speeds, but still not stable.

We can only hope that vendors will soon sell out of there devices using the A and B revisions of these chips, so that we can get some breakout boards with revision C, that supposedly will work as advertised.