Go Down

Topic: native USB losing bytes with SerialUSB.write [RESOLVED] (Read 1 time) previous topic - next topic


Apr 21, 2013, 08:32 pm Last Edit: Apr 22, 2013, 08:00 pm by exedor Reason: 1
Board: Arduino Due
Version: 1.5.2

I'm trying to send a packet of 64 bytes on an interval (does not seem to matter how fast or slow) out the native USB port in client mode on the Due.  This comes in response to a request to start a data stream from the USB Host.  When I do this, somewhere between 6 and 8 bytes, it varies, get lost on every single transmission.  Earlier I was working with slightly smaller packet sizes and those often seem to transfer without issue.  I have not yet tried larger than 64 bytes.  I know there have been quite a few USB transfer bugs and so I thought I'd try building from git clone so I followed the instructions on the site for doing so.  I already had cygwin/ant/java prepped and ready from a different project, just needed to add a couple packages.  The build went fine but I'm not finding the Due in the Board list under the Tools menu in the one that I built.

Any ideas?  I really just need to get 64 bytes from the Due to the USB Host fairly often (about 2400 times/sec ultimately.)  I guess I can try padding with something to make it a different size, but it really needs to be a minimum of 64 bytes.

So far I've tried:
 - Sending at different rates
 - Sending one byte at a time with Serial.write(byte)
 - Sending all bytes with Serial.write(buffer, len)
 - Sending one byte at a time while the crc16 checksum is being calculated.
 - Delayed send
 - Using delay commands to introduce delays on send
 - Using timers to time the send
 - Using interrupts to do the send
 - Using flush to ensure all bytes are sent before next send request or next update to buffer

Always the same behavior so I'm thinking it might be another bug in the USB libs?
Any help would be greatly appreciated!

In essence, the code is:

Code: [Select]

#define ACK_CODE_BIT    0x80  // Printable character ( is easier to see than 0x80 )
#define DATA_BUF_SIZE_B 64
volatile byte outData[DATA_BUF_SIZE_B]; // as in out the USB port
u_short *crc        = (u_short *)(outData+DATA_BUF_SIZE_B-sizeof(u_short));       // Checksum
u_int  lastWriteTime = 0;

static __inline__ uint16_t crc16_update(uint16_t crc, uint8_t a)
   int i;

   crc ^= a;
   for (i = 0; i < 8; ++i)
       if (crc & 1) crc = (crc >> 1) ^ 0xA001;
       else crc = (crc >> 1);
   return crc;

void setup()
 while (!SerialUSB) ;
 outData[1] = 0xAA;
 outData[2] = 0xFF; // Used to fill array with bytes
 for (u_int i = 3; i < DATA_BUF_SIZE_B - 4; i++)
   outData[i] = 0;
 outData[DATA_BUF_SIZE_B - 4] = 0xAA;
 outData[DATA_BUF_SIZE_B - 3] = 0xAA;
 lastWriteTime = micros();

void loop()
 u_int i = 0;
 if (micros() > lastWriteTime+416) {
   // Alternate internal data bytes of packet between 0xff and 0x33
   //outData[2] ^= 0xCC;
   for(outData[2] ^= 0xCC, i = 3; i < DATA_BUF_SIZE_B-(sizeof(u_short)*2); i++)
     outData[i] = outData[i-1] ^ 0xCC;
   for(i = 0; i < DATA_BUF_SIZE_B-2; i++)
     *crc = crc16_update(*crc, outData[i]);
   SerialUSB.write((uint8_t *)outData, DATA_BUF_SIZE_B);
   lastWriteTime = micros();

Thanks for reply I've modified this post to include an example that will compile.  The above code segment sends 64 bytes of constantly alternating payload bytes with consistent header and footer bytes so it is easy to pick out the byte loss.  On the Host side (linux) I have written a small C program which simply does a  hex dump of everything it reads from /dev/ttyACM0.  If you want that source code I'd be happy to provide it as well.



Apr 22, 2013, 06:43 am Last Edit: Apr 22, 2013, 08:23 am by exedor Reason: 1
Done, modified the original post.  I also noticed that when I send the same data over the Programming port instead of the native USB port data is not lost but of course, the needed speed isn't there.


Please do post the host side code. In particular, have you set the port to raw mode? It may be cooking your data hence losing bytes. Try "stty -F /dev/ttyACM0 sane raw" before running your code (look at the stty manpage for other options)
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html


Holy crap, you're absolutely right, DUH!  I went through that exact same exercise back when I was building my communication to the Uno to run prior solution but it was just several years ago!  That was exactly the problem!!!  The scripting that preps the device on linux is done in another section of code so I forgot it was even there.  I must have somehow thought I didn't need it anymore since it was native USB but of course the driver is still creating as a tty so obviously I would!


Go Up