so I am using an ARM9 processor (i.mx28) running a Linux Kernel to communicate with a BLDC controller via RS232 (High level protocol is based on CANOpen protocol). Messages sent to the controller are generally followed by a response.
The controller-side connector features RX, TX as well as GND, so no flow control lines or such. The controller manual states that connection must be set up using no software flow control. Thus, I configured the port to ignore DCD (using CLOCAL) as well as RTS/CTS (using ~CRTSCTS) and software flow control (using ~IXON, ~IXOFF and ~IXANY).
My problem is as follows: after setting up the serial port, writing works just fine, commands like for example a soft reset are executed instantly. Trying to read mentioned responses, however, results in "Errno 11: Resource momentarily unavailable". When I tried monitoring the messages on my computer running a terminal, read() returns 0 instead of -1, errno is hence not set. Vice versa, I tried hooking up the BLDC controller to said terminal and manually rebooting it to get to see the boot-up-message which is sent at start up. This worked fine as well.
I've been abusing Google for the last 3 days looking for similar problems, but to no avail. Among several different combinations of setting for nonblocking IO, I also tried several ways of blocking behavior, this however resulted in blocking forever and still not reading anything at all.
I suspect that the serial port is, although the termios configuration states otherwise, still expecting handshake/flow control, as hooking up the system to a computer providing RTS/CTS lines works fine.
int configureSerialPort() {
//Open Serial Port--------------------------------------------
int fileDescr = open("/dev/ttyS3", O_RDWR | O_NDELAY);
if (fileDescr < 0){
std::cout << "Unable to open Serial Port." << std::endl;
exit(1);
}
else std::cout << "Serial Port opened." << std::endl;
fcntl(fdSerial, F_SETFL, O_NONBLOCK);
//Configure Serial Port for B115200, 8N1---------
struct termios PortParams;
if (tcgetattr(fileDescr, &PortParams) < 0) {
std::cout << "Could not get Attributes." << std::endl;
exit(1);
}
else std::cout << "Got Attributes." << std::endl;
cfsetispeed(&PortParams, 115200);
cfsetospeed(&PortParams, 115200);
PortParams.c_cflag |= (CLOCAL | CREAD);
PortParams.c_cflag &= ~PARENB;
PortParams.c_cflag &= ~CSTOPB;
PortParams.c_cflag &= ~CSIZE;
PortParams.c_cflag |= CS8;
PortParams.c_cflag &= ~CRTSCTS;
PortParams.c_lflag &= ~(ICANON | ECHO | ECHONL | IEXTEN | ISIG);
PortParams.c_iflag &= ~(INPCK | ISTRIP | IGNPAR | PARMRK | IXON | IXOFF | IXANY);
PortParams.c_oflag &= ~OPOST;
PortParams.c_cc[VMIN] = 0;
PortParams.c_cc[VTIME] = 0;
if (tcsetattr(fileDescr, TCSANOW, &PortParams) != 0) {
std::cout << "Could not set Attributes." << std::endl;
exit(1);
}
else std::cout << "Port configured." << std::endl;
usleep(1000000);
tcflush(fdSerial, TCIFLUSH);
return fileDescr;
}
This is my configuration as by now, which should be fine to my understanding.
Writing and reading is done by their respective syscalls:
wrLenSerial = write(fdSerial, &resetNode, sizeof(resetNode));
if (wrLenSerial < sizeof(resetNode)) {
std::cout << "Could not send Write Command." << std::endl;
}
else std::cout << "Reset Command sent." << std::endl;
usleep(60000);
memset(inBufSerial, '\0', sizeof(inBufSerial));
rdlenSerial = read(fdSerial, inBufSerial, (sizeof(inBufSerial) - 1));
if (rdlenSerial < 0) {
std::cout << "Read Error. " << errno << std::strerror(errno) << std::endl;
}
else if (rdlenSerial == 0) {
std::cout << "Nothing read." << std::endl;
}
else {
std::cout << "Node Response: ";
for (int i = 0; i < rdlenSerial; i++) {
int r = inBufSerial[i];
std::cout << std::hex << r << std::dec << " " << std::endl;
}
}
I really hope this post is not too long to read, any thoughts are appreciated!