Created
March 17, 2021 09:10
-
-
Save rikka0w0/771b2cd2cfdc8c9af35cd88bd3110097 to your computer and use it in GitHub Desktop.
STM32F0 CRC32, supports unaligend memory as input.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* 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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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