Hi,
I am using a Linux Host to communicate with my nRF52840 as a USB CDC ACM device. As a test, I ran minicom and was able to transfer bytes to my Nordic app successfully. I used the Nordic egs to get this far. When I switch from minicom to my Linux USB Host app, I am seeing very strange byte alignment issues. If (for example), I write the following 4 bytes { 0x01, 0x02, 0x03, 0x04 } I receive 4 bytes within my Nordic app app_usbd_cdc_acm_read() call, but I receive 0x02, 0x03, 0x04, 0x00. I expected that this was a simple bug where I selected an incorrect offset, but no such "luck". My offsets are correct.
On Linux, CDC ACM driver shows my device as /ttyACM0. I have setup a udev rule as per this and simlilar articles: https://hackaday.com/2009/09/18/how-to-write-udev-rules/#comments
Specifically, I have added the following entry to a /etc/udev/rules.d/99-com.rules file entry to create /dev/ttyDwUSBBLE with specific access to my device with Vid=0x030e and Pid=0x0000
KERNEL=="ttyACM[0-9]*", SUBSYSTEM=="tty", ATTRS{idVendor}=="030e", ATTRS{idProduct}=="0000", SYMLINK="ttyDwUSBBLE"
Opening and writing to /dev/ttyACM0 and /dev/ttyDwUSBBLE has the same behaviour - the first byte written does not come through and and extra byte is added to the end of my written data.
I am quite confident that my Nordic code is fine, but that the Linux CDC driver has issues or that I am configuring the Linux CDC port incorrectly. This is my config:
// sPort is /dev/ttyACM0 bool CUSBHost::init(char* sPort) { // If already open, close first. if(m_fileDescripter > 0) { close(m_fileDescripter); m_fileDescripter = 0; } m_fileDescripter = open (sPort, O_RDWR | O_NOCTTY ); if (m_fileDescripter < 0) { printf("Error opening port %s\r\n", sPort); return false; } // Set connection speed, always 8n1 (no parity). Try default of 230k first. if(!setIfaceAttrib (B4000000)) { printf("Error setting USB Host speed.\r\n"); return false; } // All set. m_initialized = true; return true; }
This calls setIfaceAttrib() shown below.
bool CUSBHost::setIfaceAttrib (int speed)
{
struct termios tty;
memset (&tty, 0, sizeof tty);
if (tcgetattr (m_fileDescripter, &tty) != 0)
{
cout << "Error from tcgetattr()." << endl;
return false;
}
cfsetospeed (&tty, (speed_t) speed);
cfsetispeed (&tty, (speed_t) speed);
// The 3 disable lines below are suggested for Linux hosts such as the Pi.
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
tty.c_iflag &= ~(INLCR | IGNCR | ICRNL );
tty.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
tty.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed
tty.c_oflag &= ~OCRNL;
tty.c_lflag &= ~(ECHO | ECHOE | ECHONL | ICANON | ISIG | IEXTEN);
tty.c_cflag &= ~PARENB; // No parity.
tty.c_cflag &= ~CSTOPB; // Not 2 stop bits, but only 1
tty.c_cflag &= ~CSIZE; // Clear size
tty.c_cflag |= CS8; // Set to 8 bits.
tty.c_cc[VMIN] = 0; // Read doesn't block
tty.c_cc[VTIME] = 1; // 0.1 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // Turn on READ & ignore ctrl lines
// Make raw
cfmakeraw(&tty);
//tcflush(m_fileDescripter, TCIFLUSH);
if (tcsetattr (m_fileDescripter, TCSANOW, &tty) != 0)
{
cout << "Error from tcsetattr()." << endl;
return false;
}
return true;
}
If Nordic had any Linux CDC Host comms examples that would clarify how the port should be setup to talk to Nordic USB devices, that would be very helpful. I expect that my issue relates to how my port is setup in my Linux Host.
Online info suggests that Linux does things with ACM devices that could explain the strange behaviour. I think that my issue may be resolved by changing my USB CDC Host port config.
Thanks in advance,
Mark J