Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
- stm32h7b0
- stm32h735
env: # Peripheral Feature flags
FLAGS: rt,xspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc
FLAGS: rt,xspi,sdmmc,sdmmc-fatfs,fmc,usb_hs,rtc,ethernet,ltdc,crc,rand

steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- log-semihost
- log-rtt
env: # Peripheral Feature flags
FLAGS: rt,xspi,sdmmc,fmc,usb_hs,rtc,ethernet,ltdc,crc
FLAGS: rt,xspi,sdmmc,sdmmc-fatfs,fmc,usb_hs,rtc,ethernet,ltdc,crc,rand

steps:
- uses: actions/checkout@v2
Expand Down
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ version = "0.4"
default-features = false
optional = true

[dependencies.rand_core]
version = "0.6"
default-features = false
optional = true

[dev-dependencies]
cortex-m-rt = ">=0.6.15,<0.8"
cortex-m-rtic = { version = "0.5.8", default-features = false, features = ["cortex-m-7"] }
Expand Down Expand Up @@ -93,6 +98,7 @@ sdmmc-fatfs = ["embedded-sdmmc", "sdmmc"]
ethernet = ["smoltcp"]
rtc = ["chrono"]
crc = []
rand = ["rand_core"]
rt = ["stm32h7/rt"]
usb_hs = ["synopsys-usb-otg", "synopsys-usb-otg/hs"]
stm32h742 = ["stm32h7/stm32h743", "device-selected", "rm0433"]
Expand Down
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
//! External Memory
//!
//! * [Flexible Memory Controller (FMC)](crate::fmc) Feature gate `fmc`
//! * [SD Card (SDMMC)](crate::sdmmc) Feature gate `sdmmc`
//! * [SD Card (SDMMC)](crate::sdmmc) Feature gate `sdmmc` (FAT16/32 driver is available under the `sdmmc-fatfs` feature gate)
//!
//! Timing functions
//!
Expand All @@ -44,7 +44,7 @@
//! Others
//!
//! * [Cyclic Redundancy Check (CRC)](crate::crc) Feature gate `crc`
//! * [Random Number Generator](crate::rng)
//! * [Random Number Generator](crate::rng) ([rand_core::RngCore](rand_core::RngCore) is implemented under the`rand` feature gate)
//! * [System Window Watchdog](crate::watchdog)

#![cfg_attr(not(test), no_std)]
Expand Down
104 changes: 100 additions & 4 deletions src/rng.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ use crate::time::Hertz;

#[derive(Debug)]
pub enum ErrorKind {
ClockError,
SeedError,
ClockError = 1,
SeedError = 2,
}

trait KerClk {
Expand Down Expand Up @@ -131,8 +131,104 @@ macro_rules! rng_core {
};
}

rng_core!(u32, u16, u8);
// Only for types larger than 32 bits
macro_rules! rng_core_large {
($($type:ty),+) => {
$(
impl RngCore<$type> for Rng {
fn gen(&mut self) -> Result<$type, ErrorKind> {
const WORDS: usize = mem::size_of::<$type>() / mem::size_of::<u32>();
let mut res: $type = 0;

for i in 0..WORDS {
res |= (self.value()? as $type) << (i * (mem::size_of::<u32>() * 8))
}

Ok(res)
}

fn fill(&mut self, dest: &mut [$type]) -> Result<(), ErrorKind> {
let len = dest.len() * (mem::size_of::<$type>() / mem::size_of::<u32>());
let ptr = dest.as_mut_ptr() as *mut u32;
let slice_u32 = unsafe { core::slice::from_raw_parts_mut(ptr, len) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is alignment an issue?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mem::align_of::<u32>() = 4
mem::align_of::<u64>() = 8
mem::align_of::<u128>() = 8

I don't think so. u64/u128 is 8-byte aligned which would be valid for 4-byte aligned values as well. https://doc.rust-lang.org/reference/type-layout.html#size-and-alignment

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, I hadn't seen the distinction between rng_core and rng_core_large.

self.fill(slice_u32)
}
}
)+
};
}

// Test host may have > 32-bit types, which we don't consider.
macro_rules! rng_core_transmute {
($($type:ty = $from:ty),+) => {
$(
impl RngCore<$type> for Rng {
fn gen(&mut self) -> Result<$type, ErrorKind> {
let num = <Self as RngCore<$from>>::gen(self)?;
Ok(unsafe { mem::transmute::<$from, $type>(num) })
}

fn fill(&mut self, dest: &mut [$type]) -> Result<(), ErrorKind> {
let unsigned_slice = unsafe { mem::transmute::<&mut [$type], &mut [$from]>(dest) };
<Self as RngCore<$from>>::fill(self, unsigned_slice)
}
}
)+
};
}

rng_core!(u8, u16, u32);
rng_core_large!(u64, u128);
rng_core_transmute!(
i8 = u8,
i16 = u16,
i32 = u32,
i64 = u64,
i128 = u128,
isize = usize
);

// If usize is 32 bits, use the rng_core! impl
#[cfg(target_pointer_width = "32")]
rng_core!(usize);

// If usize is 64 bits, use the rng_core_large! impl
#[cfg(target_pointer_width = "64")]
rng_core_large!(usize);

// rand_core
#[cfg(feature = "rand")]
impl rand_core::RngCore for Rng {
/// Generate a random u32
/// Panics if RNG fails.
fn next_u32(&mut self) -> u32 {
self.gen().unwrap()
}

/// Generate a random u64
/// Panics if RNG fails.
fn next_u64(&mut self) -> u64 {
self.gen().unwrap()
}

/// Fill a slice with random data.
/// Panics if RNG fails.
fn fill_bytes(&mut self, dest: &mut [u8]) {
self.fill(dest).unwrap()
}

/// Try to fill a slice with random data. Return an error if RNG fails.
fn try_fill_bytes(
&mut self,
dest: &mut [u8],
) -> Result<(), rand_core::Error> {
self.fill(dest).map_err(|e| {
core::num::NonZeroU32::new(e as u32)
// This should never fail as long as no enum variant is equal to 0
.expect("Internal hal error")
.into()
})
}
}

#[cfg(feature = "rand")]
impl rand_core::CryptoRng for Rng {}