Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1] 2  Все   Вниз
  Печать  
Автор Тема: Работа с СОМ портом  (Прочитано 40797 раз)
0 Пользователей и 5 Гостей смотрят эту тему.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« : 09-08-2004 08:52 » new

В связи с организацией доступа и написанного своего шелла для платформы - возникла одна проблемка!

Общение с платформой осуществляется в виде терминального доступа через СОМ порт! В звязи с этим написан шелл - организующий подобную услугу!
В него встроена возможность перекачки файлов с хоста на платформу и обратно через YModem протокол!

Данные поступабт через тот же СОМ порт по тому же соединению!

В данный момент столкнулся с проблемкой!
Имею написанный код для винды для работы в протоколе! Передача данных организована с помощью Read/WriteFile и управлением таймаутом!

Теперь эти функции прописываются для Линуха на платформе!
Задача организовать чтение типа fgetc с возможностью прервать чтение с порта по таймауту!

Вопрос - какие функции это позволяют в Линухе?
Записан

А птичку нашу прошу не обижать!!!
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #1 : 09-08-2004 09:14 » 

Гром, для тайм таймаута в простейшем случае используют сигнал SIGALARM/ALARMSIG/ALARM (или как его там) кажется ставишь время таймаута выполняешь чтений если во премя чтения врямя ALARM истекло процесс получит сигнал ALARM который может быть обработан твоим обработчиком. Читать из порта можно как из файла. Управлять портом можно через fcntl (опятьже кажется). С компортом не работал так, что извини. Мне к нему подключать нечего, если тоько консоль дополнительную следелать из него.  Отлично
Записан

Странно всё это....
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #2 : 09-08-2004 09:26 » 

Вот тебе ссылки на всякие HOWTO:
http://www.tldp.org/HOWTO/HOWTO-INDEX/howtos.html
http://www.tldp.org/HOWTO/Remote-Serial-Console-HOWTO/index.html
http://www.tldp.org/HOWTO/Serial-HOWTO.html
http://www.tldp.org/HOWTO/Serial-Laplink-HOWTO/index.html
Я думаю этого хватить Улыбаюсь
Записан

Странно всё это....
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #3 : 09-08-2004 09:48 » 

LogRus, Я посмотрю - но проблема в том, что я должен все в одном потоке сделать - и чтение типа freadc не имеет параметра АЛАРМ - которое я мог бы выставить!
Записан

А птичку нашу прошу не обижать!!!
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #4 : 09-08-2004 10:09 » 

установка alarm и ualarm
http://www.opennet.ru/man.shtml?topic=alarm&category=2&russian=0
http://www.opennet.ru/man.shtml?topic=ualarm&russian=0&category=&submit=%F0%CF%CB%C1%DA%C1%D4%D8+man
подробней смотри
https://club.shelek.ru/download.php?id=223

множественность процессов/потоков здесь не причем.

ты спомощью alarm устанавливаешь таймаут производишь чтение снимаешь таймаут(кажется так alarm(0)Ага если по истечении времени аларм не снят приложение получит сигнал SIGALMR который ты можешь обработать при этом будут прерваны операции чтения/записи которые вернут ошибку что типа EAGAIN или разрыва канала.
подробней всё в тойже книге.
Всё труба зовёт. Чего вспомню допишу. Но позже. Работать!Работать!Работать!
Записан

Странно всё это....
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #5 : 09-08-2004 10:40 » 

А как я получив сигнал выбъю freadc с блокируемого чтения!
Записан

А птичку нашу прошу не обижать!!!
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #6 : 09-08-2004 11:01 » 

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

Странно всё это....
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 09-08-2004 12:09 » 

Стандартный обработчик сигнала завершает программу.

Примерчик работы:
Код:
void my_sig_proc(int sig) { return; }

signal(SIGALRM,my_sig_proc);
.......

alarm(1); // устанавливаем таймер на 1 секунду
res=read(fd,buf,len);
if(res==-1 && errno==EINTR) { // значит операция прервана сигналом
  }
else {
  alarm(0); // отключаем таймер
  }

Более точный таймаут можно организовать с помощью select(). Точность, теоретически, до микросекунд, а практически - зависит от ОС. select() можно использовать и с stream ф-ми: int fileno(FILE * STREAM).
« Последнее редактирование: 30-11-2007 21:58 от Алексей1153++ » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #8 : 09-08-2004 12:22 » 

Ага - если я правильно понял - после выполнения сигнала АЛАРМ - заканчивается не программа - как пишет RXL, Улыбаюсь а все ж таки функция типа колбэк!

Я поясню свою задачу - так как несколько запутался!!!

Есть

Код:
int Read(char * buf, int len, ...)
{
     int i;
     unsigned char ch;
     for (i=0; i< len; i++)
     {
            ch = fgetc(stdin);
            if (ch) buf[i] = ch;
            else
             {
                  if (ERROR) return false;
                  else
                      return true;
             }

     }
     return true;
}

Вот такая примерно в первом приближении функция чтения буфера!
Т.е. я читаю буфер и проверяю - если не пришел просто байт то выхожу нормально - если в связи с какой - то ошибкой то выхожу как с ошибкой чтения!

В момент чтения - после того как стало ясно что символ не пришел - прошел таймаут, я должен выйти из fgetc() и из процедуры!

В вашем варианте вы бинарно читаете - а мне это не надо - во вторых у вас как я уже писал есть некий колбек - мне такого желательно не иметь - надо вылетать из чтения при истечении таймаута! Т.е. нужен полный аналог неблокирумого ReadFile из винды!
« Последнее редактирование: 30-11-2007 21:59 от Алексей1153++ » Записан

А птичку нашу прошу не обижать!!!
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #9 : 09-08-2004 13:21 » 

Гром, ну ты прямо Громазека! Улыбаюсь
Такие вопросы.
Ваще это довольно стандартная практика сигналами прерывать чтение/запись.
Код:

            alarm(secs); // или ualarm(msecs);
            ch = fgetc(stdin);
            // тут проверь ошибки на предмет E_AGAIN. Типа там пусто повторить бы.
            alarm(0); // кажется так отменяется alarm
            if (ch) buf[i] = ch;
            else
             {
                  if (ERROR) return false;
                  else
                      return true;
             }

тут смотри:
http://www.opennet.ru/docs/RUS/glibc/glibc-8.html
про O_NONBLOCK можно выставлять до открытия и после функция fcntl
там же еще есть что возможно тебе подойдет.
и еще всётаки глянь книжку ссылку на которую я тебе дал я еще читал(изданную прада) очень понравилась.
Как говорится читайте маны там много не тривиального. Улыбаюсь
« Последнее редактирование: 30-11-2007 22:01 от Алексей1153++ » Записан

Странно всё это....
Anonymous
Гость
« Ответ #10 : 09-08-2004 13:47 » 

Цитата
Ага - если я правильно понял - после выполнения сигнала АЛАРМ - заканчивается не программа - как пишет RXL,  а все ж таки функция типа колбэк!
Я же говорю - стандартный обработчик сигнала ( signal(SIGимя,SIG_DFL); ). The default behavior for these signals is to cause program termination.
Поставив свой обработчик, ты сможешь сам решать, продолжать или закрывать программу.
Код:
int my_sig_proc(int sig) { exit(0); } // программа завершится
int my_sig_proc(int sig) { return; } // выполнение продолжится

Код:
#include <stdio.h>

void my_sig_proc(int sig) { return; }

...
signal(SIGALRM,my_sig_proc);
...

int Read(char * buf, int len, ...)
{
     int i;
     unsigned char ch;
     for (i=0; i< len; i++)
     {
            alarm(1);
            ch = fgetc(stdin);
            alarm(0);
            if (ch!=EOF) buf[i] = ch; // рекомендую проверку на EOF, а не на 0. Тем более, что EOF!=0
            else
             {
                  if (ferror(stdin)!=EINTR) return false; // другая ошибка
                  else
                      return true; // был таймаут
             }

     }
     return true;
}
« Последнее редактирование: 30-11-2007 22:03 от Алексей1153++ » Записан
Anonymous
Гость
« Ответ #11 : 09-08-2004 13:49 » 

LogRus, неблокируемые терминалы не рекомендую - бывают плавающие глюки с потерей данных.
Записан
Антон (LogRus)
Глобальный модератор

ru
Offline Offline
Пол: Мужской
Внимание! Люблю сахар в кубиках!


WWW
« Ответ #12 : 09-08-2004 13:53 » 

Ну я не пробовал. Гром просил не блокирующий. Улыбаюсь
Записан

Странно всё это....
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #13 : 09-08-2004 14:20 » 

Видимо терминология опять хромает - я просил организовать не блокируемый - но с помощью своей проверки - т.е. я читаю - только я - но не блокирую на всегда - а блокирую на время - по указанию тайм - аута!

Гость (RXL) Спасибо - я понял - буду пробовать!
Записан

А птичку нашу прошу не обижать!!!
darkelf
Молодой специалист

de
Offline Offline

« Ответ #14 : 10-08-2004 05:54 » 

еще можно почитать Serial Programming Guide for POSIX Operating Systems, там все подробно описано, заодно там сказано, как  устанавливать тайм-аут на прием байта (на промежуток между байтами). почитайте man tcgetattr()/tcsetattr().
Записан
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #15 : 11-08-2004 12:42 » 

Код:
#include <stdio.h>
#include "ymodem.h"
#include <unistd.h>




// globals
int count_pack=0;

int PackErrorCode=SUCCESS;
int Timeout=0;    //  in seconds

void sig_proc(int sig)|return;}


void SetPortTimeouts(int timeout)
{
  Timeout = timeout;
 
}

bool WriteFile(unsigned char * buf, unsigned int to_write, unsigned int * trans_bytes, void * reserved)
{
  int i;
  unsigned char ch;
  if (buf == NULL) return false;
  if (to_write <=0) return false;

 
  for (i=0; i<to_write; i++)
  {
     fputc(ch,stdin);
  }
  *trans_bytes = i;
  return true;
}

bool ReadFile(unsigned char * buf, unsigned int to_read, unsigned int * trans_bytes, void * reserved)
{
  int i;
  unsigned char ch;
  signal(SIGALRM,sig_proc);

  if (buf == NULL) return false;
  if (to_read == 0) return false;
  for (i=0; i<to_read; i++)
  {
     alarm(1);
     ch = fgetc(stdin);
     alarm(0);
     if (ch!=EOF) buf[i] =ch;
     else
     {
       if (ferror(stdin)) return false;
       else
        return true;
       }
  }
  *trans_bytes = i;
 
  return true;
}

На этот код выдается ошибка в компилляции

ymodem.c: In function `ReadFile':
ymodem.c:49: `SIGALRM' undeclared (first use in this function)
ymodem.c:49: (Each undeclared identifier is reported only once
ymodem.c:49: for each function it appears in.)
ymodem.c:58: warning: comparison is always true due to limited range of data type

Короче говоря - не компилируется SIGALRM - не понимает что это такое - при абстрактном добавлении

#define SIGALRM 10

Выбрасывает из программы! Совсем!!!
Какие файлы надо подгрузить кроме #include <unistd.h> дабы это заработало?
« Последнее редактирование: 30-11-2007 22:05 от Алексей1153++ » Записан

А птичку нашу прошу не обижать!!!
MOPO3
Ай да дэдушка! Вах...
Команда клуба

lt
Offline Offline
Пол: Мужской
Холадна аднака!


WWW
« Ответ #16 : 11-08-2004 13:17 » 

Если под линух то #include <signal.h>

http://www.ee.ic.ac.uk/docs/software/unix/programming/sys/comms/timer.html
Записан

MCP, MCAD, MCTS:Win, MCTS:Web
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #17 : 11-08-2004 13:35 » 

Откомпилировал - не работает - почему то все равно не выходит из заблокированного fgetc(stdin)   Ха-ха-ха помогите что я не так делаю!!!!
Записан

А птичку нашу прошу не обижать!!!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 11-08-2004 19:33 » 

Гром, возможно что ф-ия fgetc() обрабатывает ошибки и возобновляет выполнение read() при EINTR. Замени fgetc(stdin) на read(0,buf,1). Завтра проверю что к чему и уточню.
Кстати, какая ОС?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 11-08-2004 20:17 » 

А посмотри info libc в разделах "Low-Level Terminal Interface/Terminal Modes/Noncanonical Input" и "Low-Level Terminal Interface/Noncanon Example".

Вот мой вариант инициализации порта:
Код:
#include <termios.h>

char            *tty_name="/dev/ttyS0";
char            tty_bits[4]="8N1";
char            tty_fctrl[2]="N";
int             tty=0,tty_speed=19200;

int setup(void) {
    static struct termios       tios;

    tty=open(tty_name,O_NOCTTY|O_RDONLY); // !!! read only mode
    if(tty<0) return 0x40;
    if(!isatty(tty)) return 0x50;

    tcgetattr(tty,&tios);
    tios.c_iflag=IGNBRK;
    tios.c_oflag=0;
    tios.c_lflag=0;
    tios.c_cc[VMIN]=1;
    tios.c_cc[VTIME]=0; /* <<< тут-то и надо поставить таймаут в 0.1сек интервалах */
    tios.c_cflag=CLOCAL|CREAD;
    switch(tty_bits[0]) {
        case '7': tios.c_cflag|=CS7; break;
        case '8': tios.c_cflag|=CS8; break;
        default: return 0xa0;
        }
    switch(tty_bits[1]) {
        case 'N': break;
        case 'E': tios.c_cflag|=PARENB; break;
        case 'O': tios.c_cflag|=PARENB|PARODD; break;
        default: return 0xa0;
        }
    switch(tty_bits[2]) {
        case '1': break;
        case '2': tios.c_cflag|=CSTOPB; break;
        default: return 0xa0;
        }
    switch(tty_fctrl[0]) {
        case 'N': break;
        case 'S': tios.c_cflag|=IXON|IXOFF; tios.c_cc[VSTOP]=0x13; tios.c_cc[VSTART]=0x11; break;
        case 'H': tios.c_cflag|=CRTSCTS; break;
        default: return 0xa0;
        }
    cfsetspeed(&tios,tty_speed);
    tcsetattr(tty,TCSANOW,&tios);
    return 0;
    }
« Последнее редактирование: 30-11-2007 22:06 от Алексей1153++ » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #20 : 11-08-2004 20:26 » 

RXL, не тут я же писал подробно. У меня нет инициализации порта - это делает ОС - я сижу на stdin - СОМ - порте - т.е. роль клаиватурного воода выполняет сериальная коннекция...

ОС eCos - Эмбедед Линукс!
Я считываю с терминала который на PC по СОМ порту комманды в программе shell и надо ее же перевести на работу в режиме протокола а потом назад! Вот такая вот фигня - но я поробую вытащить из этого что-нибудь!
Записан

А птичку нашу прошу не обижать!!!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #21 : 11-08-2004 20:48 » 

Гром, можно сохранить состояние терминала (tcgetattr(tty,&tios)Ага, а потом востановить его. В твоем случае просто не надо менять физичексие параметры, а просто перевести в другой режим работы.

Вот страничка с примером (Low-Level Terminal Interface/Noncanon Example):
Код:
Noncanonical Mode Example
=========================

   Here is an example program that shows how you can set up a terminal
device to read single characters in noncanonical input mode, without
echo.

     #include <unistd.h>
     #include <stdio.h>
     #include <stdlib.h>
     #include <termios.h>

     /* Use this variable to remember original terminal attributes. */

     struct termios saved_attributes;

     void
     reset_input_mode (void)
     {
       tcsetattr (STDIN_FILENO, TCSANOW, &saved_attributes);
     }

     void
     set_input_mode (void)
     {
       struct termios tattr;
       char *name;

       /* Make sure stdin is a terminal. */
       if (!isatty (STDIN_FILENO))
         {
           fprintf (stderr, "Not a terminal.\n");
           exit (EXIT_FAILURE);
         }

       /* Save the terminal attributes so we can restore them later. */
       tcgetattr (STDIN_FILENO, &saved_attributes);
       atexit (reset_input_mode);

       /* Set the funny terminal modes. */
       tcgetattr (STDIN_FILENO, &tattr);
       tattr.c_lflag &= ~(ICANON|ECHO); /* Clear ICANON and ECHO. */
       tattr.c_cc[VMIN] = 1;
       tattr.c_cc[VTIME] = 0;
       tcsetattr (STDIN_FILENO, TCSAFLUSH, &tattr);
     }

     int
     main (void)
     {
       char c;

       set_input_mode ();

       while (1)
         {
           read (STDIN_FILENO, &c, 1);
           if (c == '\004')          /* `C-d' */
             break;
           else
             putchar (c);
         }

       return EXIT_SUCCESS;
     }

   This program is careful to restore the original terminal modes before
exiting or terminating with a signal.  It uses the `atexit' function
(*note Cleanups on Exit::) to make sure this is done by `exit'.

   The shell is supposed to take care of resetting the terminal modes
when a process is stopped or continued; see *Note Job Control::.  But
some existing shells do not actually do this, so you may wish to
establish handlers for job control signals that reset terminal modes.
The above example does so.

Как я понимаю, твой девайс после некой команды, полученной с терминала, переходит в режим приема-передачи файла? Тогда без перенастройки не обойдешься.
« Последнее редактирование: 30-11-2007 22:08 от Алексей1153++ » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #22 : 12-08-2004 08:44 » 

Да именно так и происходит ия должен его настроить - вот теперь понятно в какую сторону копать!!!
А то я программирую как-то криво - в чистом С и по привычке с устройствами как с видндовыми общаюсь - психология штука тонкая Жаль
Записан

А птичку нашу прошу не обижать!!!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #23 : 12-08-2004 08:52 » 

Гром, кстати - для Linux-а есть готовые утилиты работы с X/Y/Z-Modem - можеть это будет проще?
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #24 : 12-08-2004 09:00 » 

RXL, не там специфично все - Файловая система jffs все равно все перелопачивать пришлось бы - так что...
Да и я все уже написал Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #25 : 12-08-2004 10:10 » 

Гром, молодец. А при чем тут fs? Речь то о утилите.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #26 : 15-08-2004 08:26 » 

RXL, ну возможно я и приурасил Улыбаюсь файловая там действительно не причем - но не важно.
Важно то, что не смотря на то, что заработал alarm и сигнал я получаю в sig_proc выхода из процедуры fgetcc() или read() не происходит - т.е. я оказываюсь вв ситуации когда сигнал могу обработать - но выбить из читения у меня не получается Жаль
Записан

А птичку нашу прошу не обижать!!!
darkelf
Молодой специалист

de
Offline Offline

« Ответ #27 : 15-08-2004 12:02 » 

По-моему необходимо запретить перезапускать системные вызовы функцией siginterrupt().
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #28 : 15-08-2004 19:28 » 

Подробно, что и как: info libc - раздел "Signal Handling/Primitives Interrupted by Signals"
Оттуда: If you define `_BSD_SOURCE' or `_GNU_SOURCE' before calling `signal', the default is to resume primitives; otherwise, the default is to make them fail with `EINTR'.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Гром
Птычк. Тьфу, птычник... Вот!
Готовлюсь к пенсии

il
Offline Offline
Пол: Мужской
Бодрый птах


« Ответ #29 : 15-08-2004 21:32 » 

RXL, хм... что -то туманно пока...
надо проспаться Улыбаюсь
Записан

А птичку нашу прошу не обижать!!!
Страниц: [1] 2  Все   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines