diff options
| author | Raul Alimbekov <[email protected]> | 2025-12-16 09:05:22 +0300 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-12-16 09:05:22 +0300 |
| commit | c9a04b4b732b7a3b696eb8223664c1a7942b1875 (patch) | |
| tree | 6dbe5c02e66eed8d8762f13f95afd24f8db2b38c /embassy-mcxa/src/trng.rs | |
| parent | cde24a3ef1117653ba5ed4184102b33f745782fb (diff) | |
| parent | 5ae6e060ec1c90561719aabdc29d5b6e7b8b0a82 (diff) | |
Merge branch 'main' into main
Diffstat (limited to 'embassy-mcxa/src/trng.rs')
| -rw-r--r-- | embassy-mcxa/src/trng.rs | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/embassy-mcxa/src/trng.rs b/embassy-mcxa/src/trng.rs new file mode 100644 index 000000000..ce37e4b2a --- /dev/null +++ b/embassy-mcxa/src/trng.rs | |||
| @@ -0,0 +1,678 @@ | |||
| 1 | //! True Random Number Generator | ||
| 2 | |||
| 3 | use core::marker::PhantomData; | ||
| 4 | |||
| 5 | use embassy_hal_internal::Peri; | ||
| 6 | use embassy_hal_internal::interrupt::InterruptExt; | ||
| 7 | use maitake_sync::WaitCell; | ||
| 8 | use mcxa_pac::trng0::osc2_ctl::TrngEntCtl; | ||
| 9 | |||
| 10 | use crate::clocks::enable_and_reset; | ||
| 11 | use crate::clocks::periph_helpers::NoConfig; | ||
| 12 | use crate::interrupt::typelevel; | ||
| 13 | use crate::interrupt::typelevel::Handler; | ||
| 14 | use crate::peripherals::TRNG0; | ||
| 15 | |||
| 16 | static WAIT_CELL: WaitCell = WaitCell::new(); | ||
| 17 | |||
| 18 | #[allow(private_bounds)] | ||
| 19 | pub trait Mode: sealed::SealedMode {} | ||
| 20 | |||
| 21 | mod sealed { | ||
| 22 | pub trait SealedMode {} | ||
| 23 | } | ||
| 24 | |||
| 25 | macro_rules! define_mode { | ||
| 26 | ($mode:ident) => { | ||
| 27 | pub struct $mode; | ||
| 28 | impl sealed::SealedMode for $mode {} | ||
| 29 | impl Mode for $mode {} | ||
| 30 | }; | ||
| 31 | } | ||
| 32 | |||
| 33 | define_mode!(Blocking); | ||
| 34 | define_mode!(Async); | ||
| 35 | |||
| 36 | /// TRNG Driver | ||
| 37 | pub struct Trng<'d, M: Mode> { | ||
| 38 | _peri: Peri<'d, TRNG0>, | ||
| 39 | _phantom: PhantomData<M>, | ||
| 40 | } | ||
| 41 | |||
| 42 | impl<'d, M: Mode> Trng<'d, M> { | ||
| 43 | fn new_inner(_peri: Peri<'d, TRNG0>, config: Config) -> Self { | ||
| 44 | _ = unsafe { enable_and_reset::<TRNG0>(&NoConfig) }; | ||
| 45 | |||
| 46 | Self::configure(config); | ||
| 47 | Self { | ||
| 48 | _peri, | ||
| 49 | _phantom: PhantomData, | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | fn configure(config: Config) { | ||
| 54 | regs() | ||
| 55 | .mctl() | ||
| 56 | .modify(|_, w| w.rst_def().set_bit().prgm().enable().err().clear_bit_by_one()); | ||
| 57 | |||
| 58 | regs().scml().write(|w| unsafe { | ||
| 59 | w.mono_max() | ||
| 60 | .bits(config.monobit_limit_max) | ||
| 61 | .mono_rng() | ||
| 62 | .bits(config.monobit_limit_range) | ||
| 63 | }); | ||
| 64 | |||
| 65 | regs().scr1l().write(|w| unsafe { | ||
| 66 | w.run1_max() | ||
| 67 | .bits(config.run_length1_limit_max) | ||
| 68 | .run1_rng() | ||
| 69 | .bits(config.run_length1_limit_range) | ||
| 70 | }); | ||
| 71 | |||
| 72 | regs().scr2l().write(|w| unsafe { | ||
| 73 | w.run2_max() | ||
| 74 | .bits(config.run_length2_limit_max) | ||
| 75 | .run2_rng() | ||
| 76 | .bits(config.run_length2_limit_range) | ||
| 77 | }); | ||
| 78 | |||
| 79 | regs().scr3l().write(|w| unsafe { | ||
| 80 | w.run3_max() | ||
| 81 | .bits(config.run_length3_limit_max) | ||
| 82 | .run3_rng() | ||
| 83 | .bits(config.run_length3_limit_range) | ||
| 84 | }); | ||
| 85 | |||
| 86 | regs().scr4l().write(|w| unsafe { | ||
| 87 | w.run4_max() | ||
| 88 | .bits(config.run_length4_limit_max) | ||
| 89 | .run4_rng() | ||
| 90 | .bits(config.run_length4_limit_range) | ||
| 91 | }); | ||
| 92 | |||
| 93 | regs().scr5l().write(|w| unsafe { | ||
| 94 | w.run5_max() | ||
| 95 | .bits(config.run_length5_limit_max) | ||
| 96 | .run5_rng() | ||
| 97 | .bits(config.run_length5_limit_range) | ||
| 98 | }); | ||
| 99 | |||
| 100 | regs().scr6pl().write(|w| unsafe { | ||
| 101 | w.run6p_max() | ||
| 102 | .bits(config.run_length6_limit_max) | ||
| 103 | .run6p_rng() | ||
| 104 | .bits(config.run_length6_limit_range) | ||
| 105 | }); | ||
| 106 | |||
| 107 | regs() | ||
| 108 | .pkrmax() | ||
| 109 | .write(|w| unsafe { w.pkr_max().bits(config.poker_limit_max) }); | ||
| 110 | |||
| 111 | regs() | ||
| 112 | .frqmax() | ||
| 113 | .write(|w| unsafe { w.frq_max().bits(config.freq_counter_max) }); | ||
| 114 | |||
| 115 | regs() | ||
| 116 | .frqmin() | ||
| 117 | .write(|w| unsafe { w.frq_min().bits(config.freq_counter_min) }); | ||
| 118 | |||
| 119 | regs() | ||
| 120 | .sblim() | ||
| 121 | .write(|w| unsafe { w.sb_lim().bits(config.sparse_bit_limit) }); | ||
| 122 | |||
| 123 | regs().scmisc().write(|w| unsafe { | ||
| 124 | w.lrun_max() | ||
| 125 | .bits(config.long_run_limit_max) | ||
| 126 | .rty_ct() | ||
| 127 | .bits(config.retry_count) | ||
| 128 | }); | ||
| 129 | |||
| 130 | regs() | ||
| 131 | .mctl() | ||
| 132 | .modify(|_, w| w.dis_slf_tst().variant(config.self_test.into())); | ||
| 133 | |||
| 134 | regs().sdctl().write(|w| unsafe { | ||
| 135 | w.samp_size() | ||
| 136 | .bits(config.sample_size) | ||
| 137 | .ent_dly() | ||
| 138 | .bits(config.entropy_delay) | ||
| 139 | }); | ||
| 140 | |||
| 141 | regs() | ||
| 142 | .osc2_ctl() | ||
| 143 | .modify(|_, w| w.trng_ent_ctl().variant(config.osc_mode.into())); | ||
| 144 | |||
| 145 | regs().mctl().modify(|_, w| w.prgm().disable()); | ||
| 146 | |||
| 147 | let _ = regs().ent(7).read().bits(); | ||
| 148 | |||
| 149 | Self::start(); | ||
| 150 | } | ||
| 151 | |||
| 152 | fn start() { | ||
| 153 | regs().mctl().modify(|_, w| w.trng_acc().set_bit()); | ||
| 154 | } | ||
| 155 | |||
| 156 | fn stop() { | ||
| 157 | regs().mctl().modify(|_, w| w.trng_acc().clear_bit()); | ||
| 158 | } | ||
| 159 | |||
| 160 | fn blocking_wait_for_generation() { | ||
| 161 | while regs().mctl().read().ent_val().bit_is_clear() { | ||
| 162 | if regs().mctl().read().err().bit_is_set() { | ||
| 163 | regs().mctl().modify(|_, w| w.err().clear_bit_by_one()); | ||
| 164 | } | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | fn fill_chunk(chunk: &mut [u8]) { | ||
| 169 | let mut entropy = [0u32; 8]; | ||
| 170 | |||
| 171 | for (i, item) in entropy.iter_mut().enumerate() { | ||
| 172 | *item = regs().ent(i).read().bits(); | ||
| 173 | } | ||
| 174 | |||
| 175 | let entropy: [u8; 32] = unsafe { core::mem::transmute(entropy) }; | ||
| 176 | |||
| 177 | chunk.copy_from_slice(&entropy[..chunk.len()]); | ||
| 178 | } | ||
| 179 | |||
| 180 | // Blocking API | ||
| 181 | |||
| 182 | /// Fill the buffer with random bytes, blocking version. | ||
| 183 | pub fn blocking_fill_bytes(&mut self, buf: &mut [u8]) { | ||
| 184 | if buf.is_empty() { | ||
| 185 | return; // nothing to fill | ||
| 186 | } | ||
| 187 | |||
| 188 | for chunk in buf.chunks_mut(32) { | ||
| 189 | Self::blocking_wait_for_generation(); | ||
| 190 | Self::fill_chunk(chunk); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | /// Return a random u32, blocking version. | ||
| 195 | pub fn blocking_next_u32(&mut self) -> u32 { | ||
| 196 | Self::blocking_wait_for_generation(); | ||
| 197 | // New random bytes are generated only after reading ENT7 | ||
| 198 | regs().ent(7).read().bits() | ||
| 199 | } | ||
| 200 | |||
| 201 | /// Return a random u64, blocking version. | ||
| 202 | pub fn blocking_next_u64(&mut self) -> u64 { | ||
| 203 | Self::blocking_wait_for_generation(); | ||
| 204 | |||
| 205 | let mut result = u64::from(regs().ent(6).read().bits()) << 32; | ||
| 206 | // New random bytes are generated only after reading ENT7 | ||
| 207 | result |= u64::from(regs().ent(7).read().bits()); | ||
| 208 | result | ||
| 209 | } | ||
| 210 | } | ||
| 211 | |||
| 212 | impl<'d> Trng<'d, Blocking> { | ||
| 213 | /// Instantiates a new TRNG peripheral driver with 128 samples of entropy. | ||
| 214 | pub fn new_blocking_128(_peri: Peri<'d, TRNG0>) -> Self { | ||
| 215 | Self::new_inner( | ||
| 216 | _peri, | ||
| 217 | Config { | ||
| 218 | sample_size: 128, | ||
| 219 | retry_count: 1, | ||
| 220 | long_run_limit_max: 29, | ||
| 221 | monobit_limit_max: 94, | ||
| 222 | monobit_limit_range: 61, | ||
| 223 | run_length1_limit_max: 39, | ||
| 224 | run_length1_limit_range: 39, | ||
| 225 | run_length2_limit_max: 24, | ||
| 226 | run_length2_limit_range: 25, | ||
| 227 | run_length3_limit_max: 17, | ||
| 228 | run_length3_limit_range: 18, | ||
| 229 | ..Default::default() | ||
| 230 | }, | ||
| 231 | ) | ||
| 232 | } | ||
| 233 | |||
| 234 | /// Instantiates a new TRNG peripheral driver with 256 samples of entropy. | ||
| 235 | pub fn new_blocking_256(_peri: Peri<'d, TRNG0>) -> Self { | ||
| 236 | Self::new_inner( | ||
| 237 | _peri, | ||
| 238 | Config { | ||
| 239 | sample_size: 256, | ||
| 240 | retry_count: 1, | ||
| 241 | long_run_limit_max: 31, | ||
| 242 | monobit_limit_max: 171, | ||
| 243 | monobit_limit_range: 86, | ||
| 244 | run_length1_limit_max: 63, | ||
| 245 | run_length1_limit_range: 56, | ||
| 246 | run_length2_limit_max: 38, | ||
| 247 | run_length2_limit_range: 38, | ||
| 248 | run_length3_limit_max: 25, | ||
| 249 | run_length3_limit_range: 26, | ||
| 250 | ..Default::default() | ||
| 251 | }, | ||
| 252 | ) | ||
| 253 | } | ||
| 254 | |||
| 255 | /// Instantiates a new TRNG peripheral driver with 512 samples of entropy. | ||
| 256 | pub fn new_blocking_512(_peri: Peri<'d, TRNG0>) -> Self { | ||
| 257 | Self::new_inner(_peri, Default::default()) | ||
| 258 | } | ||
| 259 | |||
| 260 | /// Instantiates a new TRNG peripheral driver. | ||
| 261 | /// | ||
| 262 | /// NOTE: this constructor makes no attempt at validating the | ||
| 263 | /// parameters. If you get this wrong, the security guarantees of | ||
| 264 | /// the TRNG with regards to entropy may be violated | ||
| 265 | pub fn new_blocking_with_custom_config(_peri: Peri<'d, TRNG0>, config: Config) -> Self { | ||
| 266 | Self::new_inner(_peri, config) | ||
| 267 | } | ||
| 268 | } | ||
| 269 | |||
| 270 | impl<'d> Trng<'d, Async> { | ||
| 271 | /// Instantiates a new TRNG peripheral driver with 128 samples of entropy. | ||
| 272 | pub fn new_128( | ||
| 273 | _peri: Peri<'d, TRNG0>, | ||
| 274 | _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd, | ||
| 275 | ) -> Self { | ||
| 276 | let inst = Self::new_inner( | ||
| 277 | _peri, | ||
| 278 | Config { | ||
| 279 | sample_size: 128, | ||
| 280 | retry_count: 1, | ||
| 281 | long_run_limit_max: 29, | ||
| 282 | monobit_limit_max: 94, | ||
| 283 | monobit_limit_range: 61, | ||
| 284 | run_length1_limit_max: 39, | ||
| 285 | run_length1_limit_range: 39, | ||
| 286 | run_length2_limit_max: 24, | ||
| 287 | run_length2_limit_range: 25, | ||
| 288 | run_length3_limit_max: 17, | ||
| 289 | run_length3_limit_range: 18, | ||
| 290 | ..Default::default() | ||
| 291 | }, | ||
| 292 | ); | ||
| 293 | crate::pac::Interrupt::TRNG0.unpend(); | ||
| 294 | unsafe { | ||
| 295 | crate::pac::Interrupt::TRNG0.enable(); | ||
| 296 | } | ||
| 297 | inst | ||
| 298 | } | ||
| 299 | |||
| 300 | /// Instantiates a new TRNG peripheral driver with 256 samples of entropy. | ||
| 301 | pub fn new_256( | ||
| 302 | _peri: Peri<'d, TRNG0>, | ||
| 303 | _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd, | ||
| 304 | ) -> Self { | ||
| 305 | let inst = Self::new_inner( | ||
| 306 | _peri, | ||
| 307 | Config { | ||
| 308 | sample_size: 256, | ||
| 309 | retry_count: 1, | ||
| 310 | long_run_limit_max: 31, | ||
| 311 | monobit_limit_max: 171, | ||
| 312 | monobit_limit_range: 86, | ||
| 313 | run_length1_limit_max: 63, | ||
| 314 | run_length1_limit_range: 56, | ||
| 315 | run_length2_limit_max: 38, | ||
| 316 | run_length2_limit_range: 38, | ||
| 317 | run_length3_limit_max: 25, | ||
| 318 | run_length3_limit_range: 26, | ||
| 319 | ..Default::default() | ||
| 320 | }, | ||
| 321 | ); | ||
| 322 | crate::pac::Interrupt::TRNG0.unpend(); | ||
| 323 | unsafe { | ||
| 324 | crate::pac::Interrupt::TRNG0.enable(); | ||
| 325 | } | ||
| 326 | inst | ||
| 327 | } | ||
| 328 | |||
| 329 | /// Instantiates a new TRNG peripheral driver with 512 samples of entropy. | ||
| 330 | pub fn new_512( | ||
| 331 | _peri: Peri<'d, TRNG0>, | ||
| 332 | _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd, | ||
| 333 | ) -> Self { | ||
| 334 | let inst = Self::new_inner(_peri, Default::default()); | ||
| 335 | crate::pac::Interrupt::TRNG0.unpend(); | ||
| 336 | unsafe { | ||
| 337 | crate::pac::Interrupt::TRNG0.enable(); | ||
| 338 | } | ||
| 339 | inst | ||
| 340 | } | ||
| 341 | |||
| 342 | /// Instantiates a new TRNG peripheral driver. | ||
| 343 | /// | ||
| 344 | /// NOTE: this constructor makes no attempt at validating the | ||
| 345 | /// parameters. If you get this wrong, the security guarantees of | ||
| 346 | /// the TRNG with regards to entropy may be violated | ||
| 347 | pub fn new_with_custom_config( | ||
| 348 | _peri: Peri<'d, TRNG0>, | ||
| 349 | _irq: impl crate::interrupt::typelevel::Binding<typelevel::TRNG0, InterruptHandler> + 'd, | ||
| 350 | config: Config, | ||
| 351 | ) -> Self { | ||
| 352 | let inst = Self::new_inner(_peri, config); | ||
| 353 | crate::pac::Interrupt::TRNG0.unpend(); | ||
| 354 | unsafe { | ||
| 355 | crate::pac::Interrupt::TRNG0.enable(); | ||
| 356 | } | ||
| 357 | inst | ||
| 358 | } | ||
| 359 | |||
| 360 | fn enable_ints() { | ||
| 361 | regs().int_mask().write(|w| { | ||
| 362 | w.hw_err() | ||
| 363 | .set_bit() | ||
| 364 | .ent_val() | ||
| 365 | .set_bit() | ||
| 366 | .frq_ct_fail() | ||
| 367 | .set_bit() | ||
| 368 | .intg_flt() | ||
| 369 | .set_bit() | ||
| 370 | }); | ||
| 371 | } | ||
| 372 | |||
| 373 | async fn wait_for_generation() -> Result<(), Error> { | ||
| 374 | WAIT_CELL | ||
| 375 | .wait_for(|| { | ||
| 376 | Self::enable_ints(); | ||
| 377 | regs().mctl().read().ent_val().bit_is_set() | ||
| 378 | }) | ||
| 379 | .await | ||
| 380 | .map_err(|_| Error::ErrorStatus) | ||
| 381 | } | ||
| 382 | |||
| 383 | // Async API | ||
| 384 | |||
| 385 | /// Fill the buffer with random bytes, async version. | ||
| 386 | pub async fn async_fill_bytes(&mut self, buf: &mut [u8]) -> Result<(), Error> { | ||
| 387 | if buf.is_empty() { | ||
| 388 | return Ok(()); // nothing to fill | ||
| 389 | } | ||
| 390 | |||
| 391 | for chunk in buf.chunks_mut(32) { | ||
| 392 | Self::wait_for_generation().await?; | ||
| 393 | Self::fill_chunk(chunk); | ||
| 394 | } | ||
| 395 | |||
| 396 | Ok(()) | ||
| 397 | } | ||
| 398 | |||
| 399 | /// Return a random u32, async version. | ||
| 400 | pub async fn async_next_u32(&mut self) -> Result<u32, Error> { | ||
| 401 | Self::wait_for_generation().await?; | ||
| 402 | // New random bytes are generated only after reading ENT7 | ||
| 403 | Ok(regs().ent(7).read().bits()) | ||
| 404 | } | ||
| 405 | |||
| 406 | /// Return a random u64, async version. | ||
| 407 | pub async fn async_next_u64(&mut self) -> Result<u64, Error> { | ||
| 408 | Self::wait_for_generation().await?; | ||
| 409 | |||
| 410 | let mut result = u64::from(regs().ent(6).read().bits()) << 32; | ||
| 411 | // New random bytes are generated only after reading ENT7 | ||
| 412 | result |= u64::from(regs().ent(7).read().bits()); | ||
| 413 | |||
| 414 | Ok(result) | ||
| 415 | } | ||
| 416 | } | ||
| 417 | |||
| 418 | impl<M: Mode> Drop for Trng<'_, M> { | ||
| 419 | fn drop(&mut self) { | ||
| 420 | // wait until allowed to stop | ||
| 421 | while regs().mctl().read().tstop_ok().bit_is_clear() {} | ||
| 422 | // stop | ||
| 423 | Self::stop(); | ||
| 424 | // reset the TRNG | ||
| 425 | regs().mctl().write(|w| w.rst_def().set_bit()); | ||
| 426 | } | ||
| 427 | } | ||
| 428 | |||
| 429 | fn regs() -> &'static crate::pac::trng0::RegisterBlock { | ||
| 430 | unsafe { &*crate::pac::Trng0::ptr() } | ||
| 431 | } | ||
| 432 | |||
| 433 | /// Trng errors | ||
| 434 | #[derive(Clone, Copy, Debug)] | ||
| 435 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 436 | #[non_exhaustive] | ||
| 437 | pub enum Error { | ||
| 438 | /// Integrity error. | ||
| 439 | IntegrityError, | ||
| 440 | |||
| 441 | /// Frequency counter fail | ||
| 442 | FrequencyCountFail, | ||
| 443 | |||
| 444 | /// Error status | ||
| 445 | ErrorStatus, | ||
| 446 | |||
| 447 | /// Buffer argument is invalid | ||
| 448 | InvalidBuffer, | ||
| 449 | } | ||
| 450 | |||
| 451 | /// TRNG interrupt handler. | ||
| 452 | pub struct InterruptHandler; | ||
| 453 | |||
| 454 | impl Handler<typelevel::TRNG0> for InterruptHandler { | ||
| 455 | unsafe fn on_interrupt() { | ||
| 456 | if regs().int_status().read().bits() != 0 { | ||
| 457 | regs().int_ctrl().write(|w| { | ||
| 458 | w.hw_err() | ||
| 459 | .clear_bit() | ||
| 460 | .ent_val() | ||
| 461 | .clear_bit() | ||
| 462 | .frq_ct_fail() | ||
| 463 | .clear_bit() | ||
| 464 | .intg_flt() | ||
| 465 | .clear_bit() | ||
| 466 | }); | ||
| 467 | WAIT_CELL.wake(); | ||
| 468 | } | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | /// True random number generator configuration parameters. | ||
| 473 | #[derive(Clone, Copy, Debug)] | ||
| 474 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 475 | #[non_exhaustive] | ||
| 476 | pub struct Config { | ||
| 477 | /// Total number of Entropy samples that will be taken during | ||
| 478 | /// Entropy generation. | ||
| 479 | pub sample_size: u16, | ||
| 480 | |||
| 481 | /// Length (in system clocks) of each Entropy sample taken. | ||
| 482 | pub entropy_delay: u16, | ||
| 483 | |||
| 484 | /// Enable or disable internal self-tests. | ||
| 485 | pub self_test: SelfTest, | ||
| 486 | |||
| 487 | /// Frequency Counter Maximum Limit | ||
| 488 | pub freq_counter_max: u32, | ||
| 489 | |||
| 490 | /// Frequency Counter Minimum Limit | ||
| 491 | pub freq_counter_min: u32, | ||
| 492 | |||
| 493 | /// Statistical check monobit max limit | ||
| 494 | pub monobit_limit_max: u16, | ||
| 495 | |||
| 496 | /// Statistical check monobit range | ||
| 497 | pub monobit_limit_range: u16, | ||
| 498 | |||
| 499 | /// Statistical check run length 1 limit max | ||
| 500 | pub run_length1_limit_max: u16, | ||
| 501 | |||
| 502 | /// Statistical check run length 1 limit range | ||
| 503 | pub run_length1_limit_range: u16, | ||
| 504 | |||
| 505 | /// Statistical check run length 2 limit max | ||
| 506 | pub run_length2_limit_max: u16, | ||
| 507 | |||
| 508 | /// Statistical check run length 2 limit range | ||
| 509 | pub run_length2_limit_range: u16, | ||
| 510 | |||
| 511 | /// Statistical check run length 3 limit max | ||
| 512 | pub run_length3_limit_max: u16, | ||
| 513 | |||
| 514 | /// Statistical check run length 3 limit range | ||
| 515 | pub run_length3_limit_range: u16, | ||
| 516 | |||
| 517 | /// Statistical check run length 4 limit max | ||
| 518 | pub run_length4_limit_max: u16, | ||
| 519 | |||
| 520 | /// Statistical check run length 4 limit range | ||
| 521 | pub run_length4_limit_range: u16, | ||
| 522 | |||
| 523 | /// Statistical check run length 5 limit max | ||
| 524 | pub run_length5_limit_max: u16, | ||
| 525 | |||
| 526 | /// Statistical check run length 5 limit range | ||
| 527 | pub run_length5_limit_range: u16, | ||
| 528 | |||
| 529 | /// Statistical check run length 6 limit max | ||
| 530 | pub run_length6_limit_max: u16, | ||
| 531 | |||
| 532 | /// Statistical check run length 6 limit range | ||
| 533 | pub run_length6_limit_range: u16, | ||
| 534 | |||
| 535 | /// Retry count | ||
| 536 | pub retry_count: u8, | ||
| 537 | |||
| 538 | /// Long run limit max | ||
| 539 | pub long_run_limit_max: u8, | ||
| 540 | |||
| 541 | /// Sparse bit limit | ||
| 542 | pub sparse_bit_limit: u16, | ||
| 543 | |||
| 544 | /// Poker limit max | ||
| 545 | pub poker_limit_max: u32, | ||
| 546 | |||
| 547 | /// Oscillator mode | ||
| 548 | pub osc_mode: OscMode, | ||
| 549 | } | ||
| 550 | |||
| 551 | impl Default for Config { | ||
| 552 | fn default() -> Self { | ||
| 553 | Self { | ||
| 554 | sample_size: 512, | ||
| 555 | entropy_delay: 32_000, | ||
| 556 | self_test: SelfTest::Enabled, | ||
| 557 | freq_counter_max: 75_000, | ||
| 558 | freq_counter_min: 30_000, | ||
| 559 | monobit_limit_max: 317, | ||
| 560 | monobit_limit_range: 122, | ||
| 561 | run_length1_limit_max: 107, | ||
| 562 | run_length1_limit_range: 80, | ||
| 563 | run_length2_limit_max: 62, | ||
| 564 | run_length2_limit_range: 55, | ||
| 565 | run_length3_limit_max: 39, | ||
| 566 | run_length3_limit_range: 39, | ||
| 567 | run_length4_limit_max: 0, | ||
| 568 | run_length4_limit_range: 0, | ||
| 569 | run_length5_limit_max: 0, | ||
| 570 | run_length5_limit_range: 0, | ||
| 571 | run_length6_limit_max: 0, | ||
| 572 | run_length6_limit_range: 0, | ||
| 573 | retry_count: 1, | ||
| 574 | long_run_limit_max: 32, | ||
| 575 | sparse_bit_limit: 0, | ||
| 576 | poker_limit_max: 0, | ||
| 577 | osc_mode: OscMode::DualOscs, | ||
| 578 | } | ||
| 579 | } | ||
| 580 | } | ||
| 581 | |||
| 582 | /// Sample size. | ||
| 583 | #[derive(Clone, Copy, Debug)] | ||
| 584 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 585 | #[non_exhaustive] | ||
| 586 | pub enum SampleSize { | ||
| 587 | /// 128 bits | ||
| 588 | _128, | ||
| 589 | |||
| 590 | /// 256 bits | ||
| 591 | _256, | ||
| 592 | |||
| 593 | /// 512 bits | ||
| 594 | _512, | ||
| 595 | } | ||
| 596 | |||
| 597 | /// Enable or disable internal self-tests. | ||
| 598 | #[derive(Clone, Copy, Debug)] | ||
| 599 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 600 | #[non_exhaustive] | ||
| 601 | pub enum SelfTest { | ||
| 602 | /// Disabled. | ||
| 603 | Disabled, | ||
| 604 | |||
| 605 | /// Enabled. | ||
| 606 | Enabled, | ||
| 607 | } | ||
| 608 | |||
| 609 | impl From<SelfTest> for bool { | ||
| 610 | fn from(value: SelfTest) -> Self { | ||
| 611 | match value { | ||
| 612 | SelfTest::Disabled => true, | ||
| 613 | SelfTest::Enabled => false, | ||
| 614 | } | ||
| 615 | } | ||
| 616 | } | ||
| 617 | |||
| 618 | /// Oscillator mode. | ||
| 619 | #[derive(Clone, Copy, Debug)] | ||
| 620 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 621 | #[non_exhaustive] | ||
| 622 | pub enum OscMode { | ||
| 623 | /// Single oscillator using OSC1. | ||
| 624 | SingleOsc1, | ||
| 625 | |||
| 626 | /// Dual oscillator. | ||
| 627 | DualOscs, | ||
| 628 | |||
| 629 | /// Single oscillator using OSC2. | ||
| 630 | SingleOsc2, | ||
| 631 | } | ||
| 632 | |||
| 633 | impl From<OscMode> for TrngEntCtl { | ||
| 634 | fn from(value: OscMode) -> Self { | ||
| 635 | match value { | ||
| 636 | OscMode::SingleOsc1 => Self::TrngEntCtlSingleOsc1, | ||
| 637 | OscMode::DualOscs => Self::TrngEntCtlDualOscs, | ||
| 638 | OscMode::SingleOsc2 => Self::TrngEntCtlSingleOsc2, | ||
| 639 | } | ||
| 640 | } | ||
| 641 | } | ||
| 642 | |||
| 643 | impl<'d, M: Mode> rand_core_06::RngCore for Trng<'d, M> { | ||
| 644 | fn next_u32(&mut self) -> u32 { | ||
| 645 | self.blocking_next_u32() | ||
| 646 | } | ||
| 647 | |||
| 648 | fn next_u64(&mut self) -> u64 { | ||
| 649 | self.blocking_next_u64() | ||
| 650 | } | ||
| 651 | |||
| 652 | fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 653 | self.blocking_fill_bytes(dest); | ||
| 654 | } | ||
| 655 | |||
| 656 | fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core_06::Error> { | ||
| 657 | self.blocking_fill_bytes(dest); | ||
| 658 | Ok(()) | ||
| 659 | } | ||
| 660 | } | ||
| 661 | |||
| 662 | impl<'d, M: Mode> rand_core_06::CryptoRng for Trng<'d, M> {} | ||
| 663 | |||
| 664 | impl<'d, M: Mode> rand_core_09::RngCore for Trng<'d, M> { | ||
| 665 | fn next_u32(&mut self) -> u32 { | ||
| 666 | self.blocking_next_u32() | ||
| 667 | } | ||
| 668 | |||
| 669 | fn next_u64(&mut self) -> u64 { | ||
| 670 | self.blocking_next_u64() | ||
| 671 | } | ||
| 672 | |||
| 673 | fn fill_bytes(&mut self, dest: &mut [u8]) { | ||
| 674 | self.blocking_fill_bytes(dest); | ||
| 675 | } | ||
| 676 | } | ||
| 677 | |||
| 678 | impl<'d, M: Mode> rand_core_09::CryptoRng for Trng<'d, M> {} | ||
