diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e95dd90..ac4e90e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,9 @@ jobs: - gd32f190x4 - gd32f190x6 - gd32f190x8 + extra-features: + - rt + - rt,embedded-hal-02 rust: - stable include: @@ -41,4 +44,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: check - args: --features=${{ matrix.mcu }},rt --examples + args: --features=${{ matrix.mcu }},${{ matrix.extra-features }} --examples diff --git a/CHANGELOG.md b/CHANGELOG.md index ff7f93c..5ee6c62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [Unreleased] + +### Breaking changes + +- Moved `embedded-hal` 0.2 trait implementations behind the `embedded-hal-02` feature flag, + to make the dependency optional. + ## [0.8.0] ### Breaking changes diff --git a/Cargo.toml b/Cargo.toml index e946446..101f72a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ embedded-dma = "0.2.0" embedded-hal = "1.0.0" embedded-hal-02 = { package = "embedded-hal", version = "0.2.7", features = [ "unproven", -] } +], optional = true } embedded-io = "0.6.1" gd32f1 = { version = "0.8.0", features = ["critical-section"] } nb = "1.1.0" diff --git a/examples/adc.rs b/examples/adc.rs index 9be048d..19fcc69 100644 --- a/examples/adc.rs +++ b/examples/adc.rs @@ -6,7 +6,6 @@ use panic_semihosting as _; use cortex_m_rt::entry; use cortex_m_semihosting::hprintln; -use embedded_hal_02::adc::OneShot; use gd32f1x0_hal::{adc::Adc, pac, prelude::*}; #[entry] @@ -34,7 +33,7 @@ fn main() -> ! { let mut ch0 = gpiob.pb0.into_analog(&mut gpiob.config); loop { - let data: u16 = adc.read(&mut ch0).unwrap(); + let data: u16 = adc.read_channel(&mut ch0); hprintln!("adc1: {}", data); } } diff --git a/examples/blinky.rs b/examples/blinky.rs index 983789f..212c1da 100644 --- a/examples/blinky.rs +++ b/examples/blinky.rs @@ -11,11 +11,9 @@ use panic_halt as _; -use nb::block; - +use core::hint::spin_loop; use cortex_m_rt::entry; use embedded_hal::digital::OutputPin; -use embedded_hal_02::timer::CountDown; use gd32f1x0_hal::{pac, prelude::*, timer::Timer}; #[entry] @@ -45,9 +43,13 @@ fn main() -> ! { // Wait for the timer to trigger an update and change the state of the LED loop { - block!(timer.wait()).unwrap(); + while !timer.has_elapsed() { + spin_loop(); + } led.set_high().unwrap(); - block!(timer.wait()).unwrap(); + while !timer.has_elapsed() { + spin_loop(); + } led.set_low().unwrap(); } } diff --git a/examples/blinky_generic.rs b/examples/blinky_generic.rs index 1b9d7b6..3f785e6 100644 --- a/examples/blinky_generic.rs +++ b/examples/blinky_generic.rs @@ -6,11 +6,9 @@ use panic_halt as _; -use nb::block; - +use core::hint::spin_loop; use cortex_m_rt::entry; use embedded_hal::digital::OutputPin; -use embedded_hal_02::timer::CountDown; use gd32f1x0_hal::{pac, prelude::*, timer::Timer}; #[entry] @@ -44,11 +42,15 @@ fn main() -> ! { // Wait for the timer to trigger an update and change the state of the LED loop { - block!(timer.wait()).unwrap(); + while !timer.has_elapsed() { + spin_loop(); + } for led in leds.iter_mut() { led.set_high().unwrap(); } - block!(timer.wait()).unwrap(); + while !timer.has_elapsed() { + spin_loop(); + } for led in leds.iter_mut() { led.set_low().unwrap(); } diff --git a/examples/blinky_timer_irq.rs b/examples/blinky_timer_irq.rs index df45f4f..ec882a5 100644 --- a/examples/blinky_timer_irq.rs +++ b/examples/blinky_timer_irq.rs @@ -15,10 +15,7 @@ use panic_halt as _; use core::cell::RefCell; use cortex_m::{asm::wfi, interrupt::Mutex}; use cortex_m_rt::entry; -use embedded_hal_02::{ - digital::v2::{OutputPin, ToggleableOutputPin}, - timer::CountDown, -}; +use embedded_hal::digital::{OutputPin, StatefulOutputPin}; use gd32f1x0_hal::{ gpio::{gpioc, Output, PushPull}, pac::{interrupt, Interrupt, Peripherals, TIMER1}, @@ -57,8 +54,7 @@ fn TIMER1() { }); let _ = led.toggle(); - // TODO: Shouldn't this just return? - let _ = tim.wait(); + tim.clear_interrupt_flag(Event::Update); } #[entry] diff --git a/examples/pwm.rs b/examples/pwm.rs index 060ca71..62889d3 100644 --- a/examples/pwm.rs +++ b/examples/pwm.rs @@ -8,7 +8,7 @@ use panic_halt as _; use cortex_m::asm; use cortex_m_rt::entry; -use embedded_hal_02::{Pwm, PwmPin}; +use embedded_hal::pwm::SetDutyCycle; use gd32f1x0_hal::{ gpio::{gpioa::PA11, OutputMode, PullMode}, pac, @@ -61,23 +61,23 @@ fn main() -> ! { asm::bkpt(); - let max = pwm.get_max_duty(); + let max = pwm.max_duty_cycle(); //// Operations affecting single channels can be accessed through //// the Pwm object or via dereferencing to the pin. // Use the Pwm object to set C2 to full strength - pwm.set_duty(Channel::C2, max); + pwm.set_duty_cycle(Channel::C2, max); asm::bkpt(); // Use the Pwm object to set C2 to be dim - pwm.set_duty(Channel::C2, max / 4); + pwm.set_duty_cycle(Channel::C2, max / 4); asm::bkpt(); // Use the Pwm object to set C2 to be zero - pwm.set_duty(Channel::C2, 0); + pwm.set_duty_cycle(Channel::C2, 0); asm::bkpt(); @@ -85,17 +85,17 @@ fn main() -> ! { let mut pwm_channel = pwm.split().2.unwrap(); // Use the PwmChannel object to set C2 to be full strength - pwm_channel.set_duty(max); + pwm_channel.set_duty_cycle(max).unwrap(); asm::bkpt(); // Use the PwmChannel object to set C2 to be dim - pwm_channel.set_duty(max / 4); + pwm_channel.set_duty_cycle(max / 4).unwrap(); asm::bkpt(); // Use the PwmChannel object to set C2 to be zero - pwm_channel.set_duty(0); + pwm_channel.set_duty_cycle(0).unwrap(); asm::bkpt(); diff --git a/examples/pwm_complementary.rs b/examples/pwm_complementary.rs index 657f122..befbe30 100644 --- a/examples/pwm_complementary.rs +++ b/examples/pwm_complementary.rs @@ -8,7 +8,7 @@ use panic_halt as _; use cortex_m::asm; use cortex_m_rt::entry; -use embedded_hal_02::{Pwm, PwmPin}; +use embedded_hal::pwm::SetDutyCycle; use gd32f1x0_hal::{ gpio::{OutputMode, PullMode}, pac, @@ -81,23 +81,23 @@ fn main() -> ! { asm::bkpt(); - let max = pwm.get_max_duty(); + let max = pwm.max_duty_cycle(); //// Operations affecting single channels can be accessed through //// the Pwm object or via dereferencing to the pin. // Use the Pwm object to set C2 to full strength - pwm.set_duty(Channel::C2, max); + pwm.set_duty_cycle(Channel::C2, max); asm::bkpt(); // Use the Pwm object to set C2 to be dim - pwm.set_duty(Channel::C2, max / 4); + pwm.set_duty_cycle(Channel::C2, max / 4); asm::bkpt(); // Use the Pwm object to set C2 to be zero - pwm.set_duty(Channel::C2, 0); + pwm.set_duty_cycle(Channel::C2, 0); asm::bkpt(); @@ -105,17 +105,17 @@ fn main() -> ! { let mut pwm_channel = pwm.split().2.unwrap(); // Use the PwmChannel object to set C2 to be full strength - pwm_channel.set_duty(max); + pwm_channel.set_duty_cycle(max).unwrap(); asm::bkpt(); // Use the PwmChannel object to set C2 to be dim - pwm_channel.set_duty(max / 4); + pwm_channel.set_duty_cycle(max / 4).unwrap(); asm::bkpt(); // Use the PwmChannel object to set C2 to be zero - pwm_channel.set_duty(0); + pwm_channel.set_duty_cycle(0).unwrap(); asm::bkpt(); diff --git a/examples/timer-interrupt-rtic.rs b/examples/timer-interrupt-rtic.rs index 31af604..2b118fc 100644 --- a/examples/timer-interrupt-rtic.rs +++ b/examples/timer-interrupt-rtic.rs @@ -14,7 +14,6 @@ use panic_halt as _; use rtic::app; use embedded_hal::digital::OutputPin; -use embedded_hal_02::timer::CountDown; use gd32f1x0_hal::{ gpio::{gpioc::PC13, Output, PushPull}, pac, diff --git a/src/adc.rs b/src/adc.rs index f8f5d2b..be463ed 100644 --- a/src/adc.rs +++ b/src/adc.rs @@ -20,13 +20,21 @@ use crate::pac::{ }; use crate::rcu::{Clocks, Enable, Reset, APB2}; use core::{ - convert::Infallible, marker::PhantomData, sync::atomic::{self, Ordering}, }; use cortex_m::asm::delay; use embedded_dma::WriteBuffer; -use embedded_hal_02::adc::{Channel, OneShot}; +#[cfg(feature = "embedded-hal-02")] +use embedded_hal_02::adc::Channel as _; + +#[cfg(feature = "embedded-hal-02")] +pub trait Channel: embedded_hal_02::adc::Channel {} + +#[cfg(not(feature = "embedded-hal-02"))] +pub trait Channel { + fn channel() -> u8; +} /// The number of ADC clock cycles to wait between powering on and starting calibration. const ADC_CALIBRATION_CYCLES: u32 = 14; @@ -293,7 +301,7 @@ impl Adc { /// Set ADC sampling time for particular channel #[inline(always)] - pub fn set_sample_time>(&mut self, _pin: &C, sample_time: SampleTime) { + pub fn set_sample_time>(&mut self, _pin: &C, sample_time: SampleTime) { self.set_channel_sample_time(C::channel(), sample_time); } @@ -465,10 +473,14 @@ impl Adc { self.rb.rdata.read().rdata().bits() } + pub fn read_channel>(&mut self, _pin: &PIN) -> u16 { + self.convert(PIN::channel()) + } + /// Configure the ADC to read from the given pin with DMA. pub fn with_dma(mut self, pins: PIN, dma_ch: C0) -> AdcDma where - PIN: Channel, + PIN: Channel, { self.rb.ctl0.modify(|_, w| w.disrc().disabled()); self.rb @@ -490,15 +502,16 @@ impl Adc { } } -impl OneShot for Adc +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::adc::OneShot for Adc where WORD: From, - PIN: Channel, + PIN: Channel, { - type Error = Infallible; + type Error = core::convert::Infallible; - fn read(&mut self, _pin: &mut PIN) -> nb::Result { - let res = self.convert(PIN::channel()); + fn read(&mut self, pin: &mut PIN) -> nb::Result { + let res = self.read_channel(pin); // TODO: Should this also be scaled based on Vref? Ok(res.into()) } @@ -595,7 +608,7 @@ pub struct Sequence { impl Sequence { /// Adds the given ADC pin to the list of channels. - pub fn add_pin>(&mut self, pin: PIN) -> Result<(), PIN> { + pub fn add_pin>(&mut self, pin: PIN) -> Result<(), PIN> { if self.length >= self.channels.len() { return Err(pin); } @@ -634,11 +647,17 @@ pub struct VBat; macro_rules! adc_pins { ($ADC:ident, $($pin:ty => $chan:expr),+ $(,)*) => { $( - impl Channel<$ADC> for $pin { + #[cfg(feature = "embedded-hal-02")] + impl embedded_hal_02::adc::Channel<$ADC> for $pin { type ID = u8; fn channel() -> u8 { $chan } } + + impl Channel<$ADC> for $pin { + #[cfg(not(feature = "embedded-hal-02"))] + fn channel() -> u8 { $chan } + } )+ }; } diff --git a/src/delay.rs b/src/delay.rs index d8b301a..7b0b5d3 100644 --- a/src/delay.rs +++ b/src/delay.rs @@ -8,7 +8,6 @@ use crate::rcu::Clocks; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use embedded_hal::delay::DelayNs; -use embedded_hal_02::blocking::delay::{DelayMs, DelayUs}; /// System timer (SysTick) as a delay provider pub struct Delay { @@ -60,37 +59,43 @@ impl DelayNs for Delay { } } -impl DelayMs for Delay { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayMs for Delay { fn delay_ms(&mut self, ms: u32) { DelayNs::delay_ms(self, ms); } } -impl DelayMs for Delay { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayMs for Delay { fn delay_ms(&mut self, ms: u16) { DelayNs::delay_ms(self, ms.into()); } } -impl DelayMs for Delay { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayMs for Delay { fn delay_ms(&mut self, ms: u8) { DelayNs::delay_ms(self, ms.into()); } } -impl DelayUs for Delay { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayUs for Delay { fn delay_us(&mut self, us: u32) { DelayNs::delay_us(self, us) } } -impl DelayUs for Delay { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayUs for Delay { fn delay_us(&mut self, us: u16) { DelayNs::delay_us(self, us.into()) } } -impl DelayUs for Delay { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::delay::DelayUs for Delay { fn delay_us(&mut self, us: u8) { DelayNs::delay_us(self, us.into()) } diff --git a/src/gpio.rs b/src/gpio.rs index e7794d5..f2d0dbc 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -6,7 +6,6 @@ use crate::rcu::AHB; use core::convert::Infallible; use core::marker::PhantomData; use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin}; -use embedded_hal_02::digital::v2::toggleable; /// Extension trait to split a GPIO peripheral in independent pins and registers pub trait GpioExt { @@ -175,7 +174,8 @@ pub struct Pin { unsafe impl Sync for Pin {} unsafe impl Send for Pin {} -impl toggleable::Default for Pin> {} +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::digital::v2::toggleable::Default for Pin> {} impl ErrorType for Pin { type Error = Infallible; @@ -197,6 +197,7 @@ impl OutputPin for Pin> { } } +#[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::OutputPin for Pin> { type Error = Infallible; @@ -225,6 +226,7 @@ impl StatefulOutputPin for Pin> { } } +#[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::StatefulOutputPin for Pin> { fn is_set_high(&self) -> Result { self.is_set_low().map(|b| !b) @@ -245,6 +247,7 @@ impl InputPin for Pin> { } } +#[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::InputPin for Pin> { type Error = Infallible; @@ -267,6 +270,7 @@ impl InputPin for Pin> { } } +#[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::InputPin for Pin> { type Error = Infallible; @@ -492,7 +496,8 @@ macro_rules! gpio_core { } } - impl toggleable::Default for $PXi> {} + #[cfg(feature = "embedded-hal-02")] + impl embedded_hal_02::digital::v2::toggleable::Default for $PXi> {} impl ErrorType for $PXi { type Error = Infallible; @@ -508,6 +513,7 @@ macro_rules! gpio_core { } } + #[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::OutputPin for $PXi> { type Error = Infallible; @@ -530,6 +536,7 @@ macro_rules! gpio_core { } } + #[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::StatefulOutputPin for $PXi> { fn is_set_high(&self) -> Result { self.is_set_low().map(|b| !b) @@ -550,6 +557,7 @@ macro_rules! gpio_core { } } + #[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::InputPin for $PXi> { type Error = Infallible; @@ -572,6 +580,7 @@ macro_rules! gpio_core { } } + #[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::digital::v2::InputPin for $PXi> { type Error = Infallible; diff --git a/src/i2c.rs b/src/i2c.rs index 8e2f494..615faf6 100644 --- a/src/i2c.rs +++ b/src/i2c.rs @@ -37,7 +37,6 @@ use crate::rcu::{Clocks, Enable, GetBusFreq, Reset, APB1}; use crate::time::Hertz; use core::ops::Deref; use embedded_hal::i2c::{ErrorKind, ErrorType, NoAcknowledgeSource, Operation, SevenBitAddress}; -use embedded_hal_02::blocking::i2c::{Read, Write, WriteRead}; /// I2C error #[derive(Debug, Eq, PartialEq)] @@ -557,6 +556,7 @@ where ret } + #[cfg(feature = "embedded-hal-02")] fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { self.send_start_and_wait()?; self.send_addr_and_wait(addr, false)?; @@ -692,7 +692,8 @@ where } } -impl Write for BlockingI2c +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::i2c::Write for BlockingI2c where I2C: Deref, { @@ -707,7 +708,8 @@ where } } -impl Read for BlockingI2c +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::i2c::Read for BlockingI2c where I2C: Deref, { @@ -720,13 +722,17 @@ where } } -impl WriteRead for BlockingI2c +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::blocking::i2c::WriteRead + for BlockingI2c where I2C: Deref, { type Error = Error; fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Self::Error> { + use embedded_hal_02::blocking::i2c::Read; + if !bytes.is_empty() { self.write_without_stop(addr, bytes)?; } diff --git a/src/lib.rs b/src/lib.rs index ab3fd7e..401f7a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -63,7 +63,7 @@ //! Most of the examples require the following additional dependencies //! ```toml //! [dependencies] -//! embedded-hal = "0.2.7" +//! embedded-hal = "1.0.0" //! nb = "1.1.0" //! cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } //! cortex-m-rt = "0.7.3" diff --git a/src/pwm.rs b/src/pwm.rs index 2f4d5eb..2649158 100644 --- a/src/pwm.rs +++ b/src/pwm.rs @@ -16,7 +16,6 @@ use core::convert::Infallible; use core::marker::{Copy, PhantomData}; use core::ops::Deref; use embedded_hal::pwm::{ErrorType, SetDutyCycle}; -use embedded_hal_02::PwmPin; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum Channel { @@ -189,26 +188,20 @@ impl ComplementaryPins { } -impl PwmPin for PwmChannel { - type Duty = u16; - - fn disable(&mut self) { +impl PwmChannel { + pub fn disable(&mut self) { unsafe { &*self.timer }.disable_channel(self.channel, false); } - fn enable(&mut self) { + pub fn enable(&mut self) { unsafe { &*self.timer }.enable_channel(self.channel, false); } - fn get_duty(&self) -> u16 { + pub fn duty_cycle(&self) -> u16 { unsafe { &*self.timer }.get_duty(self.channel) } - fn get_max_duty(&self) -> u16 { - unsafe { &*self.timer }.get_max_duty() - } - - fn set_duty(&mut self, duty: u16) { + fn set_duty_cycle(&mut self, duty: u16) { unsafe { &*self.timer }.set_duty(self.channel, duty); } } @@ -219,36 +212,80 @@ impl ErrorType for PwmChannel { impl SetDutyCycle for PwmChannel { fn max_duty_cycle(&self) -> u16 { - self.get_max_duty() + unsafe { &*self.timer }.get_max_duty() } fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { - self.set_duty(duty); + self.set_duty_cycle(duty); Ok(()) } } -impl PwmPin for PwmChannelComplementary { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::PwmPin for PwmChannel { type Duty = u16; fn disable(&mut self) { - unsafe { &*self.pwm_channel.timer }.disable_channel(self.pwm_channel.channel, true); + self.disable(); } fn enable(&mut self) { + self.enable(); + } + + fn get_duty(&self) -> u16 { + self.duty_cycle() + } + + fn get_max_duty(&self) -> u16 { + self.max_duty_cycle() + } + + fn set_duty(&mut self, duty: u16) { + self.set_duty_cycle(duty); + } +} + +impl PwmChannelComplementary { + pub fn disable(&mut self) { + unsafe { &*self.pwm_channel.timer }.disable_channel(self.pwm_channel.channel, true); + } + + pub fn enable(&mut self) { unsafe { &*self.pwm_channel.timer }.enable_channel(self.pwm_channel.channel, true); } + pub fn duty_cycle(&self) -> u16 { + self.pwm_channel.duty_cycle() + } + + fn set_duty_cycle(&mut self, duty: u16) { + self.pwm_channel.set_duty_cycle(duty) + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::PwmPin for PwmChannelComplementary { + type Duty = u16; + + fn disable(&mut self) { + self.disable(); + } + + fn enable(&mut self) { + self.enable(); + } + fn get_duty(&self) -> u16 { - self.pwm_channel.get_duty() + self.duty_cycle() } fn get_max_duty(&self) -> u16 { - self.pwm_channel.get_max_duty() + self.max_duty_cycle() } fn set_duty(&mut self, duty: u16) { - self.pwm_channel.set_duty(duty) + self.set_duty_cycle(duty); } } @@ -258,11 +295,11 @@ impl ErrorType for PwmChannelComplementary { impl SetDutyCycle for PwmChannelComplementary { fn max_duty_cycle(&self) -> u16 { - self.get_max_duty() + self.pwm_channel.max_duty_cycle() } fn set_duty_cycle(&mut self, duty: u16) -> Result<(), Self::Error> { - self.set_duty(duty); + self.set_duty_cycle(duty); Ok(()) } } @@ -505,6 +542,48 @@ macro_rules! hal { } } + + pub fn disable(&mut self, channel: Channel) { + assert!(self.pins.uses_channel(channel)); + self.timer.disable_channel(channel, self.pins.uses_complementary_channel(channel)); + } + + pub fn enable(&mut self, channel: Channel) { + assert!(self.pins.uses_channel(channel)); + self.timer.enable_channel(channel, self.pins.uses_complementary_channel(channel)); + } + + pub fn duty_cycle(&self, channel: Channel) -> u16 { + assert!(self.pins.uses_channel(channel)); + self.timer.get_duty(channel) + } + + pub fn set_duty_cycle(&mut self, channel: Channel, duty: u16) { + assert!(self.pins.uses_channel(channel)); + self.timer.set_duty(channel, duty); + } + + pub fn max_duty_cycle(&self) -> u16 { + self.timer.get_max_duty() + } + + pub fn period(&self) -> Hertz { + let presaler: u32 = self.timer.psc.read().psc().bits().into(); + let auto_reload_value: u32 = self.timer.car.read().car().bits().into(); + + // Length in ms of an internal clock pulse + (self.clock.0 / (presaler * auto_reload_value)).hz() + } + + pub fn set_period(&mut self, period: T) + where + T: Into, + { + self.timer + .configure_prescaler_reload(period.into(), self.clock); + self.timer.reset_counter(); + } + $( /// Disable PWM outputs, and prevent them from being automatically enabled. pub fn output_disable(&mut self) { @@ -566,6 +645,7 @@ macro_rules! hal { )? } + #[cfg(feature = "embedded-hal-02")] impl embedded_hal_02::Pwm for Pwm<$TIMERX, PINS> where PINS: Pins<$TIMERX>, @@ -575,44 +655,34 @@ macro_rules! hal { type Time = Hertz; fn disable(&mut self, channel: Self::Channel) { - assert!(self.pins.uses_channel(channel)); - self.timer.disable_channel(channel, self.pins.uses_complementary_channel(channel)); + self.disable(channel); } fn enable(&mut self, channel: Self::Channel) { - assert!(self.pins.uses_channel(channel)); - self.timer.enable_channel(channel, self.pins.uses_complementary_channel(channel)); + self.enable(channel); } fn get_duty(&self, channel: Self::Channel) -> Self::Duty { - assert!(self.pins.uses_channel(channel)); - self.timer.get_duty(channel) + self.duty_cycle(channel) } fn set_duty(&mut self, channel: Self::Channel, duty: Self::Duty) { - assert!(self.pins.uses_channel(channel)); - self.timer.set_duty(channel, duty); + self.set_duty_cycle(channel, duty); } fn get_max_duty(&self) -> Self::Duty { - self.timer.get_max_duty() + self.max_duty_cycle() } fn get_period(&self) -> Self::Time { - let presaler: u32 = self.timer.psc.read().psc().bits().into(); - let auto_reload_value: u32 = self.timer.car.read().car().bits().into(); - - // Length in ms of an internal clock pulse - (self.clock.0 / (presaler * auto_reload_value)).hz() + self.period() } fn set_period(&mut self, period: T) where T: Into, { - self.timer - .configure_prescaler_reload(period.into(), self.clock); - self.timer.reset_counter(); + self.set_period(period); } } }; diff --git a/src/serial.rs b/src/serial.rs index 5af0b36..b8a0e37 100644 --- a/src/serial.rs +++ b/src/serial.rs @@ -376,6 +376,7 @@ impl, TXPIN: TxPin, RXPIN> W } } +#[cfg(feature = "embedded-hal-02")] impl, TXPIN: TxPin, RXPIN> embedded_hal_02::serial::Write for Serial { @@ -411,6 +412,7 @@ impl> WriteReady for Tx { } } +#[cfg(feature = "embedded-hal-02")] impl> embedded_hal_02::serial::Write for Tx { @@ -476,6 +478,7 @@ impl> ReadReady for Rx { } } +#[cfg(feature = "embedded-hal-02")] impl, TXPIN, RXPIN: RxPin> embedded_hal_02::serial::Read for Serial { @@ -486,6 +489,7 @@ impl, TXPIN, RXPIN: RxPin> } } +#[cfg(feature = "embedded-hal-02")] impl> embedded_hal_02::serial::Read for Rx { type Error = Error; diff --git a/src/timer.rs b/src/timer.rs index 3c557a4..7a76d6f 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -11,8 +11,6 @@ use crate::time::Hertz; use cast::{u16, u32, u64}; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; -use embedded_hal_02::timer::{Cancel, CountDown, Periodic}; -use void::Void; /// Interrupt events #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -133,12 +131,9 @@ impl CountDownTimer { pub fn release(self) -> SYST { self.stop().release() } -} - -impl CountDown for CountDownTimer { - type Time = Hertz; - fn start(&mut self, timeout: T) + /// Configures the timer to have the given timeout and enables it to start counting down. + pub fn start(&mut self, timeout: T) where T: Into, { @@ -151,8 +146,35 @@ impl CountDown for CountDownTimer { self.timer.enable_counter(); } - fn wait(&mut self) -> nb::Result<(), Void> { - if self.timer.has_wrapped() { + /// Returns whether the timer has finished counting down yet, and resets the flag if so. + pub fn has_elapsed(&mut self) -> bool { + self.timer.has_wrapped() + } + + /// Disables the timer. + pub fn cancel(&mut self) -> Result<(), Error> { + if !self.timer.is_counter_enabled() { + return Err(Error::Canceled); + } + + self.timer.disable_counter(); + Ok(()) + } +} + +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::timer::CountDown for CountDownTimer { + type Time = Hertz; + + fn start(&mut self, timeout: T) + where + T: Into, + { + self.start(timeout); + } + + fn wait(&mut self) -> nb::Result<(), void::Void> { + if self.has_elapsed() { Ok(()) } else { Err(nb::Error::WouldBlock) @@ -160,20 +182,17 @@ impl CountDown for CountDownTimer { } } -impl Cancel for CountDownTimer { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::timer::Cancel for CountDownTimer { type Error = Error; fn cancel(&mut self) -> Result<(), Self::Error> { - if !self.timer.is_counter_enabled() { - return Err(Self::Error::Canceled); - } - - self.timer.disable_counter(); - Ok(()) + self.cancel() } } -impl Periodic for CountDownTimer {} +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::timer::Periodic for CountDownTimer {} /// Helper methods used by other parts of the HAL, such as PWM. pub(crate) trait TimerExt { @@ -312,6 +331,34 @@ macro_rules! hal { pub fn reset(&mut self) { self.timer.reset_counter(); } + + /// Configures the timer to have the given timeout and enables it to start counting down. + pub fn start(&mut self, timeout: T) + where + T: Into, + { + // Pause counter. + self.timer.ctl0.modify(|_, w| w.cen().disabled()); + + self.timer.configure_prescaler_reload(timeout.into(), self.clock); + // Trigger an update event to load the prescaler value to the clock + self.timer.reset_counter(); + + // Start counter. + self.timer.ctl0.modify(|_, w| w.cen().enabled()); + } + + /// Disables the timer. + pub fn cancel(&mut self) -> Result<(), Error> { + let is_counter_enabled = self.timer.ctl0.read().cen().is_enabled(); + if !is_counter_enabled { + return Err(Error::Canceled); + } + + // Pause counter. + self.timer.ctl0.modify(|_, w| w.cen().disabled()); + Ok(()) + } } impl TimerExt for $TIMERX { @@ -332,25 +379,18 @@ macro_rules! hal { } } - impl CountDown for CountDownTimer<$TIMERX> { + #[cfg(feature = "embedded-hal-02")] + impl embedded_hal_02::timer::CountDown for CountDownTimer<$TIMERX> { type Time = Hertz; fn start(&mut self, timeout: T) where T: Into, { - // Pause counter. - self.timer.ctl0.modify(|_, w| w.cen().disabled()); - - self.timer.configure_prescaler_reload(timeout.into(), self.clock); - // Trigger an update event to load the prescaler value to the clock - self.timer.reset_counter(); - - // Start counter. - self.timer.ctl0.modify(|_, w| w.cen().enabled()); + self.start(timeout); } - fn wait(&mut self) -> nb::Result<(), Void> { + fn wait(&mut self) -> nb::Result<(), void::Void> { if !self.is_pending(Event::Update) { Err(nb::Error::WouldBlock) } else { @@ -360,22 +400,17 @@ macro_rules! hal { } } - impl Cancel for CountDownTimer<$TIMERX> { + #[cfg(feature = "embedded-hal-02")] + impl embedded_hal_02::timer::Cancel for CountDownTimer<$TIMERX> { type Error = Error; fn cancel(&mut self) -> Result<(), Self::Error> { - let is_counter_enabled = self.timer.ctl0.read().cen().is_enabled(); - if !is_counter_enabled { - return Err(Self::Error::Canceled); - } - - // Pause counter. - self.timer.ctl0.modify(|_, w| w.cen().disabled()); - Ok(()) + self.cancel() } } - impl Periodic for CountDownTimer<$TIMERX> {} + #[cfg(feature = "embedded-hal-02")] + impl embedded_hal_02::timer::Periodic for CountDownTimer<$TIMERX> {} }; } diff --git a/src/watchdog.rs b/src/watchdog.rs index abf2ff6..945d6e8 100644 --- a/src/watchdog.rs +++ b/src/watchdog.rs @@ -8,7 +8,6 @@ use crate::{ pac::{DBG, FWDGT}, time::MilliSeconds, }; -use embedded_hal_02::watchdog::{Watchdog, WatchdogEnable}; /// Wraps the Free Watchdog (FWDGT) peripheral pub struct FreeWatchdog { @@ -88,20 +87,35 @@ impl FreeWatchdog { self.fwdgt.ctl.write(|w| w.cmd().reset()); a } + + /// Configures the watchdog to use the given period and enables it. + pub fn start>(&mut self, period: T) { + self.setup(period.into().0); + + self.fwdgt.ctl.write(|w| w.cmd().start()); + } + + /// Resets the watchdog. + /// + /// This must be done periodically once the watchdog is started to prevent the processor being + /// reset. + pub fn feed(&mut self) { + self.fwdgt.ctl.write(|w| w.cmd().reset()); + } } -impl WatchdogEnable for FreeWatchdog { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::watchdog::WatchdogEnable for FreeWatchdog { type Time = MilliSeconds; fn start>(&mut self, period: T) { - self.setup(period.into().0); - - self.fwdgt.ctl.write(|w| w.cmd().start()); + self.start(period); } } -impl Watchdog for FreeWatchdog { +#[cfg(feature = "embedded-hal-02")] +impl embedded_hal_02::watchdog::Watchdog for FreeWatchdog { fn feed(&mut self) { - self.fwdgt.ctl.write(|w| w.cmd().reset()); + self.feed(); } }