diff --git a/Cargo.toml b/Cargo.toml index 700ce88..856d49d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ license = "MIT/Apache-2.0" [dependencies] # hpm-metapac = { path = "../hpm-data/build/hpm-metapac" } -hpm-metapac = { version = "0.0.4", git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-7b07750284fa2b5b3f6b09c72e70ea6dd4d2231d" } +hpm-metapac = { version = "0.0.5", git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-71a17c4971e813a2c7151de990cbe05fe9a19a70" } riscv = { version = "0.11", features = ["critical-section-single-hart"] } riscv-rt = { version = "0.12.2", optional = true } @@ -43,16 +43,17 @@ embedded-hal-async = "1.0.0" chrono = { version = "0.4.38", default-features = false, optional = true } mcan = { version = "0.5.0", optional = true } embedded-storage = "0.3.1" +rand_core = "0.6.4" [build-dependencies] # hpm-metapac = { path = "../hpm-data/build/hpm-metapac", default-features = false, features = [ # "metadata", # ] } -hpm-metapac = { version = "0.0.4", git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-7b07750284fa2b5b3f6b09c72e70ea6dd4d2231d", default-features = false, features = [ +hpm-metapac = { git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-71a17c4971e813a2c7151de990cbe05fe9a19a70", default-features = false, features = [ "metadata", ] } -proc-macro2 = "1.0.85" -quote = "1.0.15" +proc-macro2 = "1.0.86" +quote = "1.0.37" [features] default = ["rt", "embassy", "defmt", "time"] diff --git a/examples/hpm6300evk/Cargo.toml b/examples/hpm6300evk/Cargo.toml index e712b17..9161803 100644 --- a/examples/hpm6300evk/Cargo.toml +++ b/examples/hpm6300evk/Cargo.toml @@ -4,11 +4,11 @@ version = "0.1.0" edition = "2021" [dependencies] -# hpm-metapac = { version = "0.0.4", features = [ +# hpm-metapac = { features = [ # "hpm6360", # "memory-x", # "rt", -# ], git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-7b07750284fa2b5b3f6b09c72e70ea6dd4d2231d" } +# ], git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-71a17c4971e813a2c7151de990cbe05fe9a19a70" } hpm-hal = { path = "../..", features = ["rt", "embassy", "hpm6360"] } defmt = "0.3.8" defmt-rtt = "0.4.1" diff --git a/examples/hpm6750evkmini/Cargo.toml b/examples/hpm6750evkmini/Cargo.toml index b502196..359be6d 100644 --- a/examples/hpm6750evkmini/Cargo.toml +++ b/examples/hpm6750evkmini/Cargo.toml @@ -7,11 +7,11 @@ edition = "2021" defmt = "0.3.8" defmt-rtt = "0.4.1" embedded-hal = "1.0.0" -#hpm-metapac = { version = "0.0.4", features = [ +# hpm-metapac = { features = [ # "hpm6750", # "memory-x", # "rt", -#], git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-7b07750284fa2b5b3f6b09c72e70ea6dd4d2231d" } +#], git = "https://github.com/hpmicro-rs/hpm-metapac.git", tag = "hpm-data-71a17c4971e813a2c7151de990cbe05fe9a19a70" } hpm-hal = { path = "../..", features = ["rt", "embassy", "hpm6750", "chrono"] } diff --git a/src/lib.rs b/src/lib.rs index c41c5a9..9c93c8b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,6 +69,8 @@ pub mod dac; // motor control peripherals #[cfg(qei)] pub mod qei; +#[cfg(rng)] +pub mod rng; #[cfg(trgm)] pub mod trgm; diff --git a/src/rng.rs b/src/rng.rs new file mode 100644 index 0000000..e3cd315 --- /dev/null +++ b/src/rng.rs @@ -0,0 +1,146 @@ +//! RNG, Random Number Generator +//! +//! RNG interrupt support: +//! - seed generated, self-test done +//! - error occurred +//! - FIFO underflow +//! + +use embassy_hal_internal::{into_ref, Peripheral, PeripheralRef}; +use rand_core::{CryptoRng, RngCore}; + +use crate::pac; + +/// RNG error +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub enum Error { + /// Function error. + FuncError, + /// Self-test error. + SelfTestError, +} + +#[allow(unused)] +pub struct Rng<'d, T: Instance> { + _peri: PeripheralRef<'d, T>, +} + +impl<'d, T: Instance> Rng<'d, T> { + pub fn new(peri: impl Peripheral

+ 'd) -> Result, Error> { + into_ref!(peri); + + T::add_resource_group(0); + + let mut this = Rng { _peri: peri }; + this.init()?; + + Ok(this) + } + + fn init(&mut self) -> Result<(), Error> { + let r = T::regs(); + + // disable interrupts. RNG interrupt is useless. + r.ctrl().modify(|w| { + w.set_mirqdn(true); + w.set_mirqerr(true); + w.set_fufmod(0b00); + }); + + r.cmd().modify(|w| w.set_clrerr(true)); // clear all error and interrupt flags + r.cmd().modify(|w| w.set_gensd(true)); // generate seed + while !r.sta().read().fsddn() { + if r.sta().read().funcerr() { + return Err(Error::FuncError); + } + } + r.ctrl().modify(|w| w.set_autrsd(true)); // auto reseed + + Ok(()) + } + + pub fn reset(&mut self) -> Result<(), Error> { + T::regs().cmd().modify(|w| w.set_sftrst(true)); + self.init()?; + + Ok(()) + } + + /// Run self-test + pub fn run_selftest(&mut self) -> Result<(), Error> { + let r = T::regs(); + r.cmd().modify(|w| w.set_slfchk(true)); + + loop { + let status = r.sta().read(); + + if status.funcerr() { + return Err(Error::FuncError); + } else if status.scdn() { + // self-test done + if status.scpf() != 0 { + return Err(Error::SelfTestError); + } else { + break; + } + } + // loop until self-test done + } + + Ok(()) + } +} + +impl<'d, T: Instance> RngCore for Rng<'d, T> { + fn next_u32(&mut self) -> u32 { + while T::regs().sta().read().busy() {} + T::regs().fo2b().read().0 + } + + fn next_u64(&mut self) -> u64 { + let mut rand = self.next_u32() as u64; + rand |= (self.next_u32() as u64) << 32; + rand + } + + fn fill_bytes(&mut self, dest: &mut [u8]) { + for chunk in dest.chunks_mut(4) { + let rand = self.next_u32(); + for (slot, num) in chunk.iter_mut().zip(rand.to_ne_bytes().iter()) { + *slot = *num + } + } + } + + fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> { + self.fill_bytes(dest); + Ok(()) + } +} + +impl<'d, T: Instance> CryptoRng for Rng<'d, T> {} + +pub(crate) trait SealedInstance { + fn regs() -> pac::rng::Rng; +} + +#[allow(private_bounds)] +pub trait Instance: SealedInstance + crate::sysctl::ClockPeripheral + 'static { + // /// Interrupt for this RNG instance. + // type Interrupt: interrupt::typelevel::Interrupt; +} + +foreach_peripheral!( + (rng, $inst:ident) => { + impl SealedInstance for crate::peripherals::$inst { + fn regs() -> pac::rng::Rng { + pac::$inst + } + } + + impl Instance for crate::peripherals::$inst { + // type Interrupt = crate::interrupt::typelevel::$inst; + } + }; +);