I've read the arduino EEPROM_crc tutorial but it doesn't really explain much. Is there someone who can better explain it or give some possible leads to better information.
/***
Written by Christopher Andrews.
CRC algorithm generated by pycrc, MIT licence ( https://github.com/tpircher/pycrc ).
A CRC is a simple way of checking whether data has changed or become corrupted.
This example calculates a CRC value directly on the EEPROM values.
The purpose of this example is to highlight how the EEPROM object can be used just like an array.
***/
#include <Arduino.h>
#include <EEPROM.h>
void setup() {
//Start serial
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
//Print length of data to run CRC on.
Serial.print("EEPROM length: ");
Serial.println(EEPROM.length());
//Print the result of calling eeprom_crc()
Serial.print("CRC32 of EEPROM data: 0x");
Serial.println(eeprom_crc(), HEX);
Serial.print("\n\nDone!");
}
void loop() {
/* Empty loop */
}
unsigned long eeprom_crc(void) {
const unsigned long crc_table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
unsigned long crc = ~0L;
for (int index = 0 ; index < EEPROM.length() ; ++index) {
crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);
crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
crc = ~crc;
}
return crc;
}
Perhaps this will help. I just put a simple wrapper around the native C++ library function. This generates a 16 bit CRC on an arbitrary length array of bytes. It would be extremely easy to modify for EEPROM use.
#include <util/crc16.h>
uint16_t make_crc(uint8_t* sourceArray, uint8_t arraySize)
{
uint16_t crc = 0;
for (uint8_t i = 0; i < arraySize; i++)
{
crc = _crc16_update(crc, sourceArray[i]);
}
return crc;
}
Blade2021:
I've read the arduino EEPROM_crc tutorial but it doesn't really explain much. Is there someone who can better explain it or give some possible leads to better information.
Which part of generating a CRC are you wanting to be explained in more detail, you have not said ?
"A CRC is a simple way of checking whether data has changed or become corrupted. This example calculates a CRC value directly on the EEPROM values. This CRC is like a signature and any change in the calculated CRC means a change in the stored data."
A CRC in this case tells you if all the bytes included have the correct data and no bytes have been transposed(swapped). It should also tell you if there are any bits transposed. Any CRC will tell you if bytes have been added or deleted. they cannot tell you what was deleted or added, or where bytes/bits have been transposed.
Most CRC checking will result in 0 if the CRC bytes are included in the checking, so a compare is not necessary. IF not zero, then an error has occurred. Again, it will not tell you where.
The function is similar to "mod" checking your bank account number, or credit card number.
srnet:
Which part of generating a CRC are you wanting to be explained in more detail, you have not said ?
"A CRC is a simple way of checking whether data has changed or become corrupted. This example calculates a CRC value directly on the EEPROM values. This CRC is like a signature and any change in the calculated CRC means a change in the stored data."
I see the result it gives but I don't see how the result can be understood. Its just a random bunch of numbers that have no way of being checked to see if it falls within a set range.
What would a CRC result with if the bytes didn't receive the correct data? What would it output if I did have a corrupted block in my memory? I don't know how to compare the result of the CRC.
Here is what I use to load my EEPROM.
//Load EEPROM Memory
for (byte k; k < sysLength; k++) {
//Times the value of k by 2 to get the first address for each variable.
byte memAddress = k * 2;
int memBlockOne = EEPROM.read(memAddress);
//times the value from the EEPROM * 10 to get desired result for this sketch.
memBlockOne = memBlockOne * 10;
//See if the value falls within the limits of the variable.
if((memBlockOne > 2550) || (memBlockOne < 0)){
Serial.print("ERROR | Corrupted memory LOC:");
Serial.print(memAddress);
Serial.print(" Result:");
Serial.println(memBlockOne);
lcd.setCursor(0,0);
lcd.print("MEMCORE:");
lcd.print(memAddress);
break;
}
//Increment the address by one to get second value.
memAddress++;
int memBlockTwo = EEPROM.read(memAddress);
//Do the same as memBlockOne
memBlockTwomp = memBlockTwo * 10;
if((memBlockOne > 2550) || (memBlockOne < 0)){
Serial.print("ERROR | Corrupted memory LOC:");
Serial.print(memAddress);
Serial.print(" Result:");
Serial.println(memBlockOne);
lcd.setCursor(0,0);
lcd.print("MEMCORE:");
lcd.print(memAddress);
break;
}
//Load the value into the system array for use by the sketch.
sysArray[k] = memBlockTwo + memBlockOne;
Serial.print("EEPROM[");
Serial.print(k);
Serial.print("]: ");
Serial.println(sysArray[k]);
//Small delay to keep from overprocessing
delay(10);
}
Its not the cleanest but its worked for me so far. I load from two addresses then combine the values into one variable for my sketch. This gives me better control while remaining within the limit of 5100 ((255*10)*2)
As shown in the code I check the value before implementing it into the array but this system won't be able to check if the memory is corrupted or not. My values will be changing within the range of 0 - 255 (min, max of EEPROM) so a corrupted memory block will just give a random result when it is read, Correct?
In a transmission system the transmitter sends its computed CRC with the data. The receiver recomputes the CRC over the received data (exclusive of the received CRC). It then compares its computed CRC to the received CRC. If they don't match, there was a transmission error.
When used for an EPROM-type application, the CRC is computed and stored with the data. When the data is read back it is recomputed and compared to the CRC read from the memory.
gfvalvo:
In a transmission system the transmitter sends its computed CRC with the data. The receiver recomputes the CRC over the received data (exclusive of the received CRC). It then compares its computed CRC to the received CRC. If they don't match, there was a transmission error.
When used for an EPROM-type application, the CRC is computed and stored with the data. When the data is read back it is recomputed and compared to the CRC read from the memory.
Ok, So how do you compare the crc from the stored data to the crc from the read data? I guess what i'm asking for is there a function, variable, anything that represents the crc from the data that was written?
I can form a function to write the value to separate locations inside the eeprom and then compare the two CRC's. Would this be a pratical way of doing it? Or am I overlooking something?
unsigned long eeprom_crc(void) {
const unsigned long crc_table[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};
unsigned long crc = ~0L;
testlength = EEPROM.length()/2; //<---- Divide the test length by half.
for (int index = 0 ; index < testlength ; ++index) {
crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4);
crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4);
crc = ~crc;
}
return crc;
}
Blade2021:
Ok, So how do you compare the crc from the stored data to the crc from the read data? I guess what i'm asking for is there a function, variable, anything that represents the crc from the data that was written?
The "==" operator.
If you look at my code above, you will see that it returns a uint16_t type.
If you look at my code above, you will see that it returns a uint16_t type.
Two questions. One, would the EEPROM have to be loaded into an array then passed to the function for your function to work?
Second, What would the results be compared to? I get the == operator would be used to compare them but compare them to what? aka if(result == __________)
Blade2021:
Two questions. One, would the EEPROM have to be loaded into an array then passed to the function for your function to work?
Second, What would the results be compared to? I get the == operator would be used to compare them but compare them to what? aka if(result == __________)
That, or preferably modify the function to read/write EEPROM directly.
You compute a CRC and store it with the data. Then you retrieve the data, compute the CRC and compare it with the stored CRC value. Understand?
aarg:
It's possible to include the CRC in the CRC value but let's not go there.
Just reserve two locations in EEPROM for the CRC and compute the CRC on the remaining locations.
whew! I was kinda hoping you would say something similar to that lol. I feel like that was a bit harder to grasp then it should have been but at least its another step taken.
Thank you, Very much appreciated for your patience with on one of my "off" days
Matt
Edit: Fixed issue with function. Changed index (i) from uint8_t to int
uint16_t make_crc()
{
uint16_t crc = 0;
for (int i = 0; i < EEPROM.length(); i++)
{
crc = _crc16_update(crc, EEPROM.read(i));
}
return crc;
}