2

I'm working on a small Linux server (Ubuntu Server 13.04 running on a Beagleboard xM ARM computer) that will be communicating between a laptop wirelessly and an Arduino. The issue I seem to be having is regarding the communication between the Arduino and the Beagleboard. The program will run just fine for a certain amount of time, ~30 seconds or so, then it will halt. The program will stay running but the port apparently freezes.

The program I'm running is currently just a test program that will sweep a servo over a certain range. The code for the functions used to set up the ports was found here.

My program code is as follows, with exception of the code found in the separate thread:

    #include <errno.h>
    #include <termios.h>
    #include <stdio.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <iostream>

    using namespace std;

   ...

   int main (int argc, const char* argv[]) {
        cout << "TestIO running...\n";
        char* portname = "/dev/ttyACM0";
        // Open serial port
        int fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);

        // Return error if port cannot be opened
        if (fd < 0)
        {
                cout << "error " << errno << " opening " <<  portname << ": " << strerror (errno) << "\n";
                return -1;
        }

        set_interface_attribs (fd, B9600, 0);   // set speed to 9600 bps, 8n1 (no parity)
        set_blocking (fd, 0);                   // set no blocking

        // Read from serial port
        //char inputBuffer[64];
        //int inputLength = read(fd, inputBuffer, sizeof inputBuffer);

        double output = 575;
        char outputString[255];
        char outputLength;
        int incrimentor = 1;
        char inChar;
        for(;;) {
                if (output >= 675 )
                        incrimentor = -1;
                else if (output <= 375)
                        incrimentor = 1;
                output += incrimentor;

                // Sweep wheels on car, set drive motor to 0
                outputLength = sprintf(outputString, "%0.2f", output);
                write(fd, outputString, outputLength);
                write(fd, ",", 1);
                write(fd, "0", 1);
                write(fd, "\n", 1);

                cout << outputString << "\n";

                // Sleep thread for 5000 uS (5 ms)
                usleep(5000);
        }
        close(fd);
        return 0;
}

On a slightly different note, when the program freezes I must force it to quit the code to close the port is never reached and thus I cannot run the program again to test it. I'm curious if anyone might know how to close a serial port through a Linux command run in the terminal.

Thanks!

4

1 に答える 1

0

ハングしているプログラムを終了する方法に関する 2 番目の問題を参照してください。

すべてのシステム コールに戻り値のテストを追加することは、一般的には良い考えです。

指示されたほど多くのデータを読み書きするとは限らないread()ことに注意してください。write()

また、プロセスがシグナルを受信した場合はread()/write()を返します。

ここでは特に、ブロックする可能性のある呼び出しに結果のテストを追加します ( write()):

ssize_t writen(int fd, char * buffer, size_t size)
{
  ssize_t written_total = 0;
  ssize_t written = 0;

  while  (outputLength > written_total)
  {
    written = write(fd, buffer + written_total, size - written_total);
    if (-1 == written)
    {
      if (EINTR == errno)
      {
        /* interupted by signal -> break and leave */
        break;
      }
      elseif ((EAGAIN == errno) || (EWOULDBLOCK == errno))
      {
        continue; /* try again */
      }

      /* another error occured -> log, break and leave */

      break;
    }

    written_total += written;
  }

  if (outputLength > written_total)
  {
    if (-1 = written)
    {
      /* handle error */
    }
    else
    {
      /* notify of interruption */
    }
  }
  else
  {
    /* log succesfully transmission of all data */
  }

  return written_total;
}

int main()
{
  ...

  do
  {
    if (outputLength != writen(fd, outputString, outputLength))
    {
      fprintf(stderr, "writen(fd, outputString, outputLength) failed");
      break;
    }

    if (1 != writen(fd, ",", 1))
    {
      fprintf(stderr, "writen(fd, ",", 1)) failed");
      break;
    }

    if (1 != writen(fd, "0", 1))
    {
      fprintf(stderr, "writen(fd, "0", 1)) failed");
      break;
    }

    if (1 != writen(fd, "\n", 1))
    {
      fprintf(stderr, "writen(fd, "\n", 1)) failed");
      break;
    }
  } while (0);

  if (-1 == close(fd))
  {
    perror("close() failed");
  }

  ...
}

プログラムには、シグナルを「食べる」以外は何もしないシグナルハンドラを登録する必要があることに注意してください (SIGUSR1たとえば)。

次に、コマンドラインから次のようにして、プログラムのブロックを簡単に解除できます。

$ kill <program-pid> -SIGUSR1
于 2013-09-30T13:20:38.210 に答える