Pages: [1]   Go Down
Author Topic: [FIXED] Working Arduino CRC 32 code  (Read 1324 times)
0 Members and 1 Guest are viewing this topic.
United Kingdom
Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Right, there is this page: http://excamera.com/sphinx/article-crc.html which defines how to get a CRC-32 checksum with both Arduino and Python; exactly what I want to do.

Now, I run the Python code and everything works as expected, and I get the result as the website shows - '0xc1446436L'. However, running the code on my Arduino gives me no result. I quickly realised that there is no Serial.begin(XXX) line, so I added it in to get the following code:

Code:
#include <avr/pgmspace.h>

static PROGMEM prog_uint32_t crc_table[16] = {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};

unsigned long crc_update(unsigned long crc, byte data)
{
    byte tbl_idx;
    tbl_idx = crc ^ (data >> (0 * 4));
    crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
    tbl_idx = crc ^ (data >> (1 * 4));
    crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
    return crc;
}

unsigned long crc_string(char *s)
{
  unsigned long crc = ~0L;
  while (*s)
    crc = crc_update(crc, *s++);
  crc = ~crc;
}

void setup()
{
  Serial.begin(9600);
  Serial.println(crc_string("HELLO"), HEX);
}

void loop()
{
}

I get the result, '1001900' which is not the same as the website, I'd assume that this has something to do with the new Arduino IDE 1.0, but I'm not that smart. I've tried changing the HEX at the end of Serial.println to anything else (OCT, DEC etc.) and while the values changed, they did not match the Python output.



I realise that I probably sound idiotic, and this is probably something simple that I just don't understand. I get logic and I/O but not these deep algorithms.

Any help guys? Thanks.

EDIT: I've tried this same code on Ubuntu and Mac OS X, with two separate Arduino UNO's. The same result every time.
« Last Edit: February 09, 2012, 04:58:09 pm by TenderLoins » Logged

Ontario
Offline Offline
God Member
*****
Karma: 20
Posts: 835
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
   crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);

pgm_read_dword_near() takes a byte offset.  You calculate the table index "(tbl_idx & 0x0f)" but you have to multiply by sizeof(unsigned long) to convert this int a byte offset.
Logged

United Kingdom
Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Really appreciate the response, but I simply don't understand what you're saying. This is how I interpret what you said:

Code:
crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);

# becomes

crc = pgm_read_dword_near(crc_table + ((tbl_idx & 0x0f) * sizeof(unsigned long))) ^ (crc >> 4);

# or

crc = pgm_read_dword_near(crc_table + ((tbl_idx & 0x0f) * sizeof(tbl_idx & 0x0f))) ^ (crc >> 4);

# or

crc = pgm_read_dword_near(crc_table + ((tbl_idx * sizeof(tbl_idx & 0x0f) & 0x0f) )) ^ (crc >> 4);

All of these get the same result.

I just wish I knew C better. I copied this function from someone else, so I do not have knowledge of how it works. Thank you for your reply.
Logged

Offline Offline
Edison Member
*
Karma: 35
Posts: 1419
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think that's the problem. In C, if you add an integer quantity to a pointer that quantity is automatically (in effect) multiplied by the sizeof what the pointer points to.

A more likely problem is that crc_string doesn't return a result. At the end of the crc_string function add this:
Code:
 return crc;

Pete
[edit] Just tested it and it works.
« Last Edit: February 09, 2012, 04:47:52 pm by el_supremo » Logged

Where are the Nick Gammons of yesteryear?

United Kingdom
Offline Offline
Newbie
*
Karma: 0
Posts: 41
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think that's the problem. In C, if you add an integer quantity to a pointer that quantity is automatically (in effect) multiplied by the sizeof what the pointer points to.

A more likely problem is that crc_string doesn't return a result. At the end of the crc_string function add this:
Code:
 return crc;

Pete
[edit] Just tested it and it works.

Dude, thank you so much smiley I've wasted an evening on this, and just started delving into PROGMEM stuff (which was enlightening, even if it was off the scent). In retrospect, now you've pointed out the issue, I feel like an idiot; but we've all been there. I sound like I'm worshipping, but I would have spent my weekend getting frustrated without your help.

I'm going to change the title of this thread, and here is working Arduino CRC 32 code, courtesy of http://excamera.com/sphinx/article-crc.html and el_supremo:

Code:
#include <avr/pgmspace.h>

static PROGMEM prog_uint32_t crc_table[16] = {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};

unsigned long crc_update(unsigned long crc, byte data)
{
    byte tbl_idx;
    tbl_idx = crc ^ (data >> (0 * 4));
    crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
    tbl_idx = crc ^ (data >> (1 * 4));
    crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
    return crc;
}

unsigned long crc_string(char *s)
{
  unsigned long crc = ~0L;
  while (*s)
    crc = crc_update(crc, *s++);
  crc = ~crc;
  
  return crc;
}

void setup()
{
  Serial.begin(9600);
  Serial.println(crc_string("HELLO"), HEX);
}

void loop()
{
}
« Last Edit: February 09, 2012, 06:30:16 pm by TenderLoins » Logged

Ontario
Offline Offline
God Member
*****
Karma: 20
Posts: 835
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I don't think that's the problem.

Yes, sorry for the misdirection.  I don't know what made me think that crc_table was char[].  My bad.
Logged

Norway
Offline Offline
Newbie
*
Karma: 1
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey,

PROGMEM has changed since this code was written, so replace this line : static PROGMEM prog_uint32_t crc_table[16] = {
with: const uint32_t PROGMEM crc_table[16] = {
for it to compile and function properly.
Logged

Pages: [1]   Go Up
Jump to: