Ненадежная последовательная связь с pl2303 - PullRequest
0 голосов
/ 24 января 2019

Подключено два устройства PL2303 TX-> RX, RX-> TX и подключено к моей машине Linux

Я написал приложение на C, которое выполнит следующую операцию:

  1. Порт1 -> «отправляет известные данные размером 256 байт» -> Порт2
  2. Порт2 считывает данные и проверяет, действительно ли он получил те же данные, которые передал Порт1
  3. Порт2 -> «отправляет известные данные размером 256 байт, отличные от того, какой порт1 отправил» -> Порт1
  4. Порт1 считывает данные и проверяет, действительно ли он получил те же данные, которые передал Порт2

Использовано два потока, по одному на каждый порт

На последнем шаге, если у нас не будет «sleep + tcflush» перед чтением, буфер, считываемый Port1, будет иметь некоторые данные, которые он передал в Port2 на первом шаге.

Вот фрагмент моего кода.

// Even port number execution part
        if (!(port_num % 2)) {
            // Write to a given port
            sem_wait(&semaphore[port_num]); // Wait until read is called for odd port
            bytes_written = write(fd, write_buffer_even, size_even);
            if (bytes_written == -1 || bytes_written != size_even) {
                fprintf(fp, "%s: Failed to write buffer\n", port_name);
                thread_params->retval = -errno;
                goto exit;
            }
            // For some reason, I need to add a delay before flushing.
            // The cause of this problem lies in using a USB serial port.
            // If you use a regular serial port, you will not have this problem.
            usleep(300000L); // Required to make flush work
            tcflush(fd, TCIOFLUSH);

            // Read from a given port
            sem_post(&semaphore[port_num + 1]);
            bytes_read = read(fd, read_buffer, size_even);
            if (bytes_read == -1) {
                fprintf(fp, "%s: Failed to read buffer\n", port_name);
                thread_params->retval = -errno;
                goto exit;
            }
            // Check for read bytes, complete & valid or not
            if (size_odd != bytes_read) {
                fprintf(fp, "%s: Read size mismatch - Expected %d bytes,"
                        "Read %zd bytes\n", port_name, size_odd, bytes_read);
                thread_params->retval = -ECOMM;
                thread_params->fail_count++;
            } else {
                if(strncmp(write_buffer_odd, read_buffer, size_odd)) {
                    fprintf(fp, "%s: Read data mismatch - Expected \"%s\""
                            "Read \"%s\"", port_name, write_buffer_odd,
                            read_buffer);
                    thread_params->retval = -ECOMM;
                    thread_params->fail_count++;
                } else {
                    thread_params->success_count++;
                }
            }
        // Odd port number execution part
        } else {
            // For some reason, I need to add a delay before flushing.
            // The cause of this problem lies in using a USB serial port.
            // If you use a regular serial port, you will not have this problem.
            usleep(300000L); // Required to make flush work
            tcflush(fd, TCIOFLUSH);

            // Read from a given port
            sem_post(&semaphore[port_num - 1]);
            bytes_read = read(fd, read_buffer, size_odd);
            if (bytes_read == -1) {
                fprintf(fp, "%s: Failed to read buffer\n", port_name);
                thread_params->retval = -errno;
                goto exit;
            }
            // Check for read bytes, complete & valid or not
            if (size_even != bytes_read) {
                fprintf(fp, "%s: Read size mismatch - Expected %d bytes,"
                        "Read %zd bytes\n", port_name, size_even, bytes_read);
                thread_params->retval = -ECOMM;
                thread_params->fail_count++;
            } else {
                if(strncmp(write_buffer_even, read_buffer, size_even)) {
                    fprintf(fp, "%s: Read data mismatch - Expected \"%s\""
                            "Read \"%s\"", port_name, write_buffer_even,
                            read_buffer);
                    thread_params->retval = -ECOMM;
                    thread_params->fail_count++;
                } else {
                    thread_params->success_count++;
                }
            }

            // Write to a given port
            sem_wait(&semaphore[port_num]); // Wait until read is called for read port
            bytes_written = write(fd, write_buffer_odd, size_odd);
            if (bytes_written == -1 || bytes_written != size_odd) {
                fprintf(fp, "%s: Failed to write buffer\n", port_name);
                thread_params->retval = -errno;
                goto exit;
            }
        }

Я переключился на другие USB для последовательных устройств, таких как cp2104, cp2108, и поведение остается прежним. Какую ошибку я совершаю, я не хочу спать в своем приложении, так как это влияет на мою производительность.

Добавлены настройки termios:

// Open the port
    sprintf(port_name, "/dev/ttyUSB%d", port_num);
    fd = open(port_name, O_RDWR);
    if (fd == -1) {
        fprintf(fp, "%s: Failed to open %s  port with status:%d\n",
                __func__, port_name, -errno);
        thread_params->retval = -errno;
        goto exit;
    }

    // Set configuration for serial port
    tcgetattr(fd, &config);
    config.c_lflag &= ~(ECHO | ECHONL | ECHOE | ECHOK | ECHONL
            | ECHOCTL | ECHOPRT | ECHOKE);
    cfsetispeed(&config, B9600);
    cfsetospeed(&config, B9600);
    tcsetattr(fd, TCSANOW, &config);
...