Почему моя контрольная сумма (crc16) в uart не совпадает?

Я создал xmodem, используемый в UART.
Этот протокол имеет контрольную сумму полезной нагрузки данных в uint16_t.
Я тестировал эту часть кода, показанную ниже, но она все еще застряла.
Показано ниже на картинке.

Полученный чак и другая контрольная сумма, рассчитанная по данным полезной нагрузки, сопоставляются на первом, но не выполняются на втором

Почему нельзя сопоставить полученный патрон и другую контрольную сумму, рассчитанную по данным полезной нагрузки на втором?

никогда не совпадает контрольная сумма

Это часть кода для расчета контрольной суммы.

Отправитель 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) Я отправляю text.txt в Ubuntu, и получаю text.txt в расповской Джесси.
Показанный ниже текст — это text.txt в Ubuntu

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssss
ssssssssssssssssssssd

и это на Распибийском.

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

2) Изменение «Receiver of xmodem», например ….

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

генерирует правильную контрольную сумму, показанную ниже
введите описание изображения здесь

3) Слишком длинный текст, превышающий 1024 байта, способен выводить только часть себя.
Если я не сбрасываю сериал с помощью функции dump_serial, я не могу быть уверен в других.

4) Lorem ipsum текст показа отправителя https://justpaste.it/12eoe 9 строк, а получатель только 3 строки https://justpaste.it/12epe и отрезать.
Полезная нагрузка приемника https://justpaste.it/12epk,

2

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]