Hallo,
habe folgendes Problem, ich habe einen Buffer vom Typ uint_t16.
Über diesen Berechne ich eine CRC Summe:
1
voidCRC_append(uint16_t*buf,constintlen)
2
{
3
uint32_t*buf32=(uint32_t*)buf;
4
uint8_t*buf8=(uint8_t*)buf;
5
uint32_tCRC_sum;
6
CRC_ResetDR();
7
8
for(inti=0;i<len>>1;i++)
9
CRC->DR=buf32[i];
10
11
buf32[len>>1]=CRC->DR;
12
}
Hier wird zur Zeit noch der uint32_t in den Buffer geschrieben, jedoch
füllt er dann 2 16 Bit Zellen meines Buffers. Ich möchte aber den 32 Bit
Wert als 4 Bytes auffassen und in dementsprechend 4 16 Bit Zellen
schreiben.
Ich hoffe ich konnte das einigermaßen erklären.
zur Zeit:
buf[4] 0x616D
buf[5] 0xF037
soll:
buf[4] 0x0061
buf[5] 0x006D
buf[6] 0x00F0
buf[7] 0x0037
Hintergund ist, dass ich den 16 Bit Buffer brauch um in einer Zelle 1
Bit für eine 9 Bit Uart setze und das funktioniert mit einem uint_t8
Buffer so ja nicht.
Gruß
paule
(Die Reihenfolge musst Du noch Deinen Anforderungen und der "endianness"
Deines Controllers anpassen)
Wobei ich mich frage, welchen Sinn diese Schleife hat:
wie soll das denn einen CRC berechnen, hier wird nur was kopiert und am
Ende der zuletzt kopierte Wert wieder ausgelesen.
(vorrausgesetzt wir reden hier über C und nicht über C++ mit überladenem
Zuweisungsoperator)
An sich scheint mir das Design von CR ziemlich fragwürdig.
Das scheint mit internen globalen Variablen zu arbeiten - pfui
Dass die Funktion 'CRC_append()' keine Prüfsumme berechnet, wurde schon
festgestellt.
Außerdem würde ich mir die Prüfsumme als Funktionsergebnis zurückgeben
lassen. Die soll ja nach einer Übertragung irgendwo kontrolliert werden.
Da muss man sie nur wissen und nicht eintragen.
Sollen die 32-Bit-Werte nur für eine Datenübertragung mit Prüfsumme
aufbereitet werden? Dann setzt man (ich zumindest ;-) ) einfach einen
8-Bit-Zeiger auf den Puffer und los geht's. Für 'richtige' Berechnungen
könnte es schwieriger werden (Byte-Order!).
Hallo,
wie berechne ich denn dann eine CRC richtig.
Mein STM32 hat eine CRC Einheit, die man mit 32 Bit beschreiben kann und
mir dann einen 32Bit Wert zurückgibt. Ich sehe jetzt gerade selber das
ich quasi nur den letzten Wert aus dem CRC Register als Prüfsumme nehme.
Ich will ja am Ende nur eine CRC Summe haben, die aus 32Bit besteht.
Gruß
paule schrieb:> wie berechne ich denn dann eine CRC richtig.
So, wie's im Datenblatt steht. Die Prüfsumme berechnet die 'CRC
calculation unit'. Einfach nur Reset, dann 'CRC_DR' (sollte CRC->DR das
bedeuten??) mit Daten füttern (32 Bit!!!), wenn fertig: auslesen.
Hallo,
ja das soll es bedeuten, ich füttere die Unit per CRC->DR mit 32 Bit und
bekomme dann die Checksummer zurück. Nur dann ist mir nicht klar, wie
ich diese verarbeite, wenn ich mehr als 32 Bit Datenn habe?
Wie bilde ich dann die Checksummer über ein Vielfaches von 32 Bit?
_Datenblatt_:
3.3 CRC functional description
The CRC calculation unit mainly consists of a single 32-bit data
register, which:
● is used as an input register to enter new data in the CRC calculator
(when writing into
the register)
● holds the result of the previous CRC calculation (when reading the
register)
Each write operation into the data register creates a combination of the
previous CRC value
and the new one (CRC computation is done on the whole 32-bit data word,
and not byte per
byte).
The write operation is stalled until the end of the CRC computation,
thus allowing back-toback
write accesses or consecutive write and read accesses.
The CRC calculator can be reset to FFFF FFFFh with the RESET control bit
in the CRC_CR
register. This operation does not affect the contents of the CRC_IDR
register.
● holds the result of the previous CRC calculation (when reading the
register)
Each write operation into the data register creates a combination of the
previous CRC value
and the new one (CRC computation is done on the whole 32-bit data word,
and not byte per
byte).
das sagt mir doch, das ich meine CRC Berechnung richtig mache, wenn der
alte wert behalten wird.
Ja, bloß:
1. mit den falschen Werten, bzw. umständlich
2. was ist CRC->DR?
-^^
Ich (Achtung: Hobby-Programmierer) würde das so machen (nicht getestet):
1
uint32_tgetCRC(uint32_t*buf,uint32_tlen)// 32Bit ist doch sowieso Standard, oder??
2
{
3
uint32*p=buf;
4
CRC_CR|=1<<RESET;// sollte die Berechnung 'resetten'
Es sieht so aus, als ob der hier verwendete Controller CRC in Hardware
berechnen kann, und daß die Struktur "CRC" die Register der hierfür
zuständigen CRC-Berechnungshardware abbildet.
Das Member "DR" ist dann wohl das Datenregister, und damit ist die mir
merkwürdig erscheinende Schleife
1
for(inti=0;i<len>>1;i++)
2
CRC->DR=buf32[i];
wohl tatsächlich korrekt, weil CRC->DR in ein Register der Hardware
schreibt.
Das muss einem aber auch gesagt werden.
Ralf schrieb:> Nur, wenn 'CRC->DR' richtig ist, sollte da in dieser Struktur/ Klasse> nicht noch fix so eine Funktion zur Berechnung 'dabei' sein?
Nein, das macht die Hardware so. Die muss initialisiert werden, dann
werden nacheinander die Daten 'reingeprügelt und danach kann
--anscheinend-- aus demselben Register das Ergebnis gelesen werden.
Ob das alles wirklich so funktioniert, ist ohne Studium des zugehörigen
Datenblatt/Benutzerhandbuch des Controllers natürlich nicht
herauszufinden.
Rufus Τ. Firefly schrieb:> Ob das alles wirklich so funktioniert, ist ohne Studium des zugehörigen> Datenblatt/Benutzerhandbuch des Controllers natürlich nicht> herauszufinden.
So verstehe ich das auch.
Ich hab' mir das Datenblatt mal durchgelesen, denn mit dem STM32 habe
ich sonst nichts zu tun. Aber dort heißen die Register CRC_DR, CRC_IDR,
CRC_CR.
Wenn jetzt über eine Struktur/ Klasse darauf zugegriffen wird, muss doch
irgendwo eine Bibliothek dazu existieren. Da kann man doch gleich noch
was dazubasteln.
Ralf schrieb:> Wenn jetzt über eine Struktur/ Klasse darauf zugegriffen wird, muss doch> irgendwo eine Bibliothek dazu existieren.
Nicht zwingend.
Angenommen, die Register CRC_DR, CRC_IDR,
CRC_CR
lägen direkt hintereinander im Speicher, dann könnte eine entsprechende
Struktur diese direkt so deklarieren und nutzen:
1
typedefstruct
2
{
3
uint32_tDR;
4
uint32_tIDR;
5
uint32_tCR;
6
}CRC_REGISTER;
7
8
9
CRC_REGISTER*CRC;
10
11
CRC=(CRC_REGISTER*)0x1234000;
12
13
CRC->DR=14;
(Angenommen, die Basisadresse des CRC-Registersatzes läge bei
0x12340000)
Auf Prozessorarchitekturen mit memory-mapped I/O kann man das so
machen.
Rufus Τ. Firefly schrieb:> dann könnte eine entsprechende> Struktur diese direkt so deklarieren und nutzen
Ja, könnnnte. Wer weiß aber, was später mal so alles geändert wird.
Diese Zugriffsidee gibt's ja auch für die AVR-Register PORTx, PINx, DDRx
...
Ich dachte eher an eine ordentliche Klasse, die gleich so eine
Berechnungsfunktion zur Verfügung stellt (Wenn man schon die Register in
einer Struktur 'versteckt').
Ralf schrieb:> Ja, könnnnte. Wer weiß aber, was später mal so alles geändert wird.> Diese Zugriffsidee gibt's ja auch für die AVR-Register PORTx, PINx, DDRx> ...
diese Idee gefällt mir.
Ich kannte bisher nur die Variante mit Makros
GETDDR(PORTA)