From a6422848bb44ac1ca61e989833ce3e64ab4a6a21 Mon Sep 17 00:00:00 2001 From: James Waples Date: Sun, 25 Jul 2021 14:26:37 +0100 Subject: [PATCH] Port crate over to embedded-time --- CHANGELOG.md | 3 ++ Cargo.toml | 1 + examples/adc_pwm.rs | 2 +- examples/button.rs | 4 +- examples/lptim.rs | 2 +- examples/pwm.rs | 2 +- examples/spi.rs | 2 +- examples/spi_dma.rs | 2 +- examples/timer.rs | 2 +- examples/timer_interrupt_rtic.rs | 2 +- examples/watchdog.rs | 2 +- src/delay.rs | 14 +++-- src/i2c.rs | 2 +- src/lib.rs | 1 - src/lptim.rs | 16 +++--- src/prelude.rs | 6 ++- src/pwm.rs | 19 +++---- src/rcc.rs | 16 +++--- src/rtc.rs | 4 +- src/serial.rs | 8 ++- src/spi.rs | 2 +- src/time.rs | 89 -------------------------------- src/timer.rs | 2 +- src/watchdog.rs | 2 +- 24 files changed, 65 insertions(+), 140 deletions(-) delete mode 100755 src/time.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ec11d64..08fdc117 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,8 @@ the linker instead of having a default for the whole sub-family. ([#173]) ### Breaking Changes +- Migrate from custom `Hertz` implementation to [`embedded-time`](https://crates.io/crates/embedded-time) ([#183]) + - Add `enable` to `GeneralPurposeTimer` - `Instance::clock_frequency` is now an associated function and doesn't take `&self` anymore. @@ -119,6 +121,7 @@ _Not yet tracked in this changelog._ +[#183]: https://github.com/stm32-rs/stm32l0xx-hal/issues/183 [#148]: https://github.com/stm32-rs/stm32l0xx-hal/issues/148 [#145]: https://github.com/stm32-rs/stm32l0xx-hal/issues/145 [#144]: https://github.com/stm32-rs/stm32l0xx-hal/issues/144 diff --git a/Cargo.toml b/Cargo.toml index 4ddf27d0..8748fb07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ cortex-m = "0.7.0" cortex-m-rt = "0.6.8" cortex-m-semihosting = "0.3.2" nb = "1.0.0" +embedded-time = "0.12.0" [dependencies.cast] version = "0.2.2" diff --git a/examples/adc_pwm.rs b/examples/adc_pwm.rs index e0241220..5307124f 100644 --- a/examples/adc_pwm.rs +++ b/examples/adc_pwm.rs @@ -19,7 +19,7 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); // Configure the timer as PWM on PA1. - let pwm = pwm::Timer::new(dp.TIM2, 1.khz(), &mut rcc); + let pwm = pwm::Timer::new(dp.TIM2, 1.kHz(), &mut rcc); let mut pwm = pwm.channel2.assign(gpioa.pa1); let max_duty = pwm.get_max_duty() / 4095; pwm.enable(); diff --git a/examples/button.rs b/examples/button.rs index 4c25cbf0..d8b5520c 100644 --- a/examples/button.rs +++ b/examples/button.rs @@ -31,8 +31,8 @@ fn main() -> ! { loop { let wait = match button.is_high() { - Ok(true) => 300.ms(), - Ok(false) => 100.ms(), + Ok(true) => 300.milliseconds(), + Ok(false) => 100.milliseconds(), _ => unreachable!(), }; delay.delay(wait); diff --git a/examples/lptim.rs b/examples/lptim.rs index 9bf0882a..568bf568 100644 --- a/examples/lptim.rs +++ b/examples/lptim.rs @@ -46,7 +46,7 @@ fn main() -> ! { blink(&mut led); // 1 seconds of regular run mode - lptim.start(1.hz()); + lptim.start(1.Hz()); block!(lptim.wait()).unwrap(); Exti::unpend(exti_line); diff --git a/examples/pwm.rs b/examples/pwm.rs index 3a6ac2a2..a9730aa2 100644 --- a/examples/pwm.rs +++ b/examples/pwm.rs @@ -24,7 +24,7 @@ fn main() -> ! { let gpioa = dp.GPIOA.split(&mut rcc); // Initialize TIM2 for PWM - let pwm = pwm::Timer::new(dp.TIM2, 10.khz(), &mut rcc); + let pwm = pwm::Timer::new(dp.TIM2, 10_000.Hz(), &mut rcc); #[cfg(feature = "stm32l0x1")] let mut pwm = pwm.channel2.assign(gpioa.pa1); diff --git a/examples/spi.rs b/examples/spi.rs index 89b34a00..5ac957b0 100644 --- a/examples/spi.rs +++ b/examples/spi.rs @@ -26,7 +26,7 @@ fn main() -> ! { // Initialise the SPI peripheral. let mut spi = dp .SPI1 - .spi((sck, miso, mosi), spi::MODE_0, 100_000.hz(), &mut rcc); + .spi((sck, miso, mosi), spi::MODE_0, 100_000.Hz(), &mut rcc); loop { nss.set_low().unwrap(); diff --git a/examples/spi_dma.rs b/examples/spi_dma.rs index 58da8a91..0059036e 100644 --- a/examples/spi_dma.rs +++ b/examples/spi_dma.rs @@ -36,7 +36,7 @@ fn main() -> ! { // Initialise the SPI peripheral. let mut spi = dp .SPI1 - .spi((sck, miso, mosi), spi::MODE_0, 100_000.hz(), &mut rcc); + .spi((sck, miso, mosi), spi::MODE_0, 100_000.Hz(), &mut rcc); let mut scb = cp.SCB; let mut dma = DMA::new(dp.DMA1, &mut rcc); diff --git a/examples/timer.rs b/examples/timer.rs index daca5ca9..b3ac4941 100644 --- a/examples/timer.rs +++ b/examples/timer.rs @@ -36,7 +36,7 @@ fn main() -> ! { let led = gpioa.pa1.into_push_pull_output(); // Configure the timer. - let mut timer = dp.TIM2.timer(1.hz(), &mut rcc); + let mut timer = dp.TIM2.timer(1.Hz(), &mut rcc); timer.listen(); // Store the LED and timer in mutex refcells to make them available from the diff --git a/examples/timer_interrupt_rtic.rs b/examples/timer_interrupt_rtic.rs index 554a1dba..ab99aab8 100644 --- a/examples/timer_interrupt_rtic.rs +++ b/examples/timer_interrupt_rtic.rs @@ -30,7 +30,7 @@ const APP: () = { let led = gpioa.pa1.into_push_pull_output().downgrade(); // Configure the timer. - let mut timer = device.TIM2.timer(1.hz(), &mut rcc); + let mut timer = device.TIM2.timer(1.Hz(), &mut rcc); timer.listen(); // Return the initialised resources. diff --git a/examples/watchdog.rs b/examples/watchdog.rs index 9becbefe..413759b4 100644 --- a/examples/watchdog.rs +++ b/examples/watchdog.rs @@ -24,7 +24,7 @@ fn main() -> ! { let mut watchdog = dp.IWDG.watchdog(); // Start a watchdog with a 100ms period. - watchdog.start(100.ms()); + watchdog.start(10.Hz()); let mut counter = 50; loop { diff --git a/src/delay.rs b/src/delay.rs index 867cc985..0ec9806d 100755 --- a/src/delay.rs +++ b/src/delay.rs @@ -1,10 +1,12 @@ //! Delays + use crate::hal::blocking::delay::{DelayMs, DelayUs}; use crate::rcc::Clocks; -use crate::time::MicroSeconds; use cast::u32; +use core::convert::TryInto; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; +use embedded_time::duration::{Extensions, Microseconds}; pub trait DelayExt { fn delay(self, clocks: Clocks) -> Delay; @@ -31,11 +33,17 @@ impl Delay { let ticks_per_us = freq / 1_000_000_u32; Delay { ticks_per_us, syst } } + + /// Wait for the given time. + /// + /// Note that durations above `u32::MAX` microseconds will be clamped at `u32::MAX`. pub fn delay(&mut self, delay: T) where - T: Into, + T: TryInto, { - self.delay_us(delay.into().0) + let delay = delay.try_into().unwrap_or_else(|_| u32::MAX.microseconds()); + + self.delay_us(delay.0) } /// Releases the system timer (SysTick) resource diff --git a/src/i2c.rs b/src/i2c.rs index 9fbbfbd8..90caab99 100755 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -15,8 +15,8 @@ use crate::pac::i2c1::{ RegisterBlock, }; use crate::rcc::Rcc; -use crate::time::Hertz; use cast::u8; +use embedded_time::rate::Hertz; // I²C traits use crate::hal::blocking::i2c::{Read, Write, WriteRead}; diff --git a/src/lib.rs b/src/lib.rs index 5a5631dc..695d5b53 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -61,7 +61,6 @@ pub mod serial; pub mod signature; pub mod spi; pub mod syscfg; -pub mod time; pub mod timer; #[cfg(all( feature = "stm32-usbd", diff --git a/src/lptim.rs b/src/lptim.rs index f8dfecf4..12037c9b 100644 --- a/src/lptim.rs +++ b/src/lptim.rs @@ -5,10 +5,11 @@ use crate::hal; use crate::pac::LPTIM; use crate::pwr::PWR; use crate::rcc::Rcc; -use crate::time::{Hertz, MicroSeconds}; use cast::{u32, u64}; use core::convert::TryFrom; use core::marker::PhantomData; +use embedded_time::duration::Microseconds; +use embedded_time::rate::Hertz; use void::Void; mod sealed { @@ -85,7 +86,7 @@ pub struct Interrupts { /// The timer can be initialized either in one-shot mode or in periodic mode, using `init_oneshot` /// or `init_periodic` respectively. In periodic mode, the embedded-hal `Periodic` marker trait is /// implemented and the `CountDown` implementation uses `Hertz` as the time unit. In one-shot mode, -/// the `CountDown` implementation instead uses `MicroSeconds`, allowing for a multi-second timeout +/// the `CountDown` implementation instead uses `Microseconds`, allowing for a multi-second timeout /// to be configured (with the tradeoff being a larger code size due to use of 64-bit arithmetic). pub struct LpTimer { lptim: LPTIM, @@ -365,11 +366,11 @@ impl hal::timer::CountDown for LpTimer { impl hal::timer::Periodic for LpTimer {} impl hal::timer::CountDown for LpTimer { - type Time = MicroSeconds; + type Time = Microseconds; fn start(&mut self, period: T) where - T: Into, + T: Into, { self.configure(TimeConf::calculate_period(self.input_freq, period.into())); @@ -435,7 +436,7 @@ impl TimeConf { /// Calculates prescaler and autoreload value for producing overflows after every /// `output_period`. - fn calculate_period(input_freq: Hertz, output_period: MicroSeconds) -> Self { + fn calculate_period(input_freq: Hertz, output_period: Microseconds) -> Self { // Here, the `output_period` can be very long, resulting in an output frequency of < 1 Hz. // Fi = Frequency of input clock @@ -484,7 +485,6 @@ impl TimeConf { #[cfg(test)] mod tests { use super::*; - use crate::time::U32Ext; /// Test-only methods. impl TimeConf { @@ -498,8 +498,8 @@ mod tests { Hertz(input_freq.0 / u32(self.psc()) / u32(self.arr)) } - fn output_period(&self, input_freq: Hertz) -> MicroSeconds { - MicroSeconds( + fn output_period(&self, input_freq: Hertz) -> Microseconds { + Microseconds( u32(u64(self.psc()) * u64(self.arr) * 1_000_000 / u64(input_freq.0)).unwrap(), ) } diff --git a/src/prelude.rs b/src/prelude.rs index 62138a11..b6812b29 100755 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -15,11 +15,15 @@ pub use crate::{ pwr::PowerMode as _, rcc::RccExt as _, spi::SpiExt as _, - time::U32Ext as _, timer::TimerExt as _, watchdog::{IndependedWatchdogExt as _, WindowWatchdogExt as _}, }; +// Make items like `.Hz()`, `.microseconds()` available from embedded-time +pub use embedded_time::{ + duration::Extensions as DurationExtensions, rate::Extensions as RateExtensions, +}; + #[cfg(any( feature = "io-STM32L021", feature = "io-STM32L031", diff --git a/src/pwm.rs b/src/pwm.rs index 1527e19d..b1c9d91a 100755 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1,15 +1,13 @@ -use core::marker::PhantomData; -use core::ops::Deref; - -use cortex_m::interrupt; - use crate::gpio::gpioa::{PA0, PA1, PA2, PA3}; use crate::gpio::{AltMode, PinMode}; use crate::hal; use crate::pac::{tim2, TIM2, TIM3}; use crate::rcc::Rcc; -use crate::time::Hertz; use cast::{u16, u32}; +use core::marker::PhantomData; +use core::ops::Deref; +use cortex_m::interrupt; +use embedded_time::rate::Hertz; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use crate::gpio::{ @@ -43,7 +41,9 @@ where I: Instance, { /// Create new timer instance that is automatically started with given frequency - pub fn new(timer: I, frequency: Hertz, rcc: &mut Rcc) -> Self { + pub fn new(timer: I, frequency: impl Into, rcc: &mut Rcc) -> Self { + let frequency = frequency.into(); + timer.enable(rcc); let mut tim = Self { @@ -72,7 +72,8 @@ where /// In order to do this operation properly the function stop the timer and then starts it again. /// The duty cycle that was set before for given pin needs to adjusted according to the /// frequency - pub fn set_frequency(&mut self, frequency: Hertz, rcc: &Rcc) { + pub fn set_frequency(&mut self, frequency: impl Into, rcc: &Rcc) { + let frequency = frequency.into(); self.stop(); let (psc, arr) = get_clock_config(frequency.0, I::clock_frequency(rcc)); self.instance.psc.write(|w| w.psc().bits(psc)); @@ -268,7 +269,7 @@ where { /// This allows to dynamically change the frequency of the underlying PWM timer. /// - /// **WARNING:** + /// **WARNING:** /// This changes the frequency for all channels associated with the PWM timer. pub fn set_frequency(&mut self, frequency: Hertz, rcc: &Rcc) { let (psc, arr) = get_clock_config(frequency.0, I::clock_frequency(rcc)); diff --git a/src/rcc.rs b/src/rcc.rs index 287af4db..6d870926 100755 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -2,7 +2,7 @@ use crate::mco; use crate::pac::rcc::cfgr::{MCOPRE_A, MCOSEL_A}; use crate::pac::RCC; use crate::pwr::PWR; -use crate::time::{Hertz, U32Ext}; +use embedded_time::rate::{Extensions, Hertz}; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use crate::{pac::CRS, syscfg::SYSCFG}; @@ -340,7 +340,7 @@ impl RccExt for RCC { PLLDiv::Div3 => freq / 3, PLLDiv::Div4 => freq / 4, }; - assert!(freq <= 32.mhz().0); + assert!(freq <= 32_u32.MHz().0); self.cfgr.write(move |w| unsafe { w.pllmul() @@ -393,12 +393,12 @@ impl RccExt for RCC { let clocks = Clocks { source: cfgr.mux, - sys_clk: sys_clk.hz(), - ahb_clk: ahb_freq.hz(), - apb1_clk: apb1_freq.hz(), - apb2_clk: apb2_freq.hz(), - apb1_tim_clk: apb1_tim_freq.hz(), - apb2_tim_clk: apb2_tim_freq.hz(), + sys_clk: sys_clk.Hz(), + ahb_clk: ahb_freq.Hz(), + apb1_clk: apb1_freq.Hz(), + apb2_clk: apb2_freq.Hz(), + apb1_tim_clk: apb1_tim_freq.Hz(), + apb2_tim_clk: apb2_tim_freq.Hz(), }; Rcc { rb: self, clocks } diff --git a/src/rtc.rs b/src/rtc.rs index 91332889..238ede0f 100644 --- a/src/rtc.rs +++ b/src/rtc.rs @@ -2,6 +2,7 @@ //! //! See STM32L0x2 reference manual, chapter 26. +use embedded_time::rate::Extensions; use void::Void; use crate::{ @@ -9,7 +10,6 @@ use crate::{ pac, pwr::PWR, rcc::Rcc, - time::U32Ext, }; /// Entry point to the RTC API @@ -57,7 +57,7 @@ impl RTC { }); let apb1_clk = rcc.clocks.apb1_clk(); - let rtc_clk = 32_768u32.hz(); // LSE crystal frequency + let rtc_clk = 32_768u32.Hz(); // LSE crystal frequency // The APB1 clock must not be slower than the RTC clock. if apb1_clk < rtc_clk { diff --git a/src/serial.rs b/src/serial.rs index 66203990..28e98eb0 100755 --- a/src/serial.rs +++ b/src/serial.rs @@ -9,6 +9,7 @@ use crate::hal; use crate::hal::prelude::*; pub use crate::pac::{LPUART1, USART1, USART2, USART4, USART5}; use crate::rcc::{Rcc, LSE}; +use embedded_time::rate::{BitsPerSecond, Extensions}; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use core::{ @@ -67,9 +68,6 @@ pub enum Event { Idle, } -use crate::time::Bps; -use crate::time::U32Ext; - pub enum WordLength { DataBits8, DataBits9, @@ -93,14 +91,14 @@ pub enum StopBits { } pub struct Config { - pub baudrate: Bps, + pub baudrate: BitsPerSecond, pub wordlength: WordLength, pub parity: Parity, pub stopbits: StopBits, } impl Config { - pub fn baudrate(mut self, baudrate: Bps) -> Self { + pub fn baudrate(mut self, baudrate: BitsPerSecond) -> Self { self.baudrate = baudrate; self } diff --git a/src/spi.rs b/src/spi.rs index d880e956..a357e9e3 100755 --- a/src/spi.rs +++ b/src/spi.rs @@ -6,6 +6,7 @@ use core::{ }; use as_slice::{AsMutSlice, AsSlice}; +use embedded_time::rate::Hertz; use crate::dma::{self, Buffer}; @@ -19,7 +20,6 @@ use crate::pac::SPI1; #[cfg(any(feature = "stm32l0x2", feature = "stm32l0x3"))] use crate::pac::SPI2; use crate::rcc::Rcc; -use crate::time::Hertz; pub use hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; diff --git a/src/time.rs b/src/time.rs deleted file mode 100755 index c5363092..00000000 --- a/src/time.rs +++ /dev/null @@ -1,89 +0,0 @@ -use core::fmt; - -#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] -pub struct Bps(pub u32); - -impl fmt::Display for Bps { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} bps", self.0) - } -} - -#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] -pub struct Hertz(pub u32); - -impl fmt::Display for Hertz { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} Hz", self.0) - } -} - -#[derive(Debug, PartialEq, PartialOrd, Clone, Copy)] -pub struct MicroSeconds(pub u32); - -impl fmt::Display for MicroSeconds { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{} µs", self.0) - } -} - -/// Extension trait that adds convenience methods to the `u32` type -pub trait U32Ext { - /// Wrap in `Bps` - fn bps(self) -> Bps; - - /// Wrap in `Hertz` - fn hz(self) -> Hertz; - - /// Wrap in `Hertz` - fn khz(self) -> Hertz; - - /// Wrap in `Hertz` - fn mhz(self) -> Hertz; - - /// Wrap in `MicroSeconds` - fn us(self) -> MicroSeconds; - - /// Wrap in `MicroSeconds` - fn ms(self) -> MicroSeconds; -} - -impl U32Ext for u32 { - fn bps(self) -> Bps { - Bps(self) - } - - fn hz(self) -> Hertz { - Hertz(self) - } - - fn khz(self) -> Hertz { - Hertz(self * 1_000) - } - - fn mhz(self) -> Hertz { - Hertz(self * 1_000_000) - } - - fn us(self) -> MicroSeconds { - MicroSeconds(self) - } - - fn ms(self) -> MicroSeconds { - MicroSeconds(self * 1_000) - } -} - -impl From for MicroSeconds { - fn from(Hertz(freq): Hertz) -> MicroSeconds { - assert!(freq != 0 && freq <= 1_000_000); - MicroSeconds(1_000_000 / freq) - } -} - -impl From for Hertz { - fn from(MicroSeconds(period): MicroSeconds) -> Hertz { - assert!(period != 0 && period <= 1_000_000); - Hertz(1_000_000 / period) - } -} diff --git a/src/timer.rs b/src/timer.rs index 52dc0479..613b3ddd 100755 --- a/src/timer.rs +++ b/src/timer.rs @@ -2,10 +2,10 @@ use crate::hal::timer::{CountDown, Periodic}; use crate::pac::{tim2, tim21, tim22, tim6, TIM2, TIM21, TIM22, TIM3, TIM6}; use crate::rcc::{Clocks, Rcc}; -use crate::time::Hertz; use cast::{u16, u32}; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; +use embedded_time::rate::Hertz; use void::Void; pub trait TimerExt { diff --git a/src/watchdog.rs b/src/watchdog.rs index f9648348..0a149b30 100755 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -1,7 +1,7 @@ use crate::hal::watchdog; use crate::pac::{IWDG, WWDG}; use crate::rcc::Rcc; -use crate::time::Hertz; +use embedded_time::rate::Hertz; pub struct IndependedWatchdog { iwdg: IWDG,