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}