Program freezes when closing serial port

I am reading data via a USB connection as a serial port with the PL2303 driver. It successfully returns at runtime openand when I set their TTY parameters and does not block. When I try to close the connection, it freezes. In this state, it reads "" instead of characters.

I can normally connect to the device using cutecom. Here is the weird part:

  • If I first connected to the device via cutecom (serial monitor), my program will connect and close perfectly every time after that. He reads characters, as I expect them to read. (No ).
  • If I disconnect and reconnect the equipment, my program will hang again until it launches cutecom.

Since it works after I use cutecom, it makes me think that I missed something in my initial connection or connection settings. Here is what I use to connect:

baud_rate = 38400;
fd =  open (device_path, O_RDONLY | O_NOCTTY );

In my function set_tty_options:

struct termios tty_options;

memset (&tty_options, 0, sizeof(tty_options));
tcgetattr (fd, &tty_options);

cfsetispeed(&tty_options, baud_rate);                         // set baud rate
tty_options.c_cflag = (tty_options.c_cflag & ~CSIZE) | CS8;   // 8 bit msgs
tty_options.c_cflag |= (CLOCAL | CREAD);                      // enable reading

tty_options.c_cflag &= ~(PARENB | PARODD);                    // shut off parity
tty_options.c_cflag |= parity;
tty_options.c_cflag &= ~CSTOPB;
tty_options.c_cflag &= ~CRTSCTS;

if (tcsetattr (fd, TCSANOW, &tty_options) != 0) 
{
  printf("error %d from tcsetattr\n", errno);
  return TTY_ERROR;
}

In set_blockingfunction:

if (tcgetattr (fd, &tty) != 0)
{
  printf("error %d from tggetattr", errno);
  return FAILURE;
}

// 0 or 1 byte is enough to return from read
tty.c_cc[VMIN]  = should_block ? 1 : 0; 
tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

if (tcsetattr (fd, TCSANOW, &tty) != 0) 
{
  printf("error %d setting term attributes", errno);
  return FAILURE;
}
+5
source share
2 answers

Here is what I ended up doing. I realized this by basically copying and pasting parts from sourceecode .

  • At the opening ...

    int fd, n;
    fd = open (device_path, O_RDONLY | O_NOCTTY | O_NDELAY);
    
    ... error check fd ...
    
    n = fcntl(ail_info->ail_serial_fd, F_GETFL, 0);
    fcntl(fd, F_SETFL, n & ~O_NDELAY);
    
  • You cannot set the baud rate as I did. You must use certain B38400;

    baud = B38400;

  • Then I added a wallyk answer.

    tty_settings.c_lflag = 0;

Edit: According to the comment on the saw, I found a better way to set this for raw input.

tty_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

And it works.

0
source

, | O_SYNC , /. , .

, , , NUL, :

tty_settings.c_iflag &= ~IGNBRK;         // ignore break signal

, , , , ^ C, ^\ .. :

tty_settings.c_lflag = 0;                // no signaling chars, no echo,
                                         // no canonical processing

, set_blocking(), .

+1

All Articles