From 31031833598b9b6cef32dd55df2254285dda911b Mon Sep 17 00:00:00 2001 From: ryan kurte Date: Thu, 18 Jun 2020 14:06:24 +1200 Subject: [PATCH 1/4] refactor for e-h v1.0.0 --- Cargo.toml | 3 +- src/adc.rs | 12 +-- src/delay.rs | 40 +++++++--- src/dwt.rs | 11 ++- src/gpio.rs | 46 +++++------ src/i2c.rs | 15 ++-- src/otg_fs.rs | 4 +- src/otg_hs.rs | 4 +- src/prelude.rs | 8 +- src/pwm.rs | 204 +++++++++++++++++++++++++++++------------------- src/qei.rs | 15 ++-- src/rng.rs | 2 +- src/serial.rs | 24 +++--- src/spi.rs | 4 +- src/timer.rs | 39 ++++----- src/watchdog.rs | 12 ++- 16 files changed, 267 insertions(+), 176 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9ca36f82..8a21c92f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,8 +46,7 @@ default-features = false version = "1.0.2" [dependencies.embedded-hal] -features = ["unproven"] -version = "0.2.3" +version = "=1.0.0-alpha.1" [dev-dependencies] panic-semihosting = "0.5.3" diff --git a/src/adc.rs b/src/adc.rs index 4b72ae36..9e74d4b4 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -9,6 +9,7 @@ */ use crate::{gpio::*, signature::VrefCal, signature::VDDA_CALIB, stm32}; +use core::convert::Infallible; use core::fmt; use embedded_hal::adc::{Channel, OneShot}; @@ -26,7 +27,7 @@ macro_rules! adc_pins { $( impl Channel for $pin { type ID = u8; - fn channel() -> u8 { $chan } + const CHANNEL: Self::ID = $chan; } )+ }; @@ -633,6 +634,7 @@ macro_rules! adc { //Probably unnecessary to disable the ADC in most cases but it shouldn't do any harm either s.disable(); + s.apply_config(config); s.enable(); @@ -665,7 +667,7 @@ macro_rules! adc { } let vref_cal = VrefCal::get().read(); - let vref_samp = self.read(&mut Vref).unwrap(); //This can't actually fail, it's just in a result to satisfy hal trait + let vref_samp = self.try_read(&mut Vref).unwrap(); //This can't actually fail, it's just in a result to satisfy hal trait self.calibrated_vdda = (VDDA_CALIB * u32::from(vref_cal)) / u32::from(vref_samp); if !vref_en { @@ -873,7 +875,7 @@ macro_rules! adc { } }); - let channel = CHANNEL::channel(); + let channel = CHANNEL::CHANNEL; //Set the channel in the right sequence field match sequence { @@ -974,9 +976,9 @@ macro_rules! adc { where PIN: Channel, { - type Error = (); + type Error = Infallible; - fn read(&mut self, pin: &mut PIN) -> nb::Result { + fn try_read(&mut self, pin: &mut PIN) -> nb::Result { let enabled = self.is_enabled(); if !enabled { self.enable(); diff --git a/src/delay.rs b/src/delay.rs index 56beca43..1730b7d5 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -1,6 +1,7 @@ //! Delays use cast::u32; +use core::convert::Infallible; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; @@ -28,25 +29,36 @@ impl Delay { } impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u32) { - self.delay_us(ms * 1_000); + type Error = Infallible; + + fn try_delay_ms(&mut self, ms: u32) -> Result<(), Self::Error> { + self.try_delay_us(ms * 1_000)?; + Ok(()) } } impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u16) { - self.delay_ms(u32(ms)); + type Error = Infallible; + + fn try_delay_ms(&mut self, ms: u16) -> Result<(), Self::Error> { + self.try_delay_ms(u32(ms))?; + Ok(()) } } impl DelayMs for Delay { - fn delay_ms(&mut self, ms: u8) { - self.delay_ms(u32(ms)); + type Error = Infallible; + + fn try_delay_ms(&mut self, ms: u8) -> Result<(), Self::Error> { + self.try_delay_ms(u32(ms))?; + Ok(()) } } impl DelayUs for Delay { - fn delay_us(&mut self, us: u32) { + type Error = Infallible; + + fn try_delay_us(&mut self, us: u32) -> Result<(), Self::Error> { // The SysTick Reload Value register supports values between 1 and 0x00FFFFFF. const MAX_RVR: u32 = 0x00FF_FFFF; @@ -70,17 +82,23 @@ impl DelayUs for Delay { self.syst.disable_counter(); } + + Ok(()) } } impl DelayUs for Delay { - fn delay_us(&mut self, us: u16) { - self.delay_us(u32(us)) + type Error = Infallible; + + fn try_delay_us(&mut self, us: u16) -> Result<(), Self::Error> { + self.try_delay_us(u32(us)) } } impl DelayUs for Delay { - fn delay_us(&mut self, us: u8) { - self.delay_us(u32(us)) + type Error = Infallible; + + fn try_delay_us(&mut self, us: u8) -> Result<(), Self::Error> { + self.try_delay_us(u32(us)) } } diff --git a/src/dwt.rs b/src/dwt.rs index b650ecac..dc15dba4 100644 --- a/src/dwt.rs +++ b/src/dwt.rs @@ -2,6 +2,7 @@ use crate::rcc::Clocks; use crate::time::Hertz; +use core::convert::Infallible; use cortex_m::peripheral::{DCB, DWT}; use embedded_hal::blocking::delay::{DelayMs, DelayUs}; @@ -101,19 +102,25 @@ impl Delay { // Implement DelayUs/DelayMs for various integer types impl> DelayUs for Delay { - fn delay_us(&mut self, us: T) { + type Error = Infallible; + + fn try_delay_us(&mut self, us: T) -> Result<(), Infallible> { // Convert us to ticks let start = DWT::get_cycle_count(); let ticks = (us.into() * self.clock.0 as u64) / 1_000_000; Delay::delay_ticks(start, ticks); + Ok(()) } } impl> DelayMs for Delay { - fn delay_ms(&mut self, ms: T) { + type Error = Infallible; + + fn try_delay_ms(&mut self, ms: T) -> Result<(), Infallible> { // Convert ms to ticks let start = DWT::get_cycle_count(); let ticks = (ms.into() * self.clock.0 as u64) / 1_000; Delay::delay_ticks(start, ticks); + Ok(()) } } diff --git a/src/gpio.rs b/src/gpio.rs index e4048a3d..502f0915 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -101,7 +101,7 @@ macro_rules! gpio { use core::marker::PhantomData; use core::convert::Infallible; - use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; + use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::stm32::$GPIOX; use crate::stm32::{RCC, EXTI, SYSCFG}; @@ -150,13 +150,13 @@ macro_rules! gpio { impl OutputPin for $PXx> { type Error = Infallible; - fn set_high(&mut self) -> Result<(), Self::Error> { + fn try_set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }; Ok(()) } - fn set_low(&mut self) -> Result<(), Self::Error> { + fn try_set_low(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }; Ok(()) @@ -164,11 +164,11 @@ macro_rules! gpio { } impl StatefulOutputPin for $PXx> { - fn is_set_high(&self) -> Result { - self.is_set_low().map(|v| !v) + fn try_is_set_high(&self) -> Result { + self.try_is_set_low().map(|v| !v) } - fn is_set_low(&self) -> Result { + fn try_is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }) } @@ -179,11 +179,11 @@ macro_rules! gpio { impl InputPin for $PXx> { type Error = Infallible; - fn is_high(&self) -> Result { - self.is_low().map(|v| !v) + fn try_is_high(&self) -> Result { + self.try_is_low().map(|v| !v) } - fn is_low(&self) -> Result { + fn try_is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }) } @@ -192,11 +192,11 @@ macro_rules! gpio { impl InputPin for $PXx> { type Error = Infallible; - fn is_high(&self) -> Result { - self.is_low().map(|v| !v) + fn try_is_high(&self) -> Result { + self.try_is_low().map(|v| !v) } - fn is_low(&self) -> Result { + fn try_is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }) } @@ -670,13 +670,13 @@ macro_rules! gpio { impl OutputPin for $PXi> { type Error = Infallible; - fn set_high(&mut self) -> Result<(), Self::Error> { + fn try_set_high(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }; Ok(()) } - fn set_low(&mut self) -> Result<(), Self::Error> { + fn try_set_low(&mut self) -> Result<(), Self::Error> { // NOTE(unsafe) atomic write to a stateless register unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) }; Ok(()) @@ -684,11 +684,11 @@ macro_rules! gpio { } impl StatefulOutputPin for $PXi> { - fn is_set_high(&self) -> Result { - self.is_set_low().map(|v| !v) + fn try_is_set_high(&self) -> Result { + self.try_is_set_low().map(|v| !v) } - fn is_set_low(&self) -> Result { + fn try_is_set_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects Ok(unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }) } @@ -699,11 +699,11 @@ macro_rules! gpio { impl InputPin for $PXi> { type Error = Infallible; - fn is_high(&self) -> Result { - self.is_low().map(|v| !v) + fn try_is_high(&self) -> Result { + self.try_is_low().map(|v| !v) } - fn is_low(&self) -> Result { + fn try_is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }) } @@ -712,11 +712,11 @@ macro_rules! gpio { impl InputPin for $PXi> { type Error = Infallible; - fn is_high(&self) -> Result { - self.is_low().map(|v| !v) + fn try_is_high(&self) -> Result { + self.try_is_low().map(|v| !v) } - fn is_low(&self) -> Result { + fn try_is_low(&self) -> Result { // NOTE(unsafe) atomic read with no side effects Ok(unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }) } diff --git a/src/i2c.rs b/src/i2c.rs index c048510c..d7592d50 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -739,9 +739,14 @@ where { type Error = Error; - fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { - self.write(addr, bytes)?; - self.read(addr, buffer)?; + fn try_write_read( + &mut self, + addr: u8, + bytes: &[u8], + buffer: &mut [u8], + ) -> Result<(), Self::Error> { + self.try_write(addr, bytes)?; + self.try_read(addr, buffer)?; Ok(()) } @@ -753,7 +758,7 @@ where { type Error = Error; - fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { + fn try_write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Self::Error> { // Send a START condition self.i2c.cr1.modify(|_, w| w.start().set_bit()); @@ -793,7 +798,7 @@ where { type Error = Error; - fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { + fn try_read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { if let Some((last, buffer)) = buffer.split_last_mut() { // Send a START condition and set ACK bit self.i2c diff --git a/src/otg_fs.rs b/src/otg_fs.rs index 6fadf4d5..6a4fbb64 100644 --- a/src/otg_fs.rs +++ b/src/otg_fs.rs @@ -29,7 +29,7 @@ unsafe impl UsbPeripheral for USB { const HIGH_SPEED: bool = false; const FIFO_DEPTH_WORDS: usize = 320; - fn enable() { + fn try_enable() -> Result<(), Infallible> { let rcc = unsafe { &*stm32::RCC::ptr() }; cortex_m::interrupt::free(|_| { @@ -40,6 +40,8 @@ unsafe impl UsbPeripheral for USB { rcc.ahb2rstr.modify(|_, w| w.otgfsrst().set_bit()); rcc.ahb2rstr.modify(|_, w| w.otgfsrst().clear_bit()); }); + + Ok(()) } } diff --git a/src/otg_hs.rs b/src/otg_hs.rs index 11ece72d..cb0b9947 100644 --- a/src/otg_hs.rs +++ b/src/otg_hs.rs @@ -32,7 +32,7 @@ unsafe impl UsbPeripheral for USB { const HIGH_SPEED: bool = true; const FIFO_DEPTH_WORDS: usize = 1024; - fn enable() { + fn try_enable() -> Result<(), Infallible> { let rcc = unsafe { &*stm32::RCC::ptr() }; cortex_m::interrupt::free(|_| { @@ -43,6 +43,8 @@ unsafe impl UsbPeripheral for USB { rcc.ahb1rstr.modify(|_, w| w.otghsrst().set_bit()); rcc.ahb1rstr.modify(|_, w| w.otghsrst().clear_bit()); }); + + Ok(()) } } diff --git a/src/prelude.rs b/src/prelude.rs index 23d55710..53706771 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,7 +1,7 @@ -pub use embedded_hal::digital::v2::InputPin as _embedded_hal_digital_v2_InputPin; -pub use embedded_hal::digital::v2::OutputPin as _embedded_hal_digital_v2_OutputPin; -pub use embedded_hal::digital::v2::StatefulOutputPin as _embedded_hal_digital_v2_StatefulOutputPin; -pub use embedded_hal::digital::v2::ToggleableOutputPin as _embedded_hal_digital_v2_ToggleableOutputPin; +pub use embedded_hal::digital::InputPin as _embedded_hal_digital_v2_InputPin; +pub use embedded_hal::digital::OutputPin as _embedded_hal_digital_v2_OutputPin; +pub use embedded_hal::digital::StatefulOutputPin as _embedded_hal_digital_v2_StatefulOutputPin; +pub use embedded_hal::digital::ToggleableOutputPin as _embedded_hal_digital_v2_ToggleableOutputPin; pub use embedded_hal::prelude::*; pub use crate::gpio::GpioExt as _stm32f4xx_hal_gpio_GpioExt; diff --git a/src/pwm.rs b/src/pwm.rs index c3740403..58e22f7e 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -1,5 +1,5 @@ use cast::{u16, u32}; -use core::{marker::PhantomData, mem::MaybeUninit}; +use core::{convert::Infallible, marker::PhantomData, mem::MaybeUninit}; #[cfg(any( feature = "stm32f401", @@ -220,119 +220,143 @@ macro_rules! pwm_all_channels { unsafe { MaybeUninit::uninit().assume_init() } } - impl hal::PwmPin for PwmChannels<$TIMX, C1> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C1> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Self::Error> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 0) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Self::Error> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 0) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Self::Error> { unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } - impl hal::PwmPin for PwmChannels<$TIMX, C2> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C2> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 4) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 4) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } - impl hal::PwmPin for PwmChannels<$TIMX, C3> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C3> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 8) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 8) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr3.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).ccr3.read().ccr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } - impl hal::PwmPin for PwmChannels<$TIMX, C4> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C4> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 12) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 12) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr4.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).ccr4.read().ccr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr4.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } )+ @@ -397,61 +421,71 @@ macro_rules! pwm_2_channels { unsafe { MaybeUninit::uninit().assume_init() } } - impl hal::PwmPin for PwmChannels<$TIMX, C1> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C1> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 0) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 0) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + let v = unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }; + Ok(v) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } - impl hal::PwmPin for PwmChannels<$TIMX, C2> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C2> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 4) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 4) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + Ok(unsafe { (*$TIMX::ptr()).ccr2.read().ccr().bits() as u16 }) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + Ok(unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } )+ @@ -509,32 +543,36 @@ macro_rules! pwm_1_channel { unsafe { MaybeUninit::uninit().assume_init() } } - impl hal::PwmPin for PwmChannels<$TIMX, C1> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C1> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Self::Error> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 0) } + Ok(()) } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Self::Error> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 0) } + Ok(()) } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 } + fn try_get_duty(&self) -> Result { + Ok(unsafe { (*$TIMX::ptr()).ccr1.read().ccr().bits() as u16 }) } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { - unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 } + fn try_get_max_duty(&self) -> Result { + Ok(unsafe { (*$TIMX::ptr()).arr.read().arr().bits() as u16 }) } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Self::Error> { unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } + Ok(()) } } )+ @@ -608,118 +646,122 @@ macro_rules! pwm_tim5_f410 { unsafe { MaybeUninit::uninit().assume_init() } } - impl hal::PwmPin for PwmChannels<$TIMX, C1> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C1> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 0) } } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 0) } } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { + fn try_get_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).ccr1.read().ccr1_l().bits() as u16 } } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { + fn try_get_max_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).arr.read().arr_l().bits() as u16 } } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr1.write(|w| w.ccr1_l().bits(duty.into())) } } } - impl hal::PwmPin for PwmChannels<$TIMX, C2> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C2> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 4) } } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 4) } } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { + fn try_get_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).ccr2.read().ccr1_l().bits() as u16 } } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { + fn try_get_max_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).arr.read().arr_l().bits() as u16 } } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr2.write(|w| w.ccr1_l().bits(duty.into())) } } } - impl hal::PwmPin for PwmChannels<$TIMX, C3> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C3> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 8) } } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 8) } } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { + fn try_get_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).ccr3.read().ccr1_l().bits() as u16 } } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { + fn try_get_max_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).arr.read().arr_l().bits() as u16 } } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr3.write(|w| w.ccr1_l().bits(duty.into())) } } } - impl hal::PwmPin for PwmChannels<$TIMX, C4> { + impl hal::pwm::PwmPin for PwmChannels<$TIMX, C4> { type Duty = u16; + type Error = Infallible; //NOTE(unsafe) atomic write with no side effects - fn disable(&mut self) { + fn try_disable(&mut self) -> Result<(), Infallible> { unsafe { bb::clear(&(*$TIMX::ptr()).ccer, 12) } } //NOTE(unsafe) atomic write with no side effects - fn enable(&mut self) { + fn try_enable(&mut self) -> Result<(), Infallible> { unsafe { bb::set(&(*$TIMX::ptr()).ccer, 12) } } //NOTE(unsafe) atomic read with no side effects - fn get_duty(&self) -> u16 { + fn try_get_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).ccr4.read().ccr1_l().bits() as u16 } } //NOTE(unsafe) atomic read with no side effects - fn get_max_duty(&self) -> u16 { + fn try_get_max_duty(&self) -> Result { unsafe { (*$TIMX::ptr()).arr.read().arr_l().bits() as u16 } } //NOTE(unsafe) atomic write with no side effects - fn set_duty(&mut self, duty: u16) { + fn try_set_duty(&mut self, duty: u16) -> Result<(), Infallible> { unsafe { (*$TIMX::ptr()).ccr4.write(|w| w.ccr1_l().bits(duty.into())) } } } diff --git a/src/qei.rs b/src/qei.rs index 3a90c831..8f2a5c0b 100644 --- a/src/qei.rs +++ b/src/qei.rs @@ -1,5 +1,5 @@ //! # Quadrature Encoder Interface -use crate::hal::{self, Direction}; +use crate::hal::{self, qei::Direction}; use crate::stm32::RCC; #[cfg(any( @@ -126,18 +126,19 @@ macro_rules! hal { } } - impl hal::Qei for Qei<$TIM, PINS> { + impl hal::qei::Qei for Qei<$TIM, PINS> { type Count = $bits; + type Error = core::convert::Infallible; - fn count(&self) -> $bits { - self.tim.cnt.read().bits() as $bits + fn try_count(&self) -> Result<$bits, Self::Error> { + Ok(self.tim.cnt.read().bits() as $bits) } - fn direction(&self) -> Direction { + fn try_direction(&self) -> Result { if self.tim.cr1.read().dir().bit_is_clear() { - hal::Direction::Upcounting + Ok(hal::qei::Direction::Upcounting) } else { - hal::Direction::Downcounting + Ok(hal::qei::Direction::Downcounting) } } } diff --git a/src/rng.rs b/src/rng.rs index 5a6ec2e9..64868b5a 100644 --- a/src/rng.rs +++ b/src/rng.rs @@ -93,7 +93,7 @@ impl Rng { impl rng::Read for Rng { type Error = rand_core::Error; - fn read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> { + fn try_read(&mut self, buffer: &mut [u8]) -> Result<(), Self::Error> { self.try_fill_bytes(buffer) } } diff --git a/src/serial.rs b/src/serial.rs index 7d95f990..92f4586f 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -1508,18 +1508,18 @@ macro_rules! halUsartImpl { impl serial::Read for Serial<$USARTX, PINS> { type Error = Error; - fn read(&mut self) -> nb::Result { + fn try_read(&mut self) -> nb::Result { let mut rx: Rx<$USARTX> = Rx { _usart: PhantomData, }; - rx.read() + rx.try_read() } } impl serial::Read for Rx<$USARTX> { type Error = Error; - fn read(&mut self) -> nb::Result { + fn try_read(&mut self) -> nb::Result { // NOTE(unsafe) atomic read with no side effects let sr = unsafe { (*$USARTX::ptr()).sr.read() }; @@ -1552,25 +1552,25 @@ macro_rules! halUsartImpl { impl serial::Write for Serial<$USARTX, PINS> { type Error = Error; - fn flush(&mut self) -> nb::Result<(), Self::Error> { + fn try_flush(&mut self) -> nb::Result<(), Self::Error> { let mut tx: Tx<$USARTX> = Tx { _usart: PhantomData, }; - tx.flush() + tx.try_flush() } - fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { + fn try_write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { let mut tx: Tx<$USARTX> = Tx { _usart: PhantomData, }; - tx.write(byte) + tx.try_write(byte) } } impl serial::Write for Tx<$USARTX> { type Error = Error; - fn flush(&mut self) -> nb::Result<(), Self::Error> { + fn try_flush(&mut self) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects let sr = unsafe { (*$USARTX::ptr()).sr.read() }; @@ -1581,7 +1581,7 @@ macro_rules! halUsartImpl { } } - fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { + fn try_write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { // NOTE(unsafe) atomic read with no side effects let sr = unsafe { (*$USARTX::ptr()).sr.read() }; @@ -1765,7 +1765,11 @@ where Tx: serial::Write, { fn write_str(&mut self, s: &str) -> fmt::Result { - let _ = s.as_bytes().iter().map(|c| block!(self.write(*c))).last(); + let _ = s + .as_bytes() + .iter() + .map(|c| block!(self.try_write(*c))) + .last(); Ok(()) } } diff --git a/src/spi.rs b/src/spi.rs index d16aedd4..49c60cfc 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1013,7 +1013,7 @@ where { type Error = Error; - fn read(&mut self) -> nb::Result { + fn try_read(&mut self) -> nb::Result { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { @@ -1031,7 +1031,7 @@ where }) } - fn send(&mut self, byte: u8) -> nb::Result<(), Error> { + fn try_send(&mut self, byte: u8) -> nb::Result<(), Error> { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { diff --git a/src/timer.rs b/src/timer.rs index cc9c6445..abc550ba 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -4,7 +4,6 @@ use cast::{u16, u32}; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use embedded_hal::timer::{Cancel, CountDown, Periodic}; -use void::Void; use crate::stm32::RCC; #[cfg(any( @@ -105,14 +104,14 @@ pub enum Error { impl Timer { /// Configures the SYST clock as a periodic count down timer - pub fn syst(mut syst: SYST, timeout: T, clocks: Clocks) -> Self + pub fn syst(mut syst: SYST, timeout: T, clocks: Clocks) -> Result> where T: Into, { syst.set_clock_source(SystClkSource::Core); let mut timer = Timer { tim: syst, clocks }; - timer.start(timeout); - timer + timer.try_start(timeout)?; + Ok(timer) } /// Starts listening for an `event` @@ -132,8 +131,9 @@ impl Timer { impl CountDown for Timer { type Time = Hertz; + type Error = nb::Error; - fn start(&mut self, timeout: T) + fn try_start(&mut self, timeout: T) -> Result<(), Self::Error> where T: Into, { @@ -144,9 +144,11 @@ impl CountDown for Timer { self.tim.set_reload(rvr); self.tim.clear_current(); self.tim.enable_counter(); + + Ok(()) } - fn wait(&mut self) -> nb::Result<(), Void> { + fn try_wait(&mut self) -> nb::Result<(), Self::Error> { if self.tim.has_wrapped() { Ok(()) } else { @@ -156,11 +158,9 @@ impl CountDown for Timer { } impl Cancel for Timer { - type Error = Error; - - fn cancel(&mut self) -> Result<(), Self::Error> { + fn try_cancel(&mut self) -> Result<(), Self::Error> { if !self.tim.is_counter_enabled() { - return Err(Self::Error::Disabled); + return Err(nb::Error::Other(Error::Disabled)); } self.tim.disable_counter(); @@ -175,7 +175,7 @@ macro_rules! hal { $( impl Timer<$TIM> { /// Configures a TIM peripheral as a periodic count down timer - pub fn $tim(tim: $TIM, timeout: T, clocks: Clocks) -> Self + pub fn $tim(tim: $TIM, timeout: T, clocks: Clocks) -> Result> where T: Into, { @@ -189,9 +189,9 @@ macro_rules! hal { clocks, tim, }; - timer.start(timeout); + timer.try_start(timeout)?; - timer + Ok(timer) } /// Starts listening for an `event` @@ -240,8 +240,9 @@ macro_rules! hal { impl CountDown for Timer<$TIM> { type Time = Hertz; + type Error = nb::Error; - fn start(&mut self, timeout: T) + fn try_start(&mut self, timeout: T) -> Result<(), Self::Error> where T: Into, { @@ -262,9 +263,11 @@ macro_rules! hal { // start counter self.tim.cr1.modify(|_, w| w.cen().set_bit()); + + Ok(()) } - fn wait(&mut self) -> nb::Result<(), Void> { + fn try_wait(&mut self) -> nb::Result<(), Self::Error> { if self.tim.sr.read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { @@ -276,12 +279,10 @@ macro_rules! hal { impl Cancel for Timer<$TIM> { - type Error = Error; - - fn cancel(&mut self) -> Result<(), Self::Error> { + fn try_cancel(&mut self) -> Result<(), Self::Error> { let is_counter_enabled = self.tim.cr1.read().cen().is_enabled(); if !is_counter_enabled { - return Err(Self::Error::Disabled); + return Err(nb::Error::Other(Error::Disabled)); } // disable counter diff --git a/src/watchdog.rs b/src/watchdog.rs index 440afb57..459c018a 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -1,4 +1,5 @@ //! Watchdog peripherals +use core::convert::Infallible; use crate::{ hal::watchdog::{Watchdog, WatchdogEnable}, @@ -89,16 +90,23 @@ impl IndependentWatchdog { impl WatchdogEnable for IndependentWatchdog { type Time = MilliSeconds; + type Error = Infallible; - fn start>(&mut self, period: T) { + fn try_start>(&mut self, period: T) -> Result<(), Self::Error> { self.setup(period.into().0); self.iwdg.kr.write(|w| unsafe { w.key().bits(KR_START) }); + + Ok(()) } } impl Watchdog for IndependentWatchdog { - fn feed(&mut self) { + type Error = Infallible; + + fn try_feed(&mut self) -> Result<(), Self::Error> { self.iwdg.kr.write(|w| unsafe { w.key().bits(KR_RELOAD) }); + + Ok(()) } } From 7827992e6b222bb1d9ea04d7fb09d595d6816f80 Mon Sep 17 00:00:00 2001 From: ryan Date: Sat, 20 Jun 2020 10:07:58 +1200 Subject: [PATCH 2/4] fix timer error types --- src/timer.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/timer.rs b/src/timer.rs index abc550ba..cec4ce63 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -131,7 +131,7 @@ impl Timer { impl CountDown for Timer { type Time = Hertz; - type Error = nb::Error; + type Error = Error; fn try_start(&mut self, timeout: T) -> Result<(), Self::Error> where @@ -160,7 +160,7 @@ impl CountDown for Timer { impl Cancel for Timer { fn try_cancel(&mut self) -> Result<(), Self::Error> { if !self.tim.is_counter_enabled() { - return Err(nb::Error::Other(Error::Disabled)); + return Err(Error::Disabled); } self.tim.disable_counter(); From b096bde9243a61a849af6ba6e20546ff98cd39e4 Mon Sep 17 00:00:00 2001 From: ryan Date: Sun, 28 Jun 2020 21:30:31 +1200 Subject: [PATCH 3/4] fix otg_fs method --- src/otg_fs.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/otg_fs.rs b/src/otg_fs.rs index 6a4fbb64..6fadf4d5 100644 --- a/src/otg_fs.rs +++ b/src/otg_fs.rs @@ -29,7 +29,7 @@ unsafe impl UsbPeripheral for USB { const HIGH_SPEED: bool = false; const FIFO_DEPTH_WORDS: usize = 320; - fn try_enable() -> Result<(), Infallible> { + fn enable() { let rcc = unsafe { &*stm32::RCC::ptr() }; cortex_m::interrupt::free(|_| { @@ -40,8 +40,6 @@ unsafe impl UsbPeripheral for USB { rcc.ahb2rstr.modify(|_, w| w.otgfsrst().set_bit()); rcc.ahb2rstr.modify(|_, w| w.otgfsrst().clear_bit()); }); - - Ok(()) } } From e110483f19e49560bf8b8543b104f5662f7564b8 Mon Sep 17 00:00:00 2001 From: ryan Date: Tue, 14 Jul 2020 00:08:52 +1200 Subject: [PATCH 4/4] Added default transactional spi impl, patch for demonstration --- Cargo.toml | 3 +++ src/spi.rs | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 8a21c92f..85e7424f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,3 +123,6 @@ required-features = ["rt", "stm32f429"] [[example]] name = "rng-display" required-features = ["rt", "stm32f407"] + +[patch.crates-io] +embedded-hal = { git = "https://github.com/ryankurte/embedded-hal.git", branch = "feature/spi-transactions" } diff --git a/src/spi.rs b/src/spi.rs index 49c60cfc..5f96d16a 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -1059,3 +1059,8 @@ impl embedded_hal::blocking::spi::write::Default for Spi { } + +impl embedded_hal::blocking::spi::transactional::Default for Spi where + SPI: Deref +{ +}