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