lpc55_hal/peripherals/rng.rs
1use crate::{peripherals::syscon::Syscon, raw, typestates::init_state};
2
3crate::wrap_stateful_peripheral!(Rng, RNG);
4
5// /// HAL-ified RNG peripheral
6// pub struct Rng<State = init_state::Enabled> {
7// raw: raw::RNG,
8// _state: State,
9// }
10
11#[derive(Debug)]
12// not sure why this kind of thing is not in `svd2rust`?
13pub struct ModuleId {
14 pub id: u16,
15 pub maj_rev: u8,
16 pub min_rev: u8,
17 pub aperture: u8,
18}
19
20impl<State> Rng<State> {
21 pub fn enabled(mut self, syscon: &mut Syscon) -> Rng<init_state::Enabled> {
22 syscon.enable_clock(&mut self.raw);
23
24 Rng {
25 raw: self.raw,
26 _state: init_state::Enabled(()),
27 }
28 }
29
30 pub fn disabled(mut self, syscon: &mut Syscon) -> Rng<init_state::Disabled> {
31 syscon.disable_clock(&mut self.raw);
32
33 Rng {
34 raw: self.raw,
35 _state: init_state::Disabled,
36 }
37 }
38}
39
40impl Rng<init_state::Enabled> {
41 /// DO NOT CALL - doesn't work yet
42 #[allow(dead_code, unreachable_code)]
43 fn initialize_entropy(&self) {
44 unimplemented!();
45
46 // NB: there are functional and operational differences between
47 // the A0 and A1 versions of the chip, see UM 48.14 (page 1033)
48 //
49 // A0/A1 refer to syscon.dieid.rev
50 //
51 // Here, we assume A1 (as maj.min = 3.2 seems to indicate this)
52 // TODO: check this is true for the lpcxpresso55s69
53 // TODO: check again when going into production
54
55 // poll ONLINE_TEST_VAL
56 let val = &self.raw.online_test_val.read();
57 #[allow(non_snake_case)]
58 let REF_CHI_SQUARED = 2;
59
60 // dbg!("shift4x is", self.raw.counter_cfg.read().shift4x().bits());
61 // let _: u8 = self.raw.counter_cfg.read().shift4x().bits();
62
63 loop {
64 // activate CHI computing
65 // dbg!(self.raw.online_test_cfg.read().activate().bit()); // <-- false
66 self.raw
67 .online_test_cfg
68 .modify(|_, w| unsafe { w.data_sel().bits(4) });
69 self.raw
70 .online_test_cfg
71 .modify(|_, w| w.activate().set_bit());
72 // dbg!(self.raw.online_test_cfg.read().activate().bit()); // <-- true
73
74 // dbg!(val.min_chi_squared().bits()); // <-- 15
75 // dbg!(val.max_chi_squared().bits()); // <-- 0
76
77 // TODO: this gets stuck
78 // unimplemented!("figure out how to make this not block");
79 while val.min_chi_squared().bits() > val.max_chi_squared().bits() {}
80
81 // dbg!("passed");
82
83 if val.max_chi_squared().bits() > REF_CHI_SQUARED {
84 // reset
85 self.raw
86 .online_test_cfg
87 .modify(|_, w| w.activate().clear_bit());
88 // increment SHIFT4X, which has bit width 3
89 // self.raw.counter_cfg.modify(|_, w| (w.shift4x().bits() as u8) + 1);
90 continue;
91 } else {
92 break;
93 }
94 }
95 }
96
97 pub fn get_random_u32(&self) -> u32 {
98 for _ in 0..32 {
99 while self.raw.counter_val.read().refresh_cnt().bits() == 0 {
100 // dbg!("was not zero");
101 }
102 }
103 self.raw.random_number.read().bits()
104 }
105
106 /// random method to get some information about the RNG
107 pub fn module_id(&self) -> ModuleId {
108 ModuleId {
109 id: self.raw.moduleid.read().id().bits(),
110 maj_rev: self.raw.moduleid.read().maj_rev().bits(),
111 min_rev: self.raw.moduleid.read().min_rev().bits(),
112 aperture: self.raw.moduleid.read().aperture().bits(),
113 }
114 }
115}