aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/pages/imxrt.adoc2
-rw-r--r--embassy-imxrt/src/crc.rs190
-rw-r--r--embassy-imxrt/src/lib.rs1
-rw-r--r--examples/mimxrt6/src/bin/crc.rs175
4 files changed, 367 insertions, 1 deletions
diff --git a/docs/pages/imxrt.adoc b/docs/pages/imxrt.adoc
index adf5218e8..a84fbae03 100644
--- a/docs/pages/imxrt.adoc
+++ b/docs/pages/imxrt.adoc
@@ -9,5 +9,5 @@ The link: link:https://github.com/embassy-rs/embassy/tree/main/embassy-imxrt[Emb
9 9
10The following peripherals have a HAL implementation at present 10The following peripherals have a HAL implementation at present
11 11
12* CRC
12* GPIO 13* GPIO
13
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
3use core::marker::PhantomData;
4
5use crate::clocks::{enable_and_reset, SysconPeripheral};
6pub use crate::pac::crc_engine::mode::CrcPolynomial as Polynomial;
7use crate::{peripherals, Peri, PeripheralType};
8
9/// CRC driver.
10pub struct Crc<'d> {
11 info: Info,
12 _config: Config,
13 _lifetime: PhantomData<&'d ()>,
14}
15
16/// CRC configuration
17pub 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
37impl 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
59impl 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
72impl<'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
169struct Info {
170 regs: crate::pac::CrcEngine,
171}
172
173trait SealedInstance {
174 fn info() -> Info;
175}
176
177/// CRC instance trait.
178#[allow(private_bounds)]
179pub trait Instance: SealedInstance + PeripheralType + SysconPeripheral + 'static + Send {}
180
181impl Instance for peripherals::CRC {}
182
183impl 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}
diff --git a/embassy-imxrt/src/lib.rs b/embassy-imxrt/src/lib.rs
index ad9f81e88..d8ce97f76 100644
--- a/embassy-imxrt/src/lib.rs
+++ b/embassy-imxrt/src/lib.rs
@@ -18,6 +18,7 @@ compile_error!(
18pub(crate) mod fmt; 18pub(crate) mod fmt;
19 19
20pub mod clocks; 20pub mod clocks;
21pub mod crc;
21pub mod gpio; 22pub mod gpio;
22pub mod iopctl; 23pub mod iopctl;
23 24
diff --git a/examples/mimxrt6/src/bin/crc.rs b/examples/mimxrt6/src/bin/crc.rs
new file mode 100644
index 000000000..005a250e5
--- /dev/null
+++ b/examples/mimxrt6/src/bin/crc.rs
@@ -0,0 +1,175 @@
1#![no_std]
2#![no_main]
3
4extern crate embassy_imxrt_examples;
5
6use defmt::*;
7use embassy_executor::Spawner;
8use embassy_imxrt::crc::{Config, Crc, Polynomial};
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let mut p = embassy_imxrt::init(Default::default());
14 let data = b"123456789";
15
16 info!("Initializing CRC");
17
18 // CRC-CCITT
19 let mut crc = Crc::new(p.CRC.reborrow(), Default::default());
20 let output = crc.feed_bytes(data);
21 defmt::assert_eq!(output, 0x29b1);
22
23 // CRC16-ARC
24 let mut crc = Crc::new(
25 p.CRC.reborrow(),
26 Config {
27 polynomial: Polynomial::Crc16,
28 reverse_in: true,
29 reverse_out: true,
30 complement_out: false,
31 seed: 0,
32 ..Default::default()
33 },
34 );
35 let output = crc.feed_bytes(data);
36 defmt::assert_eq!(output, 0xbb3d);
37
38 // CRC16-CMS
39 let mut crc = Crc::new(
40 p.CRC.reborrow(),
41 Config {
42 polynomial: Polynomial::Crc16,
43 reverse_in: false,
44 reverse_out: false,
45 complement_out: false,
46 seed: 0xffff,
47 ..Default::default()
48 },
49 );
50 let output = crc.feed_bytes(data);
51 defmt::assert_eq!(output, 0xaee7);
52
53 // CRC16-DDS-110
54 let mut crc = Crc::new(
55 p.CRC.reborrow(),
56 Config {
57 polynomial: Polynomial::Crc16,
58 reverse_in: false,
59 reverse_out: false,
60 complement_out: false,
61 seed: 0x800d,
62 ..Default::default()
63 },
64 );
65 let output = crc.feed_bytes(data);
66 defmt::assert_eq!(output, 0x9ecf);
67
68 // CRC16-MAXIM-DOW
69 let mut crc = Crc::new(
70 p.CRC.reborrow(),
71 Config {
72 polynomial: Polynomial::Crc16,
73 reverse_in: true,
74 reverse_out: true,
75 complement_out: true,
76 seed: 0,
77 ..Default::default()
78 },
79 );
80 let output = crc.feed_bytes(data);
81 defmt::assert_eq!(output, 0x44c2);
82
83 // CRC16-MODBUS
84 let mut crc = Crc::new(
85 p.CRC.reborrow(),
86 Config {
87 polynomial: Polynomial::Crc16,
88 reverse_in: true,
89 reverse_out: true,
90 complement_out: false,
91 seed: 0xffff,
92 ..Default::default()
93 },
94 );
95 let output = crc.feed_bytes(data);
96 defmt::assert_eq!(output, 0x4b37);
97
98 // CRC32-BZIP2
99 let mut crc = Crc::new(
100 p.CRC.reborrow(),
101 Config {
102 polynomial: Polynomial::Crc32,
103 reverse_in: false,
104 reverse_out: false,
105 complement_out: true,
106 seed: 0xffff_ffff,
107 ..Default::default()
108 },
109 );
110 let output = crc.feed_bytes(data);
111 defmt::assert_eq!(output, 0xfc89_1918);
112
113 // CRC32-CKSUM
114 let mut crc = Crc::new(
115 p.CRC.reborrow(),
116 Config {
117 polynomial: Polynomial::Crc32,
118 reverse_in: false,
119 reverse_out: false,
120 complement_out: true,
121 seed: 0,
122 ..Default::default()
123 },
124 );
125 let output = crc.feed_bytes(data);
126 defmt::assert_eq!(output, 0x765e_7680);
127
128 // CRC32-ISO-HDLC
129 let mut crc = Crc::new(
130 p.CRC.reborrow(),
131 Config {
132 polynomial: Polynomial::Crc32,
133 reverse_in: true,
134 reverse_out: true,
135 complement_out: true,
136 seed: 0xffff_ffff,
137 ..Default::default()
138 },
139 );
140 let output = crc.feed_bytes(data);
141 defmt::assert_eq!(output, 0xcbf4_3926);
142
143 // CRC32-JAMCRC
144 let mut crc = Crc::new(
145 p.CRC.reborrow(),
146 Config {
147 polynomial: Polynomial::Crc32,
148 reverse_in: true,
149 reverse_out: true,
150 complement_out: false,
151 seed: 0xffff_ffff,
152 ..Default::default()
153 },
154 );
155 let output = crc.feed_bytes(data);
156 defmt::assert_eq!(output, 0x340b_c6d9);
157
158 // CRC32-MPEG-2
159 let mut crc = Crc::new(
160 p.CRC.reborrow(),
161 Config {
162 polynomial: Polynomial::Crc32,
163 reverse_in: false,
164 reverse_out: false,
165 complement_out: false,
166 seed: 0xffff_ffff,
167 ..Default::default()
168 },
169 );
170 let output = crc.feed_bytes(data);
171 defmt::assert_eq!(output, 0x0376_e6e7);
172
173 info!("end program");
174 cortex_m::asm::bkpt();
175}