embassy_stm32/crc/
v2v3.rs

1use crate::pac::crc::vals;
2use crate::pac::CRC as PAC_CRC;
3use crate::peripherals::CRC;
4use crate::{rcc, Peri};
5
6/// CRC driver.
7pub struct Crc<'d> {
8    _peripheral: Peri<'d, CRC>,
9    _config: Config,
10}
11
12/// CRC configuration error
13#[derive(Debug)]
14#[cfg_attr(feature = "defmt", derive(defmt::Format))]
15pub enum ConfigError {
16    /// The selected polynomial is invalid.
17    InvalidPolynomial,
18}
19
20/// CRC configuration
21pub struct Config {
22    reverse_in: InputReverseConfig,
23    reverse_out: bool,
24    #[cfg(crc_v3)]
25    poly_size: PolySize,
26    crc_init_value: u32,
27    #[cfg(crc_v3)]
28    crc_poly: u32,
29}
30
31/// Input reverse configuration.
32pub enum InputReverseConfig {
33    /// Don't reverse anything
34    None,
35    /// Reverse bytes
36    Byte,
37    /// Reverse 16-bit halfwords
38    Halfword,
39    /// Reverse 32-bit words
40    Word,
41}
42
43impl Config {
44    /// Create a new CRC config.
45    pub fn new(
46        reverse_in: InputReverseConfig,
47        reverse_out: bool,
48        #[cfg(crc_v3)] poly_size: PolySize,
49        crc_init_value: u32,
50        #[cfg(crc_v3)] crc_poly: u32,
51    ) -> Result<Self, ConfigError> {
52        // As Per RM0091 (DocID018940 Rev 9), Even polynomials are not supported.
53        #[cfg(crc_v3)]
54        if crc_poly % 2 == 0 {
55            return Err(ConfigError::InvalidPolynomial);
56        }
57        Ok(Config {
58            reverse_in,
59            reverse_out,
60            #[cfg(crc_v3)]
61            poly_size,
62            crc_init_value,
63            #[cfg(crc_v3)]
64            crc_poly,
65        })
66    }
67}
68
69/// Polynomial size
70#[cfg(crc_v3)]
71#[allow(missing_docs)]
72pub enum PolySize {
73    Width7,
74    Width8,
75    Width16,
76    Width32,
77}
78
79impl<'d> Crc<'d> {
80    /// Instantiates the CRC32 peripheral and initializes it to default values.
81    pub fn new(peripheral: Peri<'d, CRC>, config: Config) -> Self {
82        // Note: enable and reset come from RccPeripheral.
83        // reset to default values and enable CRC clock in RCC.
84        rcc::enable_and_reset::<CRC>();
85        let mut instance = Self {
86            _peripheral: peripheral,
87            _config: config,
88        };
89        instance.reconfigure();
90        instance.reset();
91        instance
92    }
93
94    /// Reset the CRC engine.
95    pub fn reset(&mut self) {
96        PAC_CRC.cr().modify(|w| w.set_reset(true));
97    }
98
99    /// Reconfigures the CRC peripheral. Doesn't reset.
100    fn reconfigure(&mut self) {
101        // Init CRC value
102        PAC_CRC.init().write_value(self._config.crc_init_value);
103        #[cfg(crc_v3)]
104        PAC_CRC.pol().write_value(self._config.crc_poly);
105
106        // configure CR components
107        // (reverse I/O, polysize, poly)
108        PAC_CRC.cr().write(|w| {
109            // configure reverse output
110            w.set_rev_out(match self._config.reverse_out {
111                true => vals::RevOut::REVERSED,
112                false => vals::RevOut::NORMAL,
113            });
114            // configure reverse input
115            w.set_rev_in(match self._config.reverse_in {
116                InputReverseConfig::None => vals::RevIn::NORMAL,
117                InputReverseConfig::Byte => vals::RevIn::BYTE,
118                InputReverseConfig::Halfword => vals::RevIn::HALF_WORD,
119                InputReverseConfig::Word => vals::RevIn::WORD,
120            });
121            // configure the polynomial.
122            #[cfg(crc_v3)]
123            w.set_polysize(match self._config.poly_size {
124                PolySize::Width7 => vals::Polysize::POLYSIZE7,
125                PolySize::Width8 => vals::Polysize::POLYSIZE8,
126                PolySize::Width16 => vals::Polysize::POLYSIZE16,
127                PolySize::Width32 => vals::Polysize::POLYSIZE32,
128            });
129        });
130    }
131
132    /// Read the CRC result value.
133    pub fn read(&self) -> u32 {
134        PAC_CRC.dr32().read()
135    }
136
137    /// Feeds a byte into the CRC peripheral. Returns the computed CRC.
138    pub fn feed_byte(&mut self, byte: u8) -> u32 {
139        PAC_CRC.dr8().write_value(byte);
140        self.read()
141    }
142
143    /// Feeds a slice of bytes into the CRC peripheral. Returns the computed CRC.
144    pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 {
145        for byte in bytes {
146            PAC_CRC.dr8().write_value(*byte);
147        }
148        self.read()
149    }
150
151    /// Feeds a halfword into the CRC peripheral. Returns the computed CRC.
152    pub fn feed_halfword(&mut self, halfword: u16) -> u32 {
153        PAC_CRC.dr16().write_value(halfword);
154        self.read()
155    }
156
157    /// Feeds a slice of halfwords into the CRC peripheral. Returns the computed CRC.
158    pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 {
159        for halfword in halfwords {
160            PAC_CRC.dr16().write_value(*halfword);
161        }
162        self.read()
163    }
164
165    /// Feeds a word into the CRC peripheral. Returns the computed CRC.
166    pub fn feed_word(&mut self, word: u32) -> u32 {
167        PAC_CRC.dr32().write_value(word as u32);
168        self.read()
169    }
170
171    /// Feeds a slice of words into the CRC peripheral. Returns the computed CRC.
172    pub fn feed_words(&mut self, words: &[u32]) -> u32 {
173        for word in words {
174            PAC_CRC.dr32().write_value(*word as u32);
175        }
176        self.read()
177    }
178}