Reputation: 51
I'm trying to receive messages from a device that uses mark parity for an address byte and space parity for the message body. The device is a "master" of a multi-drop serial bus. Based on the termios man page, I am using CMSPAR, PARENB, ~PARODD, INPCK, ~IGNPAR, and PARMRK. I expect to get a 3-byte sequence on each address byte: '\377' '\0' . It doesn't happen... I always get the address byte (and the body bytes) but no leading '\377' '\0' chars.
I tried to get PARMRK to work with odd and even parity setups just in case CMSPAR was not supported. Still no 3-byte sequences in the data stream. I'm using Ubuntu 12.04 LTS.
n_tty.c: n_tty_receive_parity_error() has the logic that implements PARMRK. 8250_core.c has the logic to flag parity errors. dmesg | grep ttyS0 shows serail8250: ... is a 16550A. Hmmm... a subsequent message shows 00:0a: ... is a 16550A. Perhaps the 8250 driver is not actually processing ttyS0?
Any ideas? Even if you don't see what I've done wrong but have gotten PARMAR to work, comments about your situation might help me.
UPDATE: My Linux is running in a VMware VM so I tried a non-VM config and now it works! I case someone knows, I'd still like to know why parity errors are not detected in a VM.
Here is my configuration code:
struct termios tio;
bzero(&tio, sizeof(tio));
tcgetattr(fd, &tio);
// Frame bus runs at 38,400 BAUD
const int BAUD_Rate = B38400;
cfsetispeed(&tio, BAUD_Rate);
cfsetospeed(&tio, BAUD_Rate);
// Initialize to raw mode. PARMRK and PARENB will be over-ridden before calling tcsetattr()
cfmakeraw(&tio);
// Ignore modem lines and enable receiver
tio.c_cflag |= (CLOCAL | CREAD);
// No flow control
tio.c_cflag &= ~CRTSCTS; // No HW flow control
tio.c_iflag &= ~(IXON | IXOFF); // Set the input flags to disable in-band flow control
// Set bits per byte
tio.c_cflag &= ~CSIZE;
tio.c_cflag |= CS8;
// Use space parity to get 3-byte sequence (0xff 0x00 <address>) on address byte
tio.c_cflag |= CMSPAR; // Set "stick" parity (either mark or space)
tio.c_cflag &= ~PARODD; // Select space parity so that only address byte causes error
// NOTE: The following block overrides PARMRK and PARENB bits cleared by cfmakeraw.
tio.c_cflag |= PARENB; // Enable parity generation
tio.c_iflag |= INPCK; // Enable parity checking
tio.c_iflag |= PARMRK; // Enable in-band marking
tio.c_iflag &= ~IGNPAR; // Make sure input parity errors are not ignored
// Set it up now
if (tcsetattr(fd, TCSANOW, &tio) == -1)
{
cout << "Failed to setup the port: " << errno << endl;
return -1;
}
Upvotes: 2
Views: 2994
Reputation: 1
I was having a similar issue (but from the opposite side):
The master of a serial protocol should be sending the 1st byte of a frame with parity mark and all the rest with parity space, while the slave would respond only with parity space.
Many serial comms drivers will ignore the "CMSPAR" bit without returning an error, so you may think that you've setup parity Mark/Space, while you've actually have selected parity Odd/Even instead.
I had to use a protocol analyser to realise that.
So I ended up checking the data of each byte before sending it and switching between odd/even parity in order to simulate the Mark/Space parity that I needed.
Most USB to Serial adapters will need a similar approach because they don't support parity mark/space.
For example, let's say we want to send the following data:
01 03 07 0F 1F
The 1st byte should be sent with parity Mark and the rest with parity space
We could do the following:
Send 01 with odd parity (parity bit=1)
Send 03 with odd parity (parity bit=0)
Send 07 with even parity (parity bit=0)
Send 0F with odd parity (parity bit=0)
Send 1F with even parity (parity bit=0)
That way we can simulate the needed result.
The catch here is that when you are switching parity, the driver is performing a lot of checks that are time consuming and this can affect the final rate of data transfer.
I was using a hacked version of the serial comms driver on an embedded device that could switch parity very fast by omitting some of the unnecessary checks for the application (like baud rate changes for example).
If your inter-character delay is critical, you may need a different solution.
Upvotes: 0