Не удается прочитать последовательный порт (UART)

Код ниже открывает второй последовательный порт, и я пытаюсь читать и писать в него. Теперь я использую функции консоли на первом порту (Tera Term Console), чтобы просмотреть там журналы (printf или dmesg).

Но я не могу читать из порта. Консоль зависает.

    int fd; /* File descriptor for the port */
    #define BUFF_SIZE 1024
    struct termios options;
    char to_write[1024];
    char to_read[1024];
    int bytes_written;

    int init_uart()
    {
        tcgetattr(fd, &options);

         /* Set Baud Rate */

        cfsetispeed( &options, B115200 );
        cfsetospeed( &options, B115200 );

        // Set the Charactor size

        options.c_cflag &= ~CSIZE; /* Mask the character size bits */
        options.c_cflag |= CS8;    /* Select 8 data bits */

        // Set parity - No Parity (8N1)

        options.c_cflag &= ~PARENB;/*no parity bit*/
        options.c_cflag &= ~CSTOPB;/* One bit stop bit*/
        options.c_cflag &= ~CSIZE;
        options.c_cflag |= CS8;/* 8 Bits Character length*/

        // Disable Hardware flowcontrol
        options.c_cflag &= ~CRTSCTS;

        // Enable Raw Input
        options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

        // Disable Software Flow control
        options.c_iflag &= ~(IXON | IXOFF | IXANY);

        // Chose raw (not processed) output
        options.c_oflag &= ~OPOST;

        if ( tcsetattr( fd, TCSANOW, &options ) == -1 ){
            printf ("Error with tcsetattr = %s\n", strerror ( errno ) );
            return -1;
        }
        return 0;
    }
    int write_uart()
    {
        int i=0;
        while (i < BUFF_SIZE-2){
            to_write[i]='a';
            i++;
        }
        to_write[i]='\n';
        to_write[i+1]='\r';
        // Write to the port
        bytes_written = write(fd, to_write, BUFF_SIZE);

        if(bytes_written < BUFF_SIZE){
            fputs("write() of 1024 bytes failed!\n", stderr);   
            return -1;
        }
        return 0;
    }

    int
    read_port(void)
    {
        int n = read(fd, to_read, sizeof(BUFF_SIZE));
        if (n < 1024){
            fputs("read failed!\n", stderr);
            return -1;
        }
        return 0;
    }

    int main()
    {
        int i=0;
        fd = open("/dev/ttyS1",O_RDWR | O_NOCTTY);
        if(fd == -1)
            perror("open_port: Unable to open /dev/ttyS1\n");
        else
            printf("ttyS0 Opened successfully\n");
        if(init_uart())
            perror("open_port: Unable to initialize /dev/ttyS0 Port\n");
        else
            printf("Port Initialization is done successfuly\n");
        if(write_uart())
            perror("write_port: Unable to write to /dev/ttyS0 Port\n");
        else
            printf("Write to the port happened successfully\n");
        if(read_port())
            perror("read_port: Unable to read from /dev/ttyS0 Port\n");
        else
            printf("Read to the port happened successfully\n");
        close(fd);
    return 0;
    }

person Pravesh Gupta    schedule 05.09.2013    source источник
comment
Приятно видеть вопрос о последовательном порте, который использует правильную инициализацию POSIX и проверку кода возврата. Но (1) вы забыли проверить код возврата tcgetattr(). (2) К какому устройству подключен этот последовательный порт? Если на другом конце последовательного канала нет устройства, то что вы ожидаете прочитать? (3) Вы уверены, что хотите перевести порт в необработанный режим? В зависимости от подключенного устройства (?), вам может понадобиться канонический режим. Если это текстовое устройство (как указывает вывод write()), то вам, вероятно, следует использовать канонический режим вместо необработанного.   -  person sawdust    schedule 07.09.2013


Ответы (1)


@randomization, я думаю, вам нужно настроить управляющие символы, то есть c_cc[VTIME] и c_cc[VMIN]. VTIME: таймер запускается при вызове чтения. read возвращается, когда доступен хотя бы один байт данных, или когда истекает время таймера. Если таймер истекает, а ввод не становится доступным, read возвращает 0. VMIN: read блокируется до тех пор, пока не станет доступным меньшее из MIN байтов или количество запрошенных байтов, и возвращает меньшее из этих двух значений. Попробуйте настроить VMIN и VTIME и протестируйте свое приложение. Вы можете настроить любой из них. Хорошее описание этих вещей можно найти на справочных страницах, например #man termios.

person Gautham Kantharaju    schedule 06.09.2013
comment
Да, VTIME и VMIN не следует оставлять неуказанными при использовании неканонического режима. Но ваши объяснения таймера и того, как/когда вернется read(), неверны. Вы упростили работу этих конфигураций без указания значений. НАПРИМЕР. таймер может быть с начала вызова (как вы упомянули), ИЛИ межсимвольный таймер или вообще без таймера. OP видит ожидаемое поведение для значений по умолчанию VMIN и VTIME. - person sawdust; 07.09.2013
comment
@sawdust, объяснение VTIME и VMIN и их возвращаемых значений взяты из справочной страницы termios. - person Gautham Kantharaju; 07.09.2013