Skip to content

Instantly share code, notes, and snippets.

@rikka0w0
Created March 17, 2021 09:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rikka0w0/771b2cd2cfdc8c9af35cd88bd3110097 to your computer and use it in GitHub Desktop.
Save rikka0w0/771b2cd2cfdc8c9af35cd88bd3110097 to your computer and use it in GitHub Desktop.
STM32F0 CRC32, supports unaligend memory as input.
/*
* Resource used:
* CRC32 peripheral
*/
#include "crc.h"
#include "stm32f0xx_ll_bus.h"
void crc32_init(void) {
// Enable CRC32's clock
LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_CRC);
crc32_reset();
}
void crc32_reset(void) {
CRC->CR = 0xE1; // Reverse output data, Reverse input data by word, Reset, RM0091 Page 224.
while (CRC->CR & 1);
}
void crc32_hash(const void* addr, size_t len) {
void* end_addr = (void*) (((uint32_t)addr >> 2) << 2);
if (addr != end_addr) {
// Align the head to 4-byte boundary
end_addr = (void*) ((char*)end_addr + 4);
while (len > 0 && addr < end_addr) {
crc32_hash8(*((const char*)addr));
addr++;
len--;
}
}
// addr is now aligned to 4-byte boundary
end_addr = (void*) ((uint32_t)addr + ((len >> 2) << 2));
while (addr < end_addr) {
crc32_hash32(*((const uint32_t*)addr));
addr += 4;
len -= 4;
}
// Hash the tailing bytes (less than 4), if any
while (len > 0) {
crc32_hash8(*((const char*)addr));
addr++;
len--;
}
}
uint32_t crc32_calc(const void* addr, size_t len) {
crc32_reset();
crc32_hash(addr, len);
return crc32_result();
}
#ifndef CRC_H_
#define CRC_H_
#include <stdint.h>
#include <stddef.h>
#define crc32_hash8(dat) (*(((uint8_t*)(&(CRC->DR)))) = dat)
#define crc32_hash16(dat) (*(((uint16_t*)(&(CRC->DR)))) = dat)
#define crc32_hash32(dat) (*(((uint32_t*)(&(CRC->DR)))) = dat)
#define crc32_result() (CRC->DR ^ 0xFFFFFFFF)
void crc32_init(void);
void crc32_reset(void);
/**
* Hash the bytes in the buffer.
* This function handles unaligned access.
* The algorithm is compatible with USB-PD.
*
* Steps are:
* 1. Call crc32_reset() to reset the CRC32 peripheral into
* its default state (clear the previous result).
* 2. Call crc32_hash() as many times as needed.
* 3. Invoke crc32_result() to get the CRC32 result.
*/
void crc32_hash(const void* addr, size_t len);
/*
* A wrapper of the above steps.
*/
uint32_t crc32_calc(const void* addr, size_t len);
#endif /* CRC_H_ */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment