Почему нельзя получить данные из "чтения" в массив uint8_t?

Пожалуйста, посоветуй мне. Я хотел бы, чтобы код получал данные из последовательного порта, такого как tty/USB0. Поэтому необходимо, чтобы этот код считывал данные из последовательного протокола, как показано ниже.

uint8_t recBlk; // receive blk from chunk
ret = read(serial_fd, &recBlk, sizeof(recBlk));
printf("Block Num is %d\n", recBlk);
fflush(stdout);
if (ret != sizeof(recBlk)) {
    perror("read");
    return -errno;
}

Однако я не понял, почему эти строки, показанные ниже, не работают, но произошла ошибка "read: invalid аргумент"

Как получить данные массива из функции чтения?

uint8_t recData[1024]; // receive data from chunk
ret = read(serial_fd, (void *)&recData, sizeof(recData));
    printf("Data buffer is %c\n", &recData);
    fflush(stdout);
if (ret != sizeof(recData)) {
     printf("Can't fetch the Data length!");
     perror("read");
     return -errno;
}

Этот код, показанный ниже, является моей реализующей функцией.

static int xmodem_receive(int serial_fd, char* filename, int _crc, int use_crc){
    int skip = 0;
    uint8_t sdCRC = 'C'; // Request-To-Send
    uint8_t sdACK = X_ACK; //
    uint8_t eof = X_EOF;
    uint8_t sdNAK = X_NAK;
    uint8_t recSTX; // receive SOH from chunk
    uint8_t recBlk; // receive blk from chunk
    uint8_t recNegBlk; // receive blk negative from chunk
    uint8_t recData[1024]; // receive data from chunk
    uint16_t recChksum;
 
    uint8_t expected_blkno;
 
    FILE *fp;
    int ret, fd;
    struct stat stat;
    // If we want to receive, We have to send NAK to Sendor.
 
    if (use_crc)
        use_crc = MAX_RETRY + 1;
 
        /* Writing as binary */
    fp = fopen(filename, "wb");
    //Send NAK still read SOH that header of one data chunks
    /*
    CRC 16
    Sending C
    Sending NAK
 
    */
    while(use_crc){
        char status;
        printf("Waiting for sender ping ...");
        fflush(stdout);
        //
        if(_crc){
            printf("Send C ping....\n");
            ret = write(serial_fd, &sdCRC, sizeof(sdCRC));
        }else{
            // send NAK before read SOH
            printf("Send NAK ping....\n");
            ret = write(serial_fd, &sdNAK, sizeof(sdNAK));
        }    // after sending NAK,receiving SOH from chunk
        fflush(stdout);
        ret = read(serial_fd, &recSTX, sizeof(recSTX));
 
 
        if(recSTX == X_STX){
            printf("STX is %c\n", &recSTX);
            break;
        }else{
            printf("Garabage payload %c\n", &recSTX);
        }
        fflush(stdout);
        if (ret != sizeof(recSTX)) {
                printf("Not working");
                fflush(stdout);
                perror("read");
                return -errno;
        }
        use_crc--;
    }
 
    expected_blkno = 1;
 
    while(ret != EOF){
        //So next, receiving blk
        ret = read(serial_fd, &recBlk, sizeof(recBlk));
        printf("Block Num is %d\n", recBlk);
        fflush(stdout);
        if (ret != sizeof(recBlk)) {
            perror("read");
            return -errno;
        }
        ret = read(serial_fd, &recNegBlk, sizeof(recNegBlk));
        printf("Negative Block Num is %d\n", recNegBlk);
        fflush(stdout);
        if (ret != sizeof(recNegBlk)) {
            perror("read");
            return -errno;
        }
        ret = read(serial_fd, (void *)&recData, sizeof(recData));
        printf("Data buffer is %c\n", &recData);
        fflush(stdout);
        if (ret != sizeof(recData)) {
            printf("Can't fetch the Data length!");
            perror("read");
            return -errno;
        }
        ret = read(serial_fd, &recChksum, sizeof(recChksum));
        printf("Check sum is %c", &recChksum);
        fflush(stdout);
        if (ret != sizeof(recChksum)) {
            printf("Can't fetch the Check sum");
            perror("read");
            return -errno;
        }
        // data block number check
        if(recBlk == 0xff - recNegBlk){
            printf("Can't fetch the Block !");
            perror("read");
 
            return -errno;
        }
        // data integrity check
        if(recChksum == swap16(crc16(recData, sizeof(recData)))){
            perror("read");
            return -errno;
        }
        // check of appended "0xff" from end of data to  end of chunk in chunk
        unsigned char *ptr = recData;
        ptr += sizeof(recData);
        while(*ptr == 0xff){
            ptr--;
        }
        fwrite(recData, (ptr - recData),1,fp); // write Datas bytes from our buffer
        // set skip flag or end connect
        ret = write(serial_fd, &eof, sizeof(uint8_t));
        if (ret != sizeof(eof) || ret != sizeof(X_STX)){
            return -errno;
        }else{
            if(ret == X_STX){
                skip = 1;
                printf("next chunk");
                fflush(stdout);
                expected_blkno++;
            }else if(ret == EOF){
                printf("EOF ...");
                ret = write(serial_fd, &sdACK, sizeof(sdACK));
                break;
            }else{
                return -errno;
            }
        }
 
    }
    printf("done.\n");
    fclose(fp);
    return 0;
 
}

Термос сеттинг здесь.

static int open_serial(const char *path, int baud)
{
        int fd;
        struct termios tty;

        fd = open(path, O_RDWR | O_SYNC);
        if (fd < 0) {
                perror("open");
                return -errno;
        }

        memset(&tty, 0, sizeof(tty));
        if (tcgetattr(fd, &tty) != 0) {
                perror("tcgetattr");
                return -errno;
        }

        cfsetospeed(&tty, baud);
        cfsetispeed(&tty, baud);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        tty.c_iflag &= ~IGNBRK;                         // disable break processing
        tty.c_lflag = 0;                                // no signaling chars, no echo,
                                                        // no canonical processing
        tty.c_oflag = 0;                                // no remapping, no delays
        tty.c_cc[VMIN]  = 1;                            // read doesn't block
        tty.c_cc[VTIME] = 5;                            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY);         // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);                // ignore modem controls,
                                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);              // shut off parity
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr(fd, TCSANOW, &tty) != 0) {
                perror("tcsetattr");
                return -errno;
        }

        return fd;
}

1 ответ

Решение

Код, который выдает "ошибку":

    uint8_t recData[1024]; // receive data from chunk
  ...
        ret = read(serial_fd, (void *)&recData, sizeof(recData));
        printf("Data buffer is %c\n", &recData);
        fflush(stdout);
        if (ret != sizeof(recData)) {
            printf("Can't fetch the Data length!");
            perror("read");
            return -errno;
        }

1.) Первая проблема - синтаксис Си.
recData - это адрес массива, а в вызовах read() и printf () адрес этого адреса передается как второй аргумент.
Операция адресации на адресе массива неверна.

2.) Второй вопрос - оценка возвращаемого значения.
Страница man описывает возможные возвращаемые значения системного вызова read().

2a.) Переменная errno действительна только в том случае, если возвращаемое значение равно -1.
Однако perror() в вашем коде будет вызываться всякий раз, когда возвращаемое значение не равно количеству байтов в массиве.
Поэтому сообщение "прочитано: неверный аргумент" может быть поддельным.

2b.) Системный вызов read() не требуется для удовлетворения запрошенного аргумента длины.
Ваша конфигурация termios определяет минимальное чтение 1 байта.
Таким образом, системный вызов read() вернет, по крайней мере, один байт и только столько данных, сколько в данный момент получено драйвером последовательного порта, до максимальной запрошенной длины.
Поэтому, когда невозможно выполнить полное чтение 1024 байта (что, вероятно, будет всегда), ваша программа будет прервана с фиктивной ошибкой.

Другие вопросы по тегам