I am trying to make an universally CRC algorithm that can be used for various lengths (e.g. 4, 5, 6, 8, 16, 32 bits).
I've manage to grasp the basics from Ross Williams site but when confronted with different implementation of various algorithms such as CRC-6/CDMA2000-A, on paper using the general algorithm and what my algorithm does it's the same thing, but not as it should be compared to a specific implementation of CRC-6.
Moreover I've compared my output to some sites such as this site and tried to adapt my code a little by how it shows the implementation on there, but I've come to the conclusion that, from my point of view, it's not working properly.
I'll post below my code and how an CRC-6 is constructed
General CRC
typedef struct
{
uint8 *CRC_Start_Address;
uint32 CRC_Message_Length_In_Bytes;
uint32 CRC_Polynomial;
uint32 CRC_Initial_Remainder;
uint32 CRC_Final_XOR_Val;
uint32 CRC_Reflect_Data;
uint32 CRC_Reflect_Remainder;
uint32 CRC_Width_Of_Poly;
uint32 CRC_Topbit; // = (1<<(CRC_Width_Of_Poly -1 )) ;
uint32 CRC_Mask;
} CRC_Custom_Poly_Type;
CRC_Custom_Poly_Type CRC;
uint32 CRC_CrcCustomPolyTest(uint32 StartAddr, uint32 Length, uint8 SeedValue, uint8 Polynomial)
{
CRC.CRC_Start_Address = (uint8 *)StartAddr;
CRC.CRC_Message_Length_In_Bytes = (uint32)Length;
CRC.CRC_Initial_Remainder = SeedValue;
CRC.CRC_Polynomial = Polynomial;
CRC.CRC_Reflect_Data = FALSE;
CRC.CRC_Reflect_Remainder = FALSE;
CRC.CRC_Final_XOR_Val = 0x0;
CRC.CRC_Width_Of_Poly = 6;
CRC.CRC_Topbit = 1U << (CRC.CRC_Width_Of_Poly - 1U);
CRC.CRC_Mask = (1U << CRC.CRC_Width_Of_Poly) - 1U;
uint8 addrIndex;
uint32 byteIndex;
uint8 copyByteIndex;
if (CRC.CRC_Reflect_Data == TRUE)
{
CRC.CRC_Polynomial = reflect(CRC.CRC_Polynomial, CRC.CRC_Width_Of_Poly);
CRC.CRC_Initial_Remainder = reflect(CRC.CRC_Initial_Remainder, CRC.CRC_Width_Of_Poly);
CRC.CRC_Final_XOR_Val = reflect(CRC.CRC_Final_XOR_Val, CRC.CRC_Width_Of_Poly);
}
for (byteIndex = 0U; byteIndex < CRC.CRC_Message_Length_In_Bytes; byteIndex++)
{
// reflection
copyByteIndex = CRC.CRC_Start_Address[byteIndex];
if (CRC.CRC_Reflect_Data == TRUE)
{
CRC.CRC_Initial_Remainder ^= ((CRC.CRC_Start_Address[byteIndex]));
for (addrIndex = 0; addrIndex < 8; ++addrIndex)
{
uint32 isSetAndReflection;
if (CRC.CRC_Width_Of_Poly < 8)
{
isSetAndReflection = (CRC.CRC_Initial_Remainder & 1U) ^ (copyByteIndex & 0x01);
copyByteIndex >>= 1U;
}
else
{
isSetAndReflection = CRC.CRC_Initial_Remainder & 1U;
}
CRC.CRC_Initial_Remainder >>= 1U;
if (isSetAndReflection)
{
CRC.CRC_Initial_Remainder ^= CRC.CRC_Polynomial;
}
CRC.CRC_Initial_Remainder = CRC.CRC_Initial_Remainder & CRC.CRC_Mask;
}
}
// no reflection
else
{
if (CRC.CRC_Width_Of_Poly > 8U)
{
CRC.CRC_Initial_Remainder ^= (uint32)(CRC.CRC_Start_Address[byteIndex]) >> (CRC.CRC_Width_Of_Poly - 8U);
}
else
{
CRC.CRC_Initial_Remainder ^= ((CRC.CRC_Start_Address[byteIndex]));
}
for (addrIndex = 0; addrIndex < 8; ++addrIndex)
{
uint32 isSetNoReflection;
if (CRC.CRC_Width_Of_Poly < 8U)
{
isSetNoReflection = ((CRC.CRC_Initial_Remainder & CRC.CRC_Topbit) );//^ ((copyByteIndex & 0x80) >> (8U - CRC.CRC_Width_Of_Poly)));
//copyByteIndex <<= 1U;
}
else if (CRC.CRC_Width_Of_Poly == 8U)
{
isSetNoReflection = CRC.CRC_Initial_Remainder & 0x80;
}
else // if (CRC.CRC_Width_Of_Poly > 8U)
{
isSetNoReflection = CRC.CRC_Initial_Remainder & CRC.CRC_Mask;
}
CRC.CRC_Initial_Remainder <<= 1U;
if (isSetNoReflection)
{
CRC.CRC_Initial_Remainder ^= CRC.CRC_Polynomial;
}
CRC.CRC_Initial_Remainder &= CRC.CRC_Mask;
}
}
}
CRC.CRC_Initial_Remainder = CRC.CRC_Initial_Remainder ^ CRC.CRC_Final_XOR_Val;
return CRC.CRC_Initial_Remainder;
}
uint32 reflect(uint32 StartAddr, uint32 Length)
{
uint32 reflection = 0x00000000;
uint8 bit;
/*
* Reflect the data about the center bit.
*/
for (bit = 0; bit < Length; ++bit)
{
/*
* If the LSB bit is set, set the reflection of it.
*/
if (StartAddr & 0x01)
{
reflection |= (1U << ((Length - 1U) - bit));
}
StartAddr = (StartAddr >> 1U);
}
return (reflection);
} /* reflect() */
Input: 0x120000
Output: 0x08
Output to be expected: 0x30
CRC-6
/* Apply the basic 6-Bit CRC formula for the 2 bits left(slower): */
/* - Polynomial generator = X^6+X^5+X^2+X+1 */
/* - Input bit = B */
/* - New ShiftReg[0] = ShiftReg[5] XOR B */
/* - New ShiftReg[1] = (ShiftReg[5] XOR B) XOR ShiftReg[0] */
/* - New ShiftReg[2] = (ShiftReg[5] XOR B) XOR ShiftReg[1] */
/* - New ShiftReg[3] = ShiftReg[2] */
/* - New ShiftReg[4] = ShiftReg[3] */
/* - New ShiftReg[5] = (ShiftReg[5] XOR B) XOR ShiftReg[4] */
Input: 0x120000
Output: 0x30
All I want to find out is:
If is something wrong with my algorithm which does not correspond to the basic concept of CRC?
Is there any possible way to generalize the algorithm in order to work on different widths ? if not why, even it's a different way form the hardware perspective?
Related
I have written a small function to calculate even parity for each 8-bit block in a 64-bit word. The function is producing incorrect results.
The following is the output for Ukey = 0x666F6F6261723132
Incorrect Output:
01100110
01101111
01101111
01100010
01100001
01110010
00110001
00110010
Correct Output:
Correct Even Parity:
01100110
01101111
01101111
01100011
01100000
01110010
00110000
00110011
KEYBITSLEN is defined as 64
BYTELEN is defined as 8
void KeyParity (uint64_t *Ukey)
{
int ParityBit;
int i, j;
ParityBit = 0;
for (i = 0; i < KEYBITSLEN; i++)
{
for (j = 0; j < BYTELEN; j++)
{
if(*(Ukey+i) & (0x01 << j))
ParityBit = !ParityBit;
}
if (i % 8 == 7)
{
*(Ukey+i) = ParityBit;
ParityBit = 0;
}
}
}
This line looks suspicious:
if(*(Ukey+i) & (0x01 << j))
So does this line:
*(Ukey+i) = ParityBit;
When i != 0, UKey+i is pointing to an entirely different 64-bit value from what Ukey points to in undefined memory space. Unless Ukey is pointing to an element of an array, this is undefined behavior.
Maybe this is closer to what you really want:
uint8_t KeyParity(uint64_t UKey)
{
uint8_t result = 0;
bool odd = false;
for (unsigned int i = 0; i < 64; i++)
{
if ((1ULL << i) & UKey)
{
odd = !odd;
}
if ((i % 8) == 7)
{
uint8_t parity = odd ? 1 : 0;
parity = parity << (i/8);
result = result | parity;
odd = false;
}
}
return result;
}
In the title you ask for "8-bit parity of a 64-bit word", but then in the body you say "even parity of each 8-bit block in a 64-bit word". These are two totally different things. Worse, these are both 8-bit values, but your "desired output" is 64 bits for a 64 bit input (which makes no sense).
You could try either:
// compute the 8-bit parity of a 64 bit number
uint8_t EightBitParity(uint64_t val) {
val ^= val >> 32;
val ^= val >> 16;
val ^= val >> 8;
return val & 0xff;
}
// compute parity of each 8-bit byte of a 64-bit number;
uint8_t ParityOfBytes(uint64_t val) {
val ^= val >> 4;
val ^= val >> 2;
val ^= val >> 1;
val &= 0x0101010101010101;
val |= val >> 28;
val |= val >> 14;
val |= val >> 7;
return val & 0xff;
}
I was looking around in the zephyr implementations and found this method for computing a crc16 checksum:
u16_t crc16(const u8_t *src, size_t len, u16_t polynomial,
u16_t initial_value, bool pad)
{
u16_t crc = initial_value;
size_t padding = pad ? sizeof(crc) : 0;
size_t i, b;
/* src length + padding (if required) */
for (i = 0; i < len + padding; i++) {
for (b = 0; b < 8; b++) {
u16_t divide = crc & 0x8000UL;
crc = (crc << 1U);
/* choose input bytes or implicit trailing zeros */
if (i < len) {
crc |= !!(src[i] & (0x80U >> b));
}
if (divide != 0U) {
crc = crc ^ polynomial;
}
}
}
return crc;
}
And I tripped over this line here:
crc |= !!(src[i] & (0x80U >> b));
I do not understand why they are using a boolean operator (!!) in this line. From my understanding this is what it does:
It basically does an implicit "casting" where it considers its operand on the right to be a boolean and negates it twice, which does not do anything besides making the output a 0 or a 1 depending on if the expression (src[i] & (0x80U >> b)) was bigger then 0 to start with.
Is this correct? Why are they using the operator in this way?
It is inserting bit 7-b from src[i] into the low bit of crc. If that bit is a 1, which will be somewhere in the result of the &, the !! turns it into a 1 in the low bit, which is then or'ed into crc.
This is truly painful to look at. A better and cleaner way to do it is crc |= (src[i] >> b) & 1;, where b counts down instead of up. E.g. int b = 8; do { b--; ... } while (b);. Better still would be to just exclusive-or the byte after the loop, which does the same thing:
/* src length + padding (if required) */
for (i = 0; i < len + padding; i++) {
for (b = 0; b < 8; b++)
crc = crc & 0x8000 ? (crc << 1) ^ polynomial : crc << 1;
if (i < len)
crc ^= src[i];
}
An optimizing compiler will unroll the b loop.
I am writing a routine in C, targeted for an embedded platform.In the routine I need to perform bitwise XOR and SHIFT RIGHT operations on 128-bit values. The target arch doesn't have SSE2, hence no native 128-bit operations supported. I came across this answer which simulates the SHIFT operations in software.
My question is, are there better ways of doing this, I mean with better data structure to represent 128-bit values and optimal way to simulate the SHIFT and XOR operations than using recursion(as done in the answer in the link). I wish to minimise usage of the limited stack memory.
You can use a structure to store 128 bit data as follows
typedef struct
{
uint32_t a;
uint32_t b;
uint32_t c;
uint32_t d;
} Type_128bit;
Then you can write a left shift function as follows
int leftshift(Type_128bit in, Type_128bit out, int value)
{
int val;
if (value >= 128)
{
return (-1); // error condition
}
else if (value < 32)
{
out->a = (in->a << value) | (in->b >> value);
out->b = (in->b << value) | (in->c >> value);
out->c = (in->c << value) | (in->d >> value);
out->d = in->d << value;
}
else if (value < 64)
{
val = value - 32;
out->a = (in->b << val) | (in->c >> val);
out->b = (in->c << val) | (in->d >> val);
out->c = (in->d << val);
out->d = 0x00;
}
else if (value < 96)
{
val = value - 64;
out->a = (in->c << val) | (in->d >> val);
out->b = (in->d << val);
out->c = 0x00;
out->d = 0x00;
}
else // value < 128
{
val = value - 96;
out->a = (in->d << val);
out->b = 0x00;
out->c = 0x00;
out->d = 0x00;
}
return (0); //success
}
This will avoid the recursion of the mentioned solution and give better runtime. But code size will increase and you need to carefully test the code.
uint32_t *shiftL(uint32_t *val, const size_t size, const size_t nbits) // <= 32
{
uint32_t mask = (1 << nbits) - 1;
mask <<= 32 - nbits;
for(size_t cword = size; cword - 1 ; cword --)
{
uint32_t temp = (val[cword - 2] & mask) >> nbits
val[cword - 1] <<= nbits;
val |= temp;
}
val[0] <<= nbits;
return val;
}
I have the following CRC function:
#define CRC8INIT 0x00
#define CRC8POLY 0x18 //0X18 = X^8+X^5+X^4+X^0
// ----------------------------------------------------------------------------
uint8_t crc8 (uint8_t *data, uint16_t number_of_bytes_in_data)
{
uint8_t crc;
uint16_t loop_count;
uint8_t bit_counter;
uint8_t b;
uint8_t feedback_bit;
crc = CRC8INIT;
for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++) {
b = data[loop_count];
bit_counter = 8;
do {
feedback_bit = (crc ^ b) & 0x01;
if (feedback_bit == 0x01) {
crc = crc ^ CRC8POLY;
}
crc = (crc >> 1) & 0x7F;
if (feedback_bit == 0x01) {
crc = crc | 0x80;
}
b = b >> 1;
bit_counter--;
} while (bit_counter > 0);
}
return crc;
}
How does 0x18 relate to the polynomial X^8+X^5+X^4+X^0?
X^8+X^5+X^4+X^0 = 100110001
0x18 = 00011000
What if I define CRC8POLY as 0xEA instead (I have seen this), what polynomial would that represent?
How does 0x18 relate to the polynomial X^8+X^5+X^4+X^0?
Since the code is a right shifting CRC, the "most significant bit" of each byte is bit 0 instead of bit 7. The poly needs to be reversed from 100110001 to 100011001, which is 0x119, after the right shift, bit 0 of 0x119 is shifted off, so 0x118 can be used instead. The code uses a second if statement to or in (0x100) >> 1 == 0x80 if the feedback bit is 1. As an alternative, since feedback_bit is 0 or 1, then (0-feeback_bit) can be used as a mask (assuming two's complement math) for the poly instead of using an if statement.
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
#define CRC8INIT 0x00
#define CRC8POLY 0x8c // 0x119 >> 1
uint8_t crc8 (uint8_t *data, uint16_t number_of_bytes_in_data)
{
uint8_t crc;
uint16_t loop_count;
uint8_t bit_counter;
uint8_t b;
uint8_t feedback_bit;
crc = CRC8INIT;
for (loop_count = 0; loop_count != number_of_bytes_in_data; loop_count++) {
b = data[loop_count];
bit_counter = 8;
do {
feedback_bit = (crc ^ b) & 0x01;
crc = (crc >> 1) ^ ((0-feedback_bit) & CRC8POLY);
b = b >> 1;
bit_counter--;
} while (bit_counter > 0);
}
return crc;
}
That CRC code is written rather oddly, where the polynomial is applied in two different places, breaking up the bits. That is, at crc = crc ^ CRCPOLY and conditionally crc = crc | 0x80. It would normally be written more like this:
unsigned crc8(unsigned char const *dat, size_t len) {
unsigned crc = 0;
for (size_t i = 0; i < len; i++) {
crc ^= dat[i];
for (int k = 0; k < 8; k++)
crc = crc & 1 ? (crc >> 1) ^ 0x8c : crc >> 1;
}
return crc;
}
where 0x8c is that polynomial reversed, without the x8 term.
Referring to Wiki article on CRC , it's crc8 realization as used in Dallas 1-wire chips. Note, that polinomial can be represented in Normal, Reversed, Reciprocal and Reversed reciprocal representations (see also Polynomial representations). Seems, that it is Reversed reciprocal representation with highest bit omitted.
I found a file to check crc of an incoming application via some interface and the program is as follows:
#define CRC16POLY 0x1021
#define PKTLEN_128 128
typedef struct Crc16Data {
uint16_t currentCrc; //!< Current CRC value.
} crc16_data_t;
void crc16_init(crc16_data_t * crc16Config)
{
// initialize running crc and byte count
crc16Config->currentCrc = 0;
}
void crc16_update(crc16_data_t * crc16Config, const uint8_t * src, uint32_t lengthInBytes)
{
uint32_t crc = crc16Config->currentCrc;
uint32_t j;
for (j=0; j < lengthInBytes; ++j)
{
uint32_t i;
uint32_t byte = src[j];
crc ^= byte << 8;
for (i = 0; i < 8; ++i)
{
uint32_t temp = crc << 1;
if (crc & 0x8000)
{
temp ^= 0x1021;
}
crc = temp;
}
}
crc16Config->currentCrc = crc;
}
void crc16_finalize(crc16_data_t * crc16Config, uint16_t * hash)
{
*hash = crc16Config->currentCrc;
}
I understood that it is simple crc software logic that doesnot involve any hardware generated crc mechanism to calculate crc of an incoming application and it is just counting the bytes of the application and adding them and placing them right? Can anyone explain what is happening inside void crc16_update(crc16_data_t * crc16Config, const uint8_t * src, uint32_t lengthInBytes) function?
And in one of the files crc16update(....) function is called as follows:
crc16_update(&crcInfo,buffer,PKTLEN_128);
where in another functions crcInfo,buffer information is found from
static void read_bytes(uint8_t * buffer, uint32_t byteCount)
{
uint32_t currentBytesRead = 0;
while(currentBytesRead != byteCount)
{
if (readOffset != writeOffset)
{
buffer[currentBytesRead++] = callback_buffer[readOffset++];
readOffset &= XMODEM_BUFLEN - 1;
}
}
}
static int read_packet(uint8_t *buffer, uint8_t idx)
{
uint8_t seq[2],crc1,crc2;
uint16_t crc16, verify16;
crc16_data_t crcInfo;
read_bytes(seq,2);
read_bytes(buffer,PKTLEN_128);
crc16_init(&crcInfo);
crc16_update(&crcInfo,buffer,PKTLEN_128);
crc16_finalize(&crcInfo,&verify16);
read_bytes(&crc1,1);
read_bytes(&crc2,1);
crc16 = ((uint16_t)crc1 << 8)|crc2;
if ((crc16 != verify16) || (seq[0] != idx) || (seq[1] != (uint8_t) ((~(uint32_t)idx)&0xff)))
return(-1);
return(0);
}
What is happening inside the function void crc16_update(crc16_data_t * crc16Config, const uint8_t * src, uint32_t lengthInBytes) ? Thanks in advance.
This code:
crc ^= byte << 8;
for (i = 0; i < 8; ++i)
{
uint32_t temp = crc << 1;
if (crc & 0x8000)
{
temp ^= 0x1021;
}
crc = temp;
}
updates the CRC with the byte. It simulates running a linear feedback shift register, whose state is the value of crc. That could can be written more compactly possibly making it easier to see what's going on:
crc ^= byte << 8;
for (int i = 0; i < 8; i++)
crc = crc & 0x8000 ? (crc << 1) ^ 0x1021 : crc << 1;
The high bit of crc determines whether or not to exclusive-or the polynomial 0x1021 with the register, after the register is shifted up one bit, with that high bit dropping off the end.
To learn more about how this implementation is arrived at, you should read Ross William's CRC tutorial.