Нужно ли спать после tcdrain ()? - PullRequest
0 голосов
/ 21 июня 2019

Я тестирую функцию записи библиотеки моего последовательного порта. Сначала я организовал дескриптор файла последовательного порта как неблокирующий дескриптор файла.Затем я вызываю tcdrain (fd) в конце моей настраиваемой функции записи.Но если я не подожду с sleep () после этой настроенной функции записи и немедленно вернусь из приложения, байты фактически не будут записываться через последовательный порт.

Итак, у меня два вопроса.

  1. Разве tcdrain () не гарантирует отправку байтов?
  2. Как реализовать настраиваемую функцию записи без вызова функции sleep ().

Я пробую ту же функцию с файлом блокировкидескриптор.Но ничего не изменилось.

Сначала я инициализирую последовательный порт следующим кодом:

struct termios stermios;
tcgetattr ( fd, &stermios );
cfsetispeed ( &stermios, handle->baudrate );
cfsetospeed ( &stermios, handle->baudrate );

stermios.c_cflag &= ~(PARENB | CSTOPB | CRTSCTS );
stermios.c_cflag |= ( CLOCAL | CREAD );
stermios.c_cflag &= ~CSIZE;
stermios.c_cflag |= CS8;

stermios.c_iflag &= (IXON | IXOFF );
stermios.c_oflag &= ~OPOST;
stermios.c_lflag &= ~(ICANON | ECHO | ECHOE );

tcflush ( fd, TCIOFLUSH );
tcsetattr ( fd, TCSANOW, termios_p );

И вот моя настраиваемая функция записи:


static int32_t surely_tcdrain ( SerialPortHandle_t const * handle_p )
{
    int32_t retval = -1;
    int32_t try_cnt = 0;

    while ( ( ++try_cnt < MAX_TCDRAIN_TRY_CNT ) &&\
            ( -1 == (retval = tcdrain ( fd ) ) ) )
    {
        if ( EINTR == errno )
        {
            usleep ( TCDRAIN_DELAY );
        }
        else
        {
            fprintf (stderr, "tcdrain() FAILED, %d, %s\n",\
                    errno, strerror ( errno ) );
            try_cnt = MAX_TCDRAIN_TRY_CNT; // Dont try again, break the loop. //
        }
    }

    return retval;
}
int32_t write_to_serial_port( int32_t fd, void * buff, size_t size )
{
  uint8_t try_cnt = 0;
  size_t total_write_size = 0;

  while ( ( total_write_size < size ) && ( ++try_cnt < 10 ) )
  {
    ssize_t w_size = -1;
    w_size = write (fd, ( ( uint8_t * ) buff + total_write_size ),\
        ( size - total_write_size ) );

    if ( w_size == -1 )
    {
      if ( ( errno != EINTR ) && ( errno != EAGAIN ) &&\
             ( errno != EWOULDBLOCK ) )
      {
         try_cnt = MAX_WRITE_TRY_CNT;
      }
      else
      {
        usleep ( WRITE_DELAY );
      }
    }
    else
    {
      total_write_size += ( ( size_t ) w_size );
    }
  }

    return ( ( surely_tcdrain ( fd ) == 0 ) &&\
            ( ( total_write_size == size ) ) ) ? 0 : -1;
}

И, наконец,Я закрыл свой дескриптор файла последовательного порта следующей функцией.

static void deinit_fd ( int32_t fd )
{
    if ( FD_INVALID != fd )
    {
        if ( 1 == isatty ( fd ) )
        {
            tcdrain ( fd ); // Wait for write all output process. //
        }
        else
        {
            // fd not referring terminal. So no need to call tcdrain(). //
        }

        close ( fd );
    }
    else
    {
        // fd is invalid. //
    }
}

Я вызываю эту функцию записи в main и после этого закрываю свой дескриптор файла и немедленно возвращаюсь из приложения.

Iожидайте, что все байты должны быть записаны через последовательный порт с моей функцией записи.Но моя функция так не работает.

1 Ответ

0 голосов
/ 21 июня 2019

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...