Страниц: 1 [2]
  Печать  
Автор Тема: RS-232  (Прочитано 14325 раз)
SUA
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #15 : Октября 09, 2006, 06:03:42 am »

Всегда пользуюсь монитором LGComSpy. Наглядно показывает все установки порта и работу флагов. Можно посмотреть сколько проводов используется в кабеле RS232 и если их больше 3х то обратить внимание как программа обрабатывает эти дополнительные линии порта (кабеля). Получаем полную картину настроек порта в Win. Программа в сети бесплатная.
Записан
BuG2BuG
Участник
*
Offline Offline

Сообщений: 0



Просмотр профиля WWW
« Ответ #16 : Октября 21, 2006, 09:09:42 pm »

Всё получилось. Описываю все шаги по-порядку.

1. Сделал заглушку TX <-> RX и прозвонил, удостоверившись, что порт действительно работает:
На первой консоли:
# dd if=/dev/ser1

На второй консоли:
# ls -la > /dev/ser1

На первой консоли получаю вывод каталога и жму ctrl-c.

2. Спаял нуль-модем, подцепил ноут с QNX к банке с линуксом, запустив на последнем minicom. Выставил на тачке в minicom baud rate = 9600. На ноуте ставлю тот же бод рейт:
# stty baud=9600 < /dev/ser1

Сначала то же самое:
# ls -la > /dev/ser1

На тачке с линем получаем вывод ls'а.

3. Запускаю программу. На лине получаю вывод своей программы, причём то, что хотел. Следовательно, проблема не в программном, а в аппаратном обеспечении. И правда, оказалось, что проблема была в программе микроконтроллера (не я её писал). Он пытался принимать пакеты по 6 байт, а QNX видимо при запуске драйвера devc-ser8250 пытается что-то писать в порт и последовательность байт сбивается. Помогает тупо перезагрузка устройства, благо у микроконтроллера оказался пин RST.

Вот исходный код, после доработок:

#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
int  main(void) {
   struct termios termios_p;
   int fd, temp,i,flag1 = 0;
    char    buf [8];
   char s[1];
   fd = open("/dev/ser1", O_RDWR | O_NOCTTY | O_NDELAY);
   if(fd < 0) printf("Error opening
"), exit(1);
   printf("Opened!
");
   if(tcgetattr(fd, &termios_p)) return -1;
   printf("Getted termios state
");
//   if(cfmakeraw(&termios_p)) return -1;
//   printf("Maked raw
");
   termios_p.c_cc[VMIN] = 0;
   termios_p.c_cc[VTIME] = 0;
   termios_p.c_cflag &= ~(CSTOPB|CS5|CS8|CS6|CS7);
   termios_p.c_cflag |= (CS8 | CREAD);
   termios_p.c_oflag |= OPOST;
//   termios_p.c_oflag &= ~OPOST;
   termios_p.c_lflag &= ~(IHFLOW | OHFLOW | PARENB | PARODD | ICANON | ECHO | ECHOE | ISIG | ECHOK | ECHONL | ECHOKE | IMAXBEL | ONLCR);
//   cfmakeraw(&termios_p);

   cfsetospeed(&termios_p, B9600);
   cfsetispeed(&termios_p, B9600);
//   system("stty < /dev/ser1");
//   sleep(2);
   printf("Setted ospeed
");
   if(tcsetattr(fd, TCSANOW, &termios_p) < 0) return -1;
//   sleep(2);
//   system("stty < /dev/ser1");
   printf("Setted attr
");
   for(i=0;i<5;i++) {
       if (flag1)
         {
           flag1=0;
           memset(buf,0x41,6);
         }
         else
          {
            flag1=1;
            memset(buf,0x00,6);
          }
      if(temp = write(fd, buf, 6)) printf("%d bytes wrote !!!
", temp);
      sleep(1);
   }
//   usleep(50000);
//   printf("Writed 6 bytes
");
   close(fd);
   printf("Closed
");
   return 0;
}


Всем спасибо, кто участвовал в дискуссии.
Записан
dsiss
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #17 : Октября 29, 2006, 12:24:06 pm »

Не подскажете, как открыть COM-порт, чтобы приложение владело им единолично, т.е. другое при попытке открытия получило ошибку?
Записан
rf
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #18 : Октября 30, 2006, 11:08:28 am »

dsiss
Не подскажете, как открыть COM-порт, чтобы приложение владело им единолично, т.е. другое при попытке открытия получило ошибку?

IMHO никак. Можно проверять количество открытых дескрипторов файла, связанных с файлом устройства порта, если > 0, то порт уже открыт другим процессом. Можно пробежать по всем процессам и посмотреть, не открыт ли каким из них файл устройства порта. Можно использовать lock-файлы. Но если стороннее приложение не выполняет этих проверок, то оно спокойно откроет порт и будет беспрепятственно работать с ним.
Записан
BuG2BuG
Участник
*
Offline Offline

Сообщений: 0



Просмотр профиля WWW
« Ответ #19 : Октября 30, 2006, 12:18:24 pm »

А в QNX нет функции flock()? В bsd она явно есть http://www.hmug.org/man/2/flock.php
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #20 : Октября 30, 2006, 12:52:55 pm »

dsiss
Не подскажете, как открыть COM-порт, чтобы приложение владело им единолично, т.е. другое при попытке открытия получило ошибку?

А если во время открытия указать флажок O_EXCL ?
Записан

rf
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #21 : Октября 31, 2006, 07:42:17 am »

lestat
А если во время открытия указать флажок O_EXCL ?

Дык вроде "Specifying O_EXCL without O_CREAT has no effect." и "If you set both O_EXCL and O_CREAT, open() fails if the file exists.". Я в прошлом году тоже пытался решить эту задачу и остановился на варианте проверки количества открытых дескрипторов файла, связанных с файлом устройства порта. (Если мне склероз не изменяет, именно так работает qtalk). С приложениями, не выполняющими такой проверки, ничего поделать, увы, нельзя...
Записан
rf
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #22 : Октября 31, 2006, 07:49:24 am »

BuG2BuG
А в QNX нет функции flock()? В bsd она явно есть  

Есть. Только flock работает с рекомендательными (advisory) блокировками, и стороннее приложение должно проверять наличие блокировок, в противном случае оно откроет файл и будет с ним работать несмотря на установленные блокировки.
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #23 : Октября 31, 2006, 09:56:24 am »

rf
Дык вроде "Specifying O_EXCL without O_CREAT has no effect." и "If you set both O_EXCL and O_CREAT, open() fails if the file exists."

Да, с ком-портами такое не пройдёт, только что проверил. POSIX определяет поведение O_EXCL как неопределённое без O_CREAT, но в каком-то из RM я встречался с поведением O_EXCL как именно эксклюзивное открытие.
Записан

rf
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #24 : Октября 31, 2006, 12:00:42 pm »

lestat
POSIX определяет поведение O_EXCL как неопределённое без O_CREAT, но в каком-то из RM я встречался с поведением O_EXCL как именно эксклюзивное открытие.

Это следует понимать так, что менеджер ресурса при установке соединения трактовал O_EXCL без O_CREAT особым образом, запрещая повторное открытие файла устройства? В таком случае можно доработать devc-ser8250, исходники вроде доступны. Осталось узнать какой RM так себя вел и подсмотреть, как оно там сделано.
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #25 : Октября 31, 2006, 12:48:53 pm »

rf
Осталось узнать какой RM так себя вел и подсмотреть, как оно там сделано

Достаточно блокировать после io_open последующие io_open и io_dup. Только в этом случае вылезет архитектурный горбище QNX6. С этим файлом ничего больше нельзя будет сделать, ни ls, ни stat, ни opendir в этом каталоге - будут идти тонные ошибок. Собственно поэтому все файлы и устройства в системе разрешено открывать больше одного раза.
Записан

rf
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #26 : Октября 31, 2006, 01:05:41 pm »

lestat
Достаточно блокировать после io_open последующие io_open и io_dup. Только в этом случае вылезет архитектурный горбище QNX6. С этим файлом ничего больше нельзя будет сделать, ни ls, ни stat, ни opendir в этом каталоге - будут идти тонные ошибок

А если, например, возвращать EBADF на все запросы чтения/записи и изменения настроек посл. порта через ioctl или devctl всем процессам, открывшим файл, кроме первого, а все остальное отрабатывать нормально?
Записан
lestat
QOR.Moderator
*****
Offline Offline

Сообщений: 985


I don't trust anything


Просмотр профиля WWW
« Ответ #27 : Октября 31, 2006, 01:11:23 pm »

rf
А если, например, возвращать EBADF на все запросы чтения/записи и изменения настроек посл. порта через ioctl или devctl всем процессам, открывшим файл, кроме первого, а все остальное отрабатывать нормально?

Ну тогда идеологически вернее будет возвращать EBUSY А так - да, отличный способ. Только могут быть проблемы, если два раза открыть порт и на обоих хэндлах сделать read(), (я не смотрел сорцы devc-ser8250) то какому хэндлу отдадут данные ?
Записан

rf
Участник
*
Offline Offline

Сообщений: 0


Просмотр профиля
« Ответ #28 : Октября 31, 2006, 01:32:29 pm »

lestat
Ну тогда идеологически вернее будет возвращать EBUSY. А так - да, отличный способ.


Я тоже сначала хотел предложить EBUSY. Но в документации на read() и write() в списке возвращаемых значений нет EBUSY, поэтому я остановился на EBADF.

lestat

Только могут быть проблемы, если два раза открыть порт и на обоих хэндлах сделать read(), (я не смотрел сорцы devc-ser8250) то какому хэндлу отдадут данные ?

Можно привязываться к тройке pid-tid-coid первого открывшего файл клиента, остальных посылать.
Записан
darkelf
QOR.Moderator
*****
Offline Offline

Сообщений: 259


Просмотр профиля
« Ответ #29 : Октября 31, 2006, 01:37:08 pm »

К сожалению не знаю, поддерживается ли это в QNX, но в linux/freebsd есть ioctl TIOCEXCL который обеспечивает данную функциональность, правда для пользователя root он там не работает. Посмотрите, может  и в QNX есть такой.
Записан
Страниц: 1 [2]
  Печать  
 
Перейти в: