Skip to content

Commit

Permalink
feat(rng): add rng driver
Browse files Browse the repository at this point in the history
  • Loading branch information
andelf committed Oct 1, 2024
1 parent 32fb3bd commit a51c638
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 8 deletions.
9 changes: 5 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down Expand Up @@ -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"]
Expand Down
4 changes: 2 additions & 2 deletions examples/hpm6300evk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 2 additions & 2 deletions examples/hpm6750evkmini/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }

Expand Down
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
146 changes: 146 additions & 0 deletions src/rng.rs
Original file line number Diff line number Diff line change
@@ -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<P = T> + 'd) -> Result<Rng<'d, T>, 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;
}
};
);

0 comments on commit a51c638

Please sign in to comment.