Getting CRC-32 over STM32 flash and consistency with other CRC-32 tools

0

I'm moving my STM32F1xx project to a solution with a bootloader. Part of this is that I want to be able to compute a CRC value over the existing bootloader and application flash ranges to compare existing and possible upload candidates.

Using a simple implementation on the STM32 which just does the following steps:

  • Enable CRC periperal
  • Reset the peripheral CRC value (sets to 0xFFFFFFFF)
  • Iterate over flash range (in this case 0x08000000 to 0x08020000) passing values to CRC peripheral
  • Return CRC peripheral output
uint32_t get_crc(void) {
    RCC->AHBENR |= RCC_AHBENR_CRCEN;
    CRC->CR |= CRC_CR_RESET;

    for(uint32_t *n = (uint32_t *)FLASH_BASE; n < (uint32_t *)(FLASH_BANK1_END + 1u); n ++) {
        CRC->DR = *n;
    }

    return CRC->DR;
}

The value I get from this is 0x0deddeb3.

To compare this value with something I am running the .bin file through two tools.

The value I get from npm's crc-32 is 0x776b0ea2

The value I get from a zip file's CRC-32 is also 0x776b0ea2

What could be causing this? Is there a difference between iterating over the entire flash range and the contents of the bin file (smaller than entire flash range)? The polynomial used by the STM32 is 0x04c11db7 which seems to be fairly standard for a CRC-32. Would the zip tool and npm crc-32 be using a different polynomial?

I have also tried iterating over bytes and half-words as well as words on the STM32 in case the other tools used a different input format.

There is a similar question on here already, but I'm hoping to use a node-js solution because that is the platform my interface application is being developed on.

c
embedded
stm32
crc
asked on Stack Overflow Oct 15, 2020 by Nathan Wride • edited Oct 15, 2020 by Nathan Wride

2 Answers

3

Calculating CRCs is a mine field. Your question already has some points to look at:

Is there a difference between iterating over the entire flash range and the contents of the bin file (smaller than entire flash range)?

Yes, of course.

Would the zip tool and npm crc-32 be using a different polynomial?

The documentation will tell you. And I'm sure that you can use another polynomial with this tools by an option.

Anyway, these are the things to consider when calculating CRCs:

  1. The amount of bytes (words, ...) to "sum up".
  2. The contents of the flash not covered by the binary file, most probably all bits set to 1.
  3. Width of the polynomial (in your case fixed to 32 bits).
  4. Value of the polynomial.
  5. Initial value for the register.
  6. Whether the bits of each byte are reflected before being processed.
  7. Whether the algorithm feeds input bytes through the register or xors them with a byte from one end and then straight into the table.
  8. Whether the final register value should be reversed (as in reflected versions).
  9. Value to XOR with the final register value.

The points 3 to the last are shamelessly copied from "A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS" that I suggest to read.

answered on Stack Overflow Oct 16, 2020 by the busybee
2

The polynomial is only one of several parameters that define a CRC. In this case the CRC is not reflected, whereas the standard zip CRC, using the same polynomial is reflected. Also that zip CRC is exclusive-or'ed with 0xffffffff at the end, whereas yours isn't. They do both get initialized the same, which is with 0xffffffff.

answered on Stack Overflow Oct 16, 2020 by Mark Adler

User contributions licensed under CC BY-SA 3.0