Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/embedded time #192

Merged
merged 12 commits into from
Mar 11, 2021
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,31 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [v0.7.0] - 2021-03-10

### Added

- Replace custom time based units with types defined in the [embedded-time][] crate ([#192])

### Breaking changes

- The `rcc` public API now expects time based units in `Megahertz`.
If the supplied frequency cannot be converted to `Hertz` the code
will `panic`. This will occur if the supplied `Megahertz` frequency
cannot fit into `u32::MAX` when converting to `Hertz`

```rust
// The supplied frequencies must be in `MHz`.
let clocks = rcc
.cfgr
.use_hse(8u32.MHz())
.hclk(48u32.MHz())
.sysclk(48u32.MHz())
.pclk1(12u32.MHz())
.pclk2(12u32.MHz())
```

[embedded-time]: https://github.com/FluenTech/embedded-time/
### Changed

- Added support for more CAN bit rates and modes. ([#186])
Expand Down Expand Up @@ -273,6 +298,7 @@ let clocks = rcc

[#208]: https://github.com/stm32-rs/stm32f3xx-hal/pull/208
[#203]: https://github.com/stm32-rs/stm32f3xx-hal/issues/203
[#192]: https://github.com/stm32-rs/stm32f3xx-hal/pull/192
[#186]: https://github.com/stm32-rs/stm32f3xx-hal/pull/186
[#184]: https://github.com/stm32-rs/stm32f3xx-hal/pull/184
[#172]: https://github.com/stm32-rs/stm32f3xx-hal/pull/172
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ nb = "0.1"
paste = "1"
rtcc = "0.2"
stm32f3 = "0.12"
embedded-time = "0.10"

[dependencies.embedded-hal-can]
version = "0.1.0"
Expand Down
11 changes: 6 additions & 5 deletions examples/can.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use cortex_m_rt::entry;

use hal::prelude::*;
use hal::stm32;
use hal::time::{duration::*, rate::*};
use hal::watchdog::IndependentWatchDog;

use hal::can::{Can, CanFilter, CanFrame, CanId, Filter, Frame, Receiver, Transmitter};
Expand All @@ -31,10 +32,10 @@ fn main() -> ! {

let _clocks = rcc
.cfgr
.use_hse(32.mhz())
.sysclk(32.mhz())
.pclk1(16.mhz())
.pclk2(16.mhz())
.use_hse(32u32.MHz())
.sysclk(32u32.MHz())
.pclk1(16u32.MHz())
.pclk2(16u32.MHz())
.freeze(&mut flash.acr);

// Configure CAN RX and TX pins (AF9)
Expand All @@ -60,7 +61,7 @@ fn main() -> ! {
// Watchdog makes sure this gets restarted periodically if nothing happens
let mut iwdg = IndependentWatchDog::new(dp.IWDG);
iwdg.stop_on_debug(&dp.DBGMCU, true);
iwdg.start(100.ms());
iwdg.start(100u32.milliseconds());

// Send an initial message!
asm::delay(100_000);
Expand Down
12 changes: 10 additions & 2 deletions examples/i2c_scanner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
#![no_std]
#![no_main]

use core::ops::Range;
use core::{convert::TryInto, ops::Range};

use panic_semihosting as _;

use cortex_m::asm;
use cortex_m_rt::entry;
use cortex_m_semihosting::{hprint, hprintln};

use hal::time::rate::*;
use stm32f3xx_hal::{self as hal, pac, prelude::*};

const VALID_ADDR_RANGE: Range<u8> = 0x08..0x78;
Expand All @@ -33,7 +34,14 @@ fn main() -> ! {
gpiob.pb6.into_af4(&mut gpiob.moder, &mut gpiob.afrl), // SCL
gpiob.pb7.into_af4(&mut gpiob.moder, &mut gpiob.afrl), // SDA
);
let mut i2c = hal::i2c::I2c::new(dp.I2C1, pins, 100.khz(), clocks, &mut rcc.apb1);

let mut i2c = hal::i2c::I2c::new(
dp.I2C1,
pins,
100u32.kHz().try_into().unwrap(),
clocks,
&mut rcc.apb1,
);

hprintln!("Start i2c scanning...").expect("Error using hprintln.");
hprintln!().unwrap();
Expand Down
28 changes: 14 additions & 14 deletions examples/pwm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use hal::gpio::GpioExt;
use hal::pac;
use hal::pwm::{tim16, tim2, tim3, tim8};
use hal::rcc::RccExt;
use hal::time::U32Ext;
use hal::time::rate::*;

#[entry]
fn main() -> ! {
Expand All @@ -28,7 +28,7 @@ fn main() -> ! {
// Configure our clocks
let mut flash = dp.FLASH.constrain();
let mut rcc = dp.RCC.constrain();
let clocks = rcc.cfgr.sysclk(16.mhz()).freeze(&mut flash.acr);
let clocks = rcc.cfgr.sysclk(16u32.MHz()).freeze(&mut flash.acr);

// Prep the pins we need in their correct alternate function
let mut gpioa = dp.GPIOA.split(&mut rcc.ahb);
Expand All @@ -52,9 +52,9 @@ fn main() -> ! {
// A four channel general purpose timer that's broadly available
let tim3_channels = tim3(
dp.TIM3,
1280, // resolution of duty cycle
50.hz(), // frequency of period
&clocks, // To get the timer's clock speed
1280, // resolution of duty cycle
50u32.Hz(), // frequency of period
&clocks, // To get the timer's clock speed
);

// Channels without pins cannot be enabled, so we can't forget to
Expand Down Expand Up @@ -101,9 +101,9 @@ fn main() -> ! {
// A 32-bit timer, so we can set a larger resolution
let tim2_channels = tim2(
dp.TIM2,
160000, // resolution of duty cycle
50.hz(), // frequency of period
&clocks, // To get the timer's clock speed
160000, // resolution of duty cycle
50u32.Hz(), // frequency of period
&clocks, // To get the timer's clock speed
);

let mut tim2_ch3 = tim2_channels.2.output_to_pb10(pb10);
Expand All @@ -116,9 +116,9 @@ fn main() -> ! {
// just use it directly
let mut tim16_ch1 = tim16(
dp.TIM16,
1280, // resolution of duty cycle
50.hz(), // frequency of period
&clocks, // To get the timer's clock speed
1280, // resolution of duty cycle
50u32.Hz(), // frequency of period
&clocks, // To get the timer's clock speed
)
.output_to_pb8(pb8);
tim16_ch1.set_duty(tim16_ch1.get_max_duty() / 20); // 5% duty cyle
Expand All @@ -130,9 +130,9 @@ fn main() -> ! {
// to complementary pins (works just like standard pins)
let tim8_channels = tim8(
dp.TIM8,
1280, // resolution of duty cycle
50.hz(), // frequency of period
&clocks, // To get the timer's clock speed
1280, // resolution of duty cycle
50u32.Hz(), // frequency of period
&clocks, // To get the timer's clock speed
);

let mut tim8_ch1 = tim8_channels.0.output_to_pc10(pc10);
Expand Down
4 changes: 2 additions & 2 deletions examples/serial_dma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use panic_semihosting as _;

use cortex_m::{asm, singleton};
use cortex_m_rt::entry;
use stm32f3xx_hal::{pac, prelude::*, serial::Serial};
use stm32f3xx_hal::{pac, prelude::*, serial::Serial, time::rate::*};

#[entry]
fn main() -> ! {
Expand All @@ -25,7 +25,7 @@ fn main() -> ! {
gpioa.pa9.into_af7(&mut gpioa.moder, &mut gpioa.afrh),
gpioa.pa10.into_af7(&mut gpioa.moder, &mut gpioa.afrh),
);
let serial = Serial::usart1(dp.USART1, pins, 9600.bps(), clocks, &mut rcc.apb2);
let serial = Serial::usart1(dp.USART1, pins, 9600.Bd(), clocks, &mut rcc.apb2);
let (tx, rx) = serial.split();

let dma1 = dp.DMA1.split(&mut rcc.ahb);
Expand Down
11 changes: 7 additions & 4 deletions examples/spi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#![no_std]
#![no_main]

use core::convert::TryInto;

use panic_semihosting as _;

use stm32f3xx_hal as hal;
Expand All @@ -13,6 +15,7 @@ use cortex_m_rt::entry;
use hal::pac;
use hal::prelude::*;
use hal::spi::{Mode, Phase, Polarity, Spi};
use hal::time::rate::*;

#[entry]
fn main() -> ! {
Expand All @@ -24,9 +27,9 @@ fn main() -> ! {

let clocks = rcc
.cfgr
.use_hse(8.mhz())
.sysclk(48.mhz())
.pclk1(24.mhz())
.use_hse(8u32.MHz())
.sysclk(48u32.MHz())
.pclk1(24u32.MHz())
.freeze(&mut flash.acr);

// Configure pins for SPI
Expand All @@ -43,7 +46,7 @@ fn main() -> ! {
dp.SPI1,
(sck, miso, mosi),
spi_mode,
3.mhz(),
3u32.MHz().try_into().unwrap(),
clocks,
&mut rcc.apb2,
);
Expand Down
9 changes: 5 additions & 4 deletions examples/usb_serial.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ use cortex_m_rt::entry;

use hal::pac;
use hal::prelude::*;
use hal::time::rate::*;
use hal::usb::{Peripheral, UsbBus};

use usb_device::prelude::*;
Expand All @@ -26,10 +27,10 @@ fn main() -> ! {

let clocks = rcc
.cfgr
.use_hse(8.mhz())
.sysclk(48.mhz())
.pclk1(24.mhz())
.pclk2(24.mhz())
.use_hse(8u32.MHz())
.sysclk(48u32.MHz())
.pclk1(24u32.MHz())
.pclk2(24u32.MHz())
.freeze(&mut flash.acr);

assert!(clocks.usbclk_valid());
Expand Down
17 changes: 7 additions & 10 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
hal::blocking::i2c::{Read, Write, WriteRead},
pac::{i2c1::RegisterBlock, rcc::cfgr3::I2C1SW_A, I2C1, RCC},
rcc::{Clocks, APB1},
time::{Hertz, U32Ext},
time::rate::*,
};

#[cfg(not(feature = "gpio-f333"))]
Expand Down Expand Up @@ -111,16 +111,13 @@ macro_rules! busy_wait {

impl<I2C, SCL, SDA> I2c<I2C, (SCL, SDA)> {
/// Configures the I2C peripheral to work in master mode
pub fn new<F>(i2c: I2C, pins: (SCL, SDA), freq: F, clocks: Clocks, apb1: &mut APB1) -> Self
pub fn new(i2c: I2C, pins: (SCL, SDA), freq: Hertz, clocks: Clocks, apb1: &mut APB1) -> Self
where
I2C: Instance,
SCL: SclPin<I2C>,
SDA: SdaPin<I2C>,
F: Into<Hertz>,
{
let freq = freq.into().0;

crate::assert!(freq <= 1_000_000);
crate::assert!(*freq.integer() <= 1_000_000);

I2C::enable_clock(apb1);

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

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

let (sdadel, scldel) = if freq > 400_000 {
let (sdadel, scldel) = if *freq.integer() > 400_000 {
// fast-mode plus
let sdadel = 0;
let scldel = i2cclk / 4_000_000 / (presc + 1) - 1;
Expand Down Expand Up @@ -451,7 +448,7 @@ macro_rules! i2c {
fn clock(clocks: &Clocks) -> Hertz {
// NOTE(unsafe) atomic read with no side effects
match unsafe { (*RCC::ptr()).cfgr3.read().$i2cXsw().variant() } {
I2C1SW_A::HSI => 8.mhz().into(),
I2C1SW_A::HSI => Hertz(8_000_000),
strom-und-spiele marked this conversation as resolved.
Show resolved Hide resolved
I2C1SW_A::SYSCLK => clocks.sysclk(),
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ pub use embedded_hal as hal;
pub use nb;
pub use nb::block;

pub use embedded_time as time;

#[cfg(feature = "defmt")]
pub(crate) use defmt::{assert, panic, unreachable, unwrap};
#[cfg(feature = "defmt")]
Expand Down Expand Up @@ -188,7 +190,6 @@ cfg_if::cfg_if! {
pub mod rtc;
pub mod serial;
pub mod spi;
pub mod time;
pub mod timer;
}
}
Expand Down
1 change: 0 additions & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ pub use crate::flash::FlashExt as _stm32f3xx_hal_flash_FlashExt;
pub use crate::gpio::GpioExt as _stm32f3xx_hal_gpio_GpioExt;
pub use crate::hal::prelude::*;
pub use crate::rcc::RccExt as _stm32f3xx_hal_rcc_RccExt;
pub use crate::time::U32Ext as _stm32f3xx_hal_time_U32Ext;
#[cfg(feature = "unproven")]
pub use crate::{
hal::digital::v2::InputPin as _embedded_hal_digital_InputPin,
Expand Down
Loading