The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]

форумы  помощь  поиск  регистрация  майллист  вход/выход  слежка  RSS
"Не работает чтение из Com порта под linux"
Вариант для распечатки  
Пред. тема | След. тема 
Форумы Программирование под UNIX (Public)
Изначальное сообщение [ Отслеживать ]

"Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 04-Фев-09, 21:27 
Здравствуйте!

Столкнулся с проблемой, что не работает чтение из ком порта, система Linux Debian 4 (ядро по умолчанию). Причем делал, глядя в рабочий исходник работающей утилиты, которая прекрасно все читает.
Симптомы такие - что я пробую select'ом проверить наличие данных для чтения, он говорит - данных нет (возвращает 0). Пробую читать (порт открыт с флагами O_RDWR | O_NOCTTY | O_NDELAY) - read возвращает -1 с errno==EAGAIN.

Что только не перепробовал, пробовал отключать код, где настраивается скорость и прочие параметры - думал, что если скорость не совпадет, просто буду получать мусор вместо реальных данных. Все равно глухо.
Все обрщения к системным вызовам проверяются на код возврата, везде все проходит нормально. Но ничего не работает. Данные в порт валятся, запускаю другую прогу - она нормально выводит данные.
Может это связано как-то с сигналами, с какими-нибудь еще масками - с тем, что не относится непосредственно к коду открытия и настройки - потому что я уже вроде все перепробовал в различных комбинциях - ни ошибок нет, ни данных.
Такое ощущение, что пропустил какой-то нюанс, но какой?

Высказать мнение | Ответить | Правка | Cообщить модератору

 Оглавление

Сообщения по теме [Сортировка по времени | RSS]


1. "Не работает чтение из Com порта под linux"  
Сообщение от vic (??) on 04-Фев-09, 22:08 
> Здравствуйте!
>
> Столкнулся с проблемой, что не работает чтение из ком порта, система
>Linux Debian 4 (ядро по умолчанию). Причем делал, глядя в рабочий
>исходник работающей утилиты, которая прекрасно все читает.
> Симптомы такие - что я пробую select'ом проверить наличие данных для
>чтения, он говорит - данных нет (возвращает 0). Пробую читать (порт
>открыт с флагами O_RDWR | O_NOCTTY | O_NDELAY) - read возвращает
>-1 с errno==EAGAIN.

либо O_NDELAY, либо select, что-нить одно, лучше select :)

>[оверквотинг удален]
>прочие параметры - думал, что если скорость не совпадет, просто буду
>получать мусор вместо реальных данных. Все равно глухо.
> Все обрщения к системным вызовам проверяются на код возврата, везде все
>проходит нормально. Но ничего не работает. Данные в порт валятся, запускаю
>другую прогу - она нормально выводит данные.
> Может это связано как-то с сигналами, с какими-нибудь еще масками -
>с тем, что не относится непосредственно к коду открытия и настройки
>- потому что я уже вроде все перепробовал в различных комбинциях
>- ни ошибок нет, ни данных.
> Такое ощущение, что пропустил какой-то нюанс, но какой?

куски кода в студию, будем думать :)

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

2. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 14:01 

>куски кода в студию, будем думать :)

Вроде ничего не забыл.

// Код открытия порта
        fSerial = :: open( MARTY_CON_NS w2ansi(sysDeviceName).c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
        if (fSerial==-1)
           return CLI_SET_POSIX_ERROR_INFO_ARGS( errno, 0, 0, (::cli::format::arg(streamNameInfo) ) );


// код настройки порта

            tcflush(fSerial, TCIOFLUSH);

            #define TIOS_SETSPEED( opts, val ) do { cfsetispeed( opts, val ); cfsetospeed( opts, val ); } while(0)
            struct termios tios;
            if ( tcgetattr( fSerial, &tios ) <0 )
               return CLI_SET_POSIX_ERROR_INFO( errno, 0, 0 );

            switch(options->baudRate)
               {
                case 50     : TIOS_SETSPEED( &tios, B50      ); break;    case 75     : TIOS_SETSPEED( &tios, B75      ); break;
                case 110    : TIOS_SETSPEED( &tios, B110     ); break;    case 134    : TIOS_SETSPEED( &tios, B134     ); break;
                case 150    : TIOS_SETSPEED( &tios, B150     ); break;    case 200    : TIOS_SETSPEED( &tios, B200     ); break;
                case 300    : TIOS_SETSPEED( &tios, B300     ); break;    case 600    : TIOS_SETSPEED( &tios, B600     ); break;
                case 1200   : TIOS_SETSPEED( &tios, B1200    ); break;    case 1800   : TIOS_SETSPEED( &tios, B1800    ); break;
                case 2400   : TIOS_SETSPEED( &tios, B2400    ); break;    case 4800   : TIOS_SETSPEED( &tios, B4800    ); break;
                case 9600   : TIOS_SETSPEED( &tios, B9600    ); break;    case 19200  : TIOS_SETSPEED( &tios, B19200   ); break;
                case 38400  : TIOS_SETSPEED( &tios, B38400   ); break;    case 57600  : TIOS_SETSPEED( &tios, B57600   ); break;
                case 115200 : TIOS_SETSPEED( &tios, B115200  ); break;    case 230400 : TIOS_SETSPEED( &tios, B230400  ); break;
                case 460800 : TIOS_SETSPEED( &tios, B460800  ); break;    case 500000 : TIOS_SETSPEED( &tios, B500000  ); break;
                case 576000 : TIOS_SETSPEED( &tios, B576000  ); break;    case 921600 : TIOS_SETSPEED( &tios, B921600  ); break;
                case 1000000: TIOS_SETSPEED( &tios, B1000000 ); break;    case 1152000: TIOS_SETSPEED( &tios, B1152000 ); break;
                case 1500000: TIOS_SETSPEED( &tios, B1500000 ); break;    case 2000000: TIOS_SETSPEED( &tios, B2000000 ); break;
                case 2500000: TIOS_SETSPEED( &tios, B2500000 ); break;    case 3000000: TIOS_SETSPEED( &tios, B3000000 ); break;
                case 3500000: TIOS_SETSPEED( &tios, B3500000 ); break;    case 4000000: TIOS_SETSPEED( &tios, B4000000 ); break;
                //case : TIOS_SETSPEED( &tios, B ); break;
                default:     return CLI_SET_ERROR_INFO_ARGS( EC_SERIAL_BAUD_NOT_SUPPORTED, 0, 0, (::cli::format::arg((UINT)options->baudRate) ) );
               }

            #undef TIOS_SETSPEED

            tios.c_cflag &= ~(CSIZE|CSTOPB|CLOCAL|CREAD|PARENB|PARODD);
            #ifdef CMSPAR
            tios.c_cflag &= ~CMSPAR;
            #endif
            //tios.c_iflag &= ~(CSIZE|CSTOPB|CLOCAL|CREAD|PARENB|PARODD);

            switch(options->dataBits)
               {
                case CLI_IO_SERIAL_DATABITS_DATABITS5:  tios.c_cflag |= CS5; break;
                case CLI_IO_SERIAL_DATABITS_DATABITS6:  tios.c_cflag |= CS6; break;
                case CLI_IO_SERIAL_DATABITS_DATABITS7:  tios.c_cflag |= CS7; break;
                case CLI_IO_SERIAL_DATABITS_DATABITS8:  tios.c_cflag |= CS8; break;
               }

            if ( options->stopBits == CLI_IO_SERIAL_STOPBITS_STOPBITS2)
               tios.c_cflag |= CSTOPB;

            if (options->parity&CLI_IO_SERIAL_PARITY_FPARITY)
               {
                tios.c_cflag |= PARENB; // enable parity
                tios.c_iflag |= (INPCK | ISTRIP); // Enable parity check and Strip parity bits
                if ( options->parity == CLI_IO_SERIAL_PARITY_ODD ) tios.c_cflag |= PARODD; // odd parity
                // else even
               }
/*
    case 3: // mark
        cflag |= PARENB | CMSPAR | PARODD;
        break;
    case 4: // space
        cflag |= PARENB | CMSPAR;
        break;
*/

            // I don't known why, but thats needed
            tios.c_cflag |= CLOCAL|CREAD;
            #ifdef HUPCL
            tios.c_cflag |= HUPCL;
            #endif

            // disable hardware flow control
            #if defined(CNEW_RTSCTS)
                tios.c_cflag &= CNEW_RTSCTS;
            #elif defined(CRTSCTS)
                tios.c_cflag &= CRTSCTS;
            #endif

            // Choosing Raw Input - clear flags
            tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

            // turn software flow control off
            tios.c_iflag &= ~(IXON | IXOFF | IXANY);

            // clear Mark parity errors
            tios.c_iflag &= ~(PARMRK);

            // Ignore parity errors - high level protocol must check incoming data
            tios.c_iflag |= IGNPAR;

            // Choosing Raw Output - clear flags
            //tios.c_oflag &= ~OPOST;
            tios.c_oflag = 0; // When the OPOST option is disabled, all other option bits in c_oflag are ignored.

            tios.c_cc[VMIN]  = 1;
            tios.c_cc[VTIME] = 0;

            if ( tcsetattr( fSerial, TCSANOW /* TCSAFLUSH */ , &tios ) <0 )
               return CLI_SET_POSIX_ERROR_INFO( errno, 0, 0 );

// Код чтения
        struct timeval Timeout;
        Timeout.tv_usec = (millisecTimeout%1000)*1000;  // в микросекунды
        Timeout.tv_sec  = millisecTimeout/1000;  // секунды

        //struct
        fd_set readFs;
        FD_ZERO( &readFs );
        FD_SET( fSerial, &readFs );
        printf("Call select, usec: %d, sec: %d\n", Timeout.tv_usec, Timeout.tv_sec);

        //Timeout.tv_usec = (millisecTimeout%1000)*1000;  // в микросекунды
        //Timeout.tv_sec  = millisecTimeout/1000;  // секунды


        //int selectRes = select(fSerial+1, &readFs, NULL, NULL, &Timeout );
        int selectRes = select(fSerial+1, &readFs, NULL, NULL, 0 );
        if (selectRes==-1 && errno!=EINTR) // ошибка и не сигнал
           return CLI_SET_POSIX_ERROR_INFO_ARGS( errno, 0, 0, (::cli::format::arg(streamNameInfo)) );
        printf("select res: %d\n", selectRes);

        if (selectRes==-1)
           {
            printf("selectRes==-1\n");
           }

        if (selectRes==0)
           {
            printf("selectRes==0\n");
           }

        if (!FD_ISSET( fSerial, &readFs ))
           {
            printf("!FD_ISSET( fSerial, &readFs )\n");
           }


        if (selectRes==-1 || selectRes==0 || (!FD_ISSET( fSerial, &readFs )) )
           {
            // ожидание прервано сигналом,
            // или истек таймаут или дескриптор не в наборе дескрипторов, готовых для чтения
            // возвращаем, что  ничего не прочитано
            if (numBytesReaded) *numBytesReaded = 0;
            return EC_OK;
           }

        ssize_t res = :: read(fSerial, buf, numBytesToRead);
        if (res==-1)
           {
            return CLI_SET_POSIX_ERROR_INFO_ARGS( errno, 0, 0, (::cli::format::arg(streamNameInfo)) );
           }
        if (numBytesReaded) *numBytesReaded = (SIZE_T)res;
        return EC_OK;


//------------
пробовал еще TIOS_SETSPEED по другому определить, вот так:

            #if defined(_HAVE_STRUCT_TERMIOS_C_ISPEED) && _HAVE_STRUCT_TERMIOS_C_ISPEED==1
                #define TIOS_OLD_SETISPEED( opts, val ) do { (opts)->c_ispeed = val;  } while(0)
            #else
                #define TIOS_OLD_SETISPEED( opts, val )
            #endif
            #if defined(_HAVE_STRUCT_TERMIOS_C_OSPEED) && _HAVE_STRUCT_TERMIOS_C_OSPEED==1
                #define TIOS_OLD_SETOSPEED( opts, val ) do { (opts)->c_ospeed = val;  } while(0)
            #else
                #define TIOS_OLD_SETOSPEED( opts, val )
            #endif

            #define TIOS_SETSPEED( opts, val ) do { \
                                                   TIOS_OLD_SETISPEED((opts), val);  \
                                                   TIOS_OLD_SETOSPEED((opts), val);  \
                                                    cfsetispeed( (opts), val );      \
                                                    cfsetospeed( (opts), val );      \
                                                    (opts)->c_cflag |= val;          \
                                                   } while(0)


все равно не работает.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

3. "Не работает чтение из Com порта под linux"  
Сообщение от vic (??) on 05-Фев-09, 14:51 
>// Код открытия порта
>        fSerial = :: open(
>MARTY_CON_NS w2ansi(sysDeviceName).c_str(), O_RDWR | O_NOCTTY | O_NDELAY);

покажите полное имя открываемого порта, то что конкретно открывается аля "/dev/ttyXXX"
O_NDELAY имхо тут нафик не нужен (т.к. есть select)

>#define TIOS_SETSPEED( opts, val ) do { cfsetispeed( opts, val );
>cfsetospeed( opts, val ); } while(0)

проще надо, просто юзать функции без вот таких ужасных оберток.

>struct termios tios;

memset(); сразу, чтобы потом не гадать.
            
>if ( tcgetattr( fSerial, &tios ) <0 )

Правило есть такое - если меняем настройки порта, то сначала сохраняем старые в отдельной структуре (tios_old), затем заполняем структуру tios_new с чистого листа только своими значениями, делаем tcsetattr(fid,&tios_new); а когда заканчиваем работать с портом, перед закрытием делаем tcsetattr(fid,&tios_old);


>[оверквотинг удален]
>    tios.c_cflag &= CRTSCTS;
>tios.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
>tios.c_iflag &= ~(IXON | IXOFF | IXANY);
>tios.c_iflag &= ~(PARMRK);
>tios.c_iflag |= IGNPAR;
>//tios.c_oflag &= ~OPOST;
>tios.c_oflag = 0; // When the OPOST option is disabled, all
>other option bits in c_oflag are ignored.
>tios.c_cc[VMIN]  = 1;
>tios.c_cc[VTIME] = 0;

вы реально видите что именно у вас выставлено в флагах после кучи #if/#else? я - нет.
сделайте аккуратное понятное заполнение флагов. Вы должны понимать для каждого флажка - нужен вам он или нет, что каждый из них означает. От этого зависит как будет работать порт.

>if (tcsetattr(fSerial, TCSANOW /* TCSAFLUSH */ , &tios) < 0)

сброс делать надо еще и после установки новых параметров: tcflush(fSerial, TCIOFLUSH);

>// Код чтения
> struct timeval Timeout;
> Timeout.tv_usec = (millisecTimeout%1000)*1000;  // в микросекунды
> Timeout.tv_sec  = millisecTimeout/1000; // секунды

чем равен millisecTimeout ? т.е. чему равны в итоге поля структуры

>        //int selectRes = select(fSerial+1, &readFs, NULL, NULL, &Timeout );
>        int selectRes = select(fSerial+1, &readFs, NULL, NULL, 0 );

дык первый или второй селект? С NULL или таймаутом?

>        ssize_t res = ::read(fSerial, buf, numBytesToRead);

numBytesToRead чему равен?

>пробовал еще TIOS_SETSPEED по другому определить, вот так:

думаете именно в скорости проблемы? скорость это только один из флажков

после установки всех параметров порта поставьте sleep(10-15sec), и в соседней консоли гляньте что вы выставили на порт утилитой stty. чтобы удостовериться что все параметры установлены корректно. и только после этого можно переходить к проблемам чтения.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

4. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 15:31 
>покажите полное имя открываемого порта, то что конкретно открывается аля "/dev/ttyXXX"

        ::std::string devName = MARTY_CON_NS w2ansi(sysDeviceName);
        fSerial = :: open( devName.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY); // HACK: disable O_NOCTTY
        if (fSerial==-1)
           return CLI_SET_POSIX_ERROR_INFO_ARGS( errno, 0, 0, (::cli::format::arg(streamNameInfo) ) );
        printf("create, system device name - [%s], handle: %d\n", devName.c_str(), fSerial );
Выводит /dev/ttyS0

>O_NDELAY имхо тут нафик не нужен (т.к. есть select)

Пробовал удалять O_NDELAY, не помогает. И еще, если убрать O_NDELAY, то запись будет блокирующая? Программа будет блокироваться, пока все указанные данные не запишутся?
Мне бы хотелось такого поведения, что при невозможности записать все записывалась часть (или 0 байт) и управление сразу же возвращалось бы. Как этого добиться?

>>#define TIOS_SETSPEED( opts, val ) do { cfsetispeed( opts, val );
>>cfsetospeed( opts, val ); } while(0)
>
>проще надо, просто юзать функции без вот таких ужасных оберток.

Обертка только для того, чтобы switch меньше и читабельнее стал.

>>struct termios tios;
>memset(); сразу, чтобы потом не гадать.
>
>>if ( tcgetattr( fSerial, &tios ) <0 )
>
>Правило есть такое - если меняем настройки порта, то сначала сохраняем старые
>в отдельной структуре (tios_old), затем заполняем структуру tios_new с чистого листа
>только своими значениями, делаем tcsetattr(fid,&tios_new); а когда заканчиваем работать с портом,
>перед закрытием делаем tcsetattr(fid,&tios_old);

Ок, попробую. Я просто придерживался подхода такого, что мало ли что там понаустановлено для нормальной работы устройства, я это не трогаю, я меняю только то, что знаю, что мне надо.

>
>вы реально видите что именно у вас выставлено в флагах после кучи
>#if/#else? я - нет.
>сделайте аккуратное понятное заполнение флагов. Вы должны понимать для каждого флажка -
>нужен вам он или нет, что каждый из них означает. От
>этого зависит как будет работать порт.

Да вроде понимаю, читал вот это описание: http://www.easysw.com/~mike/serial/serial.html
ifdef'ы - для того, чтобы компилировалось и работало не только в моем линуксе, если пишут, что флаг XXX может быть не определен в старых системах, то я проверяю, есть ли такой флаг.

>>if (tcsetattr(fSerial, TCSANOW /* TCSAFLUSH */ , &tios) < 0)
>
>сброс делать надо еще и после установки новых параметров: tcflush(fSerial, TCIOFLUSH);

Учту, спасибо.

>>// Код чтения
>> struct timeval Timeout;
>> Timeout.tv_usec = (millisecTimeout%1000)*1000;  // в микросекунды
>> Timeout.tv_sec  = millisecTimeout/1000; // секунды
>
>чем равен millisecTimeout ? т.е. чему равны в итоге поля структуры

Тестировал, передавая millisecTimeout = 100.
В этом случае Timeout.tv_sec = 0, Timeout.tv_usec = 100000.
Пробовал millisecTimeout = 1500
В этом случае Timeout.tv_sec = 1, Timeout.tv_usec = 500000.
>>        //int selectRes = select(fSerial+1, &readFs, NULL, NULL, &Timeout );
>>        int selectRes = select(fSerial+1, &readFs, NULL, NULL, 0 );
>дык первый или второй селект? С NULL или таймаутом?

второй селект блокирует намертво, это я просто пробовал разные варианты.
первый селект вываливается по таймауту.

>>        ssize_t res = ::read(fSerial, buf, numBytesToRead);
>
>numBytesToRead чему равен?

Да. Функция чтения выглядит так:
RCODE readTimeout(VOID*     buf /* [out] byte buf[]  */
                                , SIZE_T    numBytesToRead /* [in] size_t  numBytesToRead  */
                                , SIZE_T*   numBytesReaded /* [out] size_t numBytesReaded  */
                                , TICK_T    millisecTimeout /* [in] tick_t  millisecTimeout  */
                           );

Вызываю так:
        char buf[4096];
        while(1)
           {
            SIZE_T readed;
            RCODE res = ios.readTimeout( buf, sizeof(buf), &readed, 1000 );
...

>>пробовал еще TIOS_SETSPEED по другому определить, вот так:
>думаете именно в скорости проблемы? скорость это только один из флажков

Да не знаю. Мыслей нет никаких, гадаю на кофейной гуще ;)

>после установки всех параметров порта поставьте sleep(10-15sec), и в соседней консоли гляньте
>что вы выставили на порт утилитой stty. чтобы удостовериться что все
>параметры установлены корректно. и только после этого можно переходить к проблемам
>чтения.

За подсказку по stty спасибо, попробую.
Но по поводу перехода к проблемам чтения - если я неправильно настроил порт, пусть оттуда мусор идет, но ведь должно же что-то идти? или пусть тогда syscall'ы ошибку возвращают, если что-то не так. Так ведь все вроде гладко, а данных нет.

Попробую сейчас переделать с учетом ваших рекомендаций.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

5. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 16:43 
Переделал, заполняю чистую структуру:
struct termios newTios = { 0 };
memset((void*)&newTios, 0, sizeof(newTios)); // для надежности ;)


stty выдает следующее:

speed 38400 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 = 0; time = 1;
-parenb -parodd cs8 -hupcl -cstopb cread clocal -crtscts
-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

Затрудняюсь интерпретировать.
-opost - значит, что tios.c_oflag |= OPOST; ?

как такое может быть? код:

            newTios.c_oflag = 0; //!

            // Ignore parity errors - high level protocol must check incoming data
            newTios.c_iflag |= IGNPAR;
            newTios.c_cc[VMIN]  = 0;
            newTios.c_cc[VTIME] = 1;

            if ( tcsetattr( fSerial, TCSAFLUSH, &newTios ) <0 )
               return CLI_SET_POSIX_ERROR_INFO( errno, 0, 0 );
            tcflush(fSerial, TCIOFLUSH);

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

6. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 17:16 
Дошло, с минусом в начале - выключенные опции. ТОгда получается, что все настроено нормально. А данных как не было, так и нет.
Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

7. "Не работает чтение из Com порта под linux"  
Сообщение от vic (??) on 05-Фев-09, 17:31 
>        fSerial = :: open(
>devName.c_str(), O_RDWR | O_NONBLOCK | O_NOCTTY | O_NDELAY); // HACK: disable
>O_NOCTTY
>Выводит /dev/ttyS0

O_NONBLOCK |  O_NDELAY
эти два флага почти одно и тоже.
поймите либо вы включаете неблокирующий режим либо работает через связку select + read/write. Зачем мешать все в кучу.

>Пробовал удалять O_NDELAY, не помогает. И еще, если убрать O_NDELAY, то запись
>будет блокирующая? Программа будет блокироваться, пока все указанные данные не запишутся?

вы работаете с портом и данные нужно будет еще пропихивать tcdrain() при записи.
все что вам надо это через select выяснить что писать можно.

>Мне бы хотелось такого поведения, что при невозможности записать все записывалась часть
>(или 0 байт) и управление сразу же возвращалось бы. Как этого
>добиться?

write запишет столько сколько сможет (еcсно после select)

>Обертка только для того, чтобы switch меньше и читабельнее стал.

вынести в функцию?

>второй селект блокирует намертво, это я просто пробовал разные варианты.
>первый селект вываливается по таймауту.

таймаут 0 во втором и говорить - вечно ждать готовности.
таким образом оба селекта говорят что в порту нет данных для чтения. т.е. порт не получил данных, проверяйте настройки.

>Да не знаю. Мыслей нет никаких, гадаю на кофейной гуще ;)

Вы хоть с чем коннектитесь для проверки? Каким кабелем и т.п.?

>Но по поводу перехода к проблемам чтения - если я неправильно настроил
>порт, пусть оттуда мусор идет, но ведь должно же что-то идти?

не факт, может и не идти. тупо молчать пока не получит корректные данные.

>или пусть тогда syscall'ы ошибку возвращают, если что-то не так. Так
>ведь все вроде гладко, а данных нет.

их именно нет, т.к. либо они вообще не дошли, либо из-за некорректных настроек были возможно проигнорированы.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

8. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 17:58 
Вообщем, проблему решил. Переписал, но сразу не заработало. После изучения логов strace'а и медитации, почему в селект передается пустой набор, понял, что когда я ревертнул исходник перед переделкой, я вернул баг, там селекту в первом параметре +1 забыл сделать. Добавил +1 и зарботало таки ;)

>эти два флага почти одно и тоже.
>поймите либо вы включаете неблокирующий режим либо работает через связку select +
>read/write. Зачем мешать все в кучу.

Осознал.
>
>>Пробовал удалять O_NDELAY, не помогает. И еще, если убрать O_NDELAY, то запись
>>будет блокирующая? Программа будет блокироваться, пока все указанные данные не запишутся?
>
>вы работаете с портом и данные нужно будет еще пропихивать tcdrain() при
>записи.
>все что вам надо это через select выяснить что писать можно.

А зачем пропихивать? Когда уйдут, тогда и ладно.

>write запишет столько сколько сможет (еcсно после select)

Понял.
>
>>Да не знаю. Мыслей нет никаких, гадаю на кофейной гуще ;)
>
>Вы хоть с чем коннектитесь для проверки? Каким кабелем и т.п.?

Коннектился, с прибором со своим. С него исправно валятся данные, есть програмулина, с которой я сдирал работу с портом, она их исправно выводит.

>>Но по поводу перехода к проблемам чтения - если я неправильно настроил
>>порт, пусть оттуда мусор идет, но ведь должно же что-то идти?
>
>не факт, может и не идти. тупо молчать пока не получит корректные
>данные.

Угу, похоже так и было ;)
>
>>или пусть тогда syscall'ы ошибку возвращают, если что-то не так. Так
>>ведь все вроде гладко, а данных нет.
>
>их именно нет, т.к. либо они вообще не дошли, либо из-за некорректных
>настроек были возможно проигнорированы.

В этом и проблема. В винде если настройки совсем некорректные, всегда возвращается какая-то ошибка, а если вроде корректные, но что-то работает не так, то получаем мусор. А тут все сложнее ;(

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

9. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 18:18 
>>Вы хоть с чем коннектитесь для проверки? Каким кабелем и т.п.?
>
>Коннектился, с прибором со своим. С него исправно валятся данные, есть програмулина,
>с которой я сдирал работу с портом, она их исправно выводит.

Сейчас подумал, вспомнил нюанс. Кабель нуль-модемный, 3 проводка. Возможно, если я аппаратное управление потоком не отключил (или случайно включил), то наверно порт действительно мог ничего не получать.
Сейчас, вообщем, работает ;) Спасибо за помощь.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

10. "Не работает чтение из Com порта под linux"  
Сообщение от vic (??) on 05-Фев-09, 18:26 
>>>Вы хоть с чем коннектитесь для проверки? Каким кабелем и т.п.?
>>
>>Коннектился, с прибором со своим. С него исправно валятся данные, есть програмулина,
>>с которой я сдирал работу с портом, она их исправно выводит.
>
> Сейчас подумал, вспомнил нюанс. Кабель нуль-модемный, 3 проводка. Возможно, если я
>аппаратное управление потоком не отключил (или случайно включил), то наверно порт
>действительно мог ничего не получать.

аха, а еще DTR на таком кабеле тоже не поднят :) И далее в зависимости от перемычек начинаются пляски с бубном :)

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

11. "Не работает чтение из Com порта под linux"  
Сообщение от marty email(??) on 05-Фев-09, 18:55 
>аха, а еще DTR на таком кабеле тоже не поднят :) И
>далее в зависимости от перемычек начинаются пляски с бубном :)

Вспомнил, зачем при открытии указывал O_NDELAY. Про него пишут следующее:
The O_NDELAY flag tells UNIX that this program doesn't care what state the DCD signal line is in - whether the other end of the port is up and running. If you do not specify this flag, your process will be put to sleep until the DCD signal line is the space voltage.

Как я понимаю, по идее open должен подвиснуть, если DCD не в том состоянии, а мне этого бы не хотелось.

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

12. "Не работает чтение из Com порта под linux"  
Сообщение от vic (??) on 05-Фев-09, 19:09 
>[оверквотинг удален]
>
>Вспомнил, зачем при открытии указывал O_NDELAY. Про него пишут следующее:
>The O_NDELAY flag tells UNIX that this program doesn't care what state
>the DCD signal line is in - whether the other end
>of the port is up and running. If you do not
>specify this flag, your process will be put to sleep until
>the DCD signal line is the space voltage.
>
>Как я понимаю, по идее open должен подвиснуть, если DCD не в
>том состоянии, а мне этого бы не хотелось.

В таком случае есть смысл использовать этот флаг для этой цели, но для приема-передачи он уже не нужен (при использовании select), а значит его надо снять после открытия порта, чтобы не мешал :)
(если я ничего не путаю))))

Высказать мнение | Ответить | Правка | Наверх | Cообщить модератору

Архив | Удалить

Индекс форумов | Темы | Пред. тема | След. тема
Оцените тред (1=ужас, 5=супер)? [ 1 | 2 | 3 | 4 | 5 ] [Рекомендовать для помещения в FAQ]




Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру