为什么我的uart中的校验和(crc16)不匹配?

时间:2017-01-14 05:40:34

标签: c++ file-transfer uart tty crc16

我创建了UART中使用的xmodem。 该协议在uint16_t中具有数据有效载荷的校验和。 我测试了下面显示的这部分代码,但它仍然被卡住了。 在图片中显示如下。

接收到chuck,从数据有效负载计算的另一个校验和在第一个上匹配,但在第二个上失败

为什么无法匹配收到的卡盘和从第二个数据有效载荷计算的另一个校验和?

never matched checksum

这是代码计算校验和的一部分。

xmodem的发件人。(xymodem_send)

chunk.crc = swap16(crc16(chunk.payload, sizeof(chunk.payload)));

xmodem的接收者。(xmodem_receive)

    uint16_t recChksum;
    uint16_t recCRC;

    // recData is data payload
    ret = read(serial_fd, recData, sizeof(recData));

    printf("Data buffer is %c\n", &recData);
    fflush(stdout);

    // processing  up to 1024bytes
    if (ret != sizeof(recData)) {
        rec_chunk_data += ret;
        while(rec_chunk_data < sizeof(recData)){
            ret = read(serial_fd, recData + (sizeof(uint8_t) * rec_chunk_data), (sizeof(recData) - rec_chunk_data));
            rec_chunk_data += ret;
                    printf("ret is proceeding: %d\n", ret);
                    fflush(stdout);
        }
    }

    ret = read(serial_fd, &recChksum, sizeof(recChksum));

    printf("Check sum is %d\n", recChksum);
    fflush(stdout);
    // Calculating checksum from data payload
    recCRC = swap16(crc16(recData, sizeof(recData)));
    // data integrity check
    if(recChksum != recCRC){
        printf("Check sum is %d and %d\n", recChksum, swap16(crc16(recData, sizeof(recData))));
        perror("swap16");
        return -errno;
    }

而且,这是完整的源代码。

#include <stdio.h>
#include <stdlib.h>

#include <stdint.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <string>

#define X_STX 0x02
#define X_ACK 0x06
#define X_NAK 0x15
#define X_EOF 0x04

 #define MAX_RETRY (9)

#define min(a, b)       ((a) < (b) ? (a) : (b))

struct xmodem_chunk {
        uint8_t start;
        uint8_t block;
        uint8_t block_neg;
        uint8_t payload[1024];
        uint16_t crc;
} __attribute__((packed));

void printArray(const uint8_t *ptr, size_t length)
{
    //for statment to print values using array
    printf("*****This is payload*****\n");
    size_t i = 0;
    for( ; i < length; ++i )
    printf("%c", ptr[i]);
    printf("*****This is payload*****\n");
    fflush(stdout);
}

#define CRC_POLY 0x1021
static uint16_t crc_update(uint16_t crc_in, int incr)
{
    uint16_t xor1 = crc_in >> 15;
    uint16_t out1 = crc_in << 1;

    if(incr)
        out1++;

    if(xor1)
        out1 ^= CRC_POLY; // xor 0b1000000100001

    return out1;
}


static uint16_t crc16(const uint8_t *data, uint16_t size)
{
        uint16_t crc, i;

        printf("data size :%d\n",size);
        printArray(data, size); // debug

        for (crc = 0; size > 0; size--, data++)
                for (i = 0x80; i; i >>= 1)
                        crc = crc_update(crc, *data & i);

        for (i = 0; i < 16; i++)
                crc = crc_update(crc, 0);

        return crc;
}

static uint16_t swap16(uint16_t in)
{
        return (in >> 8) | ((in & 0xff) << 8);
}

enum {
        PROTOCOL_XMODEM,
        PROTOCOL_YMODEM,
};

static int xmodem_receive(int serial_fd, char* filename, int _crc, int use_crc){
    printf("serial_fd is ....%d\n", serial_fd);
    fflush(stdout);
    int skip = 0;
    uint8_t sdCRC = 'C'; // Request-To-Send
    uint8_t sdACK = X_ACK; //
    uint8_t eof = X_EOF;
    uint8_t stx = X_STX;
    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;
    uint16_t recCRC;

    uint8_t heads_or_tails;
    uint8_t expected_blkno;
    int rec_chunk_data = 0;

    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));

    printf("serial_fd is ....%d\n", serial_fd);
    fflush(stdout);


        if(recSTX == X_STX){
            printf("STX is %c::%c\n", &recSTX, X_STX);
            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){
        memset(recData, 0, sizeof(recData));
        //So next, receiving blk
        ret = read(serial_fd, &recBlk, sizeof(recBlk));

            printf("serial_fd is ....%d\n", serial_fd);
    fflush(stdout);
        printf("ret is proceeding: %d\n", ret);
        fflush(stdout);

        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("ret is proceeding: %d\n", ret);
        fflush(stdout);
            printf("serial_fd is ....%d\n", serial_fd);
    fflush(stdout);

        printf("Negative Block Num is %d\n", recNegBlk);
        fflush(stdout);
        if (ret != sizeof(recNegBlk)) {
            perror("read");
            return -errno;
        }
        ret = read(serial_fd, recData, sizeof(recData));
        printf("Data buffer is %c\n", &recData);
        fflush(stdout);
        if (ret != sizeof(recData)) {
            rec_chunk_data += ret;
            while(rec_chunk_data < sizeof(recData)){
                ret = read(serial_fd, recData + (sizeof(uint8_t) * rec_chunk_data), (sizeof(recData) - rec_chunk_data));
                rec_chunk_data += ret;
                        printf("ret is proceeding: %d\n", ret);
                        fflush(stdout);
            }
        }
        printf("ret is proceeding: %d\n", ret);
        fflush(stdout);
        ret = read(serial_fd, &recChksum, sizeof(recChksum));
        printf("ret is proceeding: %d\n", ret);
        fflush(stdout);

        printf("Check sum is %d\n", 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("valid block num :%d and %d\n", recBlk, recNegBlk);
            fflush(stdout);
        }

            printf("serial_fd is ....%d\n", serial_fd);
    fflush(stdout);

        recCRC = swap16(crc16(recData, sizeof(recData)));
        // data integrity check
        if(recChksum != recCRC){
            printf("Check sum is %d and %d, %d\n", recChksum, swap16(crc16(recData, sizeof(recData))), recCRC);
            perror("swap16");
            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, &sdACK, sizeof(sdACK));
        ret = read(serial_fd, &heads_or_tails, sizeof(heads_or_tails));
        if (ret != sizeof(eof) && ret != sizeof(X_STX)){
                printf("sizeof eof :%d\n", sizeof(eof));
                printf("sizeof STX :%d\n", sizeof(X_STX));
                printf("sizeof uint8_t :%d\n", sizeof(uint8_t));
                perror("STX EOF length check error");
            return -errno;
        }else{
            if(heads_or_tails == stx){
                printf("next chunk\n");
                fflush(stdout);
                expected_blkno++;
            }else if(heads_or_tails == eof){
                printf("EOF ...");
                fflush(stdout);
                break;
            }else{
                ret = write(serial_fd, &sdNAK, sizeof(sdNAK));
                printf("Interruption\n");
                fflush(stdout);
            }
        }

    }
    printf("done.\n");
    fclose(fp);
    return 0;

}

static int xymodem_send(int serial_fd, const char *filename, int protocol, int wait)
{
        size_t len;
        int ret, fd;
        uint8_t answer;
        struct stat stat;
        const uint8_t *buf;

        uint8_t eof = X_EOF;
        struct xmodem_chunk chunk;


        int skip_payload = 0;


        fd = open(filename, O_RDONLY);
        if (fd < 0) {
                perror("open");
                return -errno;
        }

        fstat(fd, &stat);
        len = stat.st_size;
        buf = static_cast<uint8_t*>(mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0));
        if (!buf) {
                perror("mmap");
                return -errno;
        }

        if (wait) {
                printf("Waiting for receiver ping ...");
                fflush(stdout);

                do {
                        ret = read(serial_fd, &answer, sizeof(answer));
                        if (ret != sizeof(answer)) {
                                perror("read");
                                return -errno;
                        }
                } while (answer != 'C');

                printf("done.\n");
                fflush(stdout);
        }

        if (protocol == PROTOCOL_YMODEM) {
                strncpy((char *) chunk.payload, filename, sizeof(chunk.payload));
                chunk.block = 0;
                skip_payload = 1;
        } else {
                chunk.block = 1;
        }

        chunk.start = X_STX;
        int loops = 0;
        printf("STX Setted.\n");
        fflush(stdout);
        while (len) {
                printf(" round %d\n", loops);
                fflush(stdout);
                size_t z = 0;
                int next = 0;
                char status;

                if (!skip_payload) {
                        z = min(len, sizeof(chunk.payload));
                        memcpy(chunk.payload, buf, z);
                        memset(chunk.payload + z, 0xff, sizeof(chunk.payload) - z);
        printf("file chunk: %c\n", chunk.payload);
        fflush(stdout);
                } else {
                        skip_payload = 0;
                }

                printf("%d\n", swap16(crc16(chunk.payload, sizeof(chunk.payload))));
                fflush(stdout);
                chunk.crc = swap16(crc16(chunk.payload, sizeof(chunk.payload)));
                chunk.block_neg = 0xff - chunk.block;

                ret = write(serial_fd, &chunk, sizeof(chunk));
                if (ret != sizeof(chunk))
                        return -errno;

                ret = read(serial_fd, &answer, sizeof(answer));
                if (ret != sizeof(answer))
                        return -errno;
                switch (answer) {
                case X_NAK:
                        status = 'N';
                        break;
                case X_ACK:
                        status = '.';
                        next = 1;
                        break;
                default:
                        status = '?';
                        break;
                }

                printf("%c", status);
                fflush(stdout);

                if (next) {
                        chunk.block++;
                        len -= z;
                        buf += z;
                }
        }

        ret = write(serial_fd, &eof, sizeof(eof));
        if (ret != sizeof(eof))
                return -errno;

        /* send EOT again for YMODEM */
        if (protocol == PROTOCOL_YMODEM) {
                ret = write(serial_fd, &eof, sizeof(eof));
                if (ret != sizeof(eof))
                        return -errno;
        }

        printf("done.\n");

        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;
}

static void dump_serial(int serial_fd)
{
        char in;

        for (;;) {
                read(serial_fd, &in, sizeof(in));
                printf("%c", in);
                fflush(stdout);
        }
}

#ifdef TEST_XMODEM_RECEIVE

#endif // TEST_XMODEM_RECEIVE

int main(int argc, char **argv)
{
        int a, ret, serial_fd;

        std::string devs;

        printf("args:3: %s\n", argv[3]);

        printf("STX: %c\n", X_STX);

        printf("ACK: %c\n", X_ACK);

        printf("NAK: %c\n", X_NAK);

        printf("EOF: %c\n", X_EOF);

        fflush(stdout);

        if(std::string(argv[3]) == "1"){
            devs = "/dev/ttyUSB0";
        }else{
            devs = "/dev/ttyAMA0";
        }
        printf("devs: %s\n", devs.c_str());
        fflush(stdout);

        serial_fd = open_serial( devs.c_str(), 1200);
        if (serial_fd < 0)
                return -errno;


        if(std::string(argv[2]) == "0"){
            ret = xymodem_send(serial_fd, argv[1], PROTOCOL_XMODEM, 1);
            if (ret < 0)
                return ret;
        }

        if(std::string(argv[2]) == "1"){
            ret = xmodem_receive(serial_fd, argv[1], 1, 1);
            if (ret < 0)
                return ret;
        }

        if(std::string(argv[2]) == "3"){
            dump_serial(serial_fd);
            if (ret < 0)
                return ret;
        }

        return 0;
}

后记:

1)我在Ubuntu中发送text.txt,并在Raspibian jessie中接收text.txt。 在Ubuntu中显示以下文本是text.txt

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssss
ssssssssssssssssssssd

和,这是在Raspibian。

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssss
ssssssssssssssssssssd
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ

2)更改&#34; xmodem的接收者&#34;比如......

    recCRC = swap16(crc16(recData, sizeof(recData)));
    // data integrity check
    if(recChksum /*!= recCRC*/){
        printf("Check sum is %d and %d, %d\n", recChksum, swap16(crc16(recData, sizeof(recData))), recCRC);
        perror("swap16");
        return -errno;
    }

生成正确的校验和,如下所示 enter image description here

3)太长的文本超过1024字节只能输出自身的一部分。 除非通过&#34; dump_serial&#34;转储序列号。功能,我无法确定其他人。

4)显示https://justpaste.it/12eoe的发件人的Lorem ipsum文本为9行,但接收者只有3行https://justpaste.it/12epe并被截断。 接收器有效负载为https://justpaste.it/12epk

0 个答案:

没有答案