lpc55s6x_hal/peripherals/
rng.rs

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