Hallo,
ich wundere mich gerade darüber, ob es einen Unterschied macht, ob ich
eine CRC-32 (Ethernet) Prüfsumme Byte für Byte berechne oder Wort für
Wort (uint32_t).
Java bietet mit der Klasse CRC32 die Funktion
1
update(byte[] b)
der ich das Byte-Array übergeben kann, das ich z.B. aus einer Datei
einlese.
Das Array übertrage ich nun an meinen µC und will sicherstellen, dass es
auch exakt so angekommen ist. Dazu bietet der STM32 Cortex-M3 eine
Hardwareeinheit. Die Library von STM hat auch schon eine Funktion
vorbereitet, die da heißt:
Im STM32-Manual heißt es: "CRC computation is done on the whole 32-bit
data word, and not byte per byte"
Besteht da prinzipiell ein Unterschied im Ergebnis, wenn ich das
übertragene Byte-Array einfach in ein uint32_t-Array caste und dann mit
der Library-Funktion rechnen lasse? Muss ich evtl. die Byte-Order
vertauschen? Was passiert, wenn ich die Funktion (bzw das
CRC-Hardware-Datenregister) einfach nur mit Bytes füttere und den Rest
mit Nullen auffülle?
Falls keiner spontan eine Antwort weiß, werde ich das einfach mal testen
(oder mir doch zu Gemüte führen, wie CRC eigentlich funktioniert). Wäre
aber klasse, wenn jemand spontan die Antwort wüsste.
Viele Grüße, Oliver.
Ok, ich habe nun weitergesucht und hier ist mein aktueller Stand.
Um eine CRC32 in Software auf dem µC zu berechnen, die äquivalent zur
Javas CRC32 ist, verwende ich nun folgenden Code:
1
/*
2
* Software CRC32
3
*
4
* This function calculates the CRC32 over a given byte buffer the same way as
5
* Javas CRC32 class does. Use this, if you use the Java CRC32 function.
6
*
7
* It uses a 256 lookup table, so its reasonable fast, but big in code.
crc_model.cm_init=0xFFFFFFFF;// CRC initialized to 1's
4
crc_model.cm_refin=FALSE;// CRC calculated MSB first
5
crc_model.cm_refot=FALSE;// Final result is not bit-reversed
6
crc_model.cm_xorot=0x00000000;// Final result XOR'ed with
Man sieht schon die Unterschiede zur Java-CRC. Komischerweise ist das
auch nirgends dokumentiert (habe zumindest keine Quelle gefunden), weiß
auch nicht, was sich STM dabei denkt. Wie soll man denn CRCs überprüfen,
wenn man nicht mal die Berechnungsgrundlage kennt?
Der Autor hat außerdem, mit Hilfe des "PAINLESS GUIDE TO CRC ERROR
DETECTION ALGORITHMS", eine Implementierung in C geschrieben. Der Code
ist unter obigem Link zu lesen, aber wer weiß wie lange das noch
verfügbar ist, wo STM doch momentan ständig seine Websites
verschlimmbesstert. Daher stelle ich es mal hier rein:
Wenn ich mal zu viel Zeit habe, schreibe ich mal eine Java-Methode
dafür. Da die Performance der Checksummen bei meinem Projekt allerdings
nicht wirklich wichtig ist, habe ich das mal hinten an gestellt.
Viele Grüße, Oliver.
Oliver Behr schrieb:> ich wundere mich gerade darüber, ob es einen Unterschied macht, ob ich> eine CRC-32 (Ethernet) Prüfsumme Byte für Byte berechne oder Wort für> Wort (uint32_t).
Hallo Oliver,
das ist wurscht: CRC funktioniert bitweise, es ist ja für serielle Daten
gedacht. Eine CRC-Hardware schiebt also die Daten Bit für Bit durch den
CRC-Generator, wie sie auf der Leitung TxD gesendet oder auf RxD
empfangen werden.
Bei Software im Prinzip das Gleiche: die Grundverknüpfung des nächsten
Bits mit dem bisherigen Ergebnis muss für ein Byte daher 8x, für ein
Word 16 x aufgerufen werden usw. Mit den üblichen Tabellen fasst man
z.B. die 8 Bitoperationen für ein Byte zwar zusammen, aber natürlich
ändert das nichts am zugrundeliegenden Algorithmus, und das geht eben
auch für 16 oder 32 Bit nach dem Muster for i := 1 to 32 do
Schiebe1BitRein.
Gruss Reinhard
Oliver Behr schrieb:> Wie soll man denn CRCs überprüfen,> wenn man nicht mal die Berechnungsgrundlage kennt?
Wie eine CRC berechnet wird, ist immer gleich. Unterschiedlich ist nur
das Polynom und die Länge.
Und das Polynom wird ST bestimmt irgendwo erwähnt haben.
Die Länge richtet sich hauptsächlich nach der Datenmenge.
Bis 256Byte bevorzugt man 8Bit-CRC, bis 64kB 16Bit-CRC und darüber
32Bit-CRC.
Bekannte Polynome sind:
0x8C (i-Button)
0xa001
0x1021 (X-Modem)
0x8408 (IrDA)
Peter
hallo Oliver
> Funktioniert prima, hat nur den Nachteil, dass es zusätzlich 1k im Flash> belegt und auch nicht so schnell ist, wie die HW-CRC.
ich war bei einer 1-wire anwendung auf der suche, wie man den 8-bit crc
pruefen koennte. bin dabei auf folgendes code example gestossen
http://www.dattalo.com/technical/software/pic/crc_8bit.c
Scott Dattalo beschreibt darin 3 verschiedene moeglichkeiten ( methoden
) den crc zu berechnen. einmal mit einer grossen tabelle, dann mit 2
kleinen und die dritte kommt ohne tabelle aus, nur rechnen.
so etwas muesste es ja auch fuer deinen 32-bit crc geben, denn dem liegt
ja sicherlich auch ein primzahlenpolynom zugrunde, aber halt
entsprechend hoeheren grades.
ich habe zwar genug flash, habe aber auch die letzte methode genommen.
schoene gruesse
hans
--
>so etwas muesste es ja auch fuer deinen 32-bit crc geben, denn dem liegt>ja sicherlich auch ein primzahlenpolynom zugrunde, aber halt>entsprechend hoeheren grades.
Das ist richtig. Normalerweise hat man byteweise das Problem, ob in
die Berechung der CRC das MSB oder das LSB zuerst in die CRC eingeht.
Nun zeigt aber der obige Code, dass man
- wortweise (32Bits) hantieren muss
- dies wortweise (mit dem rbit) gedreht
(Bit31<->Bit0, Bit30<->Bit1,...) werden muss.
Kurzgefasst: der HW-CRC ist zu nichts kompatibel, was man sonst im
dem Bereich verwendet. (Gerade fuer den Kommunikationsbereich gaebe
es Dutzende von Implementierungen...)
VG, auch
Hans
Hallo Hans,
ja genau, man muss nicht unbedingt die komplette Tabelle nehmen, es
reicht auch eine kleinere oder gar keine, geht dann halt zu Lasten der
Geschwindigkeit.
Ich muss ein bisschen auf die Codegröße schauen, da ich einen Bootloader
(zum flashen) schreibe und da netto vom Flash für die Applikation dann
noch genügend übrig bleiben muss. Fix sollte es beim Flashen auch gehen,
daher rein in Software ohne Tab wäre auch nicht ideal. Außerdem hat der
STM32 ja eine integrierte CRC-Einheit in Hardware, da hätte es mich
etwas gewurmt, wenn es nicht mit der gehen würde.
Wie Peter geschrieben hat, würde mir evtl auch eine 16-bit CRC reichen,
da ich immer eine Page übertrage und darüber die CRC mache. Da ließe
sich dann entweder Codegröße einsparen oder mehr Geschwindigkeit
rausholen, wenn man es in Software realisieren würde. Aber jetzt geht es
ja auch mit der Hardware-Einheit.
Viele Grüße, Oliver.