Поведение PARMRK termios не работает в Linux
Я пытаюсь получать сообщения от устройства, которое использует метку четности для байта адреса и пробел для тела сообщения. Устройство является "мастером" многоканальной последовательной шины. Основываясь на справочной странице termios, я использую CMSPAR, PARENB, ~PARODD, INPCK, ~IGNPAR и PARMRK. Я ожидаю получить 3-байтовую последовательность для каждого байта адреса: '\377' '\0' . Этого не происходит... Я всегда получаю адресный байт (и байты тела), но без начальных символов '\ 377' '\ 0'.
Я пытался заставить PARMRK работать с нечетными и четными настройками четности на случай, если CMSPAR не поддерживается. По-прежнему нет 3-байтовых последовательностей в потоке данных. Я использую Ubuntu 12.04 LTS.
n_tty.c: n_tty_receive_parity_error () имеет логику, которая реализует PARMRK. 8250_core.c имеет логику для определения ошибок четности. Dmesg | grep ttyS0 показывает serail8250: ... это 16550A. Хм... последующее сообщение показывает 00:0a: ... это 16550A. Возможно, драйвер 8250 на самом деле не обрабатывает ttyS0?
Есть идеи? Даже если вы не видите, что я сделал неправильно, но заставили PARMAR работать, комментарии о вашей ситуации могут мне помочь.
ОБНОВЛЕНИЕ: Мой Linux работает в VMware VM, поэтому я попробовал конфигурацию не-VM, и теперь она работает! В случае, если кто-то знает, я все еще хотел бы знать, почему ошибки четности не обнаруживаются в виртуальной машине.
Вот мой код конфигурации:
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;
}
1 ответ
У меня была похожая проблема (но с противоположной стороны):
Мастер последовательного протокола должен отправлять 1-й байт кадра с меткой четности, а все остальные - с пространством четности, в то время как ведомый отвечает только пространством четности.
Многие драйверы последовательной связи будут игнорировать бит "CMSPAR", не возвращая ошибку, поэтому вы можете подумать, что вы установили четность Mark/Space, хотя вместо этого вы выбрали четность Odd/Even.
Мне пришлось использовать анализатор протокола, чтобы понять это.
Поэтому я закончил проверкой данных каждого байта перед отправкой и переключался между нечетным / четным контролем четности, чтобы смоделировать четность Mark/Space, в которой я нуждался.
Большинству адаптеров USB-Serial потребуется аналогичный подход, поскольку они не поддерживают знак / пробел четности.
Например, допустим, мы хотим отправить следующие данные:
01 03 07 0F 1F
1-й байт должен быть отправлен с меткой четности, а остальные - с пространством четности.
Мы могли бы сделать следующее:
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)
Таким образом, мы можем смоделировать нужный результат.
Суть в том, что когда вы переключаете паритет, драйвер выполняет много проверок, которые отнимают много времени, и это может повлиять на конечную скорость передачи данных.
Я использовал взломанную версию драйвера последовательной связи на встроенном устройстве, которое могло очень быстро переключать четность, пропуская некоторые ненужные проверки для приложения (например, изменения скорости передачи в бодах).
Если ваша межсимвольная задержка имеет решающее значение, вам может потребоваться другое решение.