Есть один девайс, для которого в свое время я написал интерфейс для взаимодействия с PC, под Linux с ядром 2.4 (Debian), используя низкоуровневый интерфейс для работы с COM портом. (Работа через физический адрес порта, регистры COM порта, inb...)
Все прекрасно работало в течении полугода, но затем, после перехода на ядро 2.6 часто стали возникать ошибки при работе с COM портом, которые полностью отсутствовали под ядром 2.4. Ошибки заключались в появлении неожиданных байт со стороны девайса. (Пробовал вновь переключаться на 2.4 - никаких ошибок)
Нечто подобное было и на ядре 2.4, но тогда проблему удалось решить отключением модуля SERIAL из ядра. Под 2.6 отключение модуля не помогло...
>Нечто подобное было и на ядре 2.4, но тогда проблему удалось решить
>отключением модуля SERIAL из ядра. Под 2.6 отключение модуля не помогло...Похоже на проблемы с обработкой прерываний. Я бы ушёл на более высокий уровень - ну их на фиг, эти регистры, пусть у Линуса башка болит.
>Похоже на проблемы с обработкой прерываний. Я бы ушёл на более высокий
>уровень - ну их на фиг, эти регистры, пусть у Линуса
>башка болит.С termios есть проблема...
Устройство должно работать на скорости 9600 с 1 стоп битом, с space parity без flow control.
Вот текст программы:#include <stdio.h> /* Standard input/output definitions */
#include <string.h> /* String function definitions */
#include <unistd.h> /* UNIX standard function definitions */
#include <fcntl.h> /* File control definitions */
#include <errno.h> /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */
#include <iostream>using namespace std;
int main(void)
{
int n;
int fd; /* File descriptor for the port */
char buf[200];
struct termios options;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
if (fd == -1)
{perror("open_port: Unable to open /dev/ttyS0 - ");}
else fcntl(fd, F_SETFL, 0);
/************************************************************************/
//c_iflag
//options.c_iflag = 0;
options.c_iflag = IGNBRK; // Ignore BREAK condition on input.
options.c_iflag &= ~IXON; // Enable XON/XOFF flow control on output.
options.c_iflag &= ~IXOFF; // Enable XON/XOFF flow control on input.
/************************************************************************/
// c_oflag
options.c_oflag = 0;
/************************************************************************/
// c_cflag
options.c_cflag = CS8; // Число бит под 1 байт
options.c_cflag &= ~PARENB; // Не исползовать бит четности
options.c_cflag &= ~CSTOPB; // Использовать 1 стоп-бит
options.c_cflag |= CREAD; // Enable Receiver
options.c_cflag |= CLOCAL; // Ignore modem control lines.
/************************************************************************/
// clflag
options.c_lflag = ISIG; // Не генерировать сигналы при получении данных
options.c_lflag &= ~ICANON; //Запретить EOF и прочие спец символы
options.c_lflag &= ~XCASE; // (not in POSIX; not supported under Linux) If ICANON is also set, terminal is uppercase only. Input is converted to lowercase, except for characters preceded by \. On output, uppercase characters are preceded by \ and lowercase characters are converted to uppercase.
options.c_lflag &= ~ECHO; //Echo input characters.
/************************************************************************/
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
tcflush(fd, TCIOFLUSH);
tcsetattr(fd, TCSAFLUSH, &options);
// Main code
buf[0]=0xA;
n = write(fd, buf, 1);
usleep(150000);
cout << "Written:" << n << '\n';
usleep (150000);
cout << "Readen:" << read(fd,buf,1); << '\n';
close(fd);
}После ее запуска происходит запись в порт, но считывание не происходит. Аналогичные программы, написаная под низкоуровневый интерфейс и под Win32 работают без проблем. Пробовал запускать данную программу и под ядром 2.4 и под ядром 2.6 - не работает...
>> options.c_cflag |= CLOCAL; // Ignore modem control lines.Ты уверен что правильно написано? ИМХО совсем наоборот.
И проверяй параметры порта stty
Попробуйте такint open_serial_port( void )
{
struct termios options;
int fd;
int fcntl_ret;
// open the port
if( ( fd = open( MY_TTY, O_RDWR | O_NOCTTY | O_NDELAY) ) == -1 )
{
return -1;
}// Set exclusive use flag to block other open calls with EBUSY
if ( ioctl(fd, TIOCEXCL, 0) == -1 )
{
return -1;
}
// Blocking read
// fcntl(fd, F_SETFL, 0);// Non blocking read
fcntl(fd, F_SETFL, FNDELAY );
// get the current options
tcgetattr(fd, &options);cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);// Control Flags
// enable the receiver and set local mode...
options.c_cflag |= (CLOCAL | CREAD);// data : 8 bit, stop : 1 bit, parity : none
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;// disable hardware flow control
//options.c_cflag &= ~CNEW_RTSCTS;
options.c_cflag &= ~CRTSCTS;
options.c_lflag = 0;
options.c_iflag = IGNBRK;
options.c_oflag = 0; // turn off all output processing
options.c_cc[VMIN] = 1;
options.c_cc[VTIME] = 0;// set the options
tcsetattr(fd, TCSANOW, &options);
return fd;
}
А обрабатываешь ты прерывания точно только по приёму символа или все вподряд?