I have the following (simplified) code as part of an embedded application:
use rand_hc::Hc128Rng;
use rand_core::{RngCore, SeedableRng};
use crate::board_hal::{EEPROMRead, EEPROMProgram};
// Don't use AtomicRefCell because init_rng stack becomes too big
pub(crate) static mut RNG: Option<Hc128Rng> = None;
const RNG_SEED_U32_LEN: usize = 32/core::mem::size_of::<u32>();
const RNG_SEED_LOC: u32 = 0x80;
// WARNING: one temp RNG instace is created on the stack
// Using AtomicRefCell leads to *two*
pub fn init_rng() {
let mut seed: [u32; RNG_SEED_U32_LEN] = [0; RNG_SEED_U32_LEN];
unsafe {
EEPROMRead(seed.as_mut_ptr(), RNG_SEED_LOC, RNG_SEED_U32_LEN.try_into().unwrap());
let seed_u8_slice = bytemuck::bytes_of(&seed);
RNG = Some(Hc128Rng::from_seed(seed_u8_slice.try_into().unwrap()));
}
}
Which shows up as having the following stack when compiled in release mode:
The disassembly also shows that an instance of Hc128Rng
(~4KB in size when the target device has 32KB of RAM) is constructed on the stack and then memcpy
ed into the static variable's location, instead of being constructed in-place at the static variable's location. Is there a way to do an in-place construction of large structs like this (possibly using core::ptr::write
or similar)?
In this case, the immediate solution is to switch to an RNG with a smaller state (which I'll probably end up doing), but the general question still stands.