aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Balbi <[email protected]>2025-12-03 14:07:57 -0800
committerFelipe Balbi <[email protected]>2025-12-05 08:01:13 -0800
commitae285b84ed551aa5c81443fcacb73e788a6d36c2 (patch)
tree920f04c2c4fe9fbead55ec931a08a9dbd59b84bb
parenta382238225ea55ee478bbde9ddb7d0d37cf004b5 (diff)
CRC
Fixes #74 Signed-off-by: Felipe Balbi <[email protected]>
-rw-r--r--embassy-mcxa/src/clocks/mod.rs2
-rw-r--r--embassy-mcxa/src/crc.rs756
-rw-r--r--embassy-mcxa/src/lib.rs1
-rw-r--r--examples/mcxa/src/bin/crc.rs39
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
3use core::marker::PhantomData;
4
5use embassy_hal_internal::Peri;
6use mcxa_pac::crc0::ctrl::{Fxor, Tot, Totr};
7
8use crate::clocks::enable_and_reset;
9use crate::clocks::periph_helpers::NoConfig;
10use crate::peripherals::CRC0;
11
12/// CRC driver.
13pub struct Crc<'d, M> {
14 _peri: Peri<'d, CRC0>,
15 _phantom: PhantomData<M>,
16}
17
18impl<'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
74impl<'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
255impl<'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
367mod sealed {
368 pub trait SealedMode {}
369}
370
371/// Mode of operation: 32 or 16-bit CRC.
372#[allow(private_bounds)]
373pub trait Mode: sealed::SealedMode {}
374
375/// 16-bit CRC.
376pub struct Crc16;
377impl sealed::SealedMode for Crc16 {}
378impl Mode for Crc16 {}
379
380/// 32-bit CRC.
381pub struct Crc32;
382impl sealed::SealedMode for Crc32 {}
383impl Mode for Crc32 {}
384
385/// CRC configuration.
386#[derive(Copy, Clone, Debug)]
387#[non_exhaustive]
388pub 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
405impl 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
425impl 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)]
439pub 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
465impl 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)]
635pub enum Algorithm32 {
636 Bzip2,
637 C,
638 D,
639 IsoHdlc,
640 JamCrc,
641 Mpeg2,
642 Posix,
643 Q,
644 Xfer,
645}
646
647impl 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)]
719pub enum Reflect {
720 No,
721 Yes,
722}
723
724impl 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
733impl 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)]
744pub enum Complement {
745 No,
746 Yes,
747}
748
749impl 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
12pub mod adc; 12pub mod adc;
13pub mod clkout; 13pub mod clkout;
14pub mod config; 14pub mod config;
15pub mod crc;
15pub mod i2c; 16pub mod i2c;
16pub mod interrupt; 17pub mod interrupt;
17pub mod lpuart; 18pub 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
4use embassy_executor::Spawner;
5use hal::config::Config;
6use hal::crc::Crc;
7use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
8
9#[embassy_executor::main]
10async 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}