diff options
| author | Felipe Balbi <[email protected]> | 2025-04-11 14:28:59 -0700 |
|---|---|---|
| committer | Felipe Balbi <[email protected]> | 2025-05-09 07:21:40 -0700 |
| commit | d4c378e059443dbaaaece02a0f5148db62bd4484 (patch) | |
| tree | ba915c7065111c6620e2383273191241202daa26 /embassy-imxrt/src/crc.rs | |
| parent | 64a2b9b2a36adbc26117b8e76ae2b178a5e3eb9f (diff) | |
Add embassy-imxrt CRC driver
Diffstat (limited to 'embassy-imxrt/src/crc.rs')
| -rw-r--r-- | embassy-imxrt/src/crc.rs | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/embassy-imxrt/src/crc.rs b/embassy-imxrt/src/crc.rs new file mode 100644 index 000000000..24d6ba5bd --- /dev/null +++ b/embassy-imxrt/src/crc.rs | |||
| @@ -0,0 +1,190 @@ | |||
| 1 | //! Cyclic Redundancy Check (CRC) | ||
| 2 | |||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 5 | use crate::clocks::{enable_and_reset, SysconPeripheral}; | ||
| 6 | pub use crate::pac::crc_engine::mode::CrcPolynomial as Polynomial; | ||
| 7 | use crate::{peripherals, Peri, PeripheralType}; | ||
| 8 | |||
| 9 | /// CRC driver. | ||
| 10 | pub struct Crc<'d> { | ||
| 11 | info: Info, | ||
| 12 | _config: Config, | ||
| 13 | _lifetime: PhantomData<&'d ()>, | ||
| 14 | } | ||
| 15 | |||
| 16 | /// CRC configuration | ||
| 17 | pub struct Config { | ||
| 18 | /// Polynomial to be used | ||
| 19 | pub polynomial: Polynomial, | ||
| 20 | |||
| 21 | /// Reverse bit order of input? | ||
| 22 | pub reverse_in: bool, | ||
| 23 | |||
| 24 | /// 1's complement input? | ||
| 25 | pub complement_in: bool, | ||
| 26 | |||
| 27 | /// Reverse CRC bit order? | ||
| 28 | pub reverse_out: bool, | ||
| 29 | |||
| 30 | /// 1's complement CRC? | ||
| 31 | pub complement_out: bool, | ||
| 32 | |||
| 33 | /// CRC Seed | ||
| 34 | pub seed: u32, | ||
| 35 | } | ||
| 36 | |||
| 37 | impl Config { | ||
| 38 | /// Create a new CRC config. | ||
| 39 | #[must_use] | ||
| 40 | pub fn new( | ||
| 41 | polynomial: Polynomial, | ||
| 42 | reverse_in: bool, | ||
| 43 | complement_in: bool, | ||
| 44 | reverse_out: bool, | ||
| 45 | complement_out: bool, | ||
| 46 | seed: u32, | ||
| 47 | ) -> Self { | ||
| 48 | Config { | ||
| 49 | polynomial, | ||
| 50 | reverse_in, | ||
| 51 | complement_in, | ||
| 52 | reverse_out, | ||
| 53 | complement_out, | ||
| 54 | seed, | ||
| 55 | } | ||
| 56 | } | ||
| 57 | } | ||
| 58 | |||
| 59 | impl Default for Config { | ||
| 60 | fn default() -> Self { | ||
| 61 | Self { | ||
| 62 | polynomial: Polynomial::CrcCcitt, | ||
| 63 | reverse_in: false, | ||
| 64 | complement_in: false, | ||
| 65 | reverse_out: false, | ||
| 66 | complement_out: false, | ||
| 67 | seed: 0xffff, | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | |||
| 72 | impl<'d> Crc<'d> { | ||
| 73 | /// Instantiates new CRC peripheral and initializes to default values. | ||
| 74 | pub fn new<T: Instance>(_peripheral: Peri<'d, T>, config: Config) -> Self { | ||
| 75 | // enable CRC clock | ||
| 76 | enable_and_reset::<T>(); | ||
| 77 | |||
| 78 | let mut instance = Self { | ||
| 79 | info: T::info(), | ||
| 80 | _config: config, | ||
| 81 | _lifetime: PhantomData, | ||
| 82 | }; | ||
| 83 | |||
| 84 | instance.reconfigure(); | ||
| 85 | instance | ||
| 86 | } | ||
| 87 | |||
| 88 | /// Reconfigured the CRC peripheral. | ||
| 89 | fn reconfigure(&mut self) { | ||
| 90 | self.info.regs.mode().write(|w| { | ||
| 91 | w.crc_poly() | ||
| 92 | .variant(self._config.polynomial) | ||
| 93 | .bit_rvs_wr() | ||
| 94 | .variant(self._config.reverse_in) | ||
| 95 | .cmpl_wr() | ||
| 96 | .variant(self._config.complement_in) | ||
| 97 | .bit_rvs_sum() | ||
| 98 | .variant(self._config.reverse_out) | ||
| 99 | .cmpl_sum() | ||
| 100 | .variant(self._config.complement_out) | ||
| 101 | }); | ||
| 102 | |||
| 103 | // Init CRC value | ||
| 104 | self.info | ||
| 105 | .regs | ||
| 106 | .seed() | ||
| 107 | .write(|w| unsafe { w.crc_seed().bits(self._config.seed) }); | ||
| 108 | } | ||
| 109 | |||
| 110 | /// Feeds a byte into the CRC peripheral. Returns the computed checksum. | ||
| 111 | pub fn feed_byte(&mut self, byte: u8) -> u32 { | ||
| 112 | self.info.regs.wr_data8().write(|w| unsafe { w.bits(byte) }); | ||
| 113 | |||
| 114 | self.info.regs.sum().read().bits() | ||
| 115 | } | ||
| 116 | |||
| 117 | /// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum. | ||
| 118 | pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { | ||
| 119 | let (prefix, data, suffix) = unsafe { bytes.align_to::<u32>() }; | ||
| 120 | |||
| 121 | for b in prefix { | ||
| 122 | self.info.regs.wr_data8().write(|w| unsafe { w.bits(*b) }); | ||
| 123 | } | ||
| 124 | |||
| 125 | for d in data { | ||
| 126 | self.info.regs.wr_data32().write(|w| unsafe { w.bits(*d) }); | ||
| 127 | } | ||
| 128 | |||
| 129 | for b in suffix { | ||
| 130 | self.info.regs.wr_data8().write(|w| unsafe { w.bits(*b) }); | ||
| 131 | } | ||
| 132 | |||
| 133 | self.info.regs.sum().read().bits() | ||
| 134 | } | ||
| 135 | |||
| 136 | /// Feeds a halfword into the CRC peripheral. Returns the computed checksum. | ||
| 137 | pub fn feed_halfword(&mut self, halfword: u16) -> u32 { | ||
| 138 | self.info.regs.wr_data16().write(|w| unsafe { w.bits(halfword) }); | ||
| 139 | |||
| 140 | self.info.regs.sum().read().bits() | ||
| 141 | } | ||
| 142 | |||
| 143 | /// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum. | ||
| 144 | pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { | ||
| 145 | for halfword in halfwords { | ||
| 146 | self.info.regs.wr_data16().write(|w| unsafe { w.bits(*halfword) }); | ||
| 147 | } | ||
| 148 | |||
| 149 | self.info.regs.sum().read().bits() | ||
| 150 | } | ||
| 151 | |||
| 152 | /// Feeds a words into the CRC peripheral. Returns the computed checksum. | ||
| 153 | pub fn feed_word(&mut self, word: u32) -> u32 { | ||
| 154 | self.info.regs.wr_data32().write(|w| unsafe { w.bits(word) }); | ||
| 155 | |||
| 156 | self.info.regs.sum().read().bits() | ||
| 157 | } | ||
| 158 | |||
| 159 | /// Feeds an slice of words into the CRC peripheral. Returns the computed checksum. | ||
| 160 | pub fn feed_words(&mut self, words: &[u32]) -> u32 { | ||
| 161 | for word in words { | ||
| 162 | self.info.regs.wr_data32().write(|w| unsafe { w.bits(*word) }); | ||
| 163 | } | ||
| 164 | |||
| 165 | self.info.regs.sum().read().bits() | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | struct Info { | ||
| 170 | regs: crate::pac::CrcEngine, | ||
| 171 | } | ||
| 172 | |||
| 173 | trait SealedInstance { | ||
| 174 | fn info() -> Info; | ||
| 175 | } | ||
| 176 | |||
| 177 | /// CRC instance trait. | ||
| 178 | #[allow(private_bounds)] | ||
| 179 | pub trait Instance: SealedInstance + PeripheralType + SysconPeripheral + 'static + Send {} | ||
| 180 | |||
| 181 | impl Instance for peripherals::CRC {} | ||
| 182 | |||
| 183 | impl SealedInstance for peripherals::CRC { | ||
| 184 | fn info() -> Info { | ||
| 185 | // SAFETY: safe from single executor | ||
| 186 | Info { | ||
| 187 | regs: unsafe { crate::pac::CrcEngine::steal() }, | ||
| 188 | } | ||
| 189 | } | ||
| 190 | } | ||
