Skip to content

Commit 1f4ca8c

Browse files
author
Henrik Snöman
committed
Follow example configurations in RM0481 and RM0492
1 parent ff7b858 commit 1f4ca8c

File tree

3 files changed

+160
-48
lines changed

3 files changed

+160
-48
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ embedded-hal = "1.0.0"
6666
defmt = { version = "0.3.8", optional = true }
6767
paste = "1.0.15"
6868
log = { version = "0.4.20", optional = true}
69+
nb = "1.1.0"
6970
rand_core = { version = "0.6", default-features = false, optional = true }
7071

7172
[dev-dependencies]

examples/blinky_random.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,7 @@
99

1010
use cortex_m_rt::entry;
1111
use embedded_hal::delay::DelayNs;
12-
use stm32h5xx_hal::{
13-
delay::Delay,
14-
pac,
15-
prelude::*,
16-
};
12+
use stm32h5xx_hal::{delay::Delay, pac, prelude::*};
1713
#[macro_use]
1814
mod utilities;
1915

@@ -49,7 +45,7 @@ fn main() -> ! {
4945
let mut delay = Delay::new(cp.SYST, &ccdr.clocks);
5046

5147
// Get true random number generator
52-
let mut rng = dp.RNG.constrain(ccdr.peripheral.RNG, &ccdr.clocks);
48+
let mut rng = dp.RNG.rng(ccdr.peripheral.RNG, &ccdr.clocks);
5349
let mut random_bytes = [0u16; 3];
5450
match rng.fill(&mut random_bytes) {
5551
Ok(()) => info!("random bytes: {:?}", random_bytes),

src/rng.rs

Lines changed: 157 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use crate::time::Hertz;
1616
#[derive(Debug)]
1717
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
1818
pub enum ErrorKind {
19+
///Note: The clock error has no impact on generated random numbers that is the application can still read the RNG_DR register
1920
ClockError = 0,
2021
SeedError = 1,
2122
}
@@ -35,30 +36,161 @@ fn kernel_clk_unwrap(prec: rec::Rng, clocks: &CoreClocks) -> Hertz {
3536
clocks.pll1_q_ck().expect("RNG: PLL1_Q must be enabled")
3637
}
3738
RngClkSel::Lse => unimplemented!(),
38-
RngClkSel::Lsi => {
39-
clocks.lsi_ck().expect("RNG: LSI must be enabled")
40-
}
39+
RngClkSel::Lsi => clocks.lsi_ck().expect("RNG: LSI must be enabled"),
4140
}
4241
}
4342

43+
fn setup_clocks(prec: rec::Rng, clocks: &CoreClocks) -> Hertz {
44+
let prec = prec.enable().reset();
45+
46+
let hclk = clocks.hclk();
47+
let rng_clk = kernel_clk_unwrap(prec, clocks);
48+
49+
// Otherwise clock checker will always flag an error
50+
// See RM0481 Rev 2 Section 32.3.6
51+
assert!(rng_clk > (hclk / 32), "RNG: Clock too slow");
52+
53+
rng_clk
54+
}
55+
56+
#[cfg(any(
57+
feature = "stm32h562",
58+
feature = "stm32h563",
59+
feature = "stm32h573",
60+
))]
61+
62+
/// This uses the register values specified in AN4230 but have not
63+
/// performed the verification (buyer beware, users can/should do their own verification)
64+
/// Requires RNG to be disabled since some register values can only be written when RNGEN = 0
65+
pub trait RngNist {
66+
fn rng_nist_st_an4230(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng;
67+
}
68+
69+
#[cfg(any(
70+
feature = "stm32h562",
71+
feature = "stm32h563",
72+
feature = "stm32h573"
73+
))]
74+
impl RngNist for RNG {
75+
/// This uses the register values specified in AN4230 but have not
76+
/// performed the verification (buyer beware, users can/should do their own verification)
77+
/// Requires RNG to be disabled since some register values can only be written when RNGEN = 0
78+
fn rng_nist_st_an4230(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng {
79+
let rng_clk = setup_clocks(prec, clocks);
80+
81+
// ST has tested this configuration only with a RNG clock of 48MHz
82+
assert_eq!(rng_clk, Hertz::MHz(48), "RNG: Clock not 48 MHz");
83+
84+
// Set control register values, also need to write 1 to CONDRST to be able to set the other values
85+
self.cr()
86+
.write(|w| unsafe { w.bits(0x00F00E00).condrst().set_bit() });
87+
88+
// Set health test control register values
89+
self.htcr().write(|w| unsafe { w.bits(0x6A91) });
90+
91+
// Set noise source control register
92+
self.nscr().write(|w| unsafe { w.bits(0x3AF66) });
93+
94+
// Configuration done, reset CONDRST, its value goes to 0 when the reset process is
95+
// done. It takes about 2 AHB clock cycles + 2 RNG clock cycles.
96+
self.cr().write(|w| w.condrst().clear_bit());
97+
98+
// It should take about 2 AHB clock cycles + 2 RNG clock cycles
99+
while self.cr().read().condrst().bit_is_set() {}
100+
101+
// Enable RNG
102+
self.cr().modify(|_, w| w.rngen().set_bit());
103+
104+
Rng { rb: self }
105+
}
106+
}
44107

45108
pub trait RngExt {
46-
fn constrain(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng;
109+
fn rng(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng;
110+
fn rng_fast(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng;
47111
}
48112

49113
impl RngExt for RNG {
50-
fn constrain(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng {
51-
let prec = prec.enable().reset();
114+
/// This uses the register values specified in RM0481 Rev 2 section 32.6.2 RNG configuration C
115+
fn rng(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng {
116+
setup_clocks(prec, clocks);
117+
118+
// Set control register values, also need to write 1 to CONDRST to be able to set the other values
119+
self.cr().write(|w| unsafe {
120+
w.nistc()
121+
.clear_bit()
122+
.rng_config1()
123+
.bits(0x0F)
124+
.clkdiv()
125+
.bits(0x0)
126+
.rng_config2()
127+
.bits(0x0)
128+
.rng_config3()
129+
.bits(0xD)
130+
.ced()
131+
.clear_bit()
132+
.condrst()
133+
.set_bit()
134+
});
135+
136+
// Set health test control register values
137+
self.htcr().write(|w| unsafe { w.bits(0xAAC7) });
138+
139+
// Set noise source control register
140+
#[cfg(not(feature = "stm32h503"))] // Not available on H503
141+
self.nscr().write(|w| unsafe { w.bits(0x0003FFFF) });
142+
143+
// Configuration done, reset CONDRST, its value goes to 0 when the reset process is
144+
// done. It takes about 2 AHB clock cycles + 2 RNG clock cycles.
145+
self.cr().write(|w| w.condrst().clear_bit());
146+
147+
// It should take about 2 AHB clock cycles + 2 RNG clock cycles
148+
while self.cr().read().condrst().bit_is_set() {}
149+
150+
// Enable RNG
151+
self.cr().modify(|_, w| w.rngen().set_bit());
52152

53-
let hclk = clocks.hclk();
54-
let rng_clk = kernel_clk_unwrap(prec, clocks);
55-
56-
// Otherwise clock checker will always flag an error
57-
// See RM0433 Rev 6 Section 33.3.6
58-
assert!(rng_clk > hclk / 32, "RNG: Clock too slow");
153+
Rng { rb: self }
154+
}
59155

60-
self.cr()
61-
.modify(|_, w| w.ced().clear_bit().rngen().set_bit());
156+
/// This uses the register values specified in RM0481 Rev 2 section 32.6.2 RNG configuration B
157+
fn rng_fast(self, prec: rec::Rng, clocks: &CoreClocks) -> Rng {
158+
setup_clocks(prec, clocks);
159+
160+
// Set control register values, also need to write 1 to CONDRST to be able to set the other values
161+
self.cr().write(|w| unsafe {
162+
w.nistc()
163+
.set_bit()
164+
.rng_config1()
165+
.bits(0x18)
166+
.clkdiv()
167+
.bits(0x0)
168+
.rng_config2()
169+
.bits(0x0)
170+
.rng_config3()
171+
.bits(0x0)
172+
.ced()
173+
.clear_bit()
174+
.condrst()
175+
.set_bit()
176+
});
177+
178+
// Set health test control register values
179+
self.htcr().write(|w| unsafe { w.bits(0xAAC7) });
180+
181+
// Set noise source control register
182+
#[cfg(not(feature = "stm32h503"))] // Not available on H503
183+
self.nscr().write(|w| unsafe { w.bits(0x0003FFFF) });
184+
185+
// Configuration done, reset CONDRST, its value goes to 0 when the reset process is
186+
// done. It takes about 2 AHB clock cycles + 2 RNG clock cycles.
187+
self.cr().write(|w| w.condrst().clear_bit());
188+
189+
// It should take about 2 AHB clock cycles + 2 RNG clock cycles
190+
while self.cr().read().condrst().bit_is_set() {}
191+
192+
// Enable RNG
193+
self.cr().modify(|_, w| w.rngen().set_bit());
62194

63195
Rng { rb: self }
64196
}
@@ -76,36 +208,20 @@ pub struct Rng {
76208
impl Rng {
77209
/// Returns 32 bits of randomness, or error
78210
pub fn value(&mut self) -> Result<u32, ErrorKind> {
79-
loop {
80-
let status = self.rb.sr().read();
81-
if status.cecs().bit() {
82-
return Err(ErrorKind::ClockError);
83-
}
84-
if status.secs().bit() {
85-
return Err(ErrorKind::SeedError);
86-
}
87-
if status.drdy().bit() {
88-
return Ok(self.rb.dr().read().rndata().bits());
89-
}
90-
}
211+
nb::block!(self.nb_value())
91212
}
92-
213+
93214
/// Returns 32 bits of randomness, or error
94215
pub fn nb_value(&mut self) -> nb::Result<u32, ErrorKind> {
95-
loop {
96-
let status = self.rb.sr().read();
97-
if status.cecs().bit() {
98-
return Err(ErrorKind::ClockError);
99-
}
100-
if status.secs().bit() {
101-
return Err(ErrorKind::SeedError);
102-
}
103-
if status.drdy().bit() {
104-
return Ok(self.rb.dr().read().rndata().bits());
105-
}
106-
else {
107-
return Err(nb::Error::WouldBlock);
108-
}
216+
let status = self.rb.sr().read();
217+
if status.cecs().bit() {
218+
Err(nb::Error::Other(ErrorKind::ClockError))
219+
} else if status.secs().bit() {
220+
Err(nb::Error::Other(ErrorKind::SeedError))
221+
} else if status.drdy().bit() {
222+
Ok(self.rb.dr().read().rndata().bits())
223+
} else {
224+
Err(nb::Error::WouldBlock)
109225
}
110226
}
111227

@@ -271,4 +387,3 @@ impl rand_core::RngCore for Rng {
271387
})
272388
}
273389
}
274-

0 commit comments

Comments
 (0)