Skip to content

Commit e32b3f3

Browse files
committed
Change rcc API to take frequencies in MHz
1 parent c6bd1ce commit e32b3f3

File tree

10 files changed

+125
-80
lines changed

10 files changed

+125
-80
lines changed

CHANGELOG.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
77

88
## [Unreleased]
99

10+
## [v0.7.0] - 2021-03-10
11+
12+
### Added
13+
14+
- Replace custom time based units with types defined in the [embedded-time][] crate ([#191])
15+
16+
### Breaking changes
17+
18+
- The `rcc` public API now expects time based units in `Megahertz`.
19+
If the supplied frequency cannot be converted to `Hertz` the code
20+
will `panic`. This will occur if the supplied `Megahertz` frequency
21+
cannot fit into `u32::MAX` when converting to `Hertz`
22+
23+
```rust
24+
// The supplied frequencies must be in `MHz`.
25+
let clocks = rcc
26+
.cfgr
27+
.use_hse(8u32.MHz())
28+
.hclk(48u32.MHz())
29+
.sysclk(48u32.MHz())
30+
.pclk1(12u32.MHz())
31+
.pclk2(12u32.MHz())
32+
```
33+
34+
[embedded-time]: https://github.com/FluenTech/embedded-time/
35+
1036
## [v0.6.1] - 2020-12-10
1137

1238
### Changed
@@ -262,6 +288,7 @@ let clocks = rcc
262288

263289
- Support `stm32f303` device
264290

291+
[#192]: https://github.com/stm32-rs/stm32f3xx-hal/pull/192
265292
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/184
266293
[#172]: https://github.com/stm32-rs/stm32f3xx-hal/pull/172
267294
[#170]: https://github.com/stm32-rs/stm32f3xx-hal/pull/170

examples/can.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ fn main() -> ! {
3232

3333
let _clocks = rcc
3434
.cfgr
35-
.use_hse(Hertz(32_000_000))
36-
.sysclk(Hertz(32_000_000))
37-
.pclk1(Hertz(16_000_000))
38-
.pclk2(Hertz(16_000_000))
35+
.use_hse(32u32.MHz())
36+
.sysclk(32u32.MHz())
37+
.pclk1(16u32.MHz())
38+
.pclk2(16u32.MHz())
3939
.freeze(&mut flash.acr);
4040

4141
// Configure CAN RX and TX pins (AF9)

examples/i2c_scanner.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#![no_std]
77
#![no_main]
88

9-
use core::ops::Range;
9+
use core::{convert::TryInto, ops::Range};
1010

1111
use panic_semihosting as _;
1212

@@ -35,7 +35,13 @@ fn main() -> ! {
3535
gpiob.pb7.into_af4(&mut gpiob.moder, &mut gpiob.afrl), // SDA
3636
);
3737

38-
let mut i2c = hal::i2c::I2c::new(dp.I2C1, pins, 100u32.kHz(), clocks, &mut rcc.apb1).unwrap();
38+
let mut i2c = hal::i2c::I2c::new(
39+
dp.I2C1,
40+
pins,
41+
100_000u32.kHz().try_into().unwrap(),
42+
clocks,
43+
&mut rcc.apb1,
44+
);
3945

4046
hprintln!("Start i2c scanning...").expect("Error using hprintln.");
4147
hprintln!().unwrap();

examples/pwm.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn main() -> ! {
2828
// Configure our clocks
2929
let mut flash = dp.FLASH.constrain();
3030
let mut rcc = dp.RCC.constrain();
31-
let clocks = rcc.cfgr.sysclk(Hertz(16_000_000)).freeze(&mut flash.acr);
31+
let clocks = rcc.cfgr.sysclk(16u32.MHz()).freeze(&mut flash.acr);
3232

3333
// Prep the pins we need in their correct alternate function
3434
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);

examples/spi.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
#![no_std]
44
#![no_main]
55

6+
use core::convert::TryInto;
7+
68
use panic_semihosting as _;
79

810
use stm32f3xx_hal as hal;
@@ -25,9 +27,9 @@ fn main() -> ! {
2527

2628
let clocks = rcc
2729
.cfgr
28-
.use_hse(Hertz(8_000_000))
29-
.sysclk(Hertz(48_000_000))
30-
.pclk1(Hertz(24_000_000))
30+
.use_hse(8u32.MHz())
31+
.sysclk(48u32.MHz())
32+
.pclk1(24u32.MHz())
3133
.freeze(&mut flash.acr);
3234

3335
// Configure pins for SPI
@@ -44,11 +46,10 @@ fn main() -> ! {
4446
dp.SPI1,
4547
(sck, miso, mosi),
4648
spi_mode,
47-
3u32.MHz(),
49+
3u32.MHz().try_into().unwrap(),
4850
clocks,
4951
&mut rcc.apb2,
50-
)
51-
.unwrap();
52+
);
5253

5354
// Create an `u8` array, which can be transfered via SPI.
5455
let msg_send: [u8; 8] = [0xD, 0xE, 0xA, 0xD, 0xB, 0xE, 0xE, 0xF];

examples/usb_serial.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ fn main() -> ! {
2727

2828
let clocks = rcc
2929
.cfgr
30-
.use_hse(Hertz(8_000_000))
31-
.sysclk(Hertz(48_000_000))
32-
.pclk1(Hertz(24_000_000))
33-
.pclk2(Hertz(24_000_000))
30+
.use_hse(8u32.MHz())
31+
.sysclk(48u32.MHz())
32+
.pclk1(24u32.MHz())
33+
.pclk2(24u32.MHz())
3434
.freeze(&mut flash.acr);
3535

3636
assert!(clocks.usbclk_valid());

src/i2c.rs

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
//!
55
//! [examples/i2c_scanner.rs]: https://github.com/stm32-rs/stm32f3xx-hal/blob/v0.6.0/examples/i2c_scanner.rs
66
7-
use core::convert::{TryFrom, TryInto};
7+
use core::convert::TryFrom;
88
use core::ops::Deref;
99

1010
use crate::{
1111
gpio::{gpioa, gpiob, AF4},
1212
hal::blocking::i2c::{Read, Write, WriteRead},
1313
pac::{i2c1::RegisterBlock, rcc::cfgr3::I2C1SW_A, I2C1, RCC},
1414
rcc::{Clocks, APB1},
15-
time::rate::{Hertz, Rate},
15+
time::rate::Hertz,
1616
};
1717

1818
#[cfg(not(feature = "gpio-f333"))]
@@ -111,22 +111,13 @@ macro_rules! busy_wait {
111111

112112
impl<I2C, SCL, SDA> I2c<I2C, (SCL, SDA)> {
113113
/// Configures the I2C peripheral to work in master mode
114-
pub fn new<F>(
115-
i2c: I2C,
116-
pins: (SCL, SDA),
117-
freq: F,
118-
clocks: Clocks,
119-
apb1: &mut APB1,
120-
) -> Result<Self, <F as TryInto<Hertz<u32>>>::Error>
114+
pub fn new(i2c: I2C, pins: (SCL, SDA), freq: Hertz, clocks: Clocks, apb1: &mut APB1) -> Self
121115
where
122116
I2C: Instance,
123117
SCL: SclPin<I2C>,
124118
SDA: SdaPin<I2C>,
125-
F: Rate + TryInto<Hertz<u32>>,
126119
{
127-
let freq = (freq.try_into()? as Hertz).0;
128-
129-
crate::assert!(freq <= 1_000_000);
120+
crate::assert!(freq.0 <= 1_000_000);
130121

131122
I2C::enable_clock(apb1);
132123

@@ -139,16 +130,16 @@ impl<I2C, SCL, SDA> I2c<I2C, (SCL, SDA)> {
139130
// t_SYNC1 + t_SYNC2 > 4 * t_I2CCLK
140131
// t_SCL ~= t_SYNC1 + t_SYNC2 + t_SCLL + t_SCLH
141132
let i2cclk = I2C::clock(&clocks).0;
142-
let ratio = i2cclk / freq - 4;
143-
let (presc, scll, sclh, sdadel, scldel) = if freq >= 100_000 {
133+
let ratio = i2cclk / freq.0 - 4;
134+
let (presc, scll, sclh, sdadel, scldel) = if freq.0 >= 100_000 {
144135
// fast-mode or fast-mode plus
145136
// here we pick SCLL + 1 = 2 * (SCLH + 1)
146137
let presc = ratio / 387;
147138

148139
let sclh = ((ratio / (presc + 1)) - 3) / 3;
149140
let scll = 2 * (sclh + 1) - 1;
150141

151-
let (sdadel, scldel) = if freq > 400_000 {
142+
let (sdadel, scldel) = if freq.0 > 400_000 {
152143
// fast-mode plus
153144
let sdadel = 0;
154145
let scldel = i2cclk / 4_000_000 / (presc + 1) - 1;
@@ -201,7 +192,7 @@ impl<I2C, SCL, SDA> I2c<I2C, (SCL, SDA)> {
201192
// Enable the peripheral
202193
i2c.cr1.modify(|_, w| w.pe().set_bit());
203194

204-
Ok(Self { i2c, pins })
195+
Self { i2c, pins }
205196
}
206197

207198
/// Releases the I2C peripheral and associated pins

src/rcc.rs

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
//! ```
1010
//! # use cortex_m_rt::entry;
1111
//! # use stm32f3xx_hal::prelude::*;
12+
//! #use hal::time::rate::*;
13+
//!
1214
//! # #[entry]
1315
//! # fn main() -> ! {
1416
//! // Get our peripherals
@@ -33,18 +35,18 @@
3335
//! let clocks = rcc.cfgr
3436
//! // Using the external oscillator
3537
//! // Set the frequency to that of the external oscillator
36-
//! .use_hse(8.mhz())
38+
//! .use_hse(8.MHz())
3739
//! // Set the frequency for the AHB bus,
3840
//! // which the root of every following clock peripheral
39-
//! .hclk(48.mhz())
41+
//! .hclk(48.MHz())
4042
//! // The sysclk is equivalent to the core clock
41-
//! .sysclk(48.mhz())
43+
//! .sysclk(48.MHz())
4244
//! // The following are peripheral clocks, which are both
4345
//! // needed to configure specific peripherals.
4446
//! // Looking at the peripheral function parameters
4547
//! // should give more insight, which peripheral clock is needed.
46-
//! .pclk1(12.mhz())
47-
//! .pclk2(12.mhz())
48+
//! .pclk1(12.MHz())
49+
//! .pclk2(12.MHz())
4850
//! // Freeze / apply the configuration and setup all clocks
4951
//! .freeze(&mut flash.acr);
5052
//! # }
@@ -59,8 +61,10 @@ use crate::pac::{
5961
RCC,
6062
};
6163

64+
use core::convert::TryInto;
65+
6266
use crate::flash::ACR;
63-
use crate::time::rate::Hertz;
67+
use crate::time::rate::*;
6468

6569
/// Extension trait that constrains the `RCC` peripheral
6670
pub trait RccExt {
@@ -333,7 +337,12 @@ impl CFGR {
333337
///
334338
/// Will result in a hang if an external oscillator is not connected or it fails to start,
335339
/// unless [css](CFGR::enable_css) is enabled.
336-
pub fn use_hse(mut self, freq: Hertz) -> Self {
340+
///
341+
/// # Panics
342+
///
343+
/// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
344+
pub fn use_hse(mut self, freq: Megahertz) -> Self {
345+
let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
337346
self.hse = Some(freq.0);
338347
self
339348
}
@@ -360,8 +369,13 @@ impl CFGR {
360369
self
361370
}
362371

363-
/// Sets a frequency for the AHB bus
364-
pub fn hclk(mut self, freq: Hertz) -> Self {
372+
/// Sets a frequency for the AHB bus.
373+
///
374+
/// # Panics
375+
///
376+
/// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
377+
pub fn hclk(mut self, freq: Megahertz) -> Self {
378+
let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
365379
self.hclk = Some(freq.0);
366380
self
367381
}
@@ -372,7 +386,12 @@ impl CFGR {
372386
///
373387
/// If not manually set, it will be set to [`CFGR::sysclk`] frequency
374388
/// or [`CFGR::sysclk`] frequency / 2, if [`CFGR::sysclk`] > 36 Mhz
375-
pub fn pclk1(mut self, freq: Hertz) -> Self {
389+
///
390+
/// # Panics
391+
///
392+
/// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
393+
pub fn pclk1(mut self, freq: Megahertz) -> Self {
394+
let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
376395
self.pclk1 = Some(freq.0);
377396
self
378397
}
@@ -390,7 +409,11 @@ impl CFGR {
390409
///
391410
/// [stm32f302xd,stm32f302xe,stm32f303xd,stm32f303xe,stm32f398]
392411
///
393-
pub fn pclk2(mut self, freq: Hertz) -> Self {
412+
/// # Panics
413+
///
414+
/// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
415+
pub fn pclk2(mut self, freq: Megahertz) -> Self {
416+
let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
394417
self.pclk2 = Some(freq.0);
395418
self
396419
}
@@ -410,7 +433,12 @@ impl CFGR {
410433
/// even when using the internal oscillator:
411434
///
412435
/// [stm32f302xd,stm32f302xe,stm32f303xd,stm32f303xe,stm32f398]
413-
pub fn sysclk(mut self, freq: Hertz) -> Self {
436+
///
437+
/// # Panics
438+
///
439+
/// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`.
440+
pub fn sysclk(mut self, freq: Megahertz) -> Self {
441+
let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError");
414442
self.sysclk = Some(freq.0);
415443
self
416444
}
@@ -645,7 +673,7 @@ impl CFGR {
645673

646674
// This ensures, that no panic happens, when
647675
// pclk1 is not manually set.
648-
// As hclk highest value is 72.mhz()
676+
// As hclk highest value is 72.MHz()
649677
// dividing by 2 should always be sufficient
650678
if self.pclk1.is_none() && pclk1 > 36_000_000 {
651679
ppre1_bits = cfgr::PPRE1_A::DIV2;

0 commit comments

Comments
 (0)