Skip to content

Commit 1aed4b2

Browse files
authored
Merge pull request #53 from braun-embedded/rng
Add RNG API
2 parents 7acca3e + 3256dc9 commit 1aed4b2

File tree

6 files changed

+156
-37
lines changed

6 files changed

+156
-37
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ required-features = ["rt"]
114114
name = "i2c_dma"
115115
required-features = ["rt","stm32l0x2"]
116116

117+
[[example]]
118+
name = "rng"
119+
required-features = ["rt","stm32l0x2"]
120+
117121
[[example]]
118122
name = "rtc"
119123
required-features = ["stm32l0x2"]

examples/rng.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#![no_main]
2+
#![no_std]
3+
4+
5+
extern crate panic_halt;
6+
7+
use cortex_m_rt::entry;
8+
use stm32l0xx_hal::{pac, prelude::*, rcc::Config, syscfg::SYSCFG};
9+
10+
use stm32l0xx_hal::rng::Rng;
11+
12+
#[entry]
13+
fn main() -> ! {
14+
let dp = pac::Peripherals::take().unwrap();
15+
16+
let mut rcc = dp.RCC.freeze(Config::hsi16());
17+
let mut syscfg = SYSCFG::new(dp.SYSCFG_COMP, &mut rcc);
18+
19+
// constructor initializes 48 MHz clock that RNG requires
20+
// Initialize 48 MHz clock and RNG
21+
let hsi48 = rcc.enable_hsi48(&mut syscfg, dp.CRS);
22+
let mut rng = Rng::new(dp.RNG, &mut rcc, hsi48);
23+
24+
loop {
25+
// enable starts the ADC conversions that generate the random number
26+
rng.enable();
27+
// wait until the flag flips; interrupt driven is possible but no implemented
28+
rng.wait();
29+
// reading the result clears the ready flag
30+
let _ = rng.take_result();
31+
// can save some power by disabling until next random number needed
32+
rng.disable();
33+
}
34+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub mod prelude;
3333
pub mod pwm;
3434
pub mod pwr;
3535
pub mod rcc;
36+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
37+
pub mod rng;
3638
pub mod rtc;
3739
pub mod serial;
3840
pub mod spi;

src/rcc.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
use crate::pac::RCC;
22
use crate::time::{Hertz, U32Ext};
33

4+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
5+
use crate::{
6+
pac::CRS,
7+
syscfg::SYSCFG,
8+
};
9+
10+
411
/// System clock mux source
512
#[derive(Clone, Copy)]
613
pub enum ClockSrc {
@@ -170,6 +177,45 @@ pub struct Rcc {
170177
pub(crate) rb: RCC,
171178
}
172179

180+
#[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))]
181+
impl Rcc {
182+
pub fn enable_hsi48(&mut self, syscfg: &mut SYSCFG, crs: CRS) -> HSI48 {
183+
// Reset CRS peripheral
184+
self.rb.apb1rstr.modify(|_, w| w.crsrst().set_bit());
185+
self.rb.apb1rstr.modify(|_, w| w.crsrst().clear_bit());
186+
187+
// Enable CRS peripheral
188+
self.rb.apb1enr.modify(|_, w| w.crsen().set_bit());
189+
190+
// Initialize CRS
191+
crs.cfgr.write(|w|
192+
// Select LSE as synchronization source
193+
unsafe { w.syncsrc().bits(0b01) }
194+
);
195+
crs.cr.write(|w|
196+
w
197+
.autotrimen().set_bit()
198+
.cen().set_bit()
199+
);
200+
201+
// Enable VREFINT reference for HSI48 oscillator
202+
syscfg.syscfg.cfgr3.modify(|_, w|
203+
w
204+
.enref_rc48mhz().set_bit()
205+
.en_bgap().set_bit()
206+
);
207+
208+
// Select HSI48 as USB clock
209+
self.rb.ccipr.modify(|_, w| w.hsi48msel().set_bit());
210+
211+
// Enable dedicated USB clock
212+
self.rb.crrcr.modify(|_, w| w.hsi48on().set_bit());
213+
while self.rb.crrcr.read().hsi48rdy().bit_is_clear() {};
214+
215+
HSI48(())
216+
}
217+
}
218+
173219
/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
174220
pub trait RccExt {
175221
fn freeze(self, config: Config) -> Rcc;
@@ -310,6 +356,7 @@ impl RccExt for RCC {
310356

311357
Rcc { rb: self, clocks }
312358
}
359+
313360
}
314361

315362
/// Frozen clock frequencies
@@ -362,3 +409,10 @@ impl Clocks {
362409
self.apb2_tim_clk
363410
}
364411
}
412+
413+
414+
/// Token that exists only, if the HSI48 clock has been enabled
415+
///
416+
/// You can get an instance of this struct by calling [`Rcc::enable_hsi48`].
417+
#[derive(Clone, Copy)]
418+
pub struct HSI48(());

src/rng.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use crate::rcc::{HSI48, Rcc};
2+
3+
pub use crate::pac::{rng, RNG};
4+
5+
6+
pub struct Rng {
7+
rng: RNG
8+
}
9+
10+
impl Rng {
11+
// Initializes the peripheral
12+
pub fn new(rng: RNG, rcc: &mut Rcc, _: HSI48) -> Rng {
13+
// Reset peripheral
14+
rcc.rb.ahbrstr.modify(|_, w| w.rngrst().set_bit());
15+
rcc.rb.ahbrstr.modify(|_, w| w.rngrst().clear_bit());
16+
17+
// Enable peripheral clock
18+
rcc.rb.ahbenr.modify(|_, w| w.rngen().set_bit());
19+
20+
rng.cr.write(|w|
21+
w
22+
.rngen().set_bit()
23+
.ie().clear_bit()
24+
);
25+
26+
let mut ret = Self {
27+
rng
28+
};
29+
30+
ret.enable();
31+
32+
ret
33+
}
34+
35+
pub fn enable(&mut self) {
36+
self.rng.cr.write(|w|
37+
w
38+
.rngen().set_bit()
39+
.ie().clear_bit()
40+
);
41+
}
42+
43+
pub fn disable(&mut self) {
44+
self.rng.cr.modify(|_, w|
45+
w
46+
.rngen().clear_bit()
47+
.ie().clear_bit()
48+
);
49+
}
50+
51+
pub fn wait(&mut self) {
52+
while self.rng.sr.read().drdy().bit_is_clear() {}
53+
}
54+
55+
pub fn take_result(&mut self) -> u32 {
56+
self.rng.dr.read().bits()
57+
}
58+
}

src/usb.rs

Lines changed: 4 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@
1818
//! fits together.
1919
2020

21-
use crate::{
22-
pac,
23-
rcc::Rcc,
24-
syscfg::SYSCFG,
21+
use crate::rcc::{
22+
HSI48,
23+
Rcc,
2524
};
2625

2726

@@ -30,39 +29,7 @@ use crate::{
3029
/// This method takes care of the platform-specific bits of the USB
3130
/// initialization. After calling this method, you need `stm32-usbd` to actually
3231
/// do anything useful with the USB peripheral.
33-
pub fn init(rcc: &mut Rcc, syscfg: &mut SYSCFG, crs: pac::CRS) {
34-
// Reset CRS peripheral
35-
rcc.rb.apb1rstr.modify(|_, w| w.crsrst().set_bit());
36-
rcc.rb.apb1rstr.modify(|_, w| w.crsrst().clear_bit());
37-
38-
// Enable CRS peripheral
39-
rcc.rb.apb1enr.modify(|_, w| w.crsen().set_bit());
40-
41-
// Initialize CRS
42-
crs.cfgr.write(|w|
43-
// Select LSE as synchronization source
44-
unsafe { w.syncsrc().bits(0b01) }
45-
);
46-
crs.cr.write(|w|
47-
w
48-
.autotrimen().set_bit()
49-
.cen().set_bit()
50-
);
51-
52-
// Enable VREFINT reference for HSI48 oscillator
53-
syscfg.syscfg.cfgr3.modify(|_, w|
54-
w
55-
.enref_rc48mhz().set_bit()
56-
.en_bgap().set_bit()
57-
);
58-
59-
// Select HSI48 as USB clock
60-
rcc.rb.ccipr.modify(|_, w| w.hsi48msel().set_bit());
61-
62-
// Enable dedicated USB clock
63-
rcc.rb.crrcr.modify(|_, w| w.hsi48on().set_bit());
64-
while rcc.rb.crrcr.read().hsi48rdy().bit_is_clear() {};
65-
32+
pub fn init(rcc: &mut Rcc, _: HSI48) {
6633
// Reset USB peripheral
6734
rcc.rb.apb1rstr.modify(|_, w| w.usbrst().set_bit());
6835
rcc.rb.apb1rstr.modify(|_, w| w.usbrst().clear_bit());

0 commit comments

Comments
 (0)