0

I write a code to process real time video by using camera. I can run this code within any error by itself but I want to implement a UART interrupt. Basically I aim that when I take a data from UART, other processes will be interrupted and after reading data, processes will be continue.

Here my UART interrupt implemented code.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h> 
#include <netinet/in.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <errno.h>
#include <termios.h>
#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

void signal_handler_IO(int status);  

VideoCapture vid("/dev/video0", CAP_V4L2);

int n;
int fd;
int connected;
struct termios termAttr;
struct sigaction saio;
const int fps = 20;

int main(int argc, char *argv[])
{
fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
Mat frame;

if (fd == -1)
    {
        perror("open_port: Unable to open /dev/ttyO1\n");
        exit(1);
    }

saio.sa_handler = signal_handler_IO; 
saio.sa_flags = 0; 
saio.sa_restorer = NULL; //
sigaction(SIGIO,&saio,NULL); 
fcntl(fd, F_SETFL, FNDELAY|FASYNC);
fcntl(fd, F_SETOWN, getpid());
tcgetattr(fd,&termAttr);
cfsetispeed(&termAttr,B9600);
cfsetospeed(&termAttr,B9600);
termAttr.c_cflag &= ~PARENB; // --> Parity Enable
termAttr.c_cflag &= ~CSTOPB; // -->two stop bit else one 
termAttr.c_cflag &= ~CSIZE; // Character Size (C5, C6...)
termAttr.c_cflag |= CS8; // Charachter size 8 bit
termAttr.c_cflag |= (CLOCAL | CREAD); 
//CLOCAL --> Ignore modem status lines. ¦ CREAD --> Enable receiver.
termAttr.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); 
termAttr.c_iflag &= ~(IXON | IXOFF | IXANY);
termAttr.c_oflag &= ~OPOST; // OPOST --> Post-process output
tcsetattr(fd, TCSANOW, &termAttr);


printf("UART1 configured....\n");
connected = 1;

if (!vid.isOpened())
{
    return -1;
}

vid.set(CAP_PROP_FRAME_WIDTH, 1280);
vid.set(CAP_PROP_FRAME_HEIGHT, 720);

while (vid.read(frame))
{
    imshow("webcam", frame);

    if (waitKey(1000/fps) >= 0)
      break;
}   
    
    destroyAllWindows();
    vid.release();

    close(fd);
    exit(0);             
}

 void signal_handler_IO (int status)
 { 
       printf("received data from UART.\n");

 }  

Now let's get to the main problem:

When I implement UART interrupt to this code, my captured video was stopped by the core (I takes Core Dumped Error). I guess that after process interrupted and when it will continue again, compiler is try to set again the video properties which I defined as

 (vid.set(CAP_PROP_FRAME_WIDTH, 1280);) 
 (vid.set(CAP_PROP_FRAME_HEIGHT, 720);)

so I think I got such an error.

I think as I mentioned because when I deleted these size setting commands, code run very well with UART interrupt.

I try to define these commands globally but I cant do this. I take "vid does not name a type." error.

Thus, I can't solve this problem. I am not sure about why this problem occur and I don't know how it will be solved.

0andriy
  • 4,183
  • 1
  • 24
  • 37
  • *"When I implement UART interrupt to this code ..."* -- You seem to be confused, and refer to user signal as *"interrupt"*. Your program is several layers removed from the UART (including a USB layer), and is accessing a serial terminal, i.e. **/dev/tty...**. See [Linux serial drivers](http://www.linux.it/~rubini/docs/serial/serial.html), and imagine adding the USB into that hardware mix. Using a signal to "help" fetch data from the system buffer merely complicates your program and adds unnecessary overhead. You're not going to fetch that data any faster than a blocking **read()**. – sawdust Sep 28 '21 at 20:40
  • Thank's for the help but I'm Sorry, I couldn't understand your answer well. Especially, the " Your program is several layers removed from the UART" part is confused me. Maybe it is caused by my not having enough information about these topics. As far as I research, these types of POSIX Signals are used for the interruption and SIGIO signal is referred to I/O Possible signal. When this signal occurred, the routine process is interrupted and then the UART port is checked. Please correct me, If I am wrong. – ayashlokumu Sep 29 '21 at 14:31
  • *"I couldn't understand ..."* --See https://stackoverflow.com/questions/56846646/when-does-sigio-fire IOW SIGIO is from the termios subsystem, and has nothing to do with UART interrupts. Your program does not interact with the UART, but rather the termios subsystem. The device driver (and the OS) handles all interrupts from devices. Again, study that linked article. As to your signal problem, your signal handler does nothing to notify your process, and on top of that uses a restricted syscall; see https://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler – sawdust Sep 29 '21 at 22:06

1 Answers1

0

First, you cannot invoke printf(3) in a signal handler. Printf interacts with stdio, which in turn interacts with malloc(3); neither of these frameworks are signal safe. So, change your printf() to a write(2), which is safe.

That is unlikely to be your problem.

You didn't post the source to the implementation of vid, and in particular, how does vid.read deal with signals (ie EINTR)? Does it handle them correctly? Well? Perhaps return 0 if it is interrupted?

You will likely need to vet vid., so you should have a test candidate that gets a timer based signal over random intervals to gain confidence that it works.

mevets
  • 10,070
  • 1
  • 21
  • 33