1#![deny(missing_docs)]
20
21use crate::rcc::{Enable, Rcc, Reset};
22use crate::stm32::CRC;
23use core::hash::Hasher;
24use core::ptr;
25
26pub trait CrcExt {
28 fn constrain(self, rcc: &mut Rcc) -> Config;
30}
31
32impl CrcExt for CRC {
33 fn constrain(self, rcc: &mut Rcc) -> Config {
34 CRC::enable(rcc);
35 CRC::reset(rcc);
36
37 Config {
39 initial_value: 0xffff_ffff,
40 polynomial: Polynomial::L32(0x04c1_1db7),
41 input_bit_reversal: None,
42 output_bit_reversal: false,
43 }
44 }
45}
46
47pub enum Polynomial {
49 L7(u8),
51 L8(u8),
53 L16(u16),
55 L32(u32),
57}
58
59pub enum BitReversal {
61 ByByte,
63 ByHalfWord,
65 ByWord,
67}
68
69pub struct Config {
71 initial_value: u32,
72 polynomial: Polynomial,
73 input_bit_reversal: Option<BitReversal>,
74 output_bit_reversal: bool,
75}
76
77impl Config {
78 pub fn initial_value(mut self, init: u32) -> Self {
80 self.initial_value = init;
81
82 self
83 }
84
85 pub fn polynomial(mut self, polynomial: Polynomial) -> Self {
87 self.polynomial = polynomial;
88
89 self
90 }
91
92 pub fn input_bit_reversal(mut self, rev: Option<BitReversal>) -> Self {
94 self.input_bit_reversal = rev;
95
96 self
97 }
98
99 pub fn output_bit_reversal(mut self, rev: bool) -> Self {
101 self.output_bit_reversal = rev;
102
103 self
104 }
105
106 pub fn freeze(self) -> Crc {
108 let crc = unsafe { &(*CRC::ptr()) };
109
110 let (poly, poly_bits, init) = match self.polynomial {
111 Polynomial::L7(val) => ((val & 0x7f) as u32, 0b11, self.initial_value & 0x7f),
112 Polynomial::L8(val) => (val as u32, 0b10, self.initial_value & 0xff),
113 Polynomial::L16(val) => (val as u32, 0b01, self.initial_value & 0xffff),
114 Polynomial::L32(val) => (val, 0b00, self.initial_value),
115 };
116
117 let in_rev_bits = match self.input_bit_reversal {
118 None => 0b00,
119 Some(BitReversal::ByByte) => 0b01,
120 Some(BitReversal::ByHalfWord) => 0b10,
121 Some(BitReversal::ByWord) => 0b11,
122 };
123
124 crc.init.write(|w| unsafe { w.crc_init().bits(init) });
125 crc.pol.write(|w| unsafe { w.bits(poly) });
126 crc.cr.write(|w| {
127 unsafe {
128 w.rev_in()
129 .bits(in_rev_bits)
130 .polysize()
131 .bits(poly_bits)
132 .reset()
133 .set_bit();
134 }
135
136 if self.output_bit_reversal {
137 w.rev_out().set_bit()
138 } else {
139 w.rev_out().clear_bit()
140 }
141 });
142
143 Crc {}
144 }
145}
146
147pub struct Crc {}
149
150impl Crc {
151 #[inline]
153 pub fn reset(&mut self) {
154 let crc = unsafe { &(*CRC::ptr()) };
155
156 crc.cr.modify(|_, w| w.reset().set_bit());
157 }
158
159 #[inline]
164 pub fn reset_with_inital_value(&mut self, initial_value: u32) {
165 let crc = unsafe { &(*CRC::ptr()) };
166
167 crc.init
168 .write(|w| unsafe { w.crc_init().bits(initial_value) });
169 crc.cr.modify(|_, w| w.reset().set_bit());
170 }
171
172 #[inline]
174 pub fn feed(&mut self, data: &[u8]) {
175 let crc = unsafe { &(*CRC::ptr()) };
176 for byte in data {
177 unsafe {
178 ptr::write_volatile(&crc.dr as *const _ as *mut u8, *byte);
181 }
182 }
183 }
184
185 #[inline]
188 pub fn result(&mut self) -> u32 {
189 let ret = self.peek_result();
190
191 self.reset();
192
193 ret
194 }
195
196 #[inline]
199 pub fn peek_result(&self) -> u32 {
200 let crc = unsafe { &(*CRC::ptr()) };
201
202 crc.dr.read().bits()
203 }
204}
205
206impl Hasher for Crc {
207 #[inline]
208 fn finish(&self) -> u64 {
209 self.peek_result() as u64
212 }
213
214 #[inline]
215 fn write(&mut self, data: &[u8]) {
216 self.feed(data);
217 }
218}