2

I created xmodem used in UART. This protocol have checksum of data payload in uint16_t. I tested this part of code showing below, but it is still stucked. Showing below in the picture.

Received chuck and another checksum calculated from the data payload is matched on the first,but failed on the second

Why can not be matched the received chuck and another checksum calculated from the data payload on the second?

never matched checksum

This is a part of code calculating checksum.

Sender of xmodem.(xymodem_send)

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

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

And, This is full source code.

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

Postscript:

1)I send text.txt in Ubuntu,and receive text.txt in Raspibian jessie. Showing below text is text.txt in Ubuntu

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssss
ssssssssssssssssssssd

and,This is in Raspibian.

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

2)Changing "Receiver of xmodem" such as....

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

are generates the correct checksum showing below enter image description here

3)Too long text exceed 1024 bytes is only able to output a part of itself. Unless dumping the serial by "dump_serial" function, I can't make sure of others.

4)Lorem ipsum text of sender showing https://justpaste.it/12eoe is 9 rows, but receiver is only 3 rows https://justpaste.it/12epe and cut off. Receiver payload is https://justpaste.it/12epk.

NEWBIEEBIEE
  • 197
  • 2
  • 13
  • 1
    There are lots of different CRC algorithms, make sure you're using the right one. – Mark Ransom Jan 14 '17 at 06:40
  • 2
    That's unlikely going to happen.The function as crc16 used in this code is the same.so I think it's a problem of data payload processing rather than crc16 algrism. – NEWBIEEBIEE Jan 14 '17 at 06:47
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/133181/discussion-on-question-by-newbieebiee-why-my-checksumcrc16-in-uart-is-not-matc). – Bhargav Rao Jan 15 '17 at 07:48

0 Answers0