diff --git a/CHANGELOG.md b/CHANGELOG.md index c0d3efa..566f338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed +- Usw `fugit`-based time types instead of `embedded-time` - Update gpios: add `DynamicPin`, add default modes, reexport pins, resort generics, etc. - Improved RCC infrastructure. - RTC support has been rewritten. diff --git a/Cargo.toml b/Cargo.toml index 055637f..b5b1573 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,6 @@ features = ["stm32f746", "rt"] as-slice = "0.2" cortex-m = "0.7.4" cortex-m-rt = ">=0.6.15, <0.8" -embedded-time = "0.12.0" nb = "1.0" stm32f7 = "0.14.0" micromath = "2.0" @@ -29,6 +28,7 @@ stm32-fmc = { version = "0.2.0", features = ["sdram"], optional = true } rand_core = "0.6" bxcan = "0.6" bare-metal = "1.0" +fugit = "0.3.5" [dependencies.time] version = "0.3" diff --git a/src/adc.rs b/src/adc.rs index 4e1ca7b..42cb393 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -257,7 +257,7 @@ macro_rules! adc_hal { // The reference manual says that a stabilization time is needed after power_up, // this time can be found in the datasheets. // for STM32F7xx : delay(216_000_000/800_000)= delay(270 cycles) = 1.25us - delay(self.clocks.sysclk().0 / 800_000); + delay(self.clocks.sysclk().raw() / 800_000); } // 15.3.1 ADC on-off control @@ -466,7 +466,7 @@ impl Adc { // The reference manual says that a stabilization time is needed after the powering the // sensor, this time can be found in the datasheets. - delay(self.clocks.sysclk().0 / 80_000); + delay(self.clocks.sysclk().raw() / 80_000); true } else { false diff --git a/src/delay.rs b/src/delay.rs index d01f80f..db656a9 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -50,7 +50,7 @@ impl DelayUs for Delay { // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF. const MAX_RVR: u32 = 0x00FF_FFFF; - let mut total_rvr = us * (self.clocks.hclk().0 / 8_000_000); + let mut total_rvr = us * (self.clocks.hclk().raw() / 8_000_000); while total_rvr != 0 { let current_rvr = if total_rvr <= MAX_RVR { diff --git a/src/fmc.rs b/src/fmc.rs index 6202a2d..46182ad 100644 --- a/src/fmc.rs +++ b/src/fmc.rs @@ -6,9 +6,9 @@ use stm32_fmc::FmcPeripheral; use stm32_fmc::{AddressPinSet, PinsSdram, Sdram, SdramChip, SdramPinSet, SdramTargetBank}; -use crate::embedded_time::rate::Hertz; use crate::pac; use crate::rcc::{Clocks, Enable, Reset}; +use fugit::HertzU32 as Hertz; use crate::gpio::{self, Alternate}; @@ -75,7 +75,7 @@ unsafe impl FmcPeripheral for FMC { fn source_clock_hz(&self) -> u32 { // FMC block is clocked by HCLK - self.hclk.0 + self.hclk.raw() } } diff --git a/src/i2c.rs b/src/i2c.rs index 02fd19f..29a1a4d 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -3,11 +3,11 @@ // NB : this implementation started as a modified copy of https://github.com/stm32-rs/stm32f1xx-hal/blob/master/src/i2c.rs -use crate::embedded_time::rate::Hertz; use crate::gpio::{self, Alternate, OpenDrain}; use crate::hal::blocking::i2c::{Read, Write, WriteRead}; use crate::pac::{DWT, I2C1, I2C2, I2C3}; use crate::rcc::{Clocks, Enable, GetBusFreq, RccBus, Reset}; +use fugit::HertzU32 as Hertz; use nb::Error::{Other, WouldBlock}; use nb::{Error as NbError, Result as NbResult}; @@ -43,22 +43,16 @@ pub enum Mode { } impl Mode { - pub fn standard>(frequency: F) -> Self { - Mode::Standard { - frequency: frequency.into(), - } + pub fn standard(frequency: Hertz) -> Self { + Mode::Standard { frequency } } - pub fn fast>(frequency: F) -> Self { - Mode::Fast { - frequency: frequency.into(), - } + pub fn fast(frequency: Hertz) -> Self { + Mode::Fast { frequency } } - pub fn fast_plus>(frequency: F) -> Self { - Mode::FastPlus { - frequency: frequency.into(), - } + pub fn fast_plus(frequency: Hertz) -> Self { + Mode::FastPlus { frequency } } } @@ -89,7 +83,7 @@ pub struct I2c { i2c: I2C, pins: (SCL, SDA), mode: Mode, - pclk: u32, + pclk: Hertz, } /// embedded-hal compatible blocking I2C implementation @@ -209,7 +203,7 @@ fn blocking_i2c( clocks: Clocks, data_timeout_us: u32, ) -> BlockingI2c { - let sysclk_mhz = clocks.sysclk().0 / 1_000_000; + let sysclk_mhz = clocks.sysclk().to_MHz(); BlockingI2c { nb: i2c, data_timeout: data_timeout_us * sysclk_mhz, @@ -405,7 +399,7 @@ macro_rules! hal { $I2CX::enable(apb); $I2CX::reset(apb); - let pclk = <$I2CX as RccBus>::Bus::get_frequency(&clocks).0; + let pclk = <$I2CX as RccBus>::Bus::get_frequency(&clocks); let mut i2c = I2c { i2c, pins, mode, pclk }; i2c.init(); @@ -428,9 +422,9 @@ macro_rules! hal { let dnf = self.i2c.cr1.read().dnf().bits(); let i2c_timingr: I2cTiming = match self.mode { - Mode::Standard{ frequency } => calculate_timing(I2C_STANDARD_MODE_SPEC, self.pclk, frequency.0, an_filter, dnf ), - Mode::Fast{ frequency } => calculate_timing(I2C_FAST_MODE_SPEC, self.pclk, frequency.0, an_filter, dnf), - Mode::FastPlus{ frequency } => calculate_timing(I2C_FAST_PLUS_MODE_SPEC, self.pclk, frequency.0, an_filter, dnf ), + Mode::Standard{ frequency } => calculate_timing(I2C_STANDARD_MODE_SPEC, self.pclk.raw(), frequency.raw(), an_filter, dnf ), + Mode::Fast{ frequency } => calculate_timing(I2C_FAST_MODE_SPEC, self.pclk.raw(), frequency.raw(), an_filter, dnf), + Mode::FastPlus{ frequency } => calculate_timing(I2C_FAST_PLUS_MODE_SPEC, self.pclk.raw(), frequency.raw(), an_filter, dnf ), Mode::Custom{ timing_r } => { I2cTiming{ presc: ((timing_r & 0xf000_0000) >> 28 ) as u8, diff --git a/src/lib.rs b/src/lib.rs index d48eddd..bac7872 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,6 @@ compile_error!( ); pub(crate) use embedded_hal as hal; -pub use embedded_time; #[cfg(feature = "stm32f722")] pub use stm32f7::stm32f7x2 as pac; @@ -183,3 +182,18 @@ fn stripped_type_name() -> &'static str { let p = s.split("::"); p.last().unwrap() } + +/// Bits per second +pub type BitsPerSecond = fugit::HertzU32; + +/// Extension trait that adds convenience methods to the `u32` type +pub trait U32Ext { + /// Wrap in `Bps` + fn bps(self) -> BitsPerSecond; +} + +impl U32Ext for u32 { + fn bps(self) -> BitsPerSecond { + BitsPerSecond::from_raw(self) + } +} diff --git a/src/ltdc.rs b/src/ltdc.rs index b807748..8c16014 100644 --- a/src/ltdc.rs +++ b/src/ltdc.rs @@ -83,7 +83,7 @@ impl DisplayController { // Get base clock and PLLM divisor let base_clk: u32; match &hse { - Some(hse) => base_clk = hse.freq.0, + Some(hse) => base_clk = hse.freq.raw(), // If no HSE is provided, we use the HSI clock at 16 MHz None => base_clk = 16_000_000, } diff --git a/src/otg_fs.rs b/src/otg_fs.rs index 6e234ae..c6287bd 100644 --- a/src/otg_fs.rs +++ b/src/otg_fs.rs @@ -5,12 +5,12 @@ use crate::pac; -use crate::embedded_time::rate::Hertz; use crate::gpio::{ gpioa::{PA11, PA12}, Alternate, }; use crate::rcc::{Clocks, Enable, Reset}; +use fugit::HertzU32 as Hertz; pub use synopsys_usb_otg::UsbBus; use synopsys_usb_otg::UsbPeripheral; @@ -66,7 +66,7 @@ unsafe impl UsbPeripheral for USB { } fn ahb_frequency_hz(&self) -> u32 { - self.hclk.0 + self.hclk.raw() } } diff --git a/src/otg_hs.rs b/src/otg_hs.rs index d63bbb9..ad11295 100644 --- a/src/otg_hs.rs +++ b/src/otg_hs.rs @@ -10,7 +10,7 @@ use crate::gpio::{ Alternate, }; use crate::rcc::{Clocks, Enable, Reset}; -use embedded_time::rate::Hertz; +use fugit::{HertzU32 as Hertz, RateExtU32}; #[cfg(feature = "usb_hs_phy")] use synopsys_usb_otg::PhyType; @@ -51,7 +51,7 @@ impl USB { pin_dp: pins.1, hclk: clocks.hclk(), #[cfg(feature = "usb_hs_phy")] - hse: clocks.hse().unwrap_or_else(|| Hertz(0)), + hse: clocks.hse().unwrap_or_else(|| 0.Hz()), } } @@ -109,7 +109,7 @@ unsafe impl UsbPeripheral for USB { } fn ahb_frequency_hz(&self) -> u32 { - self.hclk.0 + self.hclk.raw() } #[cfg(feature = "usb_hs_phy")] @@ -135,7 +135,7 @@ unsafe impl UsbPeripheral for USB { }; // Calculate PLL1SEL - let pll1sel = match self.hse.0 { + let pll1sel = match self.hse.raw() { 12_000_000 => 0b000, 12_500_000 => 0b001, 16_000_000 => 0b011, diff --git a/src/prelude.rs b/src/prelude.rs index df503a3..e759c46 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,4 +1,4 @@ -pub use embedded_time::{duration::Extensions as _, rate::Extensions as _}; +pub use fugit::{ExtU32 as _, RateExtU32 as _}; #[cfg(feature = "fmc")] pub use crate::fmc::FmcExt as _stm327xx_hal_fmc_FmcExt; @@ -8,3 +8,4 @@ pub use crate::hal::digital::v2::{InputPin, OutputPin}; pub use crate::hal::prelude::*; pub use crate::rcc::RccExt as _stm32f7xx_hal_rcc_RccExt; pub use crate::rng::RngExt as _; +pub use crate::U32Ext as _; diff --git a/src/rcc.rs b/src/rcc.rs index a281cb9..b4c6f24 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -1,19 +1,17 @@ //! Reset and clock control. -use core::{cmp::min, convert::TryInto}; +use core::cmp::min; mod enable; -use embedded_time::fixed_point::FixedPoint; #[cfg_attr(test, allow(unused_imports))] use micromath::F32Ext; -use crate::embedded_time::rate::Hertz; use crate::pac::{rcc, FLASH, PWR, RCC}; +use fugit::{HertzU32 as Hertz, RateExtU32}; -const MAX_HERTZ: Hertz = Hertz(u32::MAX); /// Typical output frequency of the HSI oscillator. -const HSI_FREQUENCY: Hertz = Hertz(16_000_000); +const HSI_FREQUENCY: Hertz = Hertz::from_raw(16_000_000); /// Extension trait that constrains the `RCC` peripheral pub trait RccExt { @@ -155,17 +153,12 @@ impl HSEClock { /// /// Panics if the frequency is outside the valid range. The frequency must be between /// 4 MHz and 26 MHz in oscillator mode and between 1 MHz and 50 MHz in bypass mode. - pub fn new(freq: F, mode: HSEClockMode) -> Self - where - F: TryInto, - { - let freq = freq.try_into().unwrap_or(MAX_HERTZ); - + pub fn new(freq: Hertz, mode: HSEClockMode) -> Self { let valid_range = match mode { // Source: Datasheet DS12536 Rev 2, Table 38 - HSEClockMode::Oscillator => Hertz(4_000_000u32)..=Hertz(26_000_000), + HSEClockMode::Oscillator => Hertz::MHz(4)..=Hertz::MHz(26), // Source: Datasheet DS12536 Rev 2, Table 40 - HSEClockMode::Bypass => Hertz(1_000_000)..=Hertz(50_000_000), + HSEClockMode::Bypass => Hertz::MHz(1)..=Hertz::MHz(50), }; assert!(valid_range.contains(&freq)); @@ -196,8 +189,10 @@ impl LSEClock { /// Provide LSE frequency. pub fn new(mode: LSEClockMode) -> Self { // Sets the LSE clock source to 32.768 kHz. - let freq = Hertz(32_768_u32); - LSEClock { freq, mode } + LSEClock { + freq: 32_768.Hz(), + mode, + } } } @@ -348,14 +343,10 @@ impl CFGR { /// # Panics /// /// Panics if the frequency is larger than 216 MHz. - pub fn hclk(mut self, freq: F) -> Self - where - F: TryInto, - { - let f: u32 = freq.try_into().unwrap_or(MAX_HERTZ).0; - assert!(f <= 216_000_000); - - self.hclk = Some(f); + pub fn hclk(mut self, freq: Hertz) -> Self { + assert!(freq.raw() <= 216_000_000); + + self.hclk = Some(freq.raw()); self } @@ -369,15 +360,10 @@ impl CFGR { /// # Panics /// /// Panics if the frequency is not between 12.5 MHz and 216 MHz. - pub fn sysclk(mut self, sysclk: F) -> Self - where - F: TryInto, - { - let f: u32 = sysclk.try_into().unwrap_or(MAX_HERTZ).0; - - assert!((12_500_000..=216_000_000).contains(&f)); + pub fn sysclk(mut self, sysclk: Hertz) -> Self { + assert!((12_500_000..=216_000_000).contains(&sysclk.raw())); - self.sysclk = Some(f); + self.sysclk = Some(sysclk.raw()); self } @@ -388,14 +374,10 @@ impl CFGR { /// # Panics /// /// Panics if the frequency is not between 12.5 MHz and 54 MHz. - pub fn pclk1(mut self, freq: F) -> Self - where - F: TryInto, - { - let f: u32 = freq.try_into().unwrap_or(MAX_HERTZ).0; - assert!((12_500_000..=54_000_000).contains(&f)); - - self.pclk1 = Some(f); + pub fn pclk1(mut self, freq: Hertz) -> Self { + assert!((12_500_000..=54_000_000).contains(&freq.raw())); + + self.pclk1 = Some(freq.raw()); self } @@ -406,14 +388,10 @@ impl CFGR { /// # Panics /// /// Panics if the frequency is not between 12.5 MHz and 108 MHz. - pub fn pclk2(mut self, freq: F) -> Self - where - F: TryInto, - { - let f: u32 = freq.try_into().unwrap_or(MAX_HERTZ).0; - assert!((12_500_000..=108_000_000).contains(&f)); - - self.pclk2 = Some(f); + pub fn pclk2(mut self, freq: Hertz) -> Self { + assert!((12_500_000..=108_000_000).contains(&freq.raw())); + + self.pclk2 = Some(freq.raw()); self } @@ -427,7 +405,7 @@ impl CFGR { /// /// Be aware that the tolerance is up to ±47% (Min 17 kHz, Typ 32 kHz, Max 47 kHz). pub fn lsi(mut self) -> Self { - self.lsi = Some(Hertz(32_000_u32)); + self.lsi = Some(32.kHz()); self } @@ -589,7 +567,7 @@ impl CFGR { Some(hse) => hse.freq, None => HSI_FREQUENCY, } - .integer(), + .raw(), ); let mut sysclk = base_clk; @@ -781,12 +759,12 @@ impl CFGR { config.overdrive = sysclk > 180_000_000; let clocks = Clocks { - hclk: Hertz(hclk), - pclk1: Hertz(pclk1), - pclk2: Hertz(pclk2), - sysclk: Hertz(sysclk), - timclk1: Hertz(timclk1), - timclk2: Hertz(timclk2), + hclk: hclk.Hz(), + pclk1: pclk1.Hz(), + pclk2: pclk2.Hz(), + sysclk: sysclk.Hz(), + timclk1: timclk1.Hz(), + timclk2: timclk2.Hz(), pll48clk_valid, hse: self.hse.map(|hse| hse.freq), lse: self.lse.map(|lse| lse.freq), @@ -879,7 +857,7 @@ impl CFGR { Some(hse) => hse.freq, None => HSI_FREQUENCY, } - .integer(); + .raw(); let sysclk = if let Some(clk) = self.sysclk { clk @@ -945,7 +923,7 @@ impl CFGR { /// /// Set SYSCLK as 216 Mhz and setup USB clock if defined. pub fn set_defaults(self) -> Self { - self.sysclk(Hertz(216_000_000u32)) + self.sysclk(216.MHz()) } /// Configure the "mandatory" clocks (`sysclk`, `hclk`, `pclk1` and `pclk2') @@ -1053,7 +1031,7 @@ impl CFGR { if self.use_pllsai { let pllsain_freq = match self.hse.as_ref() { - Some(hse) => hse.freq.integer() as u64 / self.pllm as u64 * self.pllsain as u64, + Some(hse) => hse.freq.raw() as u64 / self.pllm as u64 * self.pllsain as u64, None => 16_000_000 / self.pllm as u64 * self.pllsain as u64, }; let pllsaip_freq = pllsain_freq @@ -1088,7 +1066,7 @@ impl CFGR { if self.use_plli2s { let plli2sn_freq = match self.hse.as_ref() { - Some(hse) => hse.freq.integer() as u64 / self.pllm as u64 * self.plli2sn as u64, + Some(hse) => hse.freq.raw() as u64 / self.pllm as u64 * self.plli2sn as u64, None => 16_000_000 / self.pllm as u64 * self.plli2sn as u64, }; let plli2sr_freq = plli2sn_freq / self.plli2sr as u64; @@ -1374,9 +1352,7 @@ pub trait Reset: RccBus { #[cfg(test)] mod tests { - use crate::prelude::*; - - use crate::embedded_time::rate::Hertz; + use fugit::{HertzU32 as Hertz, RateExtU32}; use super::{FreqRequest, CFGR}; @@ -1510,16 +1486,16 @@ mod tests { }; let mut cfgr = cfgr - .hse(HSEClock::new(25_000_000.Hz(), HSEClockMode::Bypass)) + .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass)) .use_pll() .use_pll48clk(PLL48CLK::Pllq) - .sysclk(216_000_000.Hz()); + .sysclk(216.MHz()); cfgr.pll_configure(); - assert_eq!(cfgr.hse.unwrap().freq, Hertz(25_000_000u32)); + assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25)); let (clocks, _config) = cfgr.calculate_clocks(); - assert_eq!(clocks.sysclk().0, 216_000_000); + assert_eq!(clocks.sysclk().raw(), 216_000_000); assert!(clocks.is_pll48clk_valid()); } @@ -1556,15 +1532,15 @@ mod tests { }; let mut cfgr = cfgr - .hse(HSEClock::new(25_000_000.Hz(), HSEClockMode::Bypass)) + .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass)) .use_pll48clk(PLL48CLK::Pllq) - .sysclk(216_000_000.Hz()); + .sysclk(216.MHz()); cfgr.pll_configure(); - assert_eq!(cfgr.hse.unwrap().freq, Hertz(25_000_000u32)); + assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25)); let (clocks, _config) = cfgr.calculate_clocks(); - assert_eq!(clocks.sysclk().0, 216_000_000); + assert_eq!(clocks.sysclk().raw(), 216_000_000); assert!(clocks.is_pll48clk_valid()); } @@ -1601,15 +1577,15 @@ mod tests { }; let mut cfgr = cfgr - .hse(HSEClock::new(25_000_000.Hz(), HSEClockMode::Bypass)) + .hse(HSEClock::new(25.MHz(), HSEClockMode::Bypass)) .use_pll48clk(PLL48CLK::Pllq) .set_defaults(); cfgr.pll_configure(); - assert_eq!(cfgr.hse.unwrap().freq, Hertz(25_000_000u32)); + assert_eq!(cfgr.hse.unwrap().freq, Hertz::MHz(25)); let (clocks, _config) = cfgr.calculate_clocks(); - assert_eq!(clocks.sysclk().0, 216_000_000); + assert_eq!(clocks.sysclk().raw(), 216_000_000); assert!(clocks.is_pll48clk_valid()); } @@ -1648,6 +1624,6 @@ mod tests { cfgr.pll_configure(); assert!(!cfgr.use_pll); let (clocks, _config) = cfgr.calculate_clocks(); - assert_eq!(clocks.sysclk().0, 16_000_000); + assert_eq!(clocks.sysclk().raw(), 16_000_000); } } diff --git a/src/serial.rs b/src/serial.rs index 599f770..3dfd07e 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -8,7 +8,6 @@ use core::ptr; use as_slice::{AsMutSlice, AsSlice}; use crate::dma; -use crate::embedded_time::rate::Extensions as _; use crate::hal::prelude::*; use crate::hal::serial; use crate::pac; @@ -20,8 +19,8 @@ use crate::pac::{RCC, UART4, UART5, UART7, USART1, USART2, USART3, USART6}; use crate::gpio::{self, Alternate}; -use crate::embedded_time::rate::BitsPerSecond; use crate::rcc::Clocks; +use crate::{BitsPerSecond, U32Ext}; /// Serial error #[derive(Debug)] @@ -141,14 +140,14 @@ where Oversampling::By8 => { usart.cr1.modify(|_, w| w.over8().set_bit()); - let usart_div = 2 * clocks.sysclk().0 / config.baud_rate.0; + let usart_div = 2 * clocks.sysclk() / config.baud_rate; 0xfff0 & usart_div | 0x0007 & ((usart_div & 0x000f) >> 1) } Oversampling::By16 => { usart.cr1.modify(|_, w| w.over8().clear_bit()); - clocks.sysclk().0 / config.baud_rate.0 + clocks.sysclk() / config.baud_rate } }; diff --git a/src/timer.rs b/src/timer.rs index 1da788e..b9577bd 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,12 +1,12 @@ //! Timers -use crate::embedded_time::rate::Hertz; use crate::hal::timer::{Cancel, CountDown, Periodic}; use crate::pac::{ TIM1, TIM10, TIM11, TIM12, TIM13, TIM14, TIM2, TIM3, TIM4, TIM5, TIM6, TIM7, TIM8, TIM9, }; use crate::rcc::{Clocks, Enable, RccBus, Reset}; use cast::{u16, u32}; +use fugit::{HertzU32 as Hertz, RateExtU32}; use nb; use void::Void; @@ -47,8 +47,8 @@ macro_rules! hal { self.disable(); self.timeout = timeout.into(); - let frequency = self.timeout.0; - let ticks = self.clock.0 / frequency; + let frequency = self.timeout; + let ticks = self.clock / frequency; let psc = u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| unsafe { w.psc().bits(psc) }); @@ -106,7 +106,7 @@ macro_rules! hal { let mut timer = Timer { clock, tim, - timeout: Hertz(0), + timeout: 0.Hz(), }; timer.start(timeout);