Created
September 14, 2021 12:10
-
-
Save aristotaloss/ff1566d7a1f9c872167de7c73e07799b to your computer and use it in GitHub Desktop.
STM32 CRC32 calculation example for Rust
This file contains hidden or 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
// CARGO: | |
// [dependencies] | |
// cortex-m = "0.6.0" | |
// cortex-m-rt = "0.6.10" | |
// cortex-m-semihosting = "0.3.3" | |
// panic-halt = "0.2.0" | |
#![no_std] | |
#![no_main] | |
use cortex_m_semihosting::hprintln; | |
use panic_halt as _; | |
use cortex_m::asm; | |
use cortex_m_rt::entry; | |
struct Crc32; | |
impl Crc32 { | |
pub fn calculate(data: &[u8]) -> u32 { | |
// Ensure CRC32 peripheral clock is on | |
let rcc_ahb1enr = VolatileReg::new(0x4002_3800 + 0x30); | |
rcc_ahb1enr.write::<u32>(rcc_ahb1enr.read_u32() | (1 << 12)); | |
asm::nop(); // wait cycle | |
let crc_dr = VolatileReg::new(0x4002_3000); | |
let _crc_idr = VolatileReg::new(0x4002_3000 + 0x4); | |
let crc_cr = VolatileReg::new(0x4002_3000 + 0x8); | |
let _crc_init = VolatileReg::new(0x4002_3000 + 0x10); | |
let _crc_pol = VolatileReg::new(0x4002_3000 + 0x14); | |
// Reset CRC unit, enable reflection of values (both in and out) | |
crc_cr.write::<u32>(0x1 | (1 << 7) | (1 << 5)); | |
asm::nop(); // wait cycle | |
// Note: can be optimized doing in blocks of 4 bytes w/ 4 wait cycles | |
for d in data { | |
crc_dr.write(*d); | |
asm::nop(); // wait cycle (1 per byte) | |
} | |
!crc_dr.read_u32() | |
} | |
} | |
#[entry] | |
fn main() -> ! { | |
let data = b"Bart"; | |
hprintln!("CRC32 of 'Bart' is 0x{:X}.", Crc32::calculate(data)).unwrap(); | |
loop { | |
asm::nop(); | |
} | |
} | |
struct VolatileReg { | |
addr: usize, | |
} | |
impl VolatileReg { | |
pub fn new(addr: usize) -> Self { | |
Self { addr } | |
} | |
#[inline(always)] | |
pub fn read<T: Sized>(&self) -> T { | |
unsafe { core::ptr::read_volatile::<T>(self.addr as *const T) } | |
} | |
#[inline(always)] | |
pub fn read_u32(&self) -> u32 { | |
unsafe { core::ptr::read_volatile(self.addr as *const u32) } | |
} | |
#[inline(always)] | |
pub fn write<T: Sized>(&self, v: T) { | |
unsafe { core::ptr::write_volatile::<T>(self.addr as *mut T, v) } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment