I believe the problems you've been seeing are caused by incorrect baud rate settings on the programming port.
Using "stty" to set the baud rate is not reliable. Here is a copy of your code using the proper termios functions to set the baud rate after the port is open. This version always receives the 2400 32-byte packets in 6 or 7 seconds.
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#define PKTS 2400
#define PKT_SIZE 32
#define SER_PORT_IN "/dev/ttyACM0" // On my system this is programming
#define SER_PORT_OUT "/dev/ttyACM1" // On my system this is native USB
#define SER_PORT_SPEED 115200
#define TEST_READ 1
#define TEST_WRITE 0
int main() {
time_t deltaT = 0;
int i = 0, bytes = 0, totalBytes = 0, fdIn = 0, fdOut = 0;
char buf[PKT_SIZE];
struct termios t;
#if !(TEST_READ || TEST_WRITE)
printf("Nothing to test, change TEST_READ to 1 or TEST_WRITE to 1\n");
return(0);
#endif
#if TEST_READ
// this stty command does not seem to set the baud rate in some cases
snprintf(buf, sizeof(buf)-1, "stty -F %s sane raw -echo %d", SER_PORT_IN, SER_PORT_SPEED);
errno = 0;
fdIn = open(SER_PORT_IN, O_RDWR | O_NOCTTY);
if (fdIn < 0) {
printf("ERROR: Unable to open port %s, err(%d): %s\n",
SER_PORT_IN, errno, strerror(errno));
return(-1);
}
// using the termios functions after the port is open is very reliable
tcgetattr(fdIn, &t);
cfsetispeed(&t, B115200);
tcsetattr(fdIn, TCSANOW, &t);
printf("Succfully opened %s for reading\n", SER_PORT_IN);
#endif
#if TEST_WRITE
snprintf(buf, sizeof(buf)-1, "stty -F %s sane raw -echo", SER_PORT_OUT);
system(buf);
// Time for device to reset and native USB dev node to show up again
sleep(4);
errno = 0;
fdOut = open(SER_PORT_OUT, O_RDWR | O_NOCTTY);
if (fdOut < 0) {
printf("ERROR: Unable to open port %s, err(%d): %s\n",
SER_PORT_OUT, errno, strerror(errno));
return(-1);
}
printf("Succfully opened %s for writing\n", SER_PORT_OUT);
#endif
deltaT = time(NULL);
for (i = 0; i < PKTS; i++) {
#if TEST_WRITE
// Ensure full packet is delivered
bytes = 0; totalBytes = 0;
while (totalBytes < sizeof(buf)) {
errno = 0;
bytes = write(fdOut, buf+totalBytes, sizeof(buf) - totalBytes);
if (bytes < 0) {
printf("ERROR: Unable to write to port %s, err(%d): %s\n",
SER_PORT_OUT, errno, strerror(errno));
return(-1);
}
totalBytes += bytes;
}
#endif
#if TEST_READ
bytes = 0; totalBytes = 0;
while (totalBytes < sizeof(buf)) {
errno = 0;
bytes = read(fdIn, buf+totalBytes, sizeof(buf) - totalBytes);
if (bytes < 0) {
printf("ERROR: Unable to read from port %s, err(%d): %s\n",
SER_PORT_IN, errno, strerror(errno));
return(-2);
}
//printf("read %d\n", bytes);
totalBytes += bytes;
}
#endif
}
printf("Total time to run test with %d packets of size %d was %d seconds\n",
PKTS, (int)sizeof(buf), (int)(time(NULL) - deltaT));
return 0;
}