diff --git a/CHANGELOG.md b/CHANGELOG.md index d936668a8..3ce17f58b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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]) @@ -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 diff --git a/Cargo.toml b/Cargo.toml index fbe18b5b3..3fd5fa2fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/examples/can.rs b/examples/can.rs index a72adf968..f7b86d493 100644 --- a/examples/can.rs +++ b/examples/can.rs @@ -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}; @@ -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) @@ -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); diff --git a/examples/i2c_scanner.rs b/examples/i2c_scanner.rs index cda4b365a..a68cc4e4a 100644 --- a/examples/i2c_scanner.rs +++ b/examples/i2c_scanner.rs @@ -6,7 +6,7 @@ #![no_std] #![no_main] -use core::ops::Range; +use core::{convert::TryInto, ops::Range}; use panic_semihosting as _; @@ -14,6 +14,7 @@ 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 = 0x08..0x78; @@ -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(); diff --git a/examples/pwm.rs b/examples/pwm.rs index 4457aa0d6..1fb8ff4a9 100644 --- a/examples/pwm.rs +++ b/examples/pwm.rs @@ -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() -> ! { @@ -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); @@ -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 @@ -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); @@ -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 @@ -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); diff --git a/examples/serial_dma.rs b/examples/serial_dma.rs index e3c051ff7..a5469091e 100644 --- a/examples/serial_dma.rs +++ b/examples/serial_dma.rs @@ -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() -> ! { @@ -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); diff --git a/examples/spi.rs b/examples/spi.rs index 085bbdd0c..49aa3c6a9 100644 --- a/examples/spi.rs +++ b/examples/spi.rs @@ -3,6 +3,8 @@ #![no_std] #![no_main] +use core::convert::TryInto; + use panic_semihosting as _; use stm32f3xx_hal as hal; @@ -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() -> ! { @@ -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 @@ -43,7 +46,7 @@ fn main() -> ! { dp.SPI1, (sck, miso, mosi), spi_mode, - 3.mhz(), + 3u32.MHz().try_into().unwrap(), clocks, &mut rcc.apb2, ); diff --git a/examples/usb_serial.rs b/examples/usb_serial.rs index fbf099ced..8c754d5de 100644 --- a/examples/usb_serial.rs +++ b/examples/usb_serial.rs @@ -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::*; @@ -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()); diff --git a/src/i2c.rs b/src/i2c.rs index c561799b3..8ecf8e370 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -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"))] @@ -111,16 +111,13 @@ macro_rules! busy_wait { impl I2c { /// Configures the I2C peripheral to work in master mode - pub fn new(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, SDA: SdaPin, - F: Into, { - let freq = freq.into().0; - - crate::assert!(freq <= 1_000_000); + crate::assert!(*freq.integer() <= 1_000_000); I2C::enable_clock(apb1); @@ -133,8 +130,8 @@ impl I2c { // 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; @@ -142,7 +139,7 @@ impl I2c { 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; @@ -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), I2C1SW_A::SYSCLK => clocks.sysclk(), } } diff --git a/src/lib.rs b/src/lib.rs index 927c678b4..47c79ce8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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")] @@ -188,7 +190,6 @@ cfg_if::cfg_if! { pub mod rtc; pub mod serial; pub mod spi; - pub mod time; pub mod timer; } } diff --git a/src/prelude.rs b/src/prelude.rs index 02ca404ab..b074bb994 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -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, diff --git a/src/pwm.rs b/src/pwm.rs index b832558f3..759320eb4 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -16,7 +16,7 @@ ``` // (Other imports omitted) - use stm32f3xx-hal::pwm::tim3; + use stm32f3xx-hal::{pwm::tim3, time::rate::*}; let dp = stm32f303::Peripherals::take().unwrap(); @@ -25,9 +25,9 @@ let clocks = rcc.cfgr.freeze(&mut flash.acr); // Set the resolution of our duty cycle to 9000 and our period to - // 50hz. + // 50Hz. let mut (c1_no_pins, _, _, c4_no_pins) = - tim3(device.TIM3, 9000, 50.hz(), clocks); + tim3(device.TIM3, 9000, 50.Hz(), clocks); ``` In this case, we're only going to use channel 1 and channel 4. @@ -65,7 +65,7 @@ ch4.enable(); ``` - All three pins will output a 50hz period. PA6 and PB4 will share a + All three pins will output a 50Hz period. PA6 and PB4 will share a duty cycle, but the duty cycle for PB1 can be controlled independently. @@ -84,7 +84,7 @@ ``` // (Other imports omitted) - use stm32f3xx-hal::pwm::tim16; + use stm32f3xx-hal::{pwm::tim16, time::rate::*}; let dp = stm32f303::Peripherals::take().unwrap(); @@ -93,8 +93,8 @@ let clocks = rcc.cfgr.freeze(&mut flash.acr); // Set the resolution of our duty cycle to 9000 and our period to - // 50hz. - let mut c1_no_pins = tim16(device.TIM3, 9000, 50.hz(), clocks); + // 50Hz. + let mut c1_no_pins = tim16(device.TIM3, 9000, 50.Hz(), clocks); ``` ## Complementary timers @@ -109,7 +109,7 @@ ``` // (Other imports omitted) - use stm32f3xx-hal::pwm::tim1; + use stm32f3xx-hal::{pwm::tim1, time::rate::*}; let dp = stm32f303::Peripherals::take().unwrap(); @@ -118,8 +118,8 @@ let clocks = rcc.cfgr.freeze(&mut flash.acr); // Set the resolution of our duty cycle to 9000 and our period to - // 50hz. - let mut (ch1_no_pins, _, _, _) = tim1(device.TIM3, 9000, 50.hz(), clocks); + // 50Hz. + let mut (ch1_no_pins, _, _, _) = tim1(device.TIM3, 9000, 50.Hz(), clocks); let mut gpioa = dp.GPIOB.split(&mut rcc.ahb); let pa7 = gpioa.pa7.into_af6(&mut gpioa.moder, &mut gpioa.afrl); @@ -160,7 +160,7 @@ use crate::{ hal::PwmPin, pac::{RCC, TIM15, TIM16, TIM17, TIM2}, rcc::Clocks, - time::Hertz, + time::rate::*, }; use core::marker::PhantomData; @@ -282,7 +282,7 @@ macro_rules! pwm_timer_private { // It might make sense to move into the clocks as a crate-only property. // TODO: ppre1 is used in timer.rs (never ppre2), should this be dynamic? let clock_freq = clocks.$pclkz().0 * if clocks.ppre1() == 1 { 1 } else { 2 }; - let prescale_factor = clock_freq / res as u32 / freq.0; + let prescale_factor = clock_freq / res as u32 / *freq.integer(); // NOTE(write): uses all bits of this register. tim.psc.write(|w| w.psc().bits(prescale_factor as u16 - 1)); diff --git a/src/rcc.rs b/src/rcc.rs index 876b0d5df..e1683e346 100644 --- a/src/rcc.rs +++ b/src/rcc.rs @@ -8,7 +8,8 @@ //! //! ``` //! # use cortex_m_rt::entry; -//! # use stm32f3xx_hal::prelude::*; +//! # use stm32f3xx-hal::{prelude::*, time::rate::*}; +//! //! # #[entry] //! # fn main() -> ! { //! // Get our peripherals @@ -23,7 +24,8 @@ //! //! ``` //! # use cortex_m_rt::entry; -//! # use stm32f3xx_hal::prelude::*; +//! # use stm32f3xx-hal::{prelude::*, time::rate::*}; +//! # //! # #[entry] //! # fn main() -> ! { //! # let dp = pac::Peripherals::take().unwrap(); @@ -33,18 +35,18 @@ //! let clocks = rcc.cfgr //! // Using the external oscillator //! // Set the frequency to that of the external oscillator -//! .use_hse(8.mhz()) +//! .use_hse(8.MHz()) //! // Set the frequency for the AHB bus, //! // which the root of every following clock peripheral -//! .hclk(48.mhz()) +//! .hclk(48.MHz()) //! // The sysclk is equivalent to the core clock -//! .sysclk(48.mhz()) +//! .sysclk(48.MHz()) //! // The following are peripheral clocks, which are both //! // needed to configure specific peripherals. //! // Looking at the peripheral function parameters //! // should give more insight, which peripheral clock is needed. -//! .pclk1(12.mhz()) -//! .pclk2(12.mhz()) +//! .pclk1(12.MHz()) +//! .pclk2(12.MHz()) //! // Freeze / apply the configuration and setup all clocks //! .freeze(&mut flash.acr); //! # } @@ -59,8 +61,10 @@ use crate::pac::{ RCC, }; +use core::convert::TryInto; + use crate::flash::ACR; -use crate::time::Hertz; +use crate::time::rate::*; /// Extension trait that constrains the `RCC` peripheral pub trait RccExt { @@ -333,11 +337,13 @@ impl CFGR { /// /// Will result in a hang if an external oscillator is not connected or it fails to start, /// unless [css](CFGR::enable_css) is enabled. - pub fn use_hse(mut self, freq: F) -> Self - where - F: Into, - { - self.hse = Some(freq.into().0); + /// + /// # Panics + /// + /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + pub fn use_hse(mut self, freq: Megahertz) -> Self { + let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); + self.hse = Some(*freq.integer()); self } @@ -363,12 +369,14 @@ impl CFGR { self } - /// Sets a frequency for the AHB bus - pub fn hclk(mut self, freq: F) -> Self - where - F: Into, - { - self.hclk = Some(freq.into().0); + /// Sets a frequency for the AHB bus. + /// + /// # Panics + /// + /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + pub fn hclk(mut self, freq: Megahertz) -> Self { + let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); + self.hclk = Some(*freq.integer()); self } @@ -378,11 +386,13 @@ impl CFGR { /// /// If not manually set, it will be set to [`CFGR::sysclk`] frequency /// or [`CFGR::sysclk`] frequency / 2, if [`CFGR::sysclk`] > 36 Mhz - pub fn pclk1(mut self, freq: F) -> Self - where - F: Into, - { - self.pclk1 = Some(freq.into().0); + /// + /// # Panics + /// + /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + pub fn pclk1(mut self, freq: Megahertz) -> Self { + let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); + self.pclk1 = Some(*freq.integer()); self } @@ -399,11 +409,12 @@ impl CFGR { /// /// [stm32f302xd,stm32f302xe,stm32f303xd,stm32f303xe,stm32f398] /// - pub fn pclk2(mut self, freq: F) -> Self - where - F: Into, - { - self.pclk2 = Some(freq.into().0); + /// # Panics + /// + /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + pub fn pclk2(mut self, freq: Megahertz) -> Self { + let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); + self.pclk2 = Some(*freq.integer()); self } @@ -422,11 +433,13 @@ impl CFGR { /// even when using the internal oscillator: /// /// [stm32f302xd,stm32f302xe,stm32f303xd,stm32f303xe,stm32f398] - pub fn sysclk(mut self, freq: F) -> Self - where - F: Into, - { - self.sysclk = Some(freq.into().0); + /// + /// # Panics + /// + /// Panics if conversion from `Megahertz` to `Hertz` produces a value greater then `u32::MAX`. + pub fn sysclk(mut self, freq: Megahertz) -> Self { + let freq: Hertz = crate::expect!(freq.try_into(), "ConversionError"); + self.sysclk = Some(*freq.integer()); self } @@ -660,7 +673,7 @@ impl CFGR { // This ensures, that no panic happens, when // pclk1 is not manually set. - // As hclk highest value is 72.mhz() + // As hclk highest value is 72.MHz() // dividing by 2 should always be sufficient if self.pclk1.is_none() && pclk1 > 36_000_000 { ppre1_bits = cfgr::PPRE1_A::DIV2; diff --git a/src/serial.rs b/src/serial.rs index 0a8353d75..26f1ef7fc 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -5,8 +5,9 @@ use crate::{ hal::{blocking, serial}, pac::{USART1, USART2, USART3}, rcc::{Clocks, APB1, APB2}, - time::Bps, + time::rate::*, }; + use cfg_if::cfg_if; use core::{convert::Infallible, marker::PhantomData, ptr}; @@ -111,7 +112,7 @@ macro_rules! hal { pub fn $usartX( usart: $USARTX, pins: (TX, RX), - baud_rate: Bps, + baud_rate: Baud, clocks: Clocks, apb: &mut $APB, ) -> Self @@ -124,7 +125,7 @@ macro_rules! hal { apb.rstr().modify(|_, w| w.$usartXrst().set_bit()); apb.rstr().modify(|_, w| w.$usartXrst().clear_bit()); - let brr = clocks.$pclkX().0 / baud_rate.0; + let brr = clocks.$pclkX().0 / *baud_rate.integer(); crate::assert!(brr >= 16, "impossible baud rate"); // NOTE(write): uses all bits of this register. usart.brr.write(|w| unsafe { w.bits(brr) }); diff --git a/src/spi.rs b/src/spi.rs index ea86cf504..aaca21646 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -131,7 +131,7 @@ use crate::rcc::APB1; feature = "stm32f398" ))] use crate::rcc::APB2; -use crate::time::Hertz; +use crate::time::rate::*; use core::marker::PhantomData; /// SPI error @@ -417,16 +417,15 @@ macro_rules! hal { $( impl Spi<$SPIX, (SCK, MISO, MOSI), WORD> { /// Configures the SPI peripheral to operate in full duplex master mode - pub fn $spiX( + pub fn $spiX( spi: $SPIX, pins: (SCK, MISO, MOSI), mode: Mode, - freq: F, + freq: Hertz, clocks: Clocks, apb2: &mut $APBX, ) -> Self where - F: Into, SCK: SckPin<$SPIX>, MISO: MisoPin<$SPIX>, MOSI: MosiPin<$SPIX>, @@ -468,7 +467,7 @@ macro_rules! hal { Polarity::IdleHigh => w.cpol().idle_high(), }; - w.br().variant(Self::compute_baud_rate(clocks.$pclkX(), freq.into())); + w.br().variant(Self::compute_baud_rate(clocks.$pclkX(), freq)); w.spe() .enabled() @@ -493,19 +492,18 @@ macro_rules! hal { } /// Change the baud rate of the SPI - pub fn reclock(&mut self, freq: F, clocks: Clocks) - where F: Into - { + pub fn reclock(&mut self, freq: Hertz, clocks: Clocks) { self.spi.cr1.modify(|_, w| w.spe().disabled()); + self.spi.cr1.modify(|_, w| { - w.br().variant(Self::compute_baud_rate(clocks.$pclkX(), freq.into())); + w.br().variant(Self::compute_baud_rate(clocks.$pclkX(), freq)); w.spe().enabled() }); } fn compute_baud_rate(clocks: Hertz, freq: Hertz) -> spi1::cr1::BR_A { use spi1::cr1::BR_A; - match clocks.0 / freq.0 { + match clocks.0 / *freq.integer() { 0 => crate::unreachable!(), 1..=2 => BR_A::DIV2, 3..=5 => BR_A::DIV4, diff --git a/src/time.rs b/src/time.rs deleted file mode 100644 index 759f54b11..000000000 --- a/src/time.rs +++ /dev/null @@ -1,128 +0,0 @@ -//! Time units - -use cortex_m::peripheral::DWT; - -use crate::rcc::Clocks; - -/// Bits per second -#[derive(PartialEq, PartialOrd, Clone, Copy)] -pub struct Bps(pub u32); - -/// Hertz -#[derive(PartialEq, PartialOrd, Clone, Copy)] -pub struct Hertz(pub u32); - -/// KiloHertz -#[derive(PartialEq, PartialOrd, Clone, Copy)] -pub struct KiloHertz(pub u32); - -/// MegaHertz -#[derive(PartialEq, PartialOrd, Clone, Copy)] -pub struct MegaHertz(pub u32); - -/// Time unit -#[derive(PartialEq, PartialOrd, Clone, Copy)] -pub struct MilliSeconds(pub u32); - -/// 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 `KiloHertz` - fn khz(self) -> KiloHertz; - - /// Wrap in `MegaHertz` - fn mhz(self) -> MegaHertz; - - /// Wrap in `MilliSeconds` - fn ms(self) -> MilliSeconds; -} - -impl U32Ext for u32 { - fn bps(self) -> Bps { - Bps(self) - } - - fn hz(self) -> Hertz { - Hertz(self) - } - - fn khz(self) -> KiloHertz { - KiloHertz(self) - } - - fn mhz(self) -> MegaHertz { - MegaHertz(self) - } - - fn ms(self) -> MilliSeconds { - MilliSeconds(self) - } -} - -impl From for Hertz { - fn from(val: KiloHertz) -> Self { - Self(val.0 * 1_000) - } -} - -impl From for Hertz { - fn from(val: MegaHertz) -> Self { - Self(val.0 * 1_000_000) - } -} - -impl From for KiloHertz { - fn from(val: MegaHertz) -> Self { - Self(val.0 * 1_000) - } -} - -/// A monotonic nondecreasing timer -#[derive(Clone, Copy)] -pub struct MonoTimer { - frequency: Hertz, -} - -impl MonoTimer { - /// Creates a new `Monotonic` timer - pub fn new(mut dwt: DWT, clocks: Clocks) -> Self { - dwt.enable_cycle_counter(); - - // now the CYCCNT counter can't be stopped or resetted - drop(dwt); - - MonoTimer { - frequency: clocks.hclk(), - } - } - - /// Returns the frequency at which the monotonic timer is operating at - pub fn frequency(self) -> Hertz { - self.frequency - } - - /// Returns an `Instant` corresponding to "now" - pub fn now(self) -> Instant { - Instant { - now: DWT::get_cycle_count(), - } - } -} - -/// A measurement of a monotonically nondecreasing clock -#[derive(Clone, Copy)] -pub struct Instant { - now: u32, -} - -impl Instant { - /// Ticks elapsed since the `Instant` was created - pub fn elapsed(self) -> u32 { - DWT::get_cycle_count().wrapping_sub(self.now) - } -} diff --git a/src/timer.rs b/src/timer.rs index 591351010..96e61450d 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -50,11 +50,9 @@ use crate::pac::{TIM15, TIM16, TIM17, TIM2, TIM6}; feature = "stm32f398" ))] use crate::pac::{TIM3, TIM7}; - -use void::Void; - use crate::rcc::{Clocks, APB1, APB2}; -use crate::time::Hertz; +use crate::time::rate::*; +use void::Void; /// Associated clocks with timers pub trait PclkSrc { @@ -93,11 +91,11 @@ macro_rules! hal { fn start(&mut self, timeout: T) where - T: Into, + T: Into, { self.stop(); - let frequency = timeout.into().0; + let frequency = *timeout.into().integer(); let timer_clock = $TIMX::get_clk(&self.clocks); let ticks = timer_clock.0 * if self.clocks.ppre1() == 1 { 1 } else { 2 } / frequency; diff --git a/src/watchdog.rs b/src/watchdog.rs index c8c989527..d62e8e469 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -7,7 +7,7 @@ use crate::hal::watchdog::{Watchdog, WatchdogEnable}; use crate::pac::{DBGMCU, IWDG}; -use crate::time::MilliSeconds; +use crate::time::duration::*; const LSI_KHZ: u32 = 40; const MAX_PR: u8 = 8; @@ -54,13 +54,13 @@ impl IndependentWatchDog { } /// Returns the interval in ms - pub fn interval(&self) -> MilliSeconds { + pub fn interval(&self) -> Milliseconds { while self.is_pr_updating() {} let pr = self.iwdg.pr.read().pr().bits(); let rl = self.iwdg.rlr.read().rl().bits(); let ms = Self::timeout_period(pr, rl); - MilliSeconds(ms) + Milliseconds(ms) } /// pr: Prescaler divider bits, rl: reload value @@ -93,10 +93,10 @@ impl IndependentWatchDog { } impl WatchdogEnable for IndependentWatchDog { - type Time = MilliSeconds; + type Time = Milliseconds; fn start>(&mut self, period: T) { - self.setup(period.into().0); + self.setup(*period.into().integer()); self.iwdg.kr.write(|w| w.key().start()); } diff --git a/tests/rcc.rs b/tests/rcc.rs index e2f637316..68fe51f04 100644 --- a/tests/rcc.rs +++ b/tests/rcc.rs @@ -6,7 +6,7 @@ use panic_probe as _; #[defmt_test::tests] mod tests { - use stm32f3xx_hal::{pac, prelude::*}; + use stm32f3xx_hal::{pac, prelude::*, time::rate::*}; // Test the defaults with no configuration #[test] @@ -18,10 +18,10 @@ mod tests { let clock = rcc.cfgr.freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 8.mhz().into()); - defmt::assert!(clock.hclk() == 8.mhz().into()); - defmt::assert!(clock.pclk2() == 8.mhz().into()); - defmt::assert!(clock.pclk1() == 8.mhz().into()); + defmt::assert!(clock.sysclk() == 8u32.MHz()); + defmt::assert!(clock.hclk() == 8u32.MHz()); + defmt::assert!(clock.pclk2() == 8u32.MHz()); + defmt::assert!(clock.pclk1() == 8u32.MHz()); defmt::assert!(!clock.usbclk_valid()); } @@ -37,14 +37,14 @@ mod tests { let clock = rcc .cfgr - .use_hse(8.mhz()) - .sysclk(15.mhz()) + .use_hse(8u32.MHz()) + .sysclk(15u32.MHz()) .freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 15.mhz().into()); - defmt::assert!(clock.hclk() == 15.mhz().into()); - defmt::assert!(clock.pclk2() == 15.mhz().into()); - defmt::assert!(clock.pclk1() == 15.mhz().into()); + defmt::assert!(clock.sysclk() == 15u32.MHz()); + defmt::assert!(clock.hclk() == 15u32.MHz()); + defmt::assert!(clock.pclk2() == 15u32.MHz()); + defmt::assert!(clock.pclk1() == 15u32.MHz()); defmt::assert!(!clock.usbclk_valid()); } @@ -64,12 +64,12 @@ mod tests { feature = "stm32f303xe", feature = "stm32f398", ))] { - let clock = rcc.cfgr.sysclk(72.mhz()).freeze(&mut flash.acr); + let clock = rcc.cfgr.sysclk(72u32.MHz()).freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 72.mhz().into()); - defmt::assert!(clock.hclk() == 72.mhz().into()); - defmt::assert!(clock.pclk2() == 72.mhz().into()); - defmt::assert!(clock.pclk1() == 36.mhz().into()); + defmt::assert!(clock.sysclk() == 72u32.MHz()); + defmt::assert!(clock.hclk() == 72u32.MHz()); + defmt::assert!(clock.pclk2() == 72u32.MHz()); + defmt::assert!(clock.pclk1() == 36u32.MHz()); } else { // Notice the strange part about 67 being reduced to 64? // @@ -78,12 +78,12 @@ mod tests { // and the resolution is therefor lower. // Because of the implementation the clock is then approximated to // the highest possible value (64 Mhz). - let clock = rcc.cfgr.sysclk(67.mhz()).freeze(&mut flash.acr); + let clock = rcc.cfgr.sysclk(67u32.MHz()).freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 64.mhz().into()); - defmt::assert!(clock.hclk() == 64.mhz().into()); - defmt::assert!(clock.pclk2() == 64.mhz().into()); - defmt::assert!(clock.pclk1() == 32.mhz().into()); + defmt::assert!(clock.sysclk() == 64u32.MHz()); + defmt::assert!(clock.hclk() == 64u32.MHz()); + defmt::assert!(clock.pclk2() == 64u32.MHz()); + defmt::assert!(clock.pclk1() == 32u32.MHz()); } } @@ -100,14 +100,14 @@ mod tests { let clock = rcc .cfgr - .use_hse(8.mhz()) - .sysclk(32.mhz()) + .use_hse(8u32.MHz()) + .sysclk(32u32.MHz()) .freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 32.mhz().into()); - defmt::assert!(clock.hclk() == 32.mhz().into()); - defmt::assert!(clock.pclk2() == 32.mhz().into()); - defmt::assert!(clock.pclk1() == 32.mhz().into()); + defmt::assert!(clock.sysclk() == 32u32.MHz()); + defmt::assert!(clock.hclk() == 32u32.MHz()); + defmt::assert!(clock.pclk2() == 32u32.MHz()); + defmt::assert!(clock.pclk1() == 32u32.MHz()); defmt::assert!(!clock.usbclk_valid()); } @@ -122,14 +122,14 @@ mod tests { let clock = rcc .cfgr - .use_hse(8.mhz()) - .sysclk(48.mhz()) + .use_hse(8u32.MHz()) + .sysclk(48u32.MHz()) .freeze(&mut flash.acr); // works - defmt::assert!(clock.sysclk() == 48.mhz().into()); - defmt::assert!(clock.hclk() == 48.mhz().into()); - defmt::assert!(clock.pclk2() == 48.mhz().into()); - defmt::assert!(clock.pclk1() == 24.mhz().into()); + defmt::assert!(clock.sysclk() == 48u32.MHz()); + defmt::assert!(clock.hclk() == 48u32.MHz()); + defmt::assert!(clock.pclk2() == 48u32.MHz()); + defmt::assert!(clock.pclk1() == 24u32.MHz()); defmt::assert!(clock.usbclk_valid()); } @@ -142,21 +142,21 @@ mod tests { let clock = rcc .cfgr - .use_hse(8.mhz()) - .hclk(48.mhz()) - .sysclk(48.mhz()) - .pclk1(12.mhz()) - .pclk2(12.mhz()) + .use_hse(8u32.MHz()) + .hclk(48u32.MHz()) + .sysclk(48u32.MHz()) + .pclk1(12u32.MHz()) + .pclk2(12u32.MHz()) .freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 48.mhz().into()); - defmt::assert!(clock.hclk() == 48.mhz().into()); - defmt::assert!(clock.pclk2() == 12.mhz().into()); - defmt::assert!(clock.pclk1() == 12.mhz().into()); + defmt::assert!(clock.sysclk() == 48u32.MHz()); + defmt::assert!(clock.hclk() == 48u32.MHz()); + defmt::assert!(clock.pclk2() == 12u32.MHz()); + defmt::assert!(clock.pclk1() == 12u32.MHz()); defmt::assert!(clock.usbclk_valid()); } - // Another multiple of 8.mhz() external crystal + // Another multiple of 8.MHz() external crystal #[test] fn hse_sysclk_64mhz() { let dp = unsafe { pac::Peripherals::steal() }; @@ -166,15 +166,15 @@ mod tests { let clock = rcc .cfgr - .use_hse(8.mhz()) - .pclk1(16.mhz()) - .sysclk(64.mhz()) + .use_hse(8u32.MHz()) + .pclk1(16u32.MHz()) + .sysclk(64u32.MHz()) .freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 64.mhz().into()); - defmt::assert!(clock.hclk() == 64.mhz().into()); - defmt::assert!(clock.pclk2() == 64.mhz().into()); - defmt::assert!(clock.pclk1() == 16.mhz().into()); + defmt::assert!(clock.sysclk() == 64u32.MHz()); + defmt::assert!(clock.hclk() == 64u32.MHz()); + defmt::assert!(clock.pclk2() == 64u32.MHz()); + defmt::assert!(clock.pclk1() == 16u32.MHz()); defmt::assert!(!clock.usbclk_valid()); } @@ -189,14 +189,14 @@ mod tests { let clock = rcc .cfgr - .use_hse(8.mhz()) - .sysclk(72.mhz()) + .use_hse(8u32.MHz()) + .sysclk(72u32.MHz()) .freeze(&mut flash.acr); - defmt::assert!(clock.sysclk() == 72.mhz().into()); - defmt::assert!(clock.hclk() == 72.mhz().into()); - defmt::assert!(clock.pclk2() == 72.mhz().into()); - defmt::assert!(clock.pclk1() == 36.mhz().into()); + defmt::assert!(clock.sysclk() == 72u32.MHz()); + defmt::assert!(clock.hclk() == 72u32.MHz()); + defmt::assert!(clock.pclk2() == 72u32.MHz()); + defmt::assert!(clock.pclk1() == 36u32.MHz()); defmt::assert!(clock.usbclk_valid()); } }