nrf52_hal_common/
rng.rs

1//! HAL interface to the RNG peripheral
2//!
3//! See nRF52832 product specification, chapter 26.
4
5
6use core::ops::Deref;
7use rand_core::{CryptoRng, RngCore};
8
9use crate::target::{
10    rng,
11    RNG,
12};
13
14
15pub trait RngExt : Deref<Target=rng::RegisterBlock> + Sized {
16    fn constrain(self) -> Rng;
17}
18
19impl RngExt for RNG {
20    fn constrain(self) -> Rng {
21        self.config.write(|w| w.dercen().enabled());
22        Rng(self)
23    }
24}
25
26
27/// Interface to the RNG peripheral
28///
29/// Right now, this is very basic, only providing blocking interfaces.
30pub struct Rng(RNG);
31
32impl Rng {
33    /// Fill the provided buffer with random bytes
34    ///
35    /// Will block until the buffer is full.
36    pub fn random(&mut self, buf: &mut [u8]) {
37        self.0.tasks_start.write(|w| unsafe { w.bits(1) });
38
39        for b in buf {
40            // Wait for random byte to become ready, reset the flag once it is
41            while self.0.events_valrdy.read().bits() == 0 {}
42            self.0.events_valrdy.write(|w| unsafe { w.bits(0) });
43
44            *b = self.0.value.read().value().bits();
45        }
46
47        self.0.tasks_stop.write(|w| unsafe { w.bits(1) });
48    }
49
50    /// Return a random `u8`
51    pub fn random_u8(&mut self) -> u8 {
52        let mut buf = [0; 1];
53        self.random(&mut buf);
54        buf[0]
55    }
56
57    /// Return a random `u16`
58    pub fn random_u16(&mut self) -> u16 {
59        let mut buf = [0; 2];
60        self.random(&mut buf);
61        buf[0] as u16 |
62            (buf[1] as u16) << 8
63    }
64
65    /// Return a random `u32`
66    pub fn random_u32(&mut self) -> u32 {
67        let mut buf = [0; 4];
68        self.random(&mut buf);
69        buf[0] as u32 |
70            (buf[1] as u32) <<  8 |
71            (buf[2] as u32) << 16 |
72            (buf[3] as u32) << 24
73    }
74
75    /// Return a random `u64`
76    pub fn random_u64(&mut self) -> u64 {
77        let mut buf = [0; 8];
78        self.random(&mut buf);
79        buf[0] as u64 |
80            (buf[1] as u64) <<  8 |
81            (buf[2] as u64) << 16 |
82            (buf[3] as u64) << 24 |
83            (buf[4] as u64) << 32 |
84            (buf[5] as u64) << 40 |
85            (buf[6] as u64) << 48 |
86            (buf[7] as u64) << 56
87    }
88}
89
90impl RngCore for Rng {
91    fn next_u32(&mut self) -> u32 {
92        self.random_u32()
93    }
94
95    fn next_u64(&mut self) -> u64 {
96        self.random_u64()
97    }
98
99    fn fill_bytes(&mut self, dest: &mut [u8]) {
100        self.random(dest)
101    }
102
103    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), rand_core::Error> {
104        Ok(self.fill_bytes(dest))
105    }
106}
107
108impl CryptoRng for Rng {}