Я работаю над починкой некоторых устройств GPS. Они старые и недавно имели проблему с пролонгацией количества недель, поэтому они сообщают NTP о неправильной дате. Пока мы ожидаем их замены, я сделал временное исправление программного обеспечения, которое работает на 99%.
Я беру последовательный вход из gps, анализирую его, добавляю значение коррекции и затем отправляю его обратно на псевдотерминал.
NTP не будет читать порт. Если я использую тестовую программу чтения, она будет правильно считывать данные до тех пор, пока я не попытаюсь открыть порт с нечетной четностью. Это, конечно, то, что устройство GPS должно быть.
Это настройка процедуры записи:
int GPSPortSetup(char *PortName, int *OutputPort)
{
int gps_fd;
struct termios line_ctl;
int OpenFlags;
int i;
int master, slave;
char name[100];
gps_fd = open (PortName, O_RDWR);
if (gps_fd == -1)
{
perror("Open Failed");
return -1;
}
memset(&line_ctl, 0, sizeof(line_ctl));
if (tcgetattr (gps_fd, &line_ctl) != 0)
{
perror("tcgetattr failed!");
close(gps_fd);
exit(-1);
}
cfmakeraw(&line_ctl);
line_ctl.c_iflag = 0;
line_ctl.c_oflag = 0;
line_ctl.c_cflag &= ~(CSIZE | CSTOPB);
line_ctl.c_cflag |= (CS8 | CREAD | PARENB | PARODD);
line_ctl.c_lflag &= ~(ICANON | ISIG | IEXTEN);
cfsetspeed(&line_ctl, B9600);
line_ctl.c_cc[VMIN] = 21;
line_ctl.c_cc[VTIME] = 5;
if(tcsetattr(gps_fd, TCSANOW, &line_ctl) !=0)
{
perror("tcsetattr failed");
close(gps_fd);
exit(-1);
}
if(openpty(&master, &slave, &name, &line_ctl, NULL) != 0)
{
perror("openpty");
printf("errno = %i\n", errno);
exit(-1);
}
if(grantpt(master) < 0)
{
perror("grantpt");
exit(-1);
}
if(unlockpt(master) < 0)
{
perror("unlockpt");
exit(-1);
}
*OutputPort = master;
printf("%s\n", name);
return(gps_fd);
}
Это набор портов для чтения:
int GPSPortSetup(char Direction, char *PortName)
{
int gps_fd;
struct termios line_ctl;
int OpenFlags;
int i;
switch (Direction)
{
case GPSREAD:
OpenFlags = O_RDONLY;
break;
case GPSWRITE:
OpenFlags = O_WRONLY;
break;
case GPSRW:
OpenFlags = O_RDWR;
break;
}
printf("%s\n", PortName);
gps_fd = open (PortName, O_RDWR|O_NOCTTY);
if (gps_fd == -1)
{
perror("Open Failed");
printf("errno = %i\n", errno);
printf("EEXIST %i\n", EEXIST);
printf("EISDIR %i\n", EISDIR);
printf("EACCES %i\n", EACCES);
printf("ENAMETOOLONG %i\n", ENAMETOOLONG);
printf("ENOENT %i\n", ENOENT);
printf("ENOTDIR %i\n", ENOTDIR);
printf("ENXIO %i\n", ENXIO);
printf("ENODEV %i\n", ENODEV);
printf("EROFS %i\n", EROFS);
printf("ETXTBSY %i\n", ETXTBSY);
printf("EFAULT %i\n", EFAULT);
printf("ELOOP %i\n", ELOOP);
printf("ENOSPC %i\n", ENOSPC);
printf("ENOMEM %i\n", ENOMEM);
printf("EMFILE %i\n", EMFILE);
printf("ENFILE %i\n", ENFILE);
exit(-1);
}
memset(&line_ctl, 0, sizeof(line_ctl));
if (tcgetattr (gps_fd, &line_ctl) != 0)
{
perror("tcgetattr failed!");
close(gps_fd);
exit(-1);
}
cfmakeraw(&line_ctl);
line_ctl.c_iflag = 0;
line_ctl.c_oflag = 0;
line_ctl.c_cflag &= ~(CSIZE | CSTOPB);
line_ctl.c_cflag |= CS8;
line_ctl.c_cflag |= CREAD;
line_ctl.c_cflag |= PARENB;
line_ctl.c_cflag |= PARODD;
line_ctl.c_lflag &= ~(ICANON | ISIG | IEXTEN);
cfsetspeed(&line_ctl, B9600);
line_ctl.c_cc[VMIN] = 21;
line_ctl.c_cc[VTIME] = 5;
if(tcsetattr(gps_fd, TCSANOW, &line_ctl) !=0)
{
perror("tcsetattr failed");
close(gps_fd);
exit(-1);
}
return(gps_fd);
}
Если я закомментирую строку, которая устанавливает PARENB в процедуре чтения, я увижу данные. Если я этого не сделаю, perror для tcsetattr выдает «tcsetattr failed: неверный аргумент».
Код работает, если я использую фактические последовательные порты. Я тестировал его, но читал gps, открывал реальный последовательный порт, а затем подключал его к другому реальному через нуль-модемный кабель. В этом случае NTP начнет работу и правильно прочитает данные.
Я обратился к документации NTP, чтобы найти исправление. Они показывают один, но когда я пытаюсь реализовать это исправление, я также получаю ошибки. Единицами, которые мы используем, являются Trimble Acutime 2000, Acutime Gold и Palisade. У сайтов еще нет доступа к сети, поэтому я не могу просто читать сервер в реальном времени.
У меня работает CentOS 6.5
Acutime 2000 входит в порт / dev / ttyrp22. Stty -a для него:
speed 9600 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 21; time = 5;
parenb parodd cs8 hupcl -cstopb cread clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
Открывается / dev / pts /? Stty -a для текущего открытого порта:
speed 9600 baud; rows 0; columns 0; line = 0;
intr = <undef>; quit = <undef>; erase = <undef>; kill = <undef>; eof = <undef>;
eol = <undef>; eol2 = <undef>; swtch = <undef>; start = <undef>; stop = <undef>;
susp = <undef>; rprnt = <undef>; werase = <undef>; lnext = <undef>;
flush = <undef>; min = 1; time = 0;
-parenb parodd cs8 -hupcl -cstopb cread clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -tostop -echoprt
-echoctl -echoke