Fast CRC library (uses the built-in crc-module in Teensy3)

Status
Not open for further replies.
Added PROGMEM...

It would be great if somebody could test it with an AVR (mine are collecting dust.. too much trouble to reactivate them)
 
Just tried to verify the FastCRC_example and got this.

D:\Arduino\libraries\FastCRC\FastCRC.cpp: In member function 'uint8_t FastCRC8::smbus(const uint8_t*, uint16_t)':
D:\Arduino\libraries\FastCRC\FastCRC.cpp:78:27: error: 'CRC_FLAG_NOREFLECT_8' was not declared in this scope

Using Arduino 1.0.6 and Teensy 3.1

edit.

I get the same error with FastCRC_validate.
 
Just tried to verify the FastCRC_example and got this.

D:\Arduino\libraries\FastCRC\FastCRC.cpp: In member function 'uint8_t FastCRC8::smbus(const uint8_t*, uint16_t)':
D:\Arduino\libraries\FastCRC\FastCRC.cpp:78:27: error: 'CRC_FLAG_NOREFLECT_8' was not declared in this scope

Using Arduino 1.0.6 and Teensy 3.1

edit.

I get the same error with FastCRC_validate.

Hm, i think somehow this line got lost:
Code:
#define CRC_FLAG_NOREFLECT_8 (0) //For 8-Bit CRC

Can't test this at the moment !
 
Hm, i think somehow this line got lost:
Code:
#define CRC_FLAG_NOREFLECT_8 (0) //For 8-Bit CRC

Can't test this at the moment !

Adding that line to the sketch did not help and adding it to FastCRC.cpp made it puke errors.

Code:
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::cksum_upd(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:72: multiple definition of `FastCRC8::FastCRC8()'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:68: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::cksum_upd(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:72: multiple definition of `FastCRC8::FastCRC8()'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:68: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC8::smbus(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:106: multiple definition of `FastCRC8::update(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:101: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC8::generic(unsigned char, unsigned char, unsigned long, unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:139: multiple definition of `FastCRC8::generic(unsigned char, unsigned char, unsigned long, unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:134: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC8::maxim(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:94: multiple definition of `FastCRC8::maxim(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:89: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC8::smbus(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:82: multiple definition of `FastCRC8::smbus(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:78: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::FastCRC16()':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:157: multiple definition of `FastCRC16::FastCRC16()'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:150: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::FastCRC16()':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:157: multiple definition of `FastCRC16::FastCRC16()'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:150: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::update(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:240: multiple definition of `FastCRC16::update(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:233: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::generic(unsigned short, unsigned short, unsigned long, unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:272: multiple definition of `FastCRC16::generic(unsigned short, unsigned short, unsigned long, unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:265: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::x25(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:228: multiple definition of `FastCRC16::x25(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:221: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::xmodem(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:216: multiple definition of `FastCRC16::xmodem(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:209: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::kermit(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:203: multiple definition of `FastCRC16::kermit(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:196: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::modbus(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:191: multiple definition of `FastCRC16::modbus(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:184: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::mcrf4xx(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:179: multiple definition of `FastCRC16::mcrf4xx(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:172: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC16::ccitt(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:167: multiple definition of `FastCRC16::ccitt(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:160: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::FastCRC32()':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:297: multiple definition of `FastCRC32::FastCRC32()'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:284: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::FastCRC32()':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:297: multiple definition of `FastCRC32::FastCRC32()'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:284: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::update(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:332: multiple definition of `FastCRC32::update(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:319: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::generic(unsigned long, unsigned long, unsigned long, unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:362: multiple definition of `FastCRC32::generic(unsigned long, unsigned long, unsigned long, unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:349: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::cksum(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:319: multiple definition of `FastCRC32::cksum(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:306: first defined here
FastCRC\FastCRChw.cpp.o: In function `FastCRC32::crc32(unsigned char const*, unsigned short)':
D:\Arduino\libraries\FastCRC/FastCRChw.cpp:307: multiple definition of `FastCRC32::crc32(unsigned char const*, unsigned short)'
FastCRC\FastCRC.cpp.o:D:\Arduino\libraries\FastCRC/FastCRC.cpp:294: first defined here
collect2.exe: error: ld returned 1 exit status
 
Ah.. i see.

please delete FastCRC.cpp from the FastCRC directory and insert the define from above bewteen the other defines in the .h file.
That's it.
I'll ask Paul to update the Lib with the next beta.

Regards, Frank.
 
Last edited:
Ah.. i see.

please delete FastCRC.cpp from the FastCRC directory and insert the define from above bewteen the other defines in the .h file.
That's it.
I'll ask Paul to update the Lib with the next beta.

Regards, Frank.

Redownloaded from your GitHub, that seems to have fixed it I will make a few attempts at using it today with my project.
 
Next problem, I can compile FastCRC_example, but I receive nothing on serial on my PC, I have tried changing the baud rate and running at 96 and 72MHz on the 3.1.
 
Ok, I got it working by moving nearly everything from setup and placing it in the loop. The only part I left was the Serial.begin.

Results

Code:
CRC Benchmark
Length: 16384 Bytes


Maxim (iButton) 8-Bit CRC:
FastCRC : Value 0xF6 in 350us
Software: Value 0xF6 in 12482us

MODBUS 16-Bit CRC:
FastCRC: Value 0x7029 in 350us
Software: Value 0x7029 in 18123us

XMODEM 16-Bit CRC:
FastCRC: Value 0x98D9 in 348us
Software: Value 0x98D9 in 13678us

MCRF4XX 16-Bit CRC:
FastCRC: Value 0x4A29 in 351us
Software: Value 0x4A29 in 2397us

KERMIT 16-Bit CRC:
FastCRC: Value 0xB259 in 351us

Ethernet 32-Bit CRC:
FastCRC: Value 0x1271457F in 348us

Working FastCRC_example

Code:
//FastCRC
//Quick'n dirty Benchmark
//
//(c) Frank Boesing 2014

#include <util/crc16.h>
#include <FastCRC.h>

#define Ser Serial
#define BUFSIZE 16384


FastCRC8 CRC8;
FastCRC16 CRC16;
FastCRC32 CRC32;

uint8_t buf[BUFSIZE];


// Supporting functions for Software CRC

inline uint16_t softcrc(uint16_t seed, uint8_t *data, uint16_t datalen) {
    for (uint16_t i=0; i<datalen; i++) {
        seed = _crc16_update(seed,  data[i]);
    }
    return seed;
}

inline uint16_t softcrcIbutton(uint16_t seed, uint8_t *data, uint16_t datalen) {
    for (uint16_t i=0; i<datalen; i++) {
        seed = _crc_ibutton_update(seed,  data[i]);
    }
    return seed;
}

inline uint16_t softcrcCCIT(uint16_t seed, uint8_t *data, uint16_t datalen) {
    for (uint16_t i=0; i<datalen; i++) {
        seed = _crc_ccitt_update(seed,  data[i]);
    }
    return seed;
}

inline uint16_t softcrcXMODEM(uint16_t seed, uint8_t *data, uint16_t datalen) {
    for (uint16_t i=0; i<datalen; i++) {
        seed = _crc_xmodem_update(seed,  data[i]);
    }
    return seed;
}


void setup() {



  Ser.begin(115200);

}

void loop() {
  int time;
uint32_t crc;
  
  delay(1000);
    Ser.printf("\r\n\r\nCRC Benchmark\r\n");
  Ser.printf("Length: %u Bytes\r\n\r\n", sizeof(buf));

  //Fill array with data
  for (int i=0; i<BUFSIZE; i++) {
    buf[i] = (i+1) & 0xff;
  }

  Ser.printf("\r\nMaxim (iButton) 8-Bit CRC:\r\n");
  Ser.flush();

  time = micros();
  crc = CRC8.maxim(buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("FastCRC : Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();


  time = micros();
  crc = softcrcIbutton(0, buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("Software: Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();



  Ser.println("\r\nMODBUS 16-Bit CRC:");
  Ser.flush();

  time = micros();
  crc = CRC16.modbus(buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("FastCRC: Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();

  time = micros();
  crc = softcrc(0xffff, buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("Software: Value 0x%X in %uus\r\n", crc, time);




  Ser.println("\r\nXMODEM 16-Bit CRC:");
  Ser.flush();

  time = micros();
  crc = CRC16.xmodem(buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("FastCRC: Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();

  time = micros();
  crc = softcrcXMODEM(0, buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("Software: Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();


  Ser.println("\r\nMCRF4XX 16-Bit CRC:");
  Ser.flush();

  time = micros();
  crc = CRC16.mcrf4xx(buf,BUFSIZE);
  time = micros() - time;
  Ser.printf("FastCRC: Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();


  time = micros();
  crc = softcrcCCIT(0xffff, buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("Software: Value 0x%X in %uus\r\n", crc, time);
  Ser.flush();


  Ser.println("\r\nKERMIT 16-Bit CRC:");
  Ser.flush();

  time = micros();
  crc = CRC16.kermit(buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("FastCRC: Value 0x%X in %uus\r\n", crc, time);


  Ser.println("\r\nEthernet 32-Bit CRC:");
  Ser.flush();

  time = micros();
  crc = CRC32.crc32(buf, BUFSIZE);
  time = micros() - time;
  Ser.printf("FastCRC: Value 0x%X in %uus\r\n", crc, time);

  
}
 
FYI,
I ported the FastCRC library to mbed K64F (Freescale/NXP Cortex M4F @120MHz , floating point, think teensy++3.1). The CRC implementation is the same as the teensy 3, so there was no problem porting. To compare hardware, builtin (Arduino crc16.h), and table-driven CRCs, I mangled the __MK... conditionals in the library so the IDE was forced to build the table-driven implementation. I used the latest FastCRC from github. Here are results from the benchmark example
Code:
                 Teensy 3.2 @120MHz                                mbed K64F @120MHz
      hardware CRC	                                         hardware CRC
    Maxim (iButton) FastCRC: Value:0xF6, Time: 275 us.	       Maxim (iButton) FastCRC: Value:0xf6, Time: 275 us
    Maxim (iButton) builtin: Value:0xF6, Time: 9994 us.	       Maxim (iButton) builtin: Value:0xf6, Time: 7100 us
    MODBUS FastCRC: Value:0x7029, Time: 275 us.	               MODBUS FastCRC: Value:0x7029, Time: 275 us
    MODBUS builtin: Value:0x7029, Time: 9584 us.	       MODBUS builtin: Value:0x7029, Time: 7100 us
    XMODEM FastCRC: Value:0x98D9, Time: 275 us.	               XMODEM FastCRC: Value:0x98d9, Time: 275 us
    XMODEM builtin: Value:0x98D9, Time: 10542 us.	       XMODEM builtin: Value:0x98d9, Time: 8193 us
    MCRF4XX FastCRC: Value:0x4A29, Time: 275 us.	       MCRF4XX FastCRC: Value:0x4a29, Time: 275 us
    MCRF4XX builtin: Value:0x4A29, Time: 1783 us.	       MCRF4XX builtin: Value:0x4a29, Time: 1639 us
    KERMIT FastCRC: Value:0xB259, Time: 279 us.	               KERMIT FastCRC: Value:0xb259, Time: 275 us
    Ethernet FastCRC: Value:0x1271457F, Time: 275 us.	       Ethernet FastCRC: Value:0x1271457f, Time: 275 us
	
      table-driven CRC	                                         table-driven CRC
    Maxim (iButton) FastCRC: Value:0xF6, Time: 1329 us.	       Maxim (iButton) FastCRC: Value:0xf6, Time: 997 us
    Maxim (iButton) builtin: Value:0xF6, Time: 9994 us.	       Maxim (iButton) builtin: Value:0xf6, Time: 7101 us
    MODBUS FastCRC: Value:0x7029, Time: 2226 us.	       MODBUS FastCRC: Value:0x7029, Time: 1623 us
    MODBUS builtin: Value:0x7029, Time: 9584 us.	       MODBUS builtin: Value:0x7029, Time: 7101 us
    XMODEM FastCRC: Value:0x98D9, Time: 2102 us.	       XMODEM FastCRC: Value:0x98d9, Time: 1608 us
    XMODEM builtin: Value:0x98D9, Time: 10542 us.	       XMODEM builtin: Value:0x98d9, Time: 8193 us
    MCRF4XX FastCRC: Value:0x4A29, Time: 2185 us.	       MCRF4XX FastCRC: Value:0x4a29, Time: 1664 us
    MCRF4XX builtin: Value:0x4A29, Time: 1782 us.	       MCRF4XX builtin: Value:0x4a29, Time: 1639 us
    KERMIT FastCRC: Value:0xB259, Time: 2190 us.	       KERMIT FastCRC: Value:0xb259, Time: 1650 us
    Ethernet FastCRC: Value:0x38D32145, Time: 2090 us.	       Ethernet FastCRC: Value:0x38d32145, Time: 1702 us

The hardware CRC times are unsurprisingly identical. The builtin and table-driven times are a little faster on the K64F, maybe because of different build environment/settings (mbed uses ARM cc, -O3 -Ospeed).

Frank B note the Ethernet CRC values differ between the table-driven and hardware CRCs?? The validation example reports no problems with table vs hardware. From a standalone C test from other sources, I think 0x1271457f is correct.

EDIT: table-driven Ether CRC is 0x1271457f if CRC_BIGTABLES is 0
Ethernet FastCRC: Value:0x1271457F, Time: 1862 us.
 
Last edited:
Fixed.

Thank you very much for the bugreport ! :)

In addition it fixes an other (minor) issue in the 32-BIT CRC "software-bigtables" variant- it occupied 1KB too much flash because both tables were used :)
 
I hope this helps...

Byte order in CRC generate/check, and the CRC itself. If all done on the same MCU, not an issue but if not, a convention is MSB first like the IETF RFCs.
Hardware CRC in the ARMs is 32 bit wide I/O register. Pack bytes paying attention to big endian/little endian conventions. Trickier too if you use DMA for CRC generation or checking. If you do one byte at a time via the 32 bit data register in the arm, the math falters.
CRC polynomial... Some ARMs have just one fixed poly they use. Watch the byte order on that too. And some ARMs have a programmable polynomial. The Ethernet IEEE 802.3 CRC32 is a popular one and in some ARM hardware CRC it's the only option. The ISO CRC32 is ill defined, I found.

Initial value for CRC. Standards define it. Some are 0, some are all ones, etc. Generate/check of course must use the same initial value, polynomial and its byte order, and 32 bits of the right endian convention if using hardware.

I had fits getting the ARM hardware CRC32 fixed poly to match a software equivalent running on an x86 - two ends of a data link.
 
Last edited:
FYI,
I ported the FastCRC library to mbed K64F (Freescale/NXP Cortex M4F @120MHz , floating point, think teensy++3.1). The CRC implementation is the same as the teensy 3, so there was no problem porting. To compare hardware, builtin (Arduino crc16.h), and table-driven CRCs, I mangled the __MK... conditionals in the library so the IDE was forced to build the table-driven implementation.

can you make a pullrequest, pls ?
 
can you make a pullrequest, pls ?

Well, the mods weren't technically challenging, but they were lexically messy. I'm not familiar enough with github to know if you would want a separate branch or ?
And I just altered the code so it would work on mbed k64f, not conditionally. Changes involved Serial.print to printf, replace MK dependency, redo thumb assembler (actuallly I think MBED has __RBIT() and such predefined), fix symbols for SIM_SCGC6, and getting rid of all PROGMEM artifacts! Visit mbed repository

https://developer.mbed.org/users/manitou/code/FastCRC/

and the benchmark example is https://developer.mbed.org/users/manitou/code/fastCRCperf/

This was more proof of concept, and I don't sense there is a big mbed following as there is with teensy ... maybe just make note of the mbed repository. (Of course it would be nice if I knew if git was smart enough to push your fixes into my hacks. I manually applied your fixes today...)

Your FastCRC library will work as is when the teensy++3.1 K64F arrives, so the mbed hacks are irrelevant to teensy.
 
Last edited:
I had fits getting the ARM hardware CRC32 fixed poly to match a software equivalent running on an x86 - two ends of a data link.

Amen. Though I had no real need other than knowledge. I never did get a STM34 ARM hardware CRC to generate understandable CRCs. As you noted, it had a fixed (ethernet) polynomial and only 32-bit word access. Passing it "AAAA" I couldn't figure out any pattern to reverse/flip bits to arrive at the test vector result. (Any hints?)

EDIT: Breaking news !

I revisited the mbed F446RE (ARM cortex M4F @180mhz) with its simple-minded CRC. The trick was to reverse the bits of each 32-bit input.
Code:
        CRC->CR = 1;   //reset
        while(CRC->DR != ~0);  // wait for reset
        CRC->DR = __RBIT(0x41414141);   // AAAA ;
        result = ~__RBIT(CRC->DR);
The timing for the 16384 bytes was 228us (without the RBIT(), timing was 183us, which is the expected speedup of 180mhz vs 120mhz)

Yeh!

cycles per CRC
The STM32F446RET6 reference manual says that its CRC takes 4 CPU (AHB) cycles. I couldn't find such details in the teensy 3 reference manual, but doing the math from the FastCRC benchmarks, I conclude the teensy 3 CRC also takes 4 CPU cycles.
 
Last edited:
bit order rather than byte order??

The compiler I use has a pragma to declare variable or struct as big or little endian byte order. Then ARM-magic, hardware does the flips.
Same thing for __RBIT as I recall, at the bit level.

nice.
 
Last edited:
Added PROGMEM...

It would be great if somebody could test it with an AVR (mine are collecting dust.. too much trouble to reactivate them)

It may not be worth adding conditional compilation for each CRC type and its associated tables, but as the library is now (about 23K of tables), none of the AVR engines can compile the FastCRC library. A user can cut and paste out the needed pieces for a particular algorithm thanks to your building such a comprehensive library.

Suggestion: I don't think you want noInterrupts() in your benchmark example. For the AVR-based processors, you will block the millisecond tick interrupt and possibly lose milliseconds in your elapsed-time calculation! (on the Teensy 3*, micros() disables/enables interrupts)
 
Last edited:
It may not be worth adding conditional compilation for each CRC type and its associated tables, but as the library is now (about 23K of tables), none of the AVR engines can compile the FastCRC library. A user can cut and paste out the needed pieces for a particular algorithm thanks to your building such a comprehensive library.

Suggestion: I don't think you want noInterrupts() in your benchmark example. For the AVR-based processors, you will block the millisecond tick interrupt and possibly lose milliseconds in your elapsed-time calculation! I was surprised that noInterrupts() had no effect on teensy 3 sysTick timer interrupts ( I guess because it's not an NVIC maskable interrupt).

They can't compile ? Thanks for the info.. i try it..

#ifdef ARDUINO
#error asap: buy teensy
#endif
 
You're right.. printf is not good, and the main problem are the tables for crc32.
The compiler includes only the needed tables, so it should work with own examples for every single CRC.

-> (too) much stupid editing... :-(
but ok.. you're right, the examples really should be better.
 
They can't compile ? Thanks for the info.. i try it..

#ifdef ARDUINO
#error asap: buy teensy
#endif

Not just Arduino, benchmark example wouldn't compile for Teensy LC region `RAM' overflowed by 10500 bytes

If I reduce BUFSIZE to 4096, LC will compile and run. Changing BUFSIZE argues for reporting more than elapsed time, benchmark should report megabits/sec too.
 
Last edited:
Ok, that's because of the large array in the benchmark-example. It is 16 KB. reducing to 2 or 4 KB should work for the LC.

manitou: do have have an arduino ? could you please test a single crc ? perhaps one 8-, one 16- and a 32-bit.. the validation skec
th uses an 9-byte array so it should work to comment-out the unused CRCs
 
Last edited:
Suggestion: I don't think you want noInterrupts() in your benchmark example. For the AVR-based processors, you will block the millisecond tick interrupt and possibly lose milliseconds in your elapsed-time calculation! I was surprised that noInterrupts() had no effect on teensy 3 sysTick timer interrupts ( I guess because it's not an NVIC maskable interrupt).

On the ARMs, the interrupts are called when the interrupts are re-enabled. Are they lost on AVR ?
I don't want the interrupts because they lead to not-constant values (us)..
Is it ok to reduce the bufsize in the benchmark dramatically ? Perhaps from 16 KB to 512 bytes ?
 
Ok, that's because of the large array in the benchmark-example. It is 16 KB. reducing to 2 or 4 KB should work for the LC.

manitou: do have have an arduino ? could you please test a single crc ? perhaps one 8-, one 16- and a 32-bit.. the validation skec
th uses an 9-byte array so it should work to comment-out the unused CRCs

FYI,
here is validation example on Mega2560
Code:
CRC Validation
SMBUS is ok
Maxim is ok
CCITT is ok
MCRF4XX is NOT ok
MODBUS is NOT ok
KERMIT is NOT ok
XMODEM is NOT ok
X.25 is NOT ok

CRC32 is ok
CKSUM is NOT ok
 
Last edited:
On the ARMs, the interrupts are called when the interrupts are re-enabled. Are they lost on AVR ?
I don't want the interrupts because they lead to not-constant values (us)..
Is it ok to reduce the bufsize in the benchmark dramatically ? Perhaps from 16 KB to 512 bytes ?

Yes, AVR interrupts are lost if your calculation takes many milliseconds. I don't think you'll see much jitter in your timings with interrupts enabled. i've measured ISR overhead and it's only a few microseconds. see
https://github.com/manitou48/DUEZoo/blob/master/isrperf.txt

Reducing the BUFSIZE could reduce the "speed" reported (need metric of megabits/sec) as loop-management overhead has an increased effect. So use the biggest buffer that will fit ...
 
Last edited:
well, even though most are not validating, i ran the benchmark (disabled noInterrupts) on mega2560 and added speed (mbs) using 4K buffer

Code:
CRC Benchmark
Length: 4096 Bytes

Maxim (iButton) FastCRC: Value:0x18, Time: 3904 us 8.39 mbs
Maxim (iButton) builtin: Value:0x18, Time: 15320 us 2.14 mbs
MODBUS FastCRC: Value:0x47A, Time: 5084 us 6.45 mbs
MODBUS builtin: Value:0x47A, Time: 8304 us 3.95 mbs
XMODEM FastCRC: Value:0x4B2E, Time: 5084 us 6.45 mbs
XMODEM builtin: Value:0x4B2E, Time: 8832 us 3.71 mbs
MCRF4XX FastCRC: Value:0x492A, Time: 5084 us 6.45 mbs
MCRF4XX builtin: Value:0x492A, Time: 6752 us 4.85 mbs
KERMIT FastCRC: Value:0xB2DD, Time: 5084 us 6.45 mbs
Ethernet FastCRC: Value:0xAE7F4FCF, Time: 8820 us 3.72 mbs

For speed comparison where buffer size differs, here are results for teensy 3.1 @120mhz with speed (mbs) on 16K buffer
Code:
CRC Benchmark
Length: 16384 Bytes
Maxim (iButton) FastCRC: Value:0xF6, Time: 275 us 476.63 mbs
Maxim (iButton) builtin: Value:0xF6, Time: 9993 us 13.12 mbs
MODBUS FastCRC: Value:0x7029, Time: 275 us 476.63 mbs
MODBUS builtin: Value:0x7029, Time: 9584 us 13.68 mbs
XMODEM FastCRC: Value:0x98D9, Time: 275 us 476.63 mbs
XMODEM builtin: Value:0x98D9, Time: 10539 us 12.44 mbs
MCRF4XX FastCRC: Value:0x4A29, Time: 274 us 478.36 mbs
MCRF4XX builtin: Value:0x4A29, Time: 1782 us 73.55 mbs
KERMIT FastCRC: Value:0xB259, Time: 278 us 471.48 mbs
Ethernet FastCRC: Value:0x1271457F, Time: 279 us 469.79 mbs

and below see how lost millis produces remarkable speedup when using noInterrupts() on mega2560 ;) (great if you're in Sales & Marketing)
Code:
Length: 4096 Bytes

Maxim (iButton) FastCRC: Value:0x18, Time: 772 us 42.45 mbs
Maxim (iButton) builtin: Value:0x18, Time: 772 us 42.45 mbs
MODBUS FastCRC: Value:0x47A, Time: 924 us 35.46 mbs
MODBUS builtin: Value:0x47A, Time: 1024 us 32.00 mbs
XMODEM FastCRC: Value:0x4B2E, Time: 924 us 35.46 mbs
XMODEM builtin: Value:0x4B2E, Time: 516 us 63.50 mbs
MCRF4XX FastCRC: Value:0x492A, Time: 924 us 35.46 mbs
MCRF4XX builtin: Value:0x492A, Time: 1536 us 21.33 mbs
KERMIT FastCRC: Value:0xB2DD, Time: 924 us 35.46 mbs
Ethernet FastCRC: Value:0xAE7F4FCF, Time: 1532 us 21.39 mbs

“One accurate measurement is worth a thousand expert opinions”Adm Grace Murray Hopper ( Dec 9 1906 to Jan 1 1992)
 
Last edited:
Status
Not open for further replies.
Back
Top