How to use CRC on STM32 Hardware

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
User avatar
kwagyeman
Posts: 6
Joined: Fri Apr 15, 2016 5:16 pm

How to use CRC on STM32 Hardware

Post by kwagyeman » Mon May 11, 2020 6:01 am

Hi all, I had to get really fast CRCs working on the STM32 and I wrote the following code for doing CCITT-16 CRCs:

Code: Select all

    @micropython.viper
    def __stm_crc_16(self, data, size : int) -> int: # private
        ptr32(stm.CRC + stm.CRC_CR)[0] = (1 << 3) | 1 # Reset and put into 1 byte per write mode.
        crc8 = ptr8(stm.CRC + stm.CRC_DR)
        d = ptr8(data)
        for i in range(size):
            crc8[0] = d[i]
        return ptr32(stm.CRC + stm.CRC_DR)[0]
The above code can process 32KB/s in 6us on the H7 at 480 MHz.

Code: Select all

        if omv.board_type() == "H7":
            stm.mem32[stm.RCC + stm.RCC_AHB4ENR] = stm.mem32[stm.RCC + stm.RCC_AHB4ENR] | (1 << 19) # Enable CRC clock 
            stm.mem32[stm.CRC + stm.CRC_POL] = 0x1021
        elif omv.board_type() == "F7":
            stm.mem32[stm.RCC + stm.RCC_AHB1ENR] = stm.mem32[stm.RCC + stm.RCC_AHB1ENR] | (1 << 12) # Enable CRC clock 
            stm.mem32[stm.CRC + stm.CRC_POL] = 0x1021
As the M4 does not support custom polynomials it cannot be used for the above. However, the F7 and H7 can. Note that if you want to feed the CRC hardware 16 or 32 bits at a time you have to byte reverse the data. It would be nice if MicroPython exposed __REV/__REV16 under the micropython module like how const is done for byte reversal, this would massively cut the processing time.

Anyway, I decided to post the above since I spent a while searching for answers on this and had to figure it out myself.

Notes:

The M4 CRC hardware can only do CRCs for Ethernet packets.

The M7/H7 CRC hardware can do more flexible CRCs. However, they are only efficient for big endian data. I spent quite a bit of time trying every setting the hardware had along with flipping the polynomial around to avoid having to byte reverse the input to unlock 16-bit and 32-bit writes to the CRC hardware. However, byte-reversal is unavoidable. Until MicroPython has an easy byte reversal option it is faster to just feed the hardware one byte at a time that doing the reversal in python. Note the assembler does not support byte reversal opcodes.

Post Reply