So stellen Sie STM32 ein, um Standard-CRC32 zu generieren

Lesezeit: 11 Minuten

Benutzeravatar von David Molnar
David Molnar

Ich versuche, CRC mit dem STM32L4-Hardwaremodul zu generieren. Ich möchte Fatfs-Dateien validieren, also habe ich im Grunde Byte-Arrays. Ich verwende diesen CRC Generator.

Leider kann ich nicht herausfinden, wie man STM32L4 einstellt, um das gleiche Ergebnis zu erzielen. Ich brauche CRC32 und ich habe

Aufbau:

hcrc.Instance = CRC;

/* The default polynomial is not used. It is required to defined it in CrcHandle.Init.GeneratingPolynomial*/
hcrc.Init.DefaultPolynomialUse    = DEFAULT_POLYNOMIAL_DISABLE;
/* Set the value of the polynomial */
hcrc.Init.GeneratingPolynomial    = 0x4C11DB7;
//hcrc.Init.GeneratingPolynomial    = 0xFB3EE248;
hcrc.Init.CRCLength= CRC_POLYLENGTH_32B;
/* The default init value is used */
/* The default init value is not used */
hcrc.Init.DefaultInitValueUse     = DEFAULT_INIT_VALUE_ENABLE;

/* User init value is used instead */
//hcrc.Init.InitValue               = 0;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
//hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
/* The input data are inverted by word */
//hcrc.Init.InputDataInversionMode  = CRC_INPUTDATA_INVERSION_WORD;

//hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
HAL_CRC_Init(&hcrc);

testen:

uint8_t test[] = {49,50,51,52};
uint32_t uwCRCValue = HAL_CRC_Calculate(&hcrc,(uint32_t *) test, 4);

Ergebnis: A695C4AA

Mir gehen die Ideen aus. Es gibt einen Weg, wie ich damit Erfolg habe uint32_t test[] und Eingang eingestellt ist hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
Leider habe ich uint8_t

  • Haben Sie daran gedacht, die CRC-Peripherieuhr zu aktivieren? Dein Code zeigt es nicht.

    – rost0031

    22. September 2016 um 21:55 Uhr


  • Haben Sie das entsprechende Referenzhandbuch gelesen? Das CRC-Modul verfügt über erweiterte Einstellungen für verschiedene Endianness-Fälle. Wenn Sie mit dem uint32_t-Test das richtige Ergebnis haben[]also Problem nur in Endianness-Einstellungen.

    – tragen

    23. September 2016 um 8:16 Uhr

  • Vielen Dank für Ihre Antwort. Ja, ich habe sie überprüft (ich habe den CubeMX-Codegenerator verwendet). Ich habe das Referenzhandbuch gelesen. Leider gibt mir keine Kombination von Einstellungen einen der von Standardalgorithmen berechneten CRC32.

    – David Molnar

    4. Oktober 2016 um 7:51 Uhr

  • Sie müssen Personen erwähnen, wenn Sie möchten, dass sie Ihren Kommentar sehen. Du bist der Eröffner, also erhältst du die Kommentare zu deinen Beiträgen, ohne erwähnt zu werden. Um Personen zu erwähnen, fügen Sie @ vor ihren Namen hinzu.

    – Mohammad Kholghi

    31. Juli 2021 um 6:58 Uhr

Mit CubeMX habe ich mit diesen Einstellungen generiert:

hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;

Berechnen Sie den CRC wie folgt:

uint32_t crc = HAL_CRC_Calculate(&hcrc, (uint32_t *)address, length);

Und zum Schluss invertieren:

crc = ~crc;

  • Hallo! Vielen Dank für Ihre Vorschläge. Leider kann ich Ihre Lösung nicht ausprobieren, das Projekt liegt nicht mehr auf meinem Schreibtisch. Soweit ich mich erinnern kann, war mein Problem, dass ich nicht dasselbe Ergebnis (CRC) wie STM für dieselbe Eingabe auf der PC-Seite reproduzieren kann. Versucht, das Ergebnis zum Beispiel mit dieser Seite zu berechnen sunshine2k.de/coding/javascript/crc/crc_js.html kann aber nicht das gleiche Ergebnis erzielen.

    – David Molnar

    20. Februar 2018 um 15:04 Uhr


  • Und noch etwas kam mir in den Sinn. Ich habe versucht, das uint8_t-Array als Eingabe mit der Option CRC_INPUTDATA_FORMAT_BYTES zu verwenden. Ich kann nicht das gleiche Ergebnis wie auf dem PC erzielen. Dann habe ich das Array uint32_t mit denselben 8-Bit-Daten verwendet und das richtige Ergebnis ausgewertet. Also habe ich am Ende ein größeres Array uint32_t verwendet[] statt uint8_t[] und ich könnte den Standardberechnungsalgorithmus auf der PC-Seite verwenden.

    – David Molnar

    20. Februar 2018 um 15:12 Uhr

  • @DavidMolnar Hast du getestet uint32_t uwCRCValue = HAL_CRC_Calculate(&hcrc,(uint32_t *) test, 1);? 1 = Länge des 8-Bit-Datenarrays (4) / 4

    – LeMoussel

    20. Dezember 2018 um 17:40 Uhr

  • Ich bestätige, dass dies funktioniert und Standard-CRC32 ausgibt, diese letzte Umkehrung ist kritisch. Außerdem müssen Sie die Länge der Daten nicht durch 4 teilen, wenn Sie dies festlegen CRC_INPUTDATA_FORMAT_BYTES wie die HAL das für Sie erledigt, irgendwie. Ich habe diesen Code verwendet uint32_t uwCRCValue = ~HAL_CRC_Calculate(&hcrc, (uint32_t *) msg, strlen(msg));

    – Tomislav Darlic

    3. Mai 2019 um 23:45 Uhr


Das funktioniert für mich.

static CRC_HandleTypeDef hcrc = { 
    .Instance = CRC, 
    .Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE,
    .Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE,
    .Init.CRCLength = CRC_POLYLENGTH_32B,
    .Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE,
    .Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE,
    .InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES,
};

Und die manuelle Methode

static const uint32_t crc_table[0x100] = {
  0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD, 
  0x4C11DB70, 0x48D0C6C7, 0x4593E01E, 0x4152FDA9, 0x5F15ADAC, 0x5BD4B01B, 0x569796C2, 0x52568B75, 0x6A1936C8, 0x6ED82B7F, 0x639B0DA6, 0x675A1011, 0x791D4014, 0x7DDC5DA3, 0x709F7B7A, 0x745E66CD, 
  0x9823B6E0, 0x9CE2AB57, 0x91A18D8E, 0x95609039, 0x8B27C03C, 0x8FE6DD8B, 0x82A5FB52, 0x8664E6E5, 0xBE2B5B58, 0xBAEA46EF, 0xB7A96036, 0xB3687D81, 0xAD2F2D84, 0xA9EE3033, 0xA4AD16EA, 0xA06C0B5D, 
  0xD4326D90, 0xD0F37027, 0xDDB056FE, 0xD9714B49, 0xC7361B4C, 0xC3F706FB, 0xCEB42022, 0xCA753D95, 0xF23A8028, 0xF6FB9D9F, 0xFBB8BB46, 0xFF79A6F1, 0xE13EF6F4, 0xE5FFEB43, 0xE8BCCD9A, 0xEC7DD02D, 
  0x34867077, 0x30476DC0, 0x3D044B19, 0x39C556AE, 0x278206AB, 0x23431B1C, 0x2E003DC5, 0x2AC12072, 0x128E9DCF, 0x164F8078, 0x1B0CA6A1, 0x1FCDBB16, 0x018AEB13, 0x054BF6A4, 0x0808D07D, 0x0CC9CDCA, 
  0x7897AB07, 0x7C56B6B0, 0x71159069, 0x75D48DDE, 0x6B93DDDB, 0x6F52C06C, 0x6211E6B5, 0x66D0FB02, 0x5E9F46BF, 0x5A5E5B08, 0x571D7DD1, 0x53DC6066, 0x4D9B3063, 0x495A2DD4, 0x44190B0D, 0x40D816BA, 
  0xACA5C697, 0xA864DB20, 0xA527FDF9, 0xA1E6E04E, 0xBFA1B04B, 0xBB60ADFC, 0xB6238B25, 0xB2E29692, 0x8AAD2B2F, 0x8E6C3698, 0x832F1041, 0x87EE0DF6, 0x99A95DF3, 0x9D684044, 0x902B669D, 0x94EA7B2A, 
  0xE0B41DE7, 0xE4750050, 0xE9362689, 0xEDF73B3E, 0xF3B06B3B, 0xF771768C, 0xFA325055, 0xFEF34DE2, 0xC6BCF05F, 0xC27DEDE8, 0xCF3ECB31, 0xCBFFD686, 0xD5B88683, 0xD1799B34, 0xDC3ABDED, 0xD8FBA05A, 
  0x690CE0EE, 0x6DCDFD59, 0x608EDB80, 0x644FC637, 0x7A089632, 0x7EC98B85, 0x738AAD5C, 0x774BB0EB, 0x4F040D56, 0x4BC510E1, 0x46863638, 0x42472B8F, 0x5C007B8A, 0x58C1663D, 0x558240E4, 0x51435D53, 
  0x251D3B9E, 0x21DC2629, 0x2C9F00F0, 0x285E1D47, 0x36194D42, 0x32D850F5, 0x3F9B762C, 0x3B5A6B9B, 0x0315D626, 0x07D4CB91, 0x0A97ED48, 0x0E56F0FF, 0x1011A0FA, 0x14D0BD4D, 0x19939B94, 0x1D528623, 
  0xF12F560E, 0xF5EE4BB9, 0xF8AD6D60, 0xFC6C70D7, 0xE22B20D2, 0xE6EA3D65, 0xEBA91BBC, 0xEF68060B, 0xD727BBB6, 0xD3E6A601, 0xDEA580D8, 0xDA649D6F, 0xC423CD6A, 0xC0E2D0DD, 0xCDA1F604, 0xC960EBB3, 
  0xBD3E8D7E, 0xB9FF90C9, 0xB4BCB610, 0xB07DABA7, 0xAE3AFBA2, 0xAAFBE615, 0xA7B8C0CC, 0xA379DD7B, 0x9B3660C6, 0x9FF77D71, 0x92B45BA8, 0x9675461F, 0x8832161A, 0x8CF30BAD, 0x81B02D74, 0x857130C3, 
  0x5D8A9099, 0x594B8D2E, 0x5408ABF7, 0x50C9B640, 0x4E8EE645, 0x4A4FFBF2, 0x470CDD2B, 0x43CDC09C, 0x7B827D21, 0x7F436096, 0x7200464F, 0x76C15BF8, 0x68860BFD, 0x6C47164A, 0x61043093, 0x65C52D24, 
  0x119B4BE9, 0x155A565E, 0x18197087, 0x1CD86D30, 0x029F3D35, 0x065E2082, 0x0B1D065B, 0x0FDC1BEC, 0x3793A651, 0x3352BBE6, 0x3E119D3F, 0x3AD08088, 0x2497D08D, 0x2056CD3A, 0x2D15EBE3, 0x29D4F654, 
  0xC5A92679, 0xC1683BCE, 0xCC2B1D17, 0xC8EA00A0, 0xD6AD50A5, 0xD26C4D12, 0xDF2F6BCB, 0xDBEE767C, 0xE3A1CBC1, 0xE760D676, 0xEA23F0AF, 0xEEE2ED18, 0xF0A5BD1D, 0xF464A0AA, 0xF9278673, 0xFDE69BC4, 
  0x89B8FD09, 0x8D79E0BE, 0x803AC667, 0x84FBDBD0, 0x9ABC8BD5, 0x9E7D9662, 0x933EB0BB, 0x97FFAD0C, 0xAFB010B1, 0xAB710D06, 0xA6322BDF, 0xA2F33668, 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4, 
};

uint32_t CalcCRC(uint8_t * pData, uint32_t DataLength)
{
    uint32_t Checksum = 0xFFFFFFFF;
    for(unsigned int i=0; i < DataLength; i++)
    {
        uint8_t top = (uint8_t)(Checksum >> 24);
        top ^= pData[i];
        Checksum = (Checksum << 8) ^ crc_table[top];
    }
    return Checksum;
}

  • Beachten Sie, dass es bei Verwendung der Hardware-CRC-Berechnung eine erhebliche Leistungssteigerung gibt, wenn 32-Bit-Wörter anstelle von Bytes verwendet werden.

    – Benutzer1139455

    6. September 2020 um 18:38 Uhr

Verwenden Sie den folgenden Code, um cc32 zu berechnen. CRC32-Berechnung durch die STM32-CRC-Einheit ist nicht dasselbe wie unser Standard-CRC32, es hat Big Endian verwendet und es wird kein XOR mit 0xFFFFFFFF durchgeführt.

u32 CRC32_ForBytes(u8 *pData, u32 uLen);

#define UNUSED(x) ((void)(x))

/**
 * @brief  CRC functions
 */
#define __HAL_RCC_CRC_CLK_ENABLE()   do { \
                                        __IO uint32_t tmpreg; \
                                        SET_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\
                                        /* Delay after an RCC peripheral clock enabling */\
                                        tmpreg = READ_BIT(RCC->AHBENR, RCC_AHBENR_CRCEN);\
                                        UNUSED(tmpreg); \
                                      } while(0)

#define __HAL_RCC_CRC_CLK_DISABLE()       (RCC->AHBENR &= ~(RCC_AHBENR_CRCEN))

#define CRC32_POLYNOMIAL                        ((u32)0xEDB88320)  
#define RCC_CRC_BIT                             ((u32)0x00001000)


/**
 * @brief  Calc CRC32 for data in bytes
 * @param  pData Buffer pointer
 * @param  uLen  Buffer Length
 * @retval CRC32 Checksum
 */
u32 CRC32_ForBytes(u8 *pData,u32 uLen)  
{  
    u32 uIndex= 0,uData = 0,i;  
    uIndex = uLen >> 2;  

    __HAL_RCC_CRC_CLK_ENABLE();

    /* Reset CRC generator */  
    CRC_ResetDR();

    while(uIndex--)  
    {  
#ifdef USED_BIG_ENDIAN    
        uData = __REV((u32*)pData);  
#else
        ((u8 *)&uData)[0] = pData[0];
        ((u8 *)&uData)[1] = pData[1];
        ((u8 *)&uData)[2] = pData[2];
        ((u8 *)&uData)[3] = pData[3];
#endif        
        pData += 4;  
        uData = revbit(uData);  
        CRC->DR = uData;  
    }  
    uData = revbit(CRC->DR);  
    uIndex = uLen & 0x03;  
    while(uIndex--)  
    {  
        uData ^= (u32)*pData++;  
        for(i = 0;i < 8;i++)  
          if (uData & 0x1)  
            uData = (uData >> 1) ^ CRC32_POLYNOMIAL;  
          else  
            uData >>= 1;  
    }

    __HAL_RCC_CRC_CLK_DISABLE();

    return uData^0xFFFFFFFF;  
}

static u32 revbit(u32 uData)
{  
    u32 uRevData = 0,uIndex = 0;  
    uRevData |= ((uData >> uIndex) & 0x01);  
    for(uIndex = 1;uIndex < 32;uIndex++)  
    {  
        uRevData <<= 1;  
        uRevData |= ((uData >> uIndex) & 0x01);  
    }  
    return uRevData;  
}

Berechnen Sie Ihren CRC32 wie folgt:

u32 uwCRCValue = CRC32_ForBytes(&test, 4);

  • Vielen Dank für den Code. Mein Hauptziel war es, den Hardware-Rechner zu verwenden. Ich habe mit diesem Algorithmus erfolgreich dieselbe Ausgabe auf der PC-Seite generiert CRC32 C#-Code Auf der Hardwareseite funktioniert es mit: ‘uint32_t test[] = {49,50,51,52};’ Aber wenn ich zu ändere: ‘uint8_t test[] = {49,50,51,52};’ Das Ergebnis hat sich geändert und ich kann immer noch nicht den richtigen Algorithmus finden. Es könnte ein Padding-Problem sein, aber ich habe 4 Bytes zum Testen verwendet. Ich habe am Ende eine Prüfsumme verwendet.

    – David Molnar

    4. Oktober 2016 um 8:14 Uhr

  • CRC ist im Wesentlichen der Rest nach einer sehr langen langen Division, sodass die Reihenfolge der Eingangsdatenbytes von Bedeutung ist. Die Eingangsdatenbytes sind für den CRC-Algorithmus wie eine extrem lange Zahl.

    – Benutzer50619

    5. November 2018 um 14:31 Uhr

  • Zumindest unterstützt der STM32L4 das Umkehren der Eingangsdaten. Sie können also wählen, ob die Hardware die Daten in Big- oder Little-Endian-Manier verarbeitet. So wie es ist, ist diese Antwort falsch.

    – Sven

    3. Juni 2020 um 14:58 Uhr

  • Dieser vorgeschlagene Algorithmus ist tatsächlich zu 100 % korrekt und stimmt mit jedem Standard-CRC32 für Daten beliebiger Länge überein (einschließlich Fällen, in denen (uLen % 4) > 0). Außerdem würde ich die Verwendung empfehlen __RBIT(uData) Betrieb, der es ermöglicht, die Bitreihenfolge im gesamten 32-Bit-Wort in einem Tick auf der ARM-MCU umzukehren;

    – Nik

    8. September 2021 um 18:46 Uhr

Dies ist eine kleine Anmerkung, wenn Sie sich fragen, welches Polynom hcrc.Init.GeneratingPolynomial Und hcrc.Init.CRCLength bedeutet. In Ihrem ersten Beispiel ergeben Ihre Polynomeinstellungen:

> polyviz(0x4C11DB7, 32)
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1

Wenn Sie node.js installiert haben, können Sie die unten stehende Funktion, die ich geschrieben habe, verwenden, um das Polynom des stm32-CRC-Generators in die Formel des CRC-Polynoms umzuwandeln ...+x^2+x^1+1 form.

function polyviz(Pol, PolyLength)
{
  var msb = 31;

  process.stdout.write(" x^"+(PolyLength));
  while (msb-- > 0)
  {
    if ((Pol & (1 << msb)))
    {
      if (msb == 0)
      process.stdout.write(" + 1");
      else
      process.stdout.write(" + x^"+(msb));
    }
  }
  process.stdout.write("\r\n");
}

// Examples from HAL_CRCEx_Polynomial_Set():
// * for a polynomial of degree 16, X^16 + X^12 + X^5 + 1 is written 0x1021 (Bin: 0001 0000 0010 0001 )
polyviz(0x1021, 16)
// * for a polynomial of degree 7, X^7 + X^6 + X^5 + X^2 + 1 is written 0x65 (Bin: 0110 0101)
polyviz(0x65, 7)

Mit dieser Methode können Sie bestätigen, ob Sie Ihr Polynom richtig eingestellt haben. (Da viele crc-Standards die Polynomdarstellung verwenden)

Benutzeravatar von RR
RR

Ich habe dieses Tutorial (für STM32F746) gefunden und verwende es mit STM32F407VGT6,

Es gibt viele IDE-Konfigurationen und es wird wahrscheinlich besser sein, direkt auf sie zuzugreifen. Es tut mir leid, dass ich nicht alle Inhalte direkt hier einbette:

Praktisch: CRC-Prüfsummengenerierung

Hinweis: In diesem Fall ist die zu schreibende Datei ROM.hex (Sie müssen die STM32CubeIDE konfigurieren, um diesen Vorgang ausführen zu können automatischdie IDE verwendet die *.elf-Datei, siehe Tipps unten):

Einige Tipps und Lösungen zu dieser CRC-Nutzung (Windows/Linux)

1447150cookie-checkSo stellen Sie STM32 ein, um Standard-CRC32 zu generieren

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy