2016-07-20 3 views
1

Я использую радиомодуль XBee pro, и я регистрирую некоторые радиоданные.Последовательная коммуникационная авария

Я использую последовательный порт FTDI для USB-конвертера, поэтому модуль отображается под /dev/ttyUSB0.

Я написал этот код:

void TsToCoord::serialConfig() 
{ 
    // Open Serial Port 
    cout << "Opening serial port..." << endl; 
    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); 

    if (fd < 0) 
    { 
     cout << "Error " << errno << " opening /dev/ttyUSB0: " << strerror(errno) << endl; 
    } 
    else 
    { 
     //Configure Serial Port 
     cout << "Configuring serial port..." << endl; 
     struct termios tty; 
     memset (&tty, 0, sizeof tty); 

     if (tcgetattr (fd, &tty) != 0) 
     { 
      cout << "Error " << errno << " from tcgetattr: " << strerror (errno) << endl; 
     } 

     cfsetispeed(&tty, B57600); 
     cfsetospeed(&tty, B57600); 

     tty.c_cflag &= ~PARENB; 
     tty.c_cflag &= ~CSTOPB; 
     tty.c_cflag &= ~CSIZE; 
     tty.c_cflag |= CS8; 
     tty.c_cflag &= ~CRTSCTS; 
     tty.c_lflag = 0; 
     tty.c_oflag = 0; 
     tty.c_cc[VMIN] = 1; 
     tty.c_cc[VTIME] = 50; 

     tty.c_cflag |= CREAD | CLOCAL; 

     cfmakeraw(&tty); 

     tcflush(fd, TCIFLUSH); 

     if (tcsetattr(fd, TCSANOW, &tty) != 0) 
     { 
      cout << "Error " << errno << " from tcsetattr" << endl; 
     } 
    } 
} 


void TsToCoord::listenPort() 
{ 
    // Creation of a buffer to store data from radio module 
    fill_n(buff, 2048, '\0'); 
    this-> ind = 0; 

    while(true) 
    { 
     char mes[1024]; 
     fill_n(mes, 1024, '0'); 
     //cout << "Blocking read" << endl; 
     int rd = read(fd, &mes, sizeof(mes)); 

     if (rd > 0) 
     { 
      //cout << "Storing in buffer" << endl; 
      storeInBuff(mes, rd); 
      fill_n(mes, 1024, '0'); 

      struct pollfd fds; 
      fds.fd = fd; 
      fds.events = POLLIN | POLLPRI; 
      int slct = 1; 

/* 
      int slct = 1; 
      fd_set rdfds; 
      FD_ZERO(&rdfds); 
      FD_SET(fd, &rdfds); 
      struct timeval to; 
      to.tv_sec = 0; 
      to.tv_usec = 100000; 
*/ 
      //fd_set rdfdsCopy = rdfds; 
      //cout << "Entering second while loop" << endl; 
      while (slct > 0) 
      { 
       //cout << "Call to select" << endl; 
       //slct = select((fd+1), &rdfdsCopy, NULL, NULL, &to); 
       slct = poll(&fds, 1, 100); 
       if (slct > 0) 
       { 
        //cout << "Next call to read, would not block" << endl; 
        rd = read(fd, &mes, sizeof(mes)); 
        storeInBuff(mes, rd); 
        //rdfdsCopy = rdfds; 
       } 
      } 
      findFrame(0); 
      ind = 0; 
      fill_n(buff, 2048, '\0'); 
     } 
    } 
} 

Моя проблема заключается в том, что, когда он начал это прекрасно работает. Но после 20 минут он больше не выполняет свою работу. Использование ЦП переходит на 100%, так что вызов чтения больше не блокируется. Это похоже на дескриптор файла, который больше не связан с устройством ...

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

Так я хочу спросить:

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

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

Я использую Debian 3.2.57-3 i686.

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

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

Спасибо за чтение и извините за не очень хороший английский.

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

+0

@Olaf Как-то я сказал, что в какой-то момент программа не может блокироваться при чтении, и все вызовы, которые нужно читать, не блокируют и ничего не читают, поэтому программа не делает то, для чего она была создана: данные журнала поступают от радиомодуля. Я просто хочу избежать этого, так как без этого он отлично работает и может нанести вред аппаратным средствам. – rmilville

+0

@ Kyll: OP не показал никаких усилий, обеспечив требуемые вещи. Поэтому он, по крайней мере, может найти ссылки сам. (И ссылки будут показаны в любом случае с закрытым сообщением, я не обязан оставлять комментарий вообще (и для этого вопроса это очевидно), поэтому возьми его как любезность и не говори мне, что я должен делать или нет! – Olaf

+0

@ Kyll thanks. Я вырезал код, так что появлялись только связанные с серией вещи. Я всегда думаю, что, возможно, в другом месте есть какие-то другие очевидные ошибки, поэтому я поместил весь код. Поскольку я не нашел людей, у которых была эта проблема (работает сначала, а затем случайным образом разбился), я думал, что в нем была более причудливая ошибка. Мне плохо для публикации только для теста. – rmilville

ответ

1

Быстрый просмотр вашего кода - если вы получаете EOF или ошибку при чтении (т.е. read() возвращает ноль или -1), вы будете циклически навсегда. Я вижу, что вы в сыром режиме, но я вижу различные ошибки в драйверах FTDI и прошивке, которые могут привести к этому, и это не тот случай, который вы обрабатываете.

+0

Спасибо. Я добавлю тест на то, что прочитает. Дело в том, что если read вернет 0 или -1, почему все последующие вызовы будут возвращать 0 или -1 тоже? Поскольку я хочу, чтобы эта вещь запускалась как демон, если каждый раз, когда вызов чтения делает все остальные вызовы неудачными, мне придется перезапустить демона. Дело в том, что мне иногда приходится регистрировать данные каждые 5 секунд, перезапуск каждые 30 минут не очень приемлем, потому что довольно долго перезапускать. Могут ли прошивки/драйверы ftdi вызвать эту ошибку? – rmilville

+0

Как только вы получите 0 или -1, это, вероятно, то, что вы будете продолжать получать. Как только вы получите EOF, новые данные не поступят. Когда будет ошибка, она не исчезнет. Вам нужно выяснить, что происходит и решить эту проблему. В вашем коде вы можете закрыть и снова открыть устройство. Также - нет веской причины для медленного перезапуска, должно быть миллисекунды. – janm

+0

Вот что я сделал, закройте fd и снова откройте файл, соответствующий устройству. Ну, для перезапуска, если я убил с командой kill и перезапустил ее с помощью «service ----- start», это быстро, но с «service ---- restart» это медленнее, как черт. Поскольку я добавил тест, я могу надеяться, что мне не нужно перезапускать демона. – rmilville

0

Итак, я последовал за советами @janm. Я удалил эту строку:

tty.c_cflag &= ~CRTSCTS; 

и сделал тест вроде этого:

rd = read(fd, &mes, sizeof(mes)); 
if (rd > 0) 
{ 
    doSomeStuff(); 
} 
else 
{ 
    close(fd); 
    serialConfig(); 
    listenPort(); 
} 

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

+0

Вам нужно перейти к первопричине, что означает, что вам нужно проверить 'rd <0', а затем сообщить значение' errno'. E, G см. Http://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c/38318768#38318768 Я не вижу, как удалить 'tty. c_cflag & = ~ CRTSCTS' может улучшить/исправить что угодно. FWIW У меня есть несколько адаптеров FTDI. – sawdust

Смежные вопросы