1#![deny(missing_docs)]
18
19use crate::rcc::{self, Enable};
20use crate::stm32::CRC;
21use core::hash::Hasher;
22
23pub trait CrcExt {
25 fn constrain(self, ahb1: &mut rcc::AHB1) -> Config;
27}
28
29impl CrcExt for CRC {
30 fn constrain(self, ahb1: &mut rcc::AHB1) -> Config {
31 CRC::enable(ahb1);
33
34 Config {
36 initial_value: 0xffff_ffff,
37 polynomial: Polynomial::L32(0x04c1_1db7),
38 input_bit_reversal: None,
39 output_bit_reversal: false,
40 }
41 }
42}
43
44pub enum Polynomial {
46 L7(u8),
48 L8(u8),
50 L16(u16),
52 L32(u32),
54}
55
56pub enum BitReversal {
58 ByByte,
60 ByHalfWord,
62 ByWord,
64}
65
66pub struct Config {
68 initial_value: u32,
69 polynomial: Polynomial,
70 input_bit_reversal: Option<BitReversal>,
71 output_bit_reversal: bool,
72}
73
74impl Config {
75 pub fn initial_value(mut self, init: u32) -> Self {
77 self.initial_value = init;
78
79 self
80 }
81
82 pub fn polynomial(mut self, polynomial: Polynomial) -> Self {
84 self.polynomial = polynomial;
85
86 self
87 }
88
89 pub fn input_bit_reversal(mut self, rev: BitReversal) -> Self {
91 self.input_bit_reversal = Some(rev);
92
93 self
94 }
95
96 pub fn output_bit_reversal(mut self, rev: bool) -> Self {
98 self.output_bit_reversal = rev;
99
100 self
101 }
102
103 pub fn freeze(self) -> Crc {
105 let crc = unsafe { &(*CRC::ptr()) };
106
107 let (poly, poly_bits, init) = match self.polynomial {
108 Polynomial::L7(val) => ((val & 0x7f) as u32, 0b11, self.initial_value & 0x7f),
109 Polynomial::L8(val) => (val as u32, 0b10, self.initial_value & 0xff),
110 Polynomial::L16(val) => (val as u32, 0b01, self.initial_value & 0xffff),
111 Polynomial::L32(val) => (val, 0b00, self.initial_value),
112 };
113
114 let in_rev_bits = match self.input_bit_reversal {
115 None => 0b00,
116 Some(BitReversal::ByByte) => 0b01,
117 Some(BitReversal::ByHalfWord) => 0b10,
118 Some(BitReversal::ByWord) => 0b11,
119 };
120
121 crc.init.write(|w| w.init().bits(init));
122 crc.pol.write(|w| unsafe { w.bits(poly) });
123 crc.cr.write(|w| {
124 w.rev_in()
125 .bits(in_rev_bits)
126 .polysize()
127 .bits(poly_bits)
128 .reset()
129 .set_bit();
130
131 if self.output_bit_reversal {
132 w.rev_out().set_bit()
133 } else {
134 w.rev_out().clear_bit()
135 }
136 });
137
138 Crc {}
139 }
140}
141
142pub struct Crc {}
144
145impl Crc {
146 #[inline]
148 pub fn reset(&mut self) {
149 let crc = unsafe { &(*CRC::ptr()) };
150
151 crc.cr.modify(|_, w| w.reset().set_bit());
152 }
153
154 #[inline]
159 pub fn reset_with_inital_value(&mut self, initial_value: u32) {
160 let crc = unsafe { &(*CRC::ptr()) };
161
162 crc.init.write(|w| w.init().bits(initial_value));
163 crc.cr.modify(|_, w| w.reset().set_bit());
164 }
165
166 #[inline]
168 pub fn feed(&mut self, data: &[u8]) {
169 let crc = unsafe { &(*CRC::ptr()) };
170 for &byte in data {
171 crc.dr8().write(|w| w.dr8().bits(byte));
172 }
173 }
174
175 #[inline]
178 pub fn result(&mut self) -> u32 {
179 let ret = self.peek_result();
180
181 self.reset();
182
183 ret
184 }
185
186 #[inline]
189 pub fn peek_result(&self) -> u32 {
190 let crc = unsafe { &(*CRC::ptr()) };
191
192 crc.dr().read().bits()
193 }
194}
195
196impl Hasher for Crc {
197 #[inline]
198 fn finish(&self) -> u64 {
199 self.peek_result() as u64
202 }
203
204 #[inline]
205 fn write(&mut self, data: &[u8]) {
206 self.feed(data);
207 }
208}