esp32_c3/
rng.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5use kernel::deferred_call::{DeferredCall, DeferredCallClient};
6use kernel::hil::entropy::{self, Client32, Continue, Entropy32};
7use kernel::utilities::cells::OptionalCell;
8use kernel::utilities::registers::interfaces::Readable;
9use kernel::utilities::registers::{register_structs, ReadOnly};
10use kernel::utilities::StaticRef;
11use kernel::ErrorCode;
12
13const RNG_DATA_REG: StaticRef<RngRegister> =
14    unsafe { StaticRef::new(0x6002_60B0 as *const RngRegister) };
15
16register_structs! {
17    pub RngRegister {
18        (0x0 => data: ReadOnly<u32>),
19        (0x4 => @END),
20    }
21}
22
23pub struct Rng<'a> {
24    register: StaticRef<RngRegister>,
25    client: OptionalCell<&'a dyn entropy::Client32>,
26    value: OptionalCell<u32>,
27    deferred_call: DeferredCall,
28}
29
30impl<'a> Rng<'a> {
31    pub fn new() -> Rng<'a> {
32        Rng {
33            register: RNG_DATA_REG,
34            client: OptionalCell::empty(),
35            value: OptionalCell::empty(),
36            deferred_call: DeferredCall::new(),
37        }
38    }
39}
40
41impl DeferredCallClient for Rng<'_> {
42    fn register(&'static self) {
43        self.deferred_call.register(self);
44    }
45
46    fn handle_deferred_call(&self) {
47        self.value.set(self.register.data.get());
48        self.client.map(|client| {
49            if let Continue::More = client.entropy_available(&mut RngIter(self), Ok(())) {
50                self.deferred_call.set();
51            }
52        });
53    }
54}
55
56impl<'a> Entropy32<'a> for Rng<'a> {
57    fn get(&self) -> Result<(), ErrorCode> {
58        self.deferred_call.set();
59        Ok(())
60    }
61
62    fn cancel(&self) -> Result<(), ErrorCode> {
63        Err(ErrorCode::NOSUPPORT)
64    }
65
66    fn set_client(&self, client: &'a dyn Client32) {
67        self.client.set(client);
68    }
69}
70
71struct RngIter<'a, 'b: 'a>(&'a Rng<'b>);
72
73impl Iterator for RngIter<'_, '_> {
74    type Item = u32;
75
76    fn next(&mut self) -> Option<u32> {
77        self.0.value.take()
78    }
79}