-1

im trying to get some packet from microcontroller to c# program:

i defined a structure in both places. i calculate crc32 of (sizeof(packet)-4bytes) and place it in mydata_t.crc32 ...

struct mydata_t
{
    public byte cmd;
    public UInt32 param;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
    public Char[] str_buf;
    public UInt32 crc32;
}

    private byte[] getBytes(mydata_t str)
    {
        int size = Marshal.SizeOf(str);
        byte[] arr = new byte[size];

        IntPtr ptr = Marshal.AllocHGlobal(size);
        Marshal.StructureToPtr(str, ptr, true);
        Marshal.Copy(ptr, arr, 0, size);
        Marshal.FreeHGlobal(ptr);
        return arr;
    }
    private mydata_t fromBytes(byte[] arr)
    {
        mydata_t str = new mydata_t();
        str.str_buf = new char[10];
        int size = Marshal.SizeOf(str);
        IntPtr ptr = Marshal.AllocHGlobal(size);

        Marshal.Copy(arr, 0, ptr, size);

        str = (mydata_t)Marshal.PtrToStructure(ptr, str.GetType());
        Marshal.FreeHGlobal(ptr);

        return str;
    }

public static UInt32 xcrc32(byte[] buf, int len)
{
    UInt32 crc = DefaultSeed;
    UInt32 counter = 0;
    while (len-- > 0)
    {
        crc = (crc << 8) ^ defaultTable[((crc >> 24) ^ buf[counter]) & 255];
        counter++;
    }
    return crc;
}

my CRC function takes bytes and length .. so when i recieve data.. "in bytes" i convert them to structure by using (private mydata_t fromBytes(byte[] arr))

The problem: when i convert to byte array from the structure, calculating CRC is wrong "i believe its because of the endianness of the data types in c#? how do i solve this issue ?

here what i send from microcontroller:

    mydata_t datablockTX;
    datablockTX.cmd = 2;
    datablockTX.param = 0x98765432;
    memcpy(datablockTX.str_buf,"hellohell",10);
    datablockTX.crc32 = xcrc32((char*) &datablockTX,sizeof(datablockTX) - sizeof(uint32_t)); 
    usb_write_buf((uint8_t*) &datablockTX,sizeof(datablockTX));

here what i recieved and printed:

Data Received:
    CMD: 2
    param: 2557891634
    str: hellohell
    crc: 658480750

and then the problem:

public bool ValidateCRC()
{
    bool myvalidate;
    UInt32 mycrc_val;
    byte[] mybytes = getBytes(myblock);
    mycrc_val = Crc32.Crc32Algorithm.xcrc32(mybytes, mybytes.Length- sizeof(UInt32));
    //mycrc_val = Crc32.Crc32Algorithm.xcrc32(mybytes, 1);
    myvalidate = (mycrc_val == myblock.crc32);
    Console.WriteLine("c#:" + mycrc_val + " - MCU:" + myblock.crc32 + " - bool:" + myvalidate);
    return myvalidate;
}

this is what it prints in console: c#:667986744 - SAM:658480750 - bool:False


i tried this in MCU:

        mydata_t datablockTX;
        datablockTX.cmd = 2;
        datablockTX.param = 0x98765432;
        memcpy(datablockTX.str_buf,"hellohello",10);
        //datablockTX.crc32 = xcrc32((char*) &datablockTX,sizeof(datablockTX) - sizeof(uint32_t)); 
        datablockTX.crc32 = xcrc32((char*) &datablockTX, 5); 
        usb_write_buf((uint8_t*) &datablockTX,sizeof(datablockTX));

here it what i recieved:

CMD: 2

param: 2557891634

str: hellohello

crc: 1993296691

in c#:

            byte[] mybytes = getBytes(myblock);
        //mycrc_val = Crc32.Crc32Algorithm.xcrc32(mybytes, mybytes.Length- sizeof(UInt32));
        mycrc_val = Crc32.Crc32Algorithm.xcrc32(mybytes, 5);
        myvalidate = (mycrc_val == myblock.crc32);
        Console.WriteLine("c#:" + mycrc_val + " - MCU:" + myblock.crc32 + " - bool:" + myvalidate);

Console: c#:146416248 - MCU:1993296691 - bool:False

Community
  • 1
  • 1
Hasan alattar
  • 347
  • 3
  • 19
  • 3
    The problem could be even here: `public Char[] str_buf;`... Unless your microcontroller works with UTF-16 characters :-) Probably it should be a `public byte[] str_buf`. Note that there are various CRC32 algorithms... I hope you took the code from some code manual. And yes, endianness could be a problem. – xanatos Jul 18 '18 at 14:01
  • i did convert it to byte still same, actually im printing it .. recieving exactly what im sending as text so i dont think it would be about the char encoding right? – Hasan alattar Jul 18 '18 at 14:07
  • Who knows? We don't know anything of your microcontroller. – xanatos Jul 18 '18 at 14:08
  • im recieving the right data, only thing when i calculate the CRC in c# from the byte array from structure .. i dont get the right value.. i did test the crc function with some byte array defined by me in both mcu and c# and its the same result so its not in crc function "same function in both platforms" i thought its something related to "structure padding of c compiler" ?? hmm but i dont think so because im recieving the values correctly.. – Hasan alattar Jul 18 '18 at 14:11
  • What is the `sizeof(mydata_t)` in C? – xanatos Jul 18 '18 at 14:16
  • sizeof(mydata_t) = 24 size of bytes arrived = 24 actually i did try to calculate CRC in mcu with length of (4) which should be 1 byte (cmd) 3 bytes from (uint32_t param) and then calculate it back in the c# .. its not the same.. so thats why i though its because of endianness – Hasan alattar Jul 18 '18 at 14:17
  • 2
    It is not an endianess problem, that would also affect the `param` field value and it is correct. So xcrc32() is wrong, no hope of getting help with that here. Consider the shortcut, this data is sent through USB which already adds a CRC check itself. So checking again is not necessary. – Hans Passant Jul 18 '18 at 14:29
  • im using crc through usb right now but later it will be sent through different protocol that get noisy. i've checked xcrc with bytes it works ok ? – Hasan alattar Jul 18 '18 at 14:46

1 Answers1

2

Change

public static UInt32 xcrc32(byte[] buf, int len)
{
    UInt32 crc = DefaultSeed;

to

    UInt32 crc = 0xff1fff1f;

The DefaultSeed you are using is wrong. (if you want to know, I bruteforced it... Tried all the 4 billion possible seeds). Works for both crcs you gave.

xanatos
  • 109,618
  • 12
  • 197
  • 280