I have read most if not all the threads on USB performance. I saw one posted claiming 892KBps which I would kill for right now. My application shoots 32 byte packets over the bus and needs to do so reliably and bidirectionally at least 2800 times per second which should be very achievable.
Granted, it was on an older kernel and using the 1.5.2 version of Arduino but I did have this working at one point with right around 9000 32 byte packets per second bi-directionally. Now I'm using 1.6.4 and I'm on linux kernel 3.8.13.
When I set this up with the Arduino sending data as fast as it can pump it out and the client receiving as fast as it can receive (with VMIN = 32), I get what I'm looking for around 18,300 pps. However, when I do it the other way around, I get a measly 3700 pps.
I am dying to know why this is the case. I've think I've reduced my program down to the most minimal possible:
Here is the sketch for the arduino:
void setup() {
// SerialUSB.begin is a no op anyway so why bother?
}
void loop() {
uint8_t buf[64];
while (SerialUSB.available())
SerialUSB.readBytes(buf, sizeof(buf));
}
Here is the client program, it can be run with "iotest <path_to_serial_device_file>"
Makefile:
iotest: iotest.c
gcc -m64 -o iotest iotest.c -I.
debug: iotest.c
gcc -g -m64 -o iotest iotest.c -I.
clean:
rm iotest
iotest.c:
#include <stdio.h>
#include <termios.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <time.h>
#define timersub(e, b) ((double)(e.tv_sec - b.tv_sec) + (double)(e.tv_nsec - b.tv_nsec)/(double)1000000000)
int main(int argc, char *argv[]) {
struct termios oldtio, newtio;
struct timespec begin, end;
unsigned char buf[64];
int fd = 0, bytes = 0, rc = 0, totalBytes = 0, errors = 0;
if (argc < 2) {
printf("\nUsage: iotest <path_to_serial_device>\n\n");
return(0);
}
memset(buf, 0xAA, sizeof(buf));
memset(&begin, 0, sizeof(struct timespec));
memset(&end, 0, sizeof(struct timespec));
errno = 0;
fd = open(argv[1], O_RDWR | O_NOCTTY);
if (fd <= 0) {
if (errno != ENOENT)
printf("ERROR: Unable to open port %s, err(%d): %s\n",
argv[1], errno, strerror(errno));
else
printf("ERROR(%d): %s could not be found: %s", errno, argv[1], strerror(errno));
return(1);
}
printf("Successfully opened %s, setting raw mode...\n", argv[1]);
tcgetattr(fd, &oldtio);
memcpy(&newtio, &oldtio, sizeof(struct termios));
cfmakeraw(&newtio);
newtio.c_cc[VMIN] = 0; //sizeof(struct DataFromDue);
newtio.c_cc[VTIME] = 1;
newtio.c_cflag &= ~CSTOPB;
newtio.c_cflag &= ~CRTSCTS;
newtio.c_cflag |= (CREAD | CLOCAL);
tcsetattr(fd, TCSANOW, &newtio);
tcflush(fd, TCIOFLUSH);
printf("Sending %d byte chunks as fast as possible for 60 seconds...\n", sizeof(buf));
clock_gettime(CLOCK_MONOTONIC, &begin);
int i = 0;
do {
i++;
errno = 0;
if ((rc = write(fd, buf+bytes, sizeof(buf) - bytes)) >= 0) {
bytes += rc;
} else {
errors++;
}
if (bytes == sizeof(buf)) { totalBytes += bytes; bytes = 0; }
clock_gettime(CLOCK_MONOTONIC, &end);
} while (timersub(end, begin) < 60.0f);
printf("Sent %d bytes in %f seconds at a rate of %f bytes per second with %d errors\n",
totalBytes, timersub(end, begin), (double)totalBytes / timersub(end, begin), errors);
tcsetattr(fd, TCSAFLUSH, &oldtio);
close(fd);
return 0;
}
I'd sure love to know why the performance writing to the Due is so trashy now compared to the performance of reading from the Due. This has put a major major kink in the project
Thanks in advance for any insight you can provide!