Merge pull request #4181 from felipebalbi/add-crc
Add Embassy-iMXRT CRC driver
This commit is contained in:
commit
aa85293457
@ -9,5 +9,5 @@ The link: link:https://github.com/embassy-rs/embassy/tree/main/embassy-imxrt[Emb
|
||||
|
||||
The following peripherals have a HAL implementation at present
|
||||
|
||||
* CRC
|
||||
* GPIO
|
||||
|
||||
|
||||
190
embassy-imxrt/src/crc.rs
Normal file
190
embassy-imxrt/src/crc.rs
Normal file
@ -0,0 +1,190 @@
|
||||
//! Cyclic Redundancy Check (CRC)
|
||||
|
||||
use core::marker::PhantomData;
|
||||
|
||||
use crate::clocks::{enable_and_reset, SysconPeripheral};
|
||||
pub use crate::pac::crc_engine::mode::CrcPolynomial as Polynomial;
|
||||
use crate::{peripherals, Peri, PeripheralType};
|
||||
|
||||
/// CRC driver.
|
||||
pub struct Crc<'d> {
|
||||
info: Info,
|
||||
_config: Config,
|
||||
_lifetime: PhantomData<&'d ()>,
|
||||
}
|
||||
|
||||
/// CRC configuration
|
||||
pub struct Config {
|
||||
/// Polynomial to be used
|
||||
pub polynomial: Polynomial,
|
||||
|
||||
/// Reverse bit order of input?
|
||||
pub reverse_in: bool,
|
||||
|
||||
/// 1's complement input?
|
||||
pub complement_in: bool,
|
||||
|
||||
/// Reverse CRC bit order?
|
||||
pub reverse_out: bool,
|
||||
|
||||
/// 1's complement CRC?
|
||||
pub complement_out: bool,
|
||||
|
||||
/// CRC Seed
|
||||
pub seed: u32,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
/// Create a new CRC config.
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
polynomial: Polynomial,
|
||||
reverse_in: bool,
|
||||
complement_in: bool,
|
||||
reverse_out: bool,
|
||||
complement_out: bool,
|
||||
seed: u32,
|
||||
) -> Self {
|
||||
Config {
|
||||
polynomial,
|
||||
reverse_in,
|
||||
complement_in,
|
||||
reverse_out,
|
||||
complement_out,
|
||||
seed,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
polynomial: Polynomial::CrcCcitt,
|
||||
reverse_in: false,
|
||||
complement_in: false,
|
||||
reverse_out: false,
|
||||
complement_out: false,
|
||||
seed: 0xffff,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d> Crc<'d> {
|
||||
/// Instantiates new CRC peripheral and initializes to default values.
|
||||
pub fn new<T: Instance>(_peripheral: Peri<'d, T>, config: Config) -> Self {
|
||||
// enable CRC clock
|
||||
enable_and_reset::<T>();
|
||||
|
||||
let mut instance = Self {
|
||||
info: T::info(),
|
||||
_config: config,
|
||||
_lifetime: PhantomData,
|
||||
};
|
||||
|
||||
instance.reconfigure();
|
||||
instance
|
||||
}
|
||||
|
||||
/// Reconfigured the CRC peripheral.
|
||||
fn reconfigure(&mut self) {
|
||||
self.info.regs.mode().write(|w| {
|
||||
w.crc_poly()
|
||||
.variant(self._config.polynomial)
|
||||
.bit_rvs_wr()
|
||||
.variant(self._config.reverse_in)
|
||||
.cmpl_wr()
|
||||
.variant(self._config.complement_in)
|
||||
.bit_rvs_sum()
|
||||
.variant(self._config.reverse_out)
|
||||
.cmpl_sum()
|
||||
.variant(self._config.complement_out)
|
||||
});
|
||||
|
||||
// Init CRC value
|
||||
self.info
|
||||
.regs
|
||||
.seed()
|
||||
.write(|w| unsafe { w.crc_seed().bits(self._config.seed) });
|
||||
}
|
||||
|
||||
/// Feeds a byte into the CRC peripheral. Returns the computed checksum.
|
||||
pub fn feed_byte(&mut self, byte: u8) -> u32 {
|
||||
self.info.regs.wr_data8().write(|w| unsafe { w.bits(byte) });
|
||||
|
||||
self.info.regs.sum().read().bits()
|
||||
}
|
||||
|
||||
/// Feeds an slice of bytes into the CRC peripheral. Returns the computed checksum.
|
||||
pub fn feed_bytes(&mut self, bytes: &[u8]) -> u32 {
|
||||
let (prefix, data, suffix) = unsafe { bytes.align_to::<u32>() };
|
||||
|
||||
for b in prefix {
|
||||
self.info.regs.wr_data8().write(|w| unsafe { w.bits(*b) });
|
||||
}
|
||||
|
||||
for d in data {
|
||||
self.info.regs.wr_data32().write(|w| unsafe { w.bits(*d) });
|
||||
}
|
||||
|
||||
for b in suffix {
|
||||
self.info.regs.wr_data8().write(|w| unsafe { w.bits(*b) });
|
||||
}
|
||||
|
||||
self.info.regs.sum().read().bits()
|
||||
}
|
||||
|
||||
/// Feeds a halfword into the CRC peripheral. Returns the computed checksum.
|
||||
pub fn feed_halfword(&mut self, halfword: u16) -> u32 {
|
||||
self.info.regs.wr_data16().write(|w| unsafe { w.bits(halfword) });
|
||||
|
||||
self.info.regs.sum().read().bits()
|
||||
}
|
||||
|
||||
/// Feeds an slice of halfwords into the CRC peripheral. Returns the computed checksum.
|
||||
pub fn feed_halfwords(&mut self, halfwords: &[u16]) -> u32 {
|
||||
for halfword in halfwords {
|
||||
self.info.regs.wr_data16().write(|w| unsafe { w.bits(*halfword) });
|
||||
}
|
||||
|
||||
self.info.regs.sum().read().bits()
|
||||
}
|
||||
|
||||
/// Feeds a words into the CRC peripheral. Returns the computed checksum.
|
||||
pub fn feed_word(&mut self, word: u32) -> u32 {
|
||||
self.info.regs.wr_data32().write(|w| unsafe { w.bits(word) });
|
||||
|
||||
self.info.regs.sum().read().bits()
|
||||
}
|
||||
|
||||
/// Feeds an slice of words into the CRC peripheral. Returns the computed checksum.
|
||||
pub fn feed_words(&mut self, words: &[u32]) -> u32 {
|
||||
for word in words {
|
||||
self.info.regs.wr_data32().write(|w| unsafe { w.bits(*word) });
|
||||
}
|
||||
|
||||
self.info.regs.sum().read().bits()
|
||||
}
|
||||
}
|
||||
|
||||
struct Info {
|
||||
regs: crate::pac::CrcEngine,
|
||||
}
|
||||
|
||||
trait SealedInstance {
|
||||
fn info() -> Info;
|
||||
}
|
||||
|
||||
/// CRC instance trait.
|
||||
#[allow(private_bounds)]
|
||||
pub trait Instance: SealedInstance + PeripheralType + SysconPeripheral + 'static + Send {}
|
||||
|
||||
impl Instance for peripherals::CRC {}
|
||||
|
||||
impl SealedInstance for peripherals::CRC {
|
||||
fn info() -> Info {
|
||||
// SAFETY: safe from single executor
|
||||
Info {
|
||||
regs: unsafe { crate::pac::CrcEngine::steal() },
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ compile_error!(
|
||||
pub(crate) mod fmt;
|
||||
|
||||
pub mod clocks;
|
||||
pub mod crc;
|
||||
pub mod gpio;
|
||||
pub mod iopctl;
|
||||
|
||||
|
||||
175
examples/mimxrt6/src/bin/crc.rs
Normal file
175
examples/mimxrt6/src/bin/crc.rs
Normal file
@ -0,0 +1,175 @@
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
extern crate embassy_imxrt_examples;
|
||||
|
||||
use defmt::*;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_imxrt::crc::{Config, Crc, Polynomial};
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
|
||||
#[embassy_executor::main]
|
||||
async fn main(_spawner: Spawner) {
|
||||
let mut p = embassy_imxrt::init(Default::default());
|
||||
let data = b"123456789";
|
||||
|
||||
info!("Initializing CRC");
|
||||
|
||||
// CRC-CCITT
|
||||
let mut crc = Crc::new(p.CRC.reborrow(), Default::default());
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x29b1);
|
||||
|
||||
// CRC16-ARC
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc16,
|
||||
reverse_in: true,
|
||||
reverse_out: true,
|
||||
complement_out: false,
|
||||
seed: 0,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0xbb3d);
|
||||
|
||||
// CRC16-CMS
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc16,
|
||||
reverse_in: false,
|
||||
reverse_out: false,
|
||||
complement_out: false,
|
||||
seed: 0xffff,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0xaee7);
|
||||
|
||||
// CRC16-DDS-110
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc16,
|
||||
reverse_in: false,
|
||||
reverse_out: false,
|
||||
complement_out: false,
|
||||
seed: 0x800d,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x9ecf);
|
||||
|
||||
// CRC16-MAXIM-DOW
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc16,
|
||||
reverse_in: true,
|
||||
reverse_out: true,
|
||||
complement_out: true,
|
||||
seed: 0,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x44c2);
|
||||
|
||||
// CRC16-MODBUS
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc16,
|
||||
reverse_in: true,
|
||||
reverse_out: true,
|
||||
complement_out: false,
|
||||
seed: 0xffff,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x4b37);
|
||||
|
||||
// CRC32-BZIP2
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc32,
|
||||
reverse_in: false,
|
||||
reverse_out: false,
|
||||
complement_out: true,
|
||||
seed: 0xffff_ffff,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0xfc89_1918);
|
||||
|
||||
// CRC32-CKSUM
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc32,
|
||||
reverse_in: false,
|
||||
reverse_out: false,
|
||||
complement_out: true,
|
||||
seed: 0,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x765e_7680);
|
||||
|
||||
// CRC32-ISO-HDLC
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc32,
|
||||
reverse_in: true,
|
||||
reverse_out: true,
|
||||
complement_out: true,
|
||||
seed: 0xffff_ffff,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0xcbf4_3926);
|
||||
|
||||
// CRC32-JAMCRC
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc32,
|
||||
reverse_in: true,
|
||||
reverse_out: true,
|
||||
complement_out: false,
|
||||
seed: 0xffff_ffff,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x340b_c6d9);
|
||||
|
||||
// CRC32-MPEG-2
|
||||
let mut crc = Crc::new(
|
||||
p.CRC.reborrow(),
|
||||
Config {
|
||||
polynomial: Polynomial::Crc32,
|
||||
reverse_in: false,
|
||||
reverse_out: false,
|
||||
complement_out: false,
|
||||
seed: 0xffff_ffff,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
let output = crc.feed_bytes(data);
|
||||
defmt::assert_eq!(output, 0x0376_e6e7);
|
||||
|
||||
info!("end program");
|
||||
cortex_m::asm::bkpt();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user