Linux c++ and arduino usb/serial problem.

Hoping someone might be able to give me a few tips or suggestions. First off I know enough about C++ just to get by. Most of the code that I use is from examples that I’ve found off the internet and books.
In short, I have a program on the arduino that reads 4 switches and sends the switch number and a 1 or 0 (depending on open or closed) to my linux box (ubuntu) via the serial/usb port. Everything was working fine until I switched over to different computer and the USB code seemed to have stopped working and had to do a rewrite on it to get it working again. Now it sort of works with the exception of one particular function. The function uses jwsmtp libraries to send an email out at particular points in the code. When the program starts up it sends out and email indicating that the program has started (this works) then the usb serial port is initialized. The program now loops waiting for an open switch code to be received and when it does it sends out another email. This is where the problem starts, the email never gets sent out. I think the issue is caused by the usb code for the simple reason that I can put the function anywhere before the code and it works, but after the code and it either doesnt work or causes a segfault. Below is the usb code from the program. If anybody is willing to help and needs more I can post more. The entire program is a fair length.

// *******  USB Initialization *******
        const char *usbport;
        usbport=port.c_str();
        fd = open(usbport, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if (fd <0) {perror(usbport); exit(-1); }
          saio.sa_handler=signal_handler_IO;
          saio.sa_flags=0;
          saio.sa_restorer=NULL;
          sigaction(SIGIO,&saio,NULL);
          fcntl(fd, F_SETOWN, getpid());
          fcntl(fd,F_SETFL,FASYNC);
        tcgetattr(fd,&oldtio); // save current port settings
        bzero(&newtio, sizeof(newtio));
        newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
        newtio.c_iflag = IGNPAR | ICRNL;
        newtio.c_oflag = 0;
        newtio.c_lflag = ICANON;
        newtio.c_cc[VTIME]    = 0;   // inter-character timer unused
        newtio.c_cc[VMIN]     = 3;   //  blocking read until 3 chars received
        tcflush(fd, TCIFLUSH);
        tcsetattr(fd,TCSANOW,&newtio);

One other thing, there is one particular line in the above code that executes a small function that will also cause a segfault.

saio.sa_handler=signal_handler_IO;

if I comment out the code in the function it does not segfault.

void signal_handler_IO(int status)
{
//  printf("received SIGIO signal\n");
//  wait_flag=FALSE;
}

Your code seems to come from here
http://tldp.org/HOWTO/Serial-Programming-HOWTO/

But actually doing this with a signal handler seems pretty strange to me, since - it is awful to debug

  • and a SIGIO is raised from USB-IO as well as the code that sends the e-mail.

I suggest you rewrite this part of your code with the solution given at the very bottom of the examples page using select() in section 3.4
http://tldp.org/HOWTO/Serial-Programming-HOWTO/x115.html

But if you want to keep your code, you should run it under in a debugger to check what exactly causes the segfault. I would be surprised if it has anything to do with the USB-IO.

Eberhard

I have no experience with that low level C stuff.
Wouldn't it be easier to use a higher level C++ library?
boost::asio::serial works well for me for interfacing with the arduino.

Ya, that is where I got it from. Not looking forward to redoing that part of the code but will give it a go. I'll try the stuff in section 3.4 first. Program Examples

Ulrichard, I'm assuming this is what your reffering to Boost.Asio - 1.36.0 ?

Is any one better/easier than the other?

Thank you so much for the suggestions.

Is any one better/easier than the other?

I never used the boost-libraries, so I can only speak for the solution using the basic select() call for IO.

select() is a fundamental concept in Linux/Unix for every kind of asynchronus IO (serial/network/USB-drivers).

If you want to get serious with programming for Linux I think should put some work into reading about the basics and then using select().

All higher level libs like boost and Qt provide a (C++) wrapper for the basic select() calls and give it fancy names. These libraries might lead to quicker results, but putting some time in understanding the select() call will pay off in the long run.

Eberhard

Yes, exactly. And here is what got me starting:
http://old.nabble.com/Simple-serial-port-demonstration-with-boost-asio-asynchronous-I-O-td19849520.html

Well, I have never worked directly with the linux kernel API (only through libraries), but only with the WIN32 one. Working directly with the Win32 API is no joy. Although I assume, the linux kernel is more organized, they probably still have some things in common. Kernel API's are usually low level C interfaces. Whereas high level libraries shield the user from lots of the intricate details.

On the other hand, boost::asio is not the perfect example of an easy to use library if you're not familiar with modern C++. It's very generic and has lots of options.
Also, boost::asio is cross platform. Just in case you want to some day run your app on another platform.