diff options
| author | Felipe Balbi <[email protected]> | 2025-12-03 14:07:57 -0800 |
|---|---|---|
| committer | Felipe Balbi <[email protected]> | 2025-12-05 08:01:13 -0800 |
| commit | ae285b84ed551aa5c81443fcacb73e788a6d36c2 (patch) | |
| tree | 920f04c2c4fe9fbead55ec931a08a9dbd59b84bb | |
| parent | a382238225ea55ee478bbde9ddb7d0d37cf004b5 (diff) | |
CRC
Fixes #74
Signed-off-by: Felipe Balbi <[email protected]>
| -rw-r--r-- | embassy-mcxa/src/clocks/mod.rs | 2 | ||||
| -rw-r--r-- | embassy-mcxa/src/crc.rs | 756 | ||||
| -rw-r--r-- | embassy-mcxa/src/lib.rs | 1 | ||||
| -rw-r--r-- | examples/mcxa/src/bin/crc.rs | 39 |
4 files changed, 798 insertions, 0 deletions
diff --git a/embassy-mcxa/src/clocks/mod.rs b/embassy-mcxa/src/clocks/mod.rs index 9c9e6ef3d..1b23a9d9f 100644 --- a/embassy-mcxa/src/clocks/mod.rs +++ b/embassy-mcxa/src/clocks/mod.rs | |||
| @@ -923,6 +923,8 @@ pub(crate) mod gate { | |||
| 923 | impl_cc_gate!(GPIO3, mrcc_glb_cc2, mrcc_glb_rst2, gpio3, NoConfig); | 923 | impl_cc_gate!(GPIO3, mrcc_glb_cc2, mrcc_glb_rst2, gpio3, NoConfig); |
| 924 | impl_cc_gate!(GPIO4, mrcc_glb_cc2, mrcc_glb_rst2, gpio4, NoConfig); | 924 | impl_cc_gate!(GPIO4, mrcc_glb_cc2, mrcc_glb_rst2, gpio4, NoConfig); |
| 925 | 925 | ||
| 926 | impl_cc_gate!(CRC0, mrcc_glb_cc0, mrcc_glb_rst0, crc0, NoConfig); | ||
| 927 | |||
| 926 | // These peripherals DO have meaningful configuration, and could fail if the system | 928 | // These peripherals DO have meaningful configuration, and could fail if the system |
| 927 | // clocks do not match their needs. | 929 | // clocks do not match their needs. |
| 928 | #[cfg(not(feature = "time"))] | 930 | #[cfg(not(feature = "time"))] |
diff --git a/embassy-mcxa/src/crc.rs b/embassy-mcxa/src/crc.rs new file mode 100644 index 000000000..83b5eca8d --- /dev/null +++ b/embassy-mcxa/src/crc.rs | |||
| @@ -0,0 +1,756 @@ | |||
| 1 | //! Cyclic Redundandy Check (CRC) | ||
| 2 | |||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 5 | use embassy_hal_internal::Peri; | ||
| 6 | use mcxa_pac::crc0::ctrl::{Fxor, Tot, Totr}; | ||
| 7 | |||
| 8 | use crate::clocks::enable_and_reset; | ||
| 9 | use crate::clocks::periph_helpers::NoConfig; | ||
| 10 | use crate::peripherals::CRC0; | ||
| 11 | |||
| 12 | /// CRC driver. | ||
| 13 | pub struct Crc<'d, M> { | ||
| 14 | _peri: Peri<'d, CRC0>, | ||
| 15 | _phantom: PhantomData<M>, | ||
| 16 | } | ||
| 17 | |||
| 18 | impl<'d, M: Mode> Crc<'d, M> { | ||
| 19 | fn new_inner(_peri: Peri<'d, CRC0>) -> Self { | ||
| 20 | _ = unsafe { enable_and_reset::<CRC0>(&NoConfig) }; | ||
| 21 | |||
| 22 | Crc { | ||
| 23 | _peri, | ||
| 24 | _phantom: PhantomData, | ||
| 25 | } | ||
| 26 | } | ||
| 27 | |||
| 28 | // Configure the underlying peripheral. `f` is expected to set the | ||
| 29 | // operating mode to either 16- or 32-bits. | ||
| 30 | fn configure<F>(config: Config, f: F) | ||
| 31 | where | ||
| 32 | F: FnOnce(), | ||
| 33 | { | ||
| 34 | f(); | ||
| 35 | |||
| 36 | Self::regs().ctrl().modify(|_, w| { | ||
| 37 | w.fxor() | ||
| 38 | .variant(config.complement_out.into()) | ||
| 39 | .totr() | ||
| 40 | .variant(config.reflect_out.into()) | ||
| 41 | .tot() | ||
| 42 | .variant(config.reflect_in.into()) | ||
| 43 | .was() | ||
| 44 | .data() | ||
| 45 | }); | ||
| 46 | |||
| 47 | Self::regs().gpoly32().write(|w| unsafe { w.bits(config.polynomial) }); | ||
| 48 | |||
| 49 | Self::regs().ctrl().modify(|_, w| w.was().seed()); | ||
| 50 | Self::regs().data32().write(|w| unsafe { w.bits(config.seed) }); | ||
| 51 | Self::regs().ctrl().modify(|_, w| w.was().data()); | ||
| 52 | } | ||
| 53 | |||
| 54 | fn regs() -> &'static crate::pac::crc0::RegisterBlock { | ||
| 55 | unsafe { &*crate::pac::Crc0::ptr() } | ||
| 56 | } | ||
| 57 | |||
| 58 | /// Feeds a byte into the CRC peripheral. | ||
| 59 | fn feed_byte(&mut self, byte: u8) { | ||
| 60 | Self::regs().data8().write(|w| unsafe { w.bits(byte) }); | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Feeds a halfword into the CRC peripheral. | ||
| 64 | fn feed_halfword(&mut self, halfword: u16) { | ||
| 65 | Self::regs().data16().write(|w| unsafe { w.bits(halfword) }); | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Feeds a word into the CRC peripheral. | ||
| 69 | fn feed_word(&mut self, word: u32) { | ||
| 70 | Self::regs().data32().write(|w| unsafe { w.bits(word) }); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | impl<'d> Crc<'d, Crc16> { | ||
| 75 | /// Instantiates a new CRC peripheral driver in 16-bit mode | ||
| 76 | pub fn new_crc16(peri: Peri<'d, CRC0>, config: Config) -> Self { | ||
| 77 | let inst = Self::new_inner(peri); | ||
| 78 | |||
| 79 | Self::configure(config, || { | ||
| 80 | Self::regs().ctrl().modify(|_, w| w.tcrc().b16()); | ||
| 81 | }); | ||
| 82 | |||
| 83 | inst | ||
| 84 | } | ||
| 85 | |||
| 86 | /// Instantiates a new CRC peripheral driver for the given `Algorithm16`. | ||
| 87 | pub fn new_algorithm16(peri: Peri<'d, CRC0>, algorithm: Algorithm16) -> Self { | ||
| 88 | Self::new_crc16(peri, algorithm.into_config()) | ||
| 89 | } | ||
| 90 | |||
| 91 | /// Instantiates a new CRC peripheral for the `A` algorithm. | ||
| 92 | pub fn new_a(peri: Peri<'d, CRC0>) -> Self { | ||
| 93 | Self::new_algorithm16(peri, Algorithm16::A) | ||
| 94 | } | ||
| 95 | |||
| 96 | /// Instantiates a new CRC peripheral for the `AugCcitt` algorithm. | ||
| 97 | pub fn new_aug_ccitt(peri: Peri<'d, CRC0>) -> Self { | ||
| 98 | Self::new_algorithm16(peri, Algorithm16::AugCcitt) | ||
| 99 | } | ||
| 100 | |||
| 101 | /// Instantiates a new CRC peripheral for the `Arc` algorithm. | ||
| 102 | pub fn new_arc(peri: Peri<'d, CRC0>) -> Self { | ||
| 103 | Self::new_algorithm16(peri, Algorithm16::Arc) | ||
| 104 | } | ||
| 105 | |||
| 106 | /// Instantiates a new CRC peripheral for the `Buypass` algorithm. | ||
| 107 | pub fn new_buypass(peri: Peri<'d, CRC0>) -> Self { | ||
| 108 | Self::new_algorithm16(peri, Algorithm16::Buypass) | ||
| 109 | } | ||
| 110 | |||
| 111 | /// Instantiates a new CRC peripheral for the `CcittFalse` algorithm. | ||
| 112 | pub fn new_ccitt_false(peri: Peri<'d, CRC0>) -> Self { | ||
| 113 | Self::new_algorithm16(peri, Algorithm16::CcittFalse) | ||
| 114 | } | ||
| 115 | |||
| 116 | /// Instantiates a new CRC peripheral for the `CcittZero` algorithm. | ||
| 117 | pub fn new_ccitt_zero(peri: Peri<'d, CRC0>) -> Self { | ||
| 118 | Self::new_algorithm16(peri, Algorithm16::CcittZero) | ||
| 119 | } | ||
| 120 | |||
| 121 | /// Instantiates a new CRC peripheral for the `Cdma2000` algorithm. | ||
| 122 | pub fn new_cdma_2000(peri: Peri<'d, CRC0>) -> Self { | ||
| 123 | Self::new_algorithm16(peri, Algorithm16::Cdma2000) | ||
| 124 | } | ||
| 125 | |||
| 126 | /// Instantiates a new CRC peripheral for the `Dds110` algorithm. | ||
| 127 | pub fn new_dds_110(peri: Peri<'d, CRC0>) -> Self { | ||
| 128 | Self::new_algorithm16(peri, Algorithm16::Dds110) | ||
| 129 | } | ||
| 130 | |||
| 131 | /// Instantiates a new CRC peripheral for the `DectX` algorithm. | ||
| 132 | pub fn new_dect_x(peri: Peri<'d, CRC0>) -> Self { | ||
| 133 | Self::new_algorithm16(peri, Algorithm16::DectX) | ||
| 134 | } | ||
| 135 | |||
| 136 | /// Instantiates a new CRC peripheral for the `Dnp` algorithm. | ||
| 137 | pub fn new_dnp(peri: Peri<'d, CRC0>) -> Self { | ||
| 138 | Self::new_algorithm16(peri, Algorithm16::Dnp) | ||
| 139 | } | ||
| 140 | |||
| 141 | /// Instantiates a new CRC peripheral for the `En13757` algorithm. | ||
| 142 | pub fn new_en13757(peri: Peri<'d, CRC0>) -> Self { | ||
| 143 | Self::new_algorithm16(peri, Algorithm16::En13757) | ||
| 144 | } | ||
| 145 | |||
| 146 | /// Instantiates a new CRC peripheral for the `Genibus` algorithm. | ||
| 147 | pub fn new_genibus(peri: Peri<'d, CRC0>) -> Self { | ||
| 148 | Self::new_algorithm16(peri, Algorithm16::Genibus) | ||
| 149 | } | ||
| 150 | |||
| 151 | /// Instantiates a new CRC peripheral for the `Kermit` algorithm. | ||
| 152 | pub fn new_kermit(peri: Peri<'d, CRC0>) -> Self { | ||
| 153 | Self::new_algorithm16(peri, Algorithm16::Kermit) | ||
| 154 | } | ||
| 155 | |||
| 156 | /// Instantiates a new CRC peripheral for the `Maxim` algorithm. | ||
| 157 | pub fn new_maxim(peri: Peri<'d, CRC0>) -> Self { | ||
| 158 | Self::new_algorithm16(peri, Algorithm16::Maxim) | ||
| 159 | } | ||
| 160 | |||
| 161 | /// Instantiates a new CRC peripheral for the `Mcrf4xx` algorithm. | ||
| 162 | pub fn new_mcrf4xx(peri: Peri<'d, CRC0>) -> Self { | ||
| 163 | Self::new_algorithm16(peri, Algorithm16::Mcrf4xx) | ||
| 164 | } | ||
| 165 | |||
| 166 | /// Instantiates a new CRC peripheral for the `Modbus` algorithm. | ||
| 167 | pub fn new_modbus(peri: Peri<'d, CRC0>) -> Self { | ||
| 168 | Self::new_algorithm16(peri, Algorithm16::Modbus) | ||
| 169 | } | ||
| 170 | |||
| 171 | /// Instantiates a new CRC peripheral for the `Riello` algorithm. | ||
| 172 | pub fn new_riello(peri: Peri<'d, CRC0>) -> Self { | ||
| 173 | Self::new_algorithm16(peri, Algorithm16::Riello) | ||
| 174 | } | ||
| 175 | |||
| 176 | /// Instantiates a new CRC peripheral for the `T10Dif` algorithm. | ||
| 177 | pub fn new_t10_dif(peri: Peri<'d, CRC0>) -> Self { | ||
| 178 | Self::new_algorithm16(peri, Algorithm16::T10Dif) | ||
| 179 | } | ||
| 180 | |||
| 181 | /// Instantiates a new CRC peripheral for the `Teledisk` algorithm. | ||
| 182 | pub fn new_teledisk(peri: Peri<'d, CRC0>) -> Self { | ||
| 183 | Self::new_algorithm16(peri, Algorithm16::Teledisk) | ||
| 184 | } | ||
| 185 | |||
| 186 | /// Instantiates a new CRC peripheral for the `Tms37157` algorithm. | ||
| 187 | pub fn new_tms_37157(peri: Peri<'d, CRC0>) -> Self { | ||
| 188 | Self::new_algorithm16(peri, Algorithm16::Tms37157) | ||
| 189 | } | ||
| 190 | |||
| 191 | /// Instantiates a new CRC peripheral for the `Usb` algorithm. | ||
| 192 | pub fn new_usb(peri: Peri<'d, CRC0>) -> Self { | ||
| 193 | Self::new_algorithm16(peri, Algorithm16::Usb) | ||
| 194 | } | ||
| 195 | |||
| 196 | /// Instantiates a new CRC peripheral for the `X25` algorithm. | ||
| 197 | pub fn new_x25(peri: Peri<'d, CRC0>) -> Self { | ||
| 198 | Self::new_algorithm16(peri, Algorithm16::X25) | ||
| 199 | } | ||
| 200 | |||
| 201 | /// Instantiates a new CRC peripheral for the `Xmodem` algorithm. | ||
| 202 | pub fn new_xmodem(peri: Peri<'d, CRC0>) -> Self { | ||
| 203 | Self::new_algorithm16(peri, Algorithm16::Xmodem) | ||
| 204 | } | ||
| 205 | |||
| 206 | fn read_crc(&mut self) -> u16 { | ||
| 207 | // Reference manual states: | ||
| 208 | // | ||
| 209 | // "After writing all the data, you must wait for at least two | ||
| 210 | // clock cycles to read the data from CRC Data (DATA) | ||
| 211 | // register." | ||
| 212 | cortex_m::asm::delay(2); | ||
| 213 | |||
| 214 | let ctrl = Self::regs().ctrl().read(); | ||
| 215 | |||
| 216 | // if transposition is enabled, result sits in the upper 16 bits | ||
| 217 | if ctrl.totr().is_byts_trnps() || ctrl.totr().is_byts_bts_trnps() { | ||
| 218 | (Self::regs().data32().read().bits() >> 16) as u16 | ||
| 219 | } else { | ||
| 220 | Self::regs().data16().read().bits() | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | /// Feeds a slice of bytes into the CRC peripheral. Returns the computed checksum. | ||
| 225 | pub fn feed_bytes(&mut self, bytes: &[u8]) -> u16 { | ||
| 226 | let (prefix, data, suffix) = unsafe { bytes.align_to::<u32>() }; | ||
| 227 | |||
| 228 | for b in prefix { | ||
| 229 | self.feed_byte(*b); | ||
| 230 | } | ||
| 231 | |||
| 232 | // use 32-bit writes as long as possible | ||
| 233 | for w in data { | ||
| 234 | self.feed_word(*w); | ||
| 235 | } | ||
| 236 | |||
| 237 | for b in suffix { | ||
| 238 | self.feed_byte(*b); | ||
| 239 | } | ||
| 240 | |||
| 241 | // read back result. | ||
| 242 | self.read_crc() | ||
| 243 | } | ||
| 244 | |||
| 245 | /// Feeds a slice of halfwords into the CRC peripheral. Returns the computed checksum. | ||
| 246 | pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u16 { | ||
| 247 | for halfword in halfwords { | ||
| 248 | self.feed_halfword(*halfword); | ||
| 249 | } | ||
| 250 | |||
| 251 | self.read_crc() | ||
| 252 | } | ||
| 253 | } | ||
| 254 | |||
| 255 | impl<'d> Crc<'d, Crc32> { | ||
| 256 | /// Instantiates a new CRC peripheral driver in 32-bit mode | ||
| 257 | pub fn new_crc32(peri: Peri<'d, CRC0>, config: Config) -> Self { | ||
| 258 | let inst = Self::new_inner(peri); | ||
| 259 | |||
| 260 | Self::configure(config, || { | ||
| 261 | Self::regs().ctrl().modify(|_, w| w.tcrc().b32()); | ||
| 262 | }); | ||
| 263 | |||
| 264 | inst | ||
| 265 | } | ||
| 266 | |||
| 267 | /// Instantiates a new CRC peripheral driver for the given `Algorithm32`. | ||
| 268 | pub fn new_algorithm32(peri: Peri<'d, CRC0>, algorithm: Algorithm32) -> Self { | ||
| 269 | Self::new_crc32(peri, algorithm.into_config()) | ||
| 270 | } | ||
| 271 | |||
| 272 | /// Instantiates a new CRC peripheral for the `Bzip2` algorithm. | ||
| 273 | pub fn new_bzip2(peri: Peri<'d, CRC0>) -> Self { | ||
| 274 | Self::new_algorithm32(peri, Algorithm32::Bzip2) | ||
| 275 | } | ||
| 276 | |||
| 277 | /// Instantiates a new CRC peripheral for the `C` algorithm. | ||
| 278 | pub fn new_c(peri: Peri<'d, CRC0>) -> Self { | ||
| 279 | Self::new_algorithm32(peri, Algorithm32::C) | ||
| 280 | } | ||
| 281 | |||
| 282 | /// Instantiates a new CRC peripheral for the `D` algorithm. | ||
| 283 | pub fn new_d(peri: Peri<'d, CRC0>) -> Self { | ||
| 284 | Self::new_algorithm32(peri, Algorithm32::D) | ||
| 285 | } | ||
| 286 | |||
| 287 | /// Instantiates a new CRC peripheral for the `IsoHdlc` algorithm. | ||
| 288 | pub fn new_iso_hdlc(peri: Peri<'d, CRC0>) -> Self { | ||
| 289 | Self::new_algorithm32(peri, Algorithm32::IsoHdlc) | ||
| 290 | } | ||
| 291 | |||
| 292 | /// Instantiates a new CRC peripheral for the `JamCrc` algorithm. | ||
| 293 | pub fn new_jam_crc(peri: Peri<'d, CRC0>) -> Self { | ||
| 294 | Self::new_algorithm32(peri, Algorithm32::JamCrc) | ||
| 295 | } | ||
| 296 | |||
| 297 | /// Instantiates a new CRC peripheral for the `Mpeg2` algorithm. | ||
| 298 | pub fn new_mpeg2(peri: Peri<'d, CRC0>) -> Self { | ||
| 299 | Self::new_algorithm32(peri, Algorithm32::Mpeg2) | ||
| 300 | } | ||
| 301 | |||
| 302 | /// Instantiates a new CRC peripheral for the `Posix` algorithm. | ||
| 303 | pub fn new_posix(peri: Peri<'d, CRC0>) -> Self { | ||
| 304 | Self::new_algorithm32(peri, Algorithm32::Posix) | ||
| 305 | } | ||
| 306 | |||
| 307 | /// Instantiates a new CRC peripheral for the `Q` algorithm. | ||
| 308 | pub fn new_q(peri: Peri<'d, CRC0>) -> Self { | ||
| 309 | Self::new_algorithm32(peri, Algorithm32::Q) | ||
| 310 | } | ||
| 311 | |||
| 312 | /// Instantiates a new CRC peripheral for the `Xfer` algorithm. | ||
| 313 | pub fn new_xfer(peri: Peri<'d, CRC0>) -> Self { | ||
| 314 | Self::new_algorithm32(peri, Algorithm32::Xfer) | ||
| 315 | } | ||
| 316 | |||
| 317 | fn read_crc(&mut self) -> u32 { | ||
| 318 | // Reference manual states: | ||
| 319 | // | ||
| 320 | // "After writing all the data, you must wait for at least two | ||
| 321 | // clock cycles to read the data from CRC Data (DATA) | ||
| 322 | // register." | ||
| 323 | cortex_m::asm::delay(2); | ||
| 324 | Self::regs().data32().read().bits() | ||
| 325 | } | ||
| 326 | |||
| 327 | /// Feeds a slice of bytes into the CRC peripheral. Returns the computed checksum. | ||
| 328 | pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 { | ||
| 329 | let (prefix, data, suffix) = unsafe { bytes.align_to::<u32>() }; | ||
| 330 | |||
| 331 | for b in prefix { | ||
| 332 | self.feed_byte(*b); | ||
| 333 | } | ||
| 334 | |||
| 335 | // use 32-bit writes as long as possible | ||
| 336 | for w in data { | ||
| 337 | self.feed_word(*w); | ||
| 338 | } | ||
| 339 | |||
| 340 | for b in suffix { | ||
| 341 | self.feed_byte(*b); | ||
| 342 | } | ||
| 343 | |||
| 344 | // read back result. | ||
| 345 | self.read_crc() | ||
| 346 | } | ||
| 347 | |||
| 348 | /// Feeds a slice of halfwords into the CRC peripheral. Returns the computed checksum. | ||
| 349 | pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 { | ||
| 350 | for halfword in halfwords { | ||
| 351 | self.feed_halfword(*halfword); | ||
| 352 | } | ||
| 353 | |||
| 354 | self.read_crc() | ||
| 355 | } | ||
| 356 | |||
| 357 | /// Feeds a slice of words into the CRC peripheral. Returns the computed checksum. | ||
| 358 | pub fn feed_words(&mut self, words: &[u32]) -> u32 { | ||
| 359 | for word in words { | ||
| 360 | self.feed_word(*word); | ||
| 361 | } | ||
| 362 | |||
| 363 | self.read_crc() | ||
| 364 | } | ||
| 365 | } | ||
| 366 | |||
| 367 | mod sealed { | ||
| 368 | pub trait SealedMode {} | ||
| 369 | } | ||
| 370 | |||
| 371 | /// Mode of operation: 32 or 16-bit CRC. | ||
| 372 | #[allow(private_bounds)] | ||
| 373 | pub trait Mode: sealed::SealedMode {} | ||
| 374 | |||
| 375 | /// 16-bit CRC. | ||
| 376 | pub struct Crc16; | ||
| 377 | impl sealed::SealedMode for Crc16 {} | ||
| 378 | impl Mode for Crc16 {} | ||
| 379 | |||
| 380 | /// 32-bit CRC. | ||
| 381 | pub struct Crc32; | ||
| 382 | impl sealed::SealedMode for Crc32 {} | ||
| 383 | impl Mode for Crc32 {} | ||
| 384 | |||
| 385 | /// CRC configuration. | ||
| 386 | #[derive(Copy, Clone, Debug)] | ||
| 387 | #[non_exhaustive] | ||
| 388 | pub struct Config { | ||
| 389 | /// The CRC polynomial to be used. | ||
| 390 | pub polynomial: u32, | ||
| 391 | |||
| 392 | /// Reflect bit order of input? | ||
| 393 | pub reflect_in: Reflect, | ||
| 394 | |||
| 395 | /// Reflect CRC bit order? | ||
| 396 | pub reflect_out: Reflect, | ||
| 397 | |||
| 398 | /// 1's complement CRC? | ||
| 399 | pub complement_out: Complement, | ||
| 400 | |||
| 401 | /// CRC Seed | ||
| 402 | pub seed: u32, | ||
| 403 | } | ||
| 404 | |||
| 405 | impl Config { | ||
| 406 | /// Create a new CRC config. | ||
| 407 | #[must_use] | ||
| 408 | pub fn new( | ||
| 409 | polynomial: u32, | ||
| 410 | reflect_in: Reflect, | ||
| 411 | reflect_out: Reflect, | ||
| 412 | complement_out: Complement, | ||
| 413 | seed: u32, | ||
| 414 | ) -> Self { | ||
| 415 | Config { | ||
| 416 | polynomial, | ||
| 417 | reflect_in, | ||
| 418 | reflect_out, | ||
| 419 | complement_out, | ||
| 420 | seed, | ||
| 421 | } | ||
| 422 | } | ||
| 423 | } | ||
| 424 | |||
| 425 | impl Default for Config { | ||
| 426 | fn default() -> Self { | ||
| 427 | Self { | ||
| 428 | polynomial: 0, | ||
| 429 | reflect_in: Reflect::No, | ||
| 430 | reflect_out: Reflect::No, | ||
| 431 | complement_out: Complement::No, | ||
| 432 | seed: 0xffff_ffff, | ||
| 433 | } | ||
| 434 | } | ||
| 435 | } | ||
| 436 | |||
| 437 | /// Supported standard CRC16 algorithms. | ||
| 438 | #[derive(Copy, Clone, Debug)] | ||
| 439 | pub enum Algorithm16 { | ||
| 440 | A, | ||
| 441 | Arc, | ||
| 442 | AugCcitt, | ||
| 443 | Buypass, | ||
| 444 | CcittFalse, | ||
| 445 | CcittZero, | ||
| 446 | Cdma2000, | ||
| 447 | Dds110, | ||
| 448 | DectX, | ||
| 449 | Dnp, | ||
| 450 | En13757, | ||
| 451 | Genibus, | ||
| 452 | Kermit, | ||
| 453 | Maxim, | ||
| 454 | Mcrf4xx, | ||
| 455 | Modbus, | ||
| 456 | Riello, | ||
| 457 | T10Dif, | ||
| 458 | Teledisk, | ||
| 459 | Tms37157, | ||
| 460 | Usb, | ||
| 461 | X25, | ||
| 462 | Xmodem, | ||
| 463 | } | ||
| 464 | |||
| 465 | impl Algorithm16 { | ||
| 466 | fn into_config(self) -> Config { | ||
| 467 | match self { | ||
| 468 | Algorithm16::A => Config { | ||
| 469 | polynomial: 0x1021, | ||
| 470 | reflect_in: Reflect::Yes, | ||
| 471 | reflect_out: Reflect::Yes, | ||
| 472 | complement_out: Complement::No, | ||
| 473 | seed: 0xc6c6, | ||
| 474 | }, | ||
| 475 | Algorithm16::Arc => Config { | ||
| 476 | polynomial: 0x8005, | ||
| 477 | reflect_in: Reflect::Yes, | ||
| 478 | reflect_out: Reflect::Yes, | ||
| 479 | complement_out: Complement::No, | ||
| 480 | seed: 0, | ||
| 481 | }, | ||
| 482 | Algorithm16::AugCcitt => Config { | ||
| 483 | polynomial: 0x1021, | ||
| 484 | reflect_in: Reflect::No, | ||
| 485 | reflect_out: Reflect::No, | ||
| 486 | complement_out: Complement::No, | ||
| 487 | seed: 0x1d0f, | ||
| 488 | }, | ||
| 489 | Algorithm16::Buypass => Config { | ||
| 490 | polynomial: 0x8005, | ||
| 491 | reflect_in: Reflect::No, | ||
| 492 | reflect_out: Reflect::No, | ||
| 493 | complement_out: Complement::No, | ||
| 494 | seed: 0, | ||
| 495 | }, | ||
| 496 | Algorithm16::CcittFalse => Config { | ||
| 497 | polynomial: 0x1021, | ||
| 498 | reflect_in: Reflect::No, | ||
| 499 | reflect_out: Reflect::No, | ||
| 500 | complement_out: Complement::No, | ||
| 501 | seed: 0xffff, | ||
| 502 | }, | ||
| 503 | Algorithm16::CcittZero => Config { | ||
| 504 | polynomial: 0x1021, | ||
| 505 | reflect_in: Reflect::No, | ||
| 506 | reflect_out: Reflect::No, | ||
| 507 | complement_out: Complement::No, | ||
| 508 | seed: 0, | ||
| 509 | }, | ||
| 510 | Algorithm16::Cdma2000 => Config { | ||
| 511 | polynomial: 0xc867, | ||
| 512 | reflect_in: Reflect::No, | ||
| 513 | reflect_out: Reflect::No, | ||
| 514 | complement_out: Complement::No, | ||
| 515 | seed: 0xffff, | ||
| 516 | }, | ||
| 517 | Algorithm16::Dds110 => Config { | ||
| 518 | polynomial: 0x8005, | ||
| 519 | reflect_in: Reflect::No, | ||
| 520 | reflect_out: Reflect::No, | ||
| 521 | complement_out: Complement::No, | ||
| 522 | seed: 0x800d, | ||
| 523 | }, | ||
| 524 | Algorithm16::DectX => Config { | ||
| 525 | polynomial: 0x0589, | ||
| 526 | reflect_in: Reflect::No, | ||
| 527 | reflect_out: Reflect::No, | ||
| 528 | complement_out: Complement::No, | ||
| 529 | seed: 0, | ||
| 530 | }, | ||
| 531 | Algorithm16::Dnp => Config { | ||
| 532 | polynomial: 0x3d65, | ||
| 533 | reflect_in: Reflect::Yes, | ||
| 534 | reflect_out: Reflect::Yes, | ||
| 535 | complement_out: Complement::Yes, | ||
| 536 | seed: 0, | ||
| 537 | }, | ||
| 538 | Algorithm16::En13757 => Config { | ||
| 539 | polynomial: 0x3d65, | ||
| 540 | reflect_in: Reflect::No, | ||
| 541 | reflect_out: Reflect::No, | ||
| 542 | complement_out: Complement::Yes, | ||
| 543 | seed: 0, | ||
| 544 | }, | ||
| 545 | Algorithm16::Genibus => Config { | ||
| 546 | polynomial: 0x1021, | ||
| 547 | reflect_in: Reflect::No, | ||
| 548 | reflect_out: Reflect::No, | ||
| 549 | complement_out: Complement::Yes, | ||
| 550 | seed: 0xffff, | ||
| 551 | }, | ||
| 552 | Algorithm16::Kermit => Config { | ||
| 553 | polynomial: 0x1021, | ||
| 554 | reflect_in: Reflect::Yes, | ||
| 555 | reflect_out: Reflect::Yes, | ||
| 556 | complement_out: Complement::No, | ||
| 557 | seed: 0, | ||
| 558 | }, | ||
| 559 | Algorithm16::Maxim => Config { | ||
| 560 | polynomial: 0x8005, | ||
| 561 | reflect_in: Reflect::Yes, | ||
| 562 | reflect_out: Reflect::Yes, | ||
| 563 | complement_out: Complement::Yes, | ||
| 564 | seed: 0, | ||
| 565 | }, | ||
| 566 | Algorithm16::Mcrf4xx => Config { | ||
| 567 | polynomial: 0x1021, | ||
| 568 | reflect_in: Reflect::Yes, | ||
| 569 | reflect_out: Reflect::Yes, | ||
| 570 | complement_out: Complement::No, | ||
| 571 | seed: 0xffff, | ||
| 572 | }, | ||
| 573 | Algorithm16::Modbus => Config { | ||
| 574 | polynomial: 0x8005, | ||
| 575 | reflect_in: Reflect::Yes, | ||
| 576 | reflect_out: Reflect::Yes, | ||
| 577 | complement_out: Complement::No, | ||
| 578 | seed: 0xffff, | ||
| 579 | }, | ||
| 580 | Algorithm16::Riello => Config { | ||
| 581 | polynomial: 0x1021, | ||
| 582 | reflect_in: Reflect::Yes, | ||
| 583 | reflect_out: Reflect::Yes, | ||
| 584 | complement_out: Complement::No, | ||
| 585 | seed: 0xb2aa, | ||
| 586 | }, | ||
| 587 | Algorithm16::T10Dif => Config { | ||
| 588 | polynomial: 0x8bb7, | ||
| 589 | reflect_in: Reflect::No, | ||
| 590 | reflect_out: Reflect::No, | ||
| 591 | complement_out: Complement::No, | ||
| 592 | seed: 0, | ||
| 593 | }, | ||
| 594 | Algorithm16::Teledisk => Config { | ||
| 595 | polynomial: 0xa097, | ||
| 596 | reflect_in: Reflect::No, | ||
| 597 | reflect_out: Reflect::No, | ||
| 598 | complement_out: Complement::No, | ||
| 599 | seed: 0, | ||
| 600 | }, | ||
| 601 | Algorithm16::Tms37157 => Config { | ||
| 602 | polynomial: 0x1021, | ||
| 603 | reflect_in: Reflect::Yes, | ||
| 604 | reflect_out: Reflect::Yes, | ||
| 605 | complement_out: Complement::No, | ||
| 606 | seed: 0x89ec, | ||
| 607 | }, | ||
| 608 | Algorithm16::Usb => Config { | ||
| 609 | polynomial: 0x8005, | ||
| 610 | reflect_in: Reflect::Yes, | ||
| 611 | reflect_out: Reflect::Yes, | ||
| 612 | complement_out: Complement::No, | ||
| 613 | seed: 0xffff, | ||
| 614 | }, | ||
| 615 | Algorithm16::X25 => Config { | ||
| 616 | polynomial: 0x1021, | ||
| 617 | reflect_in: Reflect::Yes, | ||
| 618 | reflect_out: Reflect::Yes, | ||
| 619 | complement_out: Complement::Yes, | ||
| 620 | seed: 0xffff, | ||
| 621 | }, | ||
| 622 | Algorithm16::Xmodem => Config { | ||
| 623 | polynomial: 0x1021, | ||
| 624 | reflect_in: Reflect::No, | ||
| 625 | reflect_out: Reflect::No, | ||
| 626 | complement_out: Complement::No, | ||
| 627 | seed: 0, | ||
| 628 | }, | ||
| 629 | } | ||
| 630 | } | ||
| 631 | } | ||
| 632 | |||
| 633 | /// Supported standard CRC32 algorithms. | ||
| 634 | #[derive(Copy, Clone, Debug)] | ||
| 635 | pub enum Algorithm32 { | ||
| 636 | Bzip2, | ||
| 637 | C, | ||
| 638 | D, | ||
| 639 | IsoHdlc, | ||
| 640 | JamCrc, | ||
| 641 | Mpeg2, | ||
| 642 | Posix, | ||
| 643 | Q, | ||
| 644 | Xfer, | ||
| 645 | } | ||
| 646 | |||
| 647 | impl Algorithm32 { | ||
| 648 | fn into_config(self) -> Config { | ||
| 649 | match self { | ||
| 650 | Algorithm32::Bzip2 => Config { | ||
| 651 | polynomial: 0x04c1_1db7, | ||
| 652 | reflect_in: Reflect::No, | ||
| 653 | reflect_out: Reflect::No, | ||
| 654 | complement_out: Complement::Yes, | ||
| 655 | seed: 0xffff_ffff, | ||
| 656 | }, | ||
| 657 | Algorithm32::C => Config { | ||
| 658 | polynomial: 0x1edc_6f41, | ||
| 659 | reflect_in: Reflect::Yes, | ||
| 660 | reflect_out: Reflect::Yes, | ||
| 661 | complement_out: Complement::Yes, | ||
| 662 | seed: 0xffff_ffff, | ||
| 663 | }, | ||
| 664 | Algorithm32::D => Config { | ||
| 665 | polynomial: 0xa833_982b, | ||
| 666 | reflect_in: Reflect::Yes, | ||
| 667 | reflect_out: Reflect::Yes, | ||
| 668 | complement_out: Complement::Yes, | ||
| 669 | seed: 0xffff_ffff, | ||
| 670 | }, | ||
| 671 | Algorithm32::IsoHdlc => Config { | ||
| 672 | polynomial: 0x04c1_1db7, | ||
| 673 | reflect_in: Reflect::Yes, | ||
| 674 | reflect_out: Reflect::Yes, | ||
| 675 | complement_out: Complement::Yes, | ||
| 676 | seed: 0xffff_ffff, | ||
| 677 | }, | ||
| 678 | Algorithm32::JamCrc => Config { | ||
| 679 | polynomial: 0x04c1_1db7, | ||
| 680 | reflect_in: Reflect::Yes, | ||
| 681 | reflect_out: Reflect::Yes, | ||
| 682 | complement_out: Complement::No, | ||
| 683 | seed: 0xffff_ffff, | ||
| 684 | }, | ||
| 685 | Algorithm32::Mpeg2 => Config { | ||
| 686 | polynomial: 0x04c1_1db7, | ||
| 687 | reflect_in: Reflect::No, | ||
| 688 | reflect_out: Reflect::No, | ||
| 689 | complement_out: Complement::No, | ||
| 690 | seed: 0xffff_ffff, | ||
| 691 | }, | ||
| 692 | Algorithm32::Posix => Config { | ||
| 693 | polynomial: 0x04c1_1db7, | ||
| 694 | reflect_in: Reflect::No, | ||
| 695 | reflect_out: Reflect::No, | ||
| 696 | complement_out: Complement::Yes, | ||
| 697 | seed: 0, | ||
| 698 | }, | ||
| 699 | Algorithm32::Q => Config { | ||
| 700 | polynomial: 0x8141_41ab, | ||
| 701 | reflect_in: Reflect::No, | ||
| 702 | reflect_out: Reflect::No, | ||
| 703 | complement_out: Complement::No, | ||
| 704 | seed: 0, | ||
| 705 | }, | ||
| 706 | Algorithm32::Xfer => Config { | ||
| 707 | polynomial: 0x0000_00af, | ||
| 708 | reflect_in: Reflect::No, | ||
| 709 | reflect_out: Reflect::No, | ||
| 710 | complement_out: Complement::No, | ||
| 711 | seed: 0, | ||
| 712 | }, | ||
| 713 | } | ||
| 714 | } | ||
| 715 | } | ||
| 716 | |||
| 717 | /// Reflect bit order. | ||
| 718 | #[derive(Copy, Clone, Debug)] | ||
| 719 | pub enum Reflect { | ||
| 720 | No, | ||
| 721 | Yes, | ||
| 722 | } | ||
| 723 | |||
| 724 | impl From<Reflect> for Tot { | ||
| 725 | fn from(value: Reflect) -> Tot { | ||
| 726 | match value { | ||
| 727 | Reflect::No => Tot::BytsTrnps, | ||
| 728 | Reflect::Yes => Tot::BytsBtsTrnps, | ||
| 729 | } | ||
| 730 | } | ||
| 731 | } | ||
| 732 | |||
| 733 | impl From<Reflect> for Totr { | ||
| 734 | fn from(value: Reflect) -> Totr { | ||
| 735 | match value { | ||
| 736 | Reflect::No => Totr::Notrnps, | ||
| 737 | Reflect::Yes => Totr::BytsBtsTrnps, | ||
| 738 | } | ||
| 739 | } | ||
| 740 | } | ||
| 741 | |||
| 742 | /// 1's complement output. | ||
| 743 | #[derive(Copy, Clone, Debug)] | ||
| 744 | pub enum Complement { | ||
| 745 | No, | ||
| 746 | Yes, | ||
| 747 | } | ||
| 748 | |||
| 749 | impl From<Complement> for Fxor { | ||
| 750 | fn from(value: Complement) -> Fxor { | ||
| 751 | match value { | ||
| 752 | Complement::No => Fxor::Noxor, | ||
| 753 | Complement::Yes => Fxor::Invert, | ||
| 754 | } | ||
| 755 | } | ||
| 756 | } | ||
diff --git a/embassy-mcxa/src/lib.rs b/embassy-mcxa/src/lib.rs index c6d8adc8f..64eeb4012 100644 --- a/embassy-mcxa/src/lib.rs +++ b/embassy-mcxa/src/lib.rs | |||
| @@ -12,6 +12,7 @@ pub mod pins; // pin mux helpers | |||
| 12 | pub mod adc; | 12 | pub mod adc; |
| 13 | pub mod clkout; | 13 | pub mod clkout; |
| 14 | pub mod config; | 14 | pub mod config; |
| 15 | pub mod crc; | ||
| 15 | pub mod i2c; | 16 | pub mod i2c; |
| 16 | pub mod interrupt; | 17 | pub mod interrupt; |
| 17 | pub mod lpuart; | 18 | pub mod lpuart; |
diff --git a/examples/mcxa/src/bin/crc.rs b/examples/mcxa/src/bin/crc.rs new file mode 100644 index 000000000..417b4f865 --- /dev/null +++ b/examples/mcxa/src/bin/crc.rs | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use hal::config::Config; | ||
| 6 | use hal::crc::Crc; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 8 | |||
| 9 | #[embassy_executor::main] | ||
| 10 | async fn main(_spawner: Spawner) { | ||
| 11 | let config = Config::default(); | ||
| 12 | let mut p = hal::init(config); | ||
| 13 | |||
| 14 | defmt::info!("CRC example"); | ||
| 15 | |||
| 16 | let buf = b"123456789"; | ||
| 17 | |||
| 18 | let mut crc = Crc::new_ccitt_false(p.CRC0.reborrow()); | ||
| 19 | let sum = crc.feed_bytes(buf); | ||
| 20 | assert_eq!(sum, 0x29b1); | ||
| 21 | |||
| 22 | let mut crc = Crc::new_maxim(p.CRC0.reborrow()); | ||
| 23 | let sum = crc.feed_bytes(buf); | ||
| 24 | assert_eq!(sum, 0x44c2); | ||
| 25 | |||
| 26 | let mut crc = Crc::new_kermit(p.CRC0.reborrow()); | ||
| 27 | let sum = crc.feed_bytes(buf); | ||
| 28 | assert_eq!(sum, 0x2189); | ||
| 29 | |||
| 30 | let mut crc = Crc::new_iso_hdlc(p.CRC0.reborrow()); | ||
| 31 | let sum = crc.feed_bytes(buf); | ||
| 32 | assert_eq!(sum, 0xcbf4_3926); | ||
| 33 | |||
| 34 | let mut crc = Crc::new_posix(p.CRC0.reborrow()); | ||
| 35 | let sum = crc.feed_bytes(buf); | ||
| 36 | assert_eq!(sum, 0x765e_7680); | ||
| 37 | |||
| 38 | defmt::info!("CRC successful"); | ||
| 39 | } | ||
