Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use of CRC instruction (lack of) #1

Open
henkmuller opened this issue Aug 25, 2011 · 1 comment
Open

Use of CRC instruction (lack of) #1

henkmuller opened this issue Aug 25, 2011 · 1 comment

Comments

@henkmuller
Copy link
Member

I am puzzled that the CAN stack uses a soft implementation of the CRC, rather than the CRC instruction - which should save a considerable amount of time. I was going to try this in a forked repo, but the current CAN implementation does not have any self-testing harness so I have held off for a bit.

Just to capture my thoughts:

The polynomial and bitstrings have to be reversed, after that it is plain sailing (some code attached that computes a crc over a 26 bit packet that includes 15-bit CRC and shows that a soft and hard CRC end up with the same '0000' indicating that the packet is correct)

On a normal packet:

  • You use the first 9 bits of the ID to initialise the CRC (reverse order).
  • You then fold in the 8 bits comprising two bits of the ID, the IDE, RTR, and r0 bits, and three bits of the DLC
  • You then fold in every time you have received 7 bits of a byte.
  • You then fold in every time you have received 7 bits of the CRC.
  • You then fold in every time you have received the final 8 bits of the CRC, and bob is your uncle.

On an extended packet:

  • You use the ID, SSR, IDE, and the first 16 bits of identifier B to initialise the CRC (reverse order).
  • You then fold in the 8 bits comprising two bits of the ID, RTR, r0, and r1 bits, and three bits of the DLC
    (at this point you are in sync with the normal packet)

Code::

include <stdio.h>

include <xs1.h>

include <xclib.h>

int crc15(int nxtBit, unsigned int crc_rg) {
#pragma xta label "excludeCrc"
int crc_nxt = (nxtBit ^ (crc_rg >> 14)) & 0x1;
crc_rg = crc_rg << 1;
if (crc_nxt) {
crc_rg = crc_rg ^ 0x4599;
}
return crc_rg;
}

char bitstring[] = {
1,0,0, 1,1,0,1,0,0,1,0,
1,1,0,1,1,0,0,1,1,0,1,1,0,0,1
};

int main(void) {
unsigned int cc = 0;
int bits;
int poly = 0x4cd1;
for(int i = 0; i < 26; i++) {
cc = crc15(bitstring[i], cc);
}
printf("%04x\n", cc&0x7fff);
cc = 0;
bits = 0;
for(int i = 0; i < 2; i++) {
bits = bits << 1 | bitstring[i];
}
cc = bitrev(bits);
for(int j = 0; j < 3; j++) {
bits = 0;
for(int i = 2; i < 10; i++) {
bits = bits << 1 | bitstring[i+j*8];
}
crc8shr(cc, bitrev(bits)>>24, poly);
}
crc32(cc, 0, poly);
printf("%04x\n", bitrev(cc)>>17&0x7fff);
}

@DavidNorman
Copy link
Contributor

Thanks. I'll look into it when I get back. CANs problem paths do not have crc in them (maybe one does, but not all). What we need to make CAN 1MHz friendly is better control of switch statements and a way of passing constants to inlined functions.

David Norman
Bristol

On 25 Aug 2011, at 13:16, "henkmuller" [email protected] wrote:

I am puzzled that the CAN stack uses a soft implementation of the CRC, rather than the CRC instruction - which should save a considerable amount of time. I was going to try this in a forked repo, but the current CAN implementation does not have any self-testing harness so I have held off for a bit.

Just to capture my thoughts:

The polynomial and bitstrings have to be reversed, after that it is plain sailing (some code attached that computes a crc over a 26 bit packet that includes 15-bit CRC and shows that a soft and hard CRC end up with the same '0000' indicating that the packet is correct)

On a normal packet:
You use the first 9 bits of the ID to initialise the CRC (reverse order).
You then fold in the 8 bits comprising two bits of the ID, the IDE, RTR, and r0 bits, and three bits of the DLC
You then fold in every time you have received 7 bits of a byte.
You then fold in every time you have received 7 bits of the CRC.
You then fold in every time you have received the final 8 bits of the CRC, and bob is your uncle.

On an extended packet:
You use the ID, SSR, IDE, and the first 16 bits of identifier B to initialise the CRC (reverse order).
You then fold in the 8 bits comprising two bits of the ID, RTR, r0, and r1 bits, and three bits of the DLC
(at this point you are in sync with the normal packet)

#include <stdio.h>
#include <xs1.h>
#include <xclib.h>

int crc15(int nxtBit, unsigned int crc_rg) {
#pragma xta label "excludeCrc"
int crc_nxt = (nxtBit ^ (crc_rg >> 14)) & 0x1;
crc_rg = crc_rg << 1;
if (crc_nxt) {
crc_rg = crc_rg ^ 0x4599;
}
return crc_rg;
}

char bitstring[] = {
1,0,0, 1,1,0,1,0,0,1,0,
1,1,0,1,1,0,0,1,1,0,1,1,0,0,1
};

int main(void) {
unsigned int cc = 0;
int bits;
int poly = 0x4cd1;
for(int i = 0; i < 26; i++) {
cc = crc15(bitstring[i], cc);
}
printf("%04x\n", cc&0x7fff);
cc = 0;
bits = 0;
for(int i = 0; i < 2; i++) {
bits = bits << 1 | bitstring[i];
}
cc = bitrev(bits);
for(int j = 0; j < 3; j++) {
bits = 0;
for(int i = 2; i < 10; i++) {
bits = bits << 1 | bitstring[i+j*8];
}
crc8shr(cc, bitrev(bits)>>24, poly);
}
crc32(cc, 0, poly);
printf("%04x\n", bitrev(cc)>>17&0x7fff);
}

Reply to this email directly or view it on GitHub:
#1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants