Forum: Mikrocontroller und Digitale Elektronik CRC32 mit stm32


von Flo (Gast)


Lesenswert?

Hi Leuts,

ich schreib nen Bootcode mit der aktuelle IAR Kickstart version.
Dabei habe ich also 2 Softwareteile im FLASH.
Ich spiele den Bootcode rein und bestimme er steht in den 1. 8 kB.

Im 2. Teil also der Application die ich extra compiliere wird dann der 
weitere Speicherbereich angegeben.

Nun zum CRC 32 Problem.
Benutzt wird in beidem Compiler und softare die Ethernet CRC32. 
(0x4C11DB7)

Bootcode:
Ich benutze die Hardware im stm32 um die CRC32 zu validieren.
Zum Testen nehme ich dabei genau eine Adresse mit 32 Bit(in der 
Application auch so eingestellt).
Also berechne ich die CRC32 z.B. nur über den Wert 0x20000440
-> laut (http://www.lammertbies.nl/comm/info/crc-calculation.html)
0x93C6F4B6

Application:
In der Application benutzte ich den Compiler um die CRC32 zu erstellen. 
Hier liegt vermutlich auch der Fehler. Ich weis nicht welche 
Einstellungen für Complement, Bitorder und Reverse byte order within 
Word ich brauche.
(der eingestellte CRC Bereich wurde ebenfalls auf eine Adresse 
Beschränkt)

Auf jeden Fall komme ich bisher nie auf einen Erfolgreichen Vergleich.

Wäre für Vorschläge dankbar.

Gruß Flo

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Auf https://my.st.com/public/STe2ecommunities/default.aspx crc in das 
Suchfeld eintippen. Man findet dann zumindest einen Thread C-Quellcode, 
in dem der CRC analog zur STM32 Hardware implementiert ist.

von Flo (Gast)


Lesenswert?

Hi nochmal,
also die Antwort hat mir nicht viel geholfen.
Auch mit einigen der Beispiele kam ich auf keinen grünen Zweig.

1. Auf dem stm32:

CRC_ResetDR();

u32Crc = CRC_GetCRC();

u32Crc32 = CRC_CalcCRC(0x20000440);

Wie muss ich das in C umwandeln, damit ich wie bei dem oben genannten 
Onlinerechner 0x93C6F4B6 raus bekomme?

Ich finde nirgends im Datenblatt wie die Formateinstellungen der CRC32 
sind.

2. Auf dem PC:
Habe von IAR keinerlei support über die Einstellung im Compiler 
gefunden, da die CRC32 vermutlich noch nicht soo lange drin ist.
(Project->Options->Linker->Checksum)
Da ich nun die Einstellungen bei der Hardware nicht weis kann ich auch 
hier nicht genau sagen was ich einstellen muss.
Zum Testen:
CRC über eine 32 Bit Adresse,
CRC32,
StartValue: 0xFFFFFFFF;
AsIs/1er Komplement,
LSB/MSB,
Reverse Byteorder in Word?

Hat wer Vroschläge?

Gruß Flo

von Dirk W. (dirkw)


Lesenswert?


von Flo (Gast)


Lesenswert?

Hallo,
Danke erstmal für die Antworten!
Also inzwischen geht immer noch nicht mehr.
Aber ich versuche im folgendes. Die revbit Funktion stammt von einem 
Beispiel hier:
https://my.st.com/public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fARM%20CortexM3%20STM32%2fCRC%20calculation%20in%20software&FolderCTID=0x01200200770978C69A1141439FE559EB459D758000626BE2B829C32145B9EB5739142DC17E&currentviews=2028

sorry für den langen Link. Aber das Beispiel steht weiter unten im dem 
Thread.

Beim Link von Dirk war ich schon und das hier ist quasi aus beiden Foren 
zusammengebaut denke ich.

Ich verwende die Funktion folgender maßen um zu testen:

uint32_t revbit(uint32_t data)
{
asm("rbit r0,r0");
return data;
};

void main ()
{
  /*here is the Init of variables */

  /* here is the Peripheral setup */

  CRC_ResetDR();

  u32Crc = CRC_GetCRC();

  u32DoubleWord= 0x20000770;

  u32DoubleWord = revbit(u32DoubleWord);

  u32Crc32 = CRC_CalcCRC(u32DoubleWord);

  u32Crc32=revbit(u32Crc32 ^ 0xFFFFFFFFL);
}

Das Ergebnis bei Lammert Bies ist:0x9E3297D9
Das Ergebnis der obigen Berechnung ist bei: u32Crc32=0x745A49CD

Wenn wer nen blöden Fehler sieht bitte schreien ;)

Grüße Flo

von Dirk W. (dirkw)


Lesenswert?

Hi,

Probier mal:
u32Crc32=revbit(u32Crc32 ^ 0xFFFFFFFFL);
zu
u32Crc32=revbit(u32Crc32) ^ 0xFFFFFFFFL;

Schau dir auch mal das an:
Beitrag "CRC - Byte-weise oder Wort-weise?"

CU Dirk

von Flo (Gast)


Lesenswert?

Hi Dirk,
also die Änderung hab ich auch probiert. Aber mir dann überlegt das es 
grad wurst ist. denn ob ich nun ne XOR machen bevor oder nachdem ich 
revbit mache ist grad wurst.

Ich hab noch gesehn, das die beiden Assembler Anwendungen andere 
Variablendeklarationen haben. Also ich nutze
u32 revbit(u32 data)
{
asm("rbit r0,r0");
return data;
};

aber statt u32 uint32_t. Ich weis nicht ob der Compiler hier u32 kennen 
müsste?! Auch im getesteten Beispiel von Dirks letztem Link werden u32 
und uint32_t verwendet.

Macht das was aus??
Weis jemand wie ich den Teil verwenden kann?

<BR>    crc_model.cm_width = 32;            // 32-bit CRC
<BR>    crc_model.cm_poly  = 0x04C11DB7;    // CRC-32 polynomial
<BR>    crc_model.cm_init  = 0xFFFFFFFF;    // CRC initialized to 1's
<BR>    crc_model.cm_refin = FALSE;         // CRC calculated MSB first
<BR>    crc_model.cm_refot = FALSE;         // Final result is not

Ich müsste vermutlich das einbinden um cm_t zu nutzen?!
<BR>//  IMPORTED FUNCTIONS AND MACROS :
<BR>//      cm_ini(), cm_nxt(), cm_crc()

<BR>cm_t        crc_model;

Danke Gruß Flo

von Dirk W. (dirkw)


Lesenswert?

Hi,


Hab mir gerade nochmal die Werte aus dem Beispiel angesehen.

CRC32: 0x70070020 => 745a49cd
CRC32: 0x20000770 => 9e3297d9

Einfach die Byte-Order umdrehen... ^_^



CU Dirk

von Flo (Gast)


Lesenswert?

Hi Dirk,
danke dir. Das war der ausschlaggebende Tipp.
Für alle die es brauch und zu Faul sind es selber zu basteln nochmal 
hier. Damit kann man die Berechnungen von Lammber nachvollziehen. 
Funktioniert bei mir in IAR Kickstart. Wenn wer eine Idee hat das zu 
vereinfachen nur her. Ich vermute man könnte auch irgendwas schneller 
machen oder weglassen.

uint32_t u32RevByte(uint32_t u32RevValue)
{
  uint8_t HighWordLoNibble, HighWordHighNibble, LowWordLoNibble;
  unint8_t LowWordHighNibble;

  /* Copy orignial bytes to temp variables */
  HighWordHighNibble = (uint8_t)((u32RevValue>>24)&0xFF);
  HighWordLoNibble = (uint8_t)((u32RevValue>>16)&0xFF);
  LowWordHighNibble = (uint8_t)((u32RevValue>>8)&0xFF);
  LowWordLoNibble = (uint8_t)((u32RevValue)&0xFF);

  /* rev byte order in variable */
  u32RevValue=(uint32_t)HighWordHighNibble;
  u32RevValue=u32RevValue|((uint32_t)(HighWordLoNibble<<8)&0x0000FF00));
  u32RevValue=u32RevValue|((uint32_t)((LowWordHighNibble<<16)&0x00FF0000)) 
;
  u32RevValue=u32RevValue|((uint32_t)((LowWordLoNibble<<24)&0xFF000000));
  return u32RevValue;
}

uint32_t revbit(uint32_t data)
{
asm("rbit r0,r0");
return data;
};

void main ()
{
  /*here is the Init of variables */

  /* here is the Peripheral setup */

  CRC_ResetDR();

  u32Crc = CRC_GetCRC();

  u32DoubleWord= 0x20000770;

  u32DoubleWord = revbit(u32DoubleWord);

  u32Crc32 = CRC_CalcCRC(u32DoubleWord);

  u32Crc32=revbit(u32Crc32 ^ 0xFFFFFFFFL);
}



Nun zur anderen Seite:
Ich weis Dirk hat oben die Einstellungen in einer Software für CRC 
gepostet. Aber weis jemand sicher ob das die original Einstellungen 
sind, die auch der stm32 mikrocontroller hat.
Weil dort sind sie ja neu gesetzt. Das heißt noch nicht es sind die 
original Einstellungen oder?

Gruß Flo

von Flo (Gast)


Lesenswert?

Also hier nochmal die Frage, da vermutlich nach der Anwort oben keiner 
weiter gelesen hat.

Nun zur anderen Seite:
Ich weis Dirk hat oben die Einstellungen in einer Software für CRC
gepostet. Aber weis jemand sicher ob das die original Einstellungen
sind, die auch der stm32 mikrocontroller hat.
Weil dort sind sie ja neu gesetzt. Das heißt noch nicht es sind die
original Einstellungen oder?

Alternative: Weis jemand ne Software die mir vor dem Download in den 
FLASH ne CRC32 berechnet und die ich dann ans Ende vom FLASH schreiben 
kann?

Gruß Flo

von Meloun (Gast)


Lesenswert?

to Flo:

komisch, habe ich dein Kode einfach kopiert aber bekomme ich andere CRC 
als du schreibst.

Kannst du es bitte nochmal checken und schreiben ein Beispiel?

Danke.

von Jedi82 (Gast)


Lesenswert?

Danke für die Codefragmente! Hätte echt nicht gedacht, dass man mit 
einer HW-CRC Implementierung auf dem Cortex M3 solche Verrenkungen 
machen muss um ein bisschen CRC32 zu berechnen...

Anbei Democode für dem STM32F107 bzw. STM32F10x (für KEIL)
liefert korrekte Ergebnisse im Vergleich zu folgendem online calculator:
http://www.lammertbies.nl/comm/info/crc-calculation.html

/* Functions */

__asm u32 revbit(u32 data)
{
  rbit r0, r0
  bx lr
}

uint32_t u32RevByte(uint32_t u32RevValue)
{
  uint8_t HighWordLoNibble, HighWordHighNibble, LowWordLoNibble;
  uint8_t LowWordHighNibble;

  /* Copy orignial bytes to temp variables */
  HighWordHighNibble = (uint8_t)((u32RevValue>>24)&0xFF);
  HighWordLoNibble = (uint8_t)((u32RevValue>>16)&0xFF);
  LowWordHighNibble = (uint8_t)((u32RevValue>>8)&0xFF);
  LowWordLoNibble = (uint8_t)((u32RevValue)&0xFF);

  /* rev byte order in variable */
  u32RevValue=(uint32_t)HighWordHighNibble;
  u32RevValue=u32RevValue|((uint32_t)(HighWordLoNibble<<8)&0x0000FF00);
  u32RevValue=u32RevValue|((uint32_t)((LowWordHighNibble<<16)&0x00FF0000)) 
;
  u32RevValue=u32RevValue|((uint32_t)((LowWordLoNibble<<24)&0xFF000000));
  return u32RevValue;
}


/* Demo */

/* Variablen */
UInt32 CRC_Test_U32;
UInt32 CRC_Test_Result;

/* Code */
CRC_ResetDR();
CRC_Test_Result=revbit(CRC_CalcCRC(revbit(u32RevByte(CRC_Test_U32))) ^ 
0xffffffff);

von Arne (Gast)


Lesenswert?

Mal ne Frage:
statt
1
uint32_t u32RevByte(uint32_t u32RevValue)
ginge doch auch die asm Anweisung
1
rev r0, r0
oder nicht?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.