#![feature(prelude_import)] #![no_std] #![allow(non_camel_case_types)] #![allow(clippy::uninit_assumed_init)] #[prelude_import] use core::prelude::rust_2018::*; #[macro_use] extern crate core; #[macro_use] extern crate compiler_builtins; pub use stm32f0; #[cfg(any(feature = "stm32f030", feature = "stm32f070"))] pub use stm32f0::stm32f0x0 as pac; #[cfg(feature = "device-selected")] pub mod adc { //! # API for the Analog to Digital converter //! //! Currently implements oneshot conversion with variable sampling times. //! Also references for the internal temperature sense, voltage //! reference and battery sense are provided. //! //! ## Example //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::pac; //! use crate::hal::prelude::*; //! use crate::hal::adc::Adc; //! //! cortex_m::interrupt::free(|cs| { //! let mut p = pac::Peripherals::take().unwrap(); //! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH); //! //! let gpioa = p.GPIOA.split(&mut rcc); //! //! let mut led = gpioa.pa1.into_push_pull_pull_output(cs); //! let mut an_in = gpioa.pa0.into_analog(cs); //! //! let mut delay = Delay::new(cp.SYST, &rcc); //! //! let mut adc = Adc::new(p.ADC, &mut rcc); //! //! loop { //! let val: u16 = adc.read(&mut an_in).unwrap(); //! if val < ((1 << 8) - 1) { //! led.set_low(); //! } else { //! led.set_high(); //! } //! delay.delay_ms(50_u16); //! } //! }); //! ``` const VREFCAL: *const u16 = 0x1FFF_F7BA as *const u16; const VTEMPCAL30: *const u16 = 0x1FFF_F7B8 as *const u16; const VTEMPCAL110: *const u16 = 0x1FFF_F7C2 as *const u16; const VDD_CALIB: u16 = 3300; use core::ptr; use embedded_hal::{ adc::{Channel, OneShot}, blocking::delay::DelayUs, }; use crate::{ delay::Delay, gpio::*, pac::{ adc::{ cfgr1::{ALIGN_A, RES_A}, smpr::SMP_A, }, ADC, }, rcc::Rcc, }; /// Analog to Digital converter interface pub struct Adc { rb: ADC, sample_time: AdcSampleTime, align: AdcAlign, precision: AdcPrecision, } /// ADC Sampling time /// /// Options for the sampling time, each is T + 0.5 ADC clock cycles. pub enum AdcSampleTime { /// 1.5 cycles sampling time T_1, /// 7.5 cycles sampling time T_7, /// 13.5 cycles sampling time T_13, /// 28.5 cycles sampling time T_28, /// 41.5 cycles sampling time T_41, /// 55.5 cycles sampling time T_55, /// 71.5 cycles sampling time T_71, /// 239.5 cycles sampling time T_239, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for AdcSampleTime { #[inline] fn clone(&self) -> AdcSampleTime { { *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for AdcSampleTime {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for AdcSampleTime { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&AdcSampleTime::T_1,) => ::core::fmt::Formatter::write_str(f, "T_1"), (&AdcSampleTime::T_7,) => ::core::fmt::Formatter::write_str(f, "T_7"), (&AdcSampleTime::T_13,) => ::core::fmt::Formatter::write_str(f, "T_13"), (&AdcSampleTime::T_28,) => ::core::fmt::Formatter::write_str(f, "T_28"), (&AdcSampleTime::T_41,) => ::core::fmt::Formatter::write_str(f, "T_41"), (&AdcSampleTime::T_55,) => ::core::fmt::Formatter::write_str(f, "T_55"), (&AdcSampleTime::T_71,) => ::core::fmt::Formatter::write_str(f, "T_71"), (&AdcSampleTime::T_239,) => ::core::fmt::Formatter::write_str(f, "T_239"), } } } impl ::core::marker::StructuralPartialEq for AdcSampleTime {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for AdcSampleTime { #[inline] fn eq(&self, other: &AdcSampleTime) -> bool { { let __self_vi = ::core::intrinsics::discriminant_value(&*self); let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other); if true && __self_vi == __arg_1_vi { match (&*self, &*other) { _ => true, } } else { false } } } } impl AdcSampleTime { /// Get the default sample time (currently 239.5 cycles) pub fn default() -> Self { AdcSampleTime::T_239 } } impl From for SMP_A { fn from(val: AdcSampleTime) -> Self { match val { AdcSampleTime::T_1 => SMP_A::CYCLES1_5, AdcSampleTime::T_7 => SMP_A::CYCLES7_5, AdcSampleTime::T_13 => SMP_A::CYCLES13_5, AdcSampleTime::T_28 => SMP_A::CYCLES28_5, AdcSampleTime::T_41 => SMP_A::CYCLES41_5, AdcSampleTime::T_55 => SMP_A::CYCLES55_5, AdcSampleTime::T_71 => SMP_A::CYCLES71_5, AdcSampleTime::T_239 => SMP_A::CYCLES239_5, } } } /// ADC Result Alignment pub enum AdcAlign { /// Left aligned results (most significant bits) /// /// Results in all precisions returning a value in the range 0-65535. /// Depending on the precision the result will step by larger or smaller /// amounts. Left, /// Right aligned results (least significant bits) /// /// Results in all precisions returning values from 0-(2^bits-1) in /// steps of 1. Right, /// Left aligned results without correction of 6bit values. /// /// Returns left aligned results exactly as shown in RM0091 Fig.37. /// Where the values are left aligned within the u16, with the exception /// of 6 bit mode where the value is left aligned within the first byte of /// the u16. LeftAsRM, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for AdcAlign { #[inline] fn clone(&self) -> AdcAlign { { *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for AdcAlign {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for AdcAlign { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&AdcAlign::Left,) => ::core::fmt::Formatter::write_str(f, "Left"), (&AdcAlign::Right,) => ::core::fmt::Formatter::write_str(f, "Right"), (&AdcAlign::LeftAsRM,) => ::core::fmt::Formatter::write_str(f, "LeftAsRM"), } } } impl ::core::marker::StructuralPartialEq for AdcAlign {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for AdcAlign { #[inline] fn eq(&self, other: &AdcAlign) -> bool { { let __self_vi = ::core::intrinsics::discriminant_value(&*self); let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other); if true && __self_vi == __arg_1_vi { match (&*self, &*other) { _ => true, } } else { false } } } } impl AdcAlign { /// Get the default alignment (currently right aligned) pub fn default() -> Self { AdcAlign::Right } } impl From for ALIGN_A { fn from(val: AdcAlign) -> Self { match val { AdcAlign::Left => ALIGN_A::LEFT, AdcAlign::Right => ALIGN_A::RIGHT, AdcAlign::LeftAsRM => ALIGN_A::LEFT, } } } /// ADC Sampling Precision pub enum AdcPrecision { /// 12 bit precision B_12, /// 10 bit precision B_10, /// 8 bit precision B_8, /// 6 bit precision B_6, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for AdcPrecision { #[inline] fn clone(&self) -> AdcPrecision { { *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for AdcPrecision {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for AdcPrecision { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&AdcPrecision::B_12,) => ::core::fmt::Formatter::write_str(f, "B_12"), (&AdcPrecision::B_10,) => ::core::fmt::Formatter::write_str(f, "B_10"), (&AdcPrecision::B_8,) => ::core::fmt::Formatter::write_str(f, "B_8"), (&AdcPrecision::B_6,) => ::core::fmt::Formatter::write_str(f, "B_6"), } } } impl ::core::marker::StructuralPartialEq for AdcPrecision {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for AdcPrecision { #[inline] fn eq(&self, other: &AdcPrecision) -> bool { { let __self_vi = ::core::intrinsics::discriminant_value(&*self); let __arg_1_vi = ::core::intrinsics::discriminant_value(&*other); if true && __self_vi == __arg_1_vi { match (&*self, &*other) { _ => true, } } else { false } } } } impl AdcPrecision { /// Get the default precision (currently 12 bit precision) pub fn default() -> Self { AdcPrecision::B_12 } } impl From for RES_A { fn from(val: AdcPrecision) -> Self { match val { AdcPrecision::B_12 => RES_A::TWELVEBIT, AdcPrecision::B_10 => RES_A::TENBIT, AdcPrecision::B_8 => RES_A::EIGHTBIT, AdcPrecision::B_6 => RES_A::SIXBIT, } } } impl Channel for gpioa::PA0 { type ID = u8; fn channel() -> u8 { 0_u8 } } impl Channel for gpioa::PA1 { type ID = u8; fn channel() -> u8 { 1_u8 } } impl Channel for gpioa::PA2 { type ID = u8; fn channel() -> u8 { 2_u8 } } impl Channel for gpioa::PA3 { type ID = u8; fn channel() -> u8 { 3_u8 } } impl Channel for gpioa::PA4 { type ID = u8; fn channel() -> u8 { 4_u8 } } impl Channel for gpioa::PA5 { type ID = u8; fn channel() -> u8 { 5_u8 } } impl Channel for gpioa::PA6 { type ID = u8; fn channel() -> u8 { 6_u8 } } impl Channel for gpioa::PA7 { type ID = u8; fn channel() -> u8 { 7_u8 } } impl Channel for gpiob::PB0 { type ID = u8; fn channel() -> u8 { 8_u8 } } impl Channel for gpiob::PB1 { type ID = u8; fn channel() -> u8 { 9_u8 } } impl Channel for gpioc::PC0 { type ID = u8; fn channel() -> u8 { 10_u8 } } impl Channel for gpioc::PC1 { type ID = u8; fn channel() -> u8 { 11_u8 } } impl Channel for gpioc::PC2 { type ID = u8; fn channel() -> u8 { 12_u8 } } impl Channel for gpioc::PC3 { type ID = u8; fn channel() -> u8 { 13_u8 } } impl Channel for gpioc::PC4 { type ID = u8; fn channel() -> u8 { 14_u8 } } impl Channel for gpioc::PC5 { type ID = u8; fn channel() -> u8 { 15_u8 } } /// Internal temperature sensor (ADC Channel 16) pub struct VTemp; #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for VTemp { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self { VTemp => ::core::fmt::Formatter::write_str(f, "VTemp"), } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::default::Default for VTemp { #[inline] fn default() -> VTemp { VTemp {} } } /// Internal voltage reference (ADC Channel 17) pub struct VRef; #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for VRef { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self { VRef => ::core::fmt::Formatter::write_str(f, "VRef"), } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::default::Default for VRef { #[inline] fn default() -> VRef { VRef {} } } impl Channel for VTemp { type ID = u8; fn channel() -> u8 { 16_u8 } } impl Channel for VRef { type ID = u8; fn channel() -> u8 { 17_u8 } } impl VTemp { /// Init a new VTemp pub fn new() -> Self { VTemp::default() } /// Enable the internal temperature sense, this has a wake up time /// tSTART which can be found in your micro's datasheet, you /// must wait at least that long after enabling before taking a reading. /// Remember to disable when not in use. pub fn enable(&mut self, adc: &mut Adc) { adc.rb.ccr.modify(|_, w| w.tsen().set_bit()); } /// Disable the internal temperature sense. pub fn disable(&mut self, adc: &mut Adc) { adc.rb.ccr.modify(|_, w| w.tsen().clear_bit()); } /// Checks if the temperature sensor is enabled, does not account for the /// tSTART time however. pub fn is_enabled(&self, adc: &Adc) -> bool { adc.rb.ccr.read().tsen().bit_is_set() } fn convert_temp(vtemp: u16, vdda: u16) -> i16 { let vtemp30_cal = i32::from(unsafe { ptr::read(VTEMPCAL30) }) * 100; let vtemp110_cal = i32::from(unsafe { ptr::read(VTEMPCAL110) }) * 100; let mut temperature = i32::from(vtemp) * 100; temperature = (temperature * (i32::from(vdda) / i32::from(VDD_CALIB))) - vtemp30_cal; temperature *= (110 - 30) * 100; temperature /= vtemp110_cal - vtemp30_cal; temperature += 3000; temperature as i16 } /// Read the value of the internal temperature sensor and return the /// result in 100ths of a degree centigrade. /// /// Given a delay reference it will attempt to restrict to the /// minimum delay needed to ensure a 10 us tSTART value. /// Otherwise it will approximate the required delay using ADC reads. pub fn read(adc: &mut Adc, delay: Option<&mut Delay>) -> i16 { let mut vtemp = Self::new(); let vtemp_preenable = vtemp.is_enabled(adc); if !vtemp_preenable { vtemp.enable(adc); if let Some(dref) = delay { dref.delay_us(2_u16); } else { VRef::read_vdda(adc); } } let vdda = VRef::read_vdda(adc); let prev_cfg = adc.default_cfg(); let vtemp_val = adc.read(&mut vtemp).unwrap(); if !vtemp_preenable { vtemp.disable(adc); } adc.restore_cfg(prev_cfg); Self::convert_temp(vtemp_val, vdda) } } impl VRef { /// Init a new VRef pub fn new() -> Self { VRef::default() } /// Enable the internal voltage reference, remember to disable when not in use. pub fn enable(&mut self, adc: &mut Adc) { adc.rb.ccr.modify(|_, w| w.vrefen().set_bit()); } /// Disable the internal reference voltage. pub fn disable(&mut self, adc: &mut Adc) { adc.rb.ccr.modify(|_, w| w.vrefen().clear_bit()); } /// Returns if the internal voltage reference is enabled. pub fn is_enabled(&self, adc: &Adc) -> bool { adc.rb.ccr.read().vrefen().bit_is_set() } /// Reads the value of VDDA in milli-volts pub fn read_vdda(adc: &mut Adc) -> u16 { let vrefint_cal = u32::from(unsafe { ptr::read(VREFCAL) }); let mut vref = Self::new(); let prev_cfg = adc.default_cfg(); let vref_val: u32 = if vref.is_enabled(adc) { adc.read(&mut vref).unwrap() } else { vref.enable(adc); let ret = adc.read(&mut vref).unwrap(); vref.disable(adc); ret }; adc.restore_cfg(prev_cfg); (u32::from(VDD_CALIB) * vrefint_cal / vref_val) as u16 } } /// A stored ADC config, can be restored by using the `Adc::restore_cfg` method pub struct StoredConfig(AdcSampleTime, AdcAlign, AdcPrecision); #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for StoredConfig {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for StoredConfig { #[inline] fn clone(&self) -> StoredConfig { { let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for StoredConfig { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match *self { StoredConfig(ref __self_0_0, ref __self_0_1, ref __self_0_2) => { let debug_trait_builder = &mut ::core::fmt::Formatter::debug_tuple(f, "StoredConfig"); let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0_0)); let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0_1)); let _ = ::core::fmt::DebugTuple::field(debug_trait_builder, &&(*__self_0_2)); ::core::fmt::DebugTuple::finish(debug_trait_builder) } } } } impl ::core::marker::StructuralPartialEq for StoredConfig {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for StoredConfig { #[inline] fn eq(&self, other: &StoredConfig) -> bool { match *other { StoredConfig(ref __self_1_0, ref __self_1_1, ref __self_1_2) => match *self { StoredConfig(ref __self_0_0, ref __self_0_1, ref __self_0_2) => { (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1) && (*__self_0_2) == (*__self_1_2) } }, } } #[inline] fn ne(&self, other: &StoredConfig) -> bool { match *other { StoredConfig(ref __self_1_0, ref __self_1_1, ref __self_1_2) => match *self { StoredConfig(ref __self_0_0, ref __self_0_1, ref __self_0_2) => { (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1) || (*__self_0_2) != (*__self_1_2) } }, } } } impl Adc { /// Init a new Adc /// /// Sets all configurable parameters to defaults, enables the HSI14 clock /// for the ADC if it is not already enabled and performs a boot time /// calibration. As such this method may take an appreciable time to run. pub fn new(adc: ADC, rcc: &mut Rcc) -> Self { let mut s = Self { rb: adc, sample_time: AdcSampleTime::default(), align: AdcAlign::default(), precision: AdcPrecision::default(), }; s.select_clock(rcc); s.calibrate(); s } /// Saves a copy of the current ADC config pub fn save_cfg(&mut self) -> StoredConfig { StoredConfig(self.sample_time, self.align, self.precision) } /// Restores a stored config pub fn restore_cfg(&mut self, cfg: StoredConfig) { self.sample_time = cfg.0; self.align = cfg.1; self.precision = cfg.2; } /// Resets the ADC config to default, returning the existing config as /// a stored config. pub fn default_cfg(&mut self) -> StoredConfig { let cfg = self.save_cfg(); self.sample_time = AdcSampleTime::default(); self.align = AdcAlign::default(); self.precision = AdcPrecision::default(); cfg } /// Set the Adc sampling time /// /// Options can be found in [AdcSampleTime](crate::adc::AdcSampleTime). pub fn set_sample_time(&mut self, t_samp: AdcSampleTime) { self.sample_time = t_samp; } /// Set the Adc result alignment /// /// Options can be found in [AdcAlign](crate::adc::AdcAlign). pub fn set_align(&mut self, align: AdcAlign) { self.align = align; } /// Set the Adc precision /// /// Options can be found in [AdcPrecision](crate::adc::AdcPrecision). pub fn set_precision(&mut self, precision: AdcPrecision) { self.precision = precision; } /// Returns the largest possible sample value for the current settings pub fn max_sample(&self) -> u16 { match self.align { AdcAlign::Left => u16::max_value(), AdcAlign::LeftAsRM => match self.precision { AdcPrecision::B_6 => u16::from(u8::max_value()), _ => u16::max_value(), }, AdcAlign::Right => match self.precision { AdcPrecision::B_12 => (1 << 12) - 1, AdcPrecision::B_10 => (1 << 10) - 1, AdcPrecision::B_8 => (1 << 8) - 1, AdcPrecision::B_6 => (1 << 6) - 1, }, } } /// Read the value of a channel and converts the result to milli-volts pub fn read_abs_mv>(&mut self, pin: &mut PIN) -> u16 { let vdda = u32::from(VRef::read_vdda(self)); let v: u32 = self.read(pin).unwrap(); let max_samp = u32::from(self.max_sample()); (v * vdda / max_samp) as u16 } fn calibrate(&mut self) { if self.rb.cr.read().aden().is_enabled() { self.rb.cr.modify(|_, w| w.addis().disable()); } while self.rb.cr.read().aden().is_enabled() {} self.rb.cfgr1.modify(|_, w| w.dmaen().disabled()); self.rb.cr.modify(|_, w| w.adcal().start_calibration()); while self.rb.cr.read().adcal().is_calibrating() {} } fn select_clock(&mut self, rcc: &mut Rcc) { rcc.regs.apb2enr.modify(|_, w| w.adcen().enabled()); rcc.regs.cr2.modify(|_, w| w.hsi14on().on()); while rcc.regs.cr2.read().hsi14rdy().is_not_ready() {} } fn power_up(&mut self) { if self.rb.isr.read().adrdy().is_ready() { self.rb.isr.modify(|_, w| w.adrdy().clear()); } self.rb.cr.modify(|_, w| w.aden().enabled()); while self.rb.isr.read().adrdy().is_not_ready() {} } fn power_down(&mut self) { self.rb.cr.modify(|_, w| w.adstp().stop_conversion()); while self.rb.cr.read().adstp().is_stopping() {} self.rb.cr.modify(|_, w| w.addis().disable()); while self.rb.cr.read().aden().is_enabled() {} } fn convert(&mut self, chan: u8) -> u16 { self.rb.chselr.write(|w| unsafe { w.bits(1_u32 << chan) }); self.rb .smpr .write(|w| w.smp().variant(self.sample_time.into())); self.rb.cfgr1.modify(|_, w| { w.res() .variant(self.precision.into()) .align() .variant(self.align.into()) }); self.rb.cr.modify(|_, w| w.adstart().start_conversion()); while self.rb.isr.read().eoc().is_not_complete() {} let res = self.rb.dr.read().bits() as u16; if self.align == AdcAlign::Left && self.precision == AdcPrecision::B_6 { res << 8 } else { res } } } impl OneShot for Adc where WORD: From, PIN: Channel, { type Error = (); fn read(&mut self, _pin: &mut PIN) -> nb::Result { self.power_up(); let res = self.convert(PIN::channel()); self.power_down(); Ok(res.into()) } } } #[cfg(feature = "device-selected")] pub mod delay { //! API for delays with the systick timer //! //! Please be aware of potential overflows when using `delay_us`. //! E.g. at 48MHz the maximum delay is 89 seconds. //! //! Consider using the timers api as a more flexible interface //! //! # Example //! //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::pac; //! use crate::hal::prelude::*; //! use crate::hal::delay::Delay; //! use cortex_m::peripheral::Peripherals; //! //! let mut p = pac::Peripherals::take().unwrap(); //! let mut cp = cortex_m::Peripherals::take().unwrap(); //! //! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH); //! let mut delay = Delay::new(cp.SYST, &rcc); //! loop { //! delay.delay_ms(1_000_u16); //! } //! ``` use cast::{u16, u32}; use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use crate::rcc::Rcc; use embedded_hal::blocking::delay::{DelayMs, DelayUs}; /// System timer (SysTick) as a delay provider pub struct Delay { scale: u32, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for Delay { #[inline] fn clone(&self) -> Delay { match *self { Delay { scale: ref __self_0_0, } => Delay { scale: ::core::clone::Clone::clone(&(*__self_0_0)), }, } } } const SYSTICK_RANGE: u32 = 0x0100_0000; impl Delay { /// Configures the system timer (SysTick) as a delay provider pub fn new(mut syst: SYST, rcc: &Rcc) -> Delay { syst.set_clock_source(SystClkSource::Core); syst.set_reload(SYSTICK_RANGE - 1); syst.clear_current(); syst.enable_counter(); if !(rcc.clocks.hclk().0 >= 1_000_000) { ::core::panicking::panic("assertion failed: rcc.clocks.hclk().0 >= 1_000_000") }; let scale = rcc.clocks.hclk().0 / 1_000_000; Delay { scale } } } impl DelayMs for Delay { fn delay_ms(&mut self, mut ms: u32) { const MAX_MS: u32 = 0x0000_FFFF; while ms != 0 { let current_ms = if ms <= MAX_MS { ms } else { MAX_MS }; self.delay_us(current_ms * 1_000); ms -= current_ms; } } } impl DelayMs for Delay { fn delay_ms(&mut self, ms: u16) { self.delay_us(u32(ms) * 1_000); } } impl DelayMs for Delay { fn delay_ms(&mut self, ms: u8) { self.delay_ms(u16(ms)); } } impl DelayUs for Delay { fn delay_us(&mut self, us: u32) { const MAX_TICKS: u32 = 0x007F_FFFF; let mut total_ticks = us * self.scale; while total_ticks != 0 { let current_ticks = if total_ticks <= MAX_TICKS { total_ticks } else { MAX_TICKS }; let start_count = SYST::get_current(); total_ticks -= current_ticks; while (start_count.wrapping_sub(SYST::get_current()) % SYSTICK_RANGE) < current_ticks {} } } } impl DelayUs for Delay { fn delay_us(&mut self, us: u16) { self.delay_us(u32(us)) } } impl DelayUs for Delay { fn delay_us(&mut self, us: u8) { self.delay_us(u32(us)) } } } #[cfg(feature = "device-selected")] pub mod i2c { use core::ops::Deref; use embedded_hal::blocking::i2c::{Read, Write, WriteRead}; use crate::{ gpio::*, rcc::Rcc, time::{KiloHertz, U32Ext}, }; /// I2C abstraction pub struct I2c { i2c: I2C, pins: (SCLPIN, SDAPIN), } pub trait SclPin {} pub trait SdaPin {} impl SclPin for gpiob::PB6> {} impl SclPin for gpiob::PB8> {} impl SdaPin for gpiob::PB7> {} impl SdaPin for gpiob::PB9> {} pub enum Error { OVERRUN, NACK, BUS, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for Error { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&Error::OVERRUN,) => ::core::fmt::Formatter::write_str(f, "OVERRUN"), (&Error::NACK,) => ::core::fmt::Formatter::write_str(f, "NACK"), (&Error::BUS,) => ::core::fmt::Formatter::write_str(f, "BUS"), } } } use crate::pac::I2C1; impl I2c { pub fn i2c1(i2c: I2C1, pins: (SCLPIN, SDAPIN), speed: KiloHertz, rcc: &mut Rcc) -> Self where SCLPIN: SclPin, SDAPIN: SdaPin, { rcc.regs.apb1enr.modify(|_, w| w.i2c1en().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.i2c1rst().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.i2c1rst().clear_bit()); I2c { i2c, pins }.i2c_init(speed) } } #[allow(dead_code)] type I2cRegisterBlock = crate::pac::i2c1::RegisterBlock; impl I2c where I2C: Deref, { fn i2c_init(self, speed: KiloHertz) -> Self { use core::cmp; self.i2c.cr1.modify(|_, w| w.pe().clear_bit()); let presc; let scldel; let sdadel; let sclh; let scll; const FREQ: u32 = 8_000_000; if speed <= 100_u32.khz() { presc = 1; scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8; sclh = scll - 4; sdadel = 2; scldel = 4; } else { presc = 0; scll = cmp::max((((FREQ >> presc) >> 1) / speed.0) - 1, 255) as u8; sclh = scll - 6; sdadel = 1; scldel = 3; } self.i2c.timingr.write(|w| { w.presc() .bits(presc) .scldel() .bits(scldel) .sdadel() .bits(sdadel) .sclh() .bits(sclh) .scll() .bits(scll) }); self.i2c.cr1.modify(|_, w| w.pe().set_bit()); self } pub fn release(self) -> (I2C, (SCLPIN, SDAPIN)) { (self.i2c, self.pins) } fn check_and_clear_error_flags( &self, isr: &crate::stm32::i2c1::isr::R, ) -> Result<(), Error> { if isr.ovr().bit_is_set() { self.i2c.icr.write(|w| w.ovrcf().set_bit()); return Err(Error::OVERRUN); } if isr.arlo().bit_is_set() | isr.berr().bit_is_set() { self.i2c .icr .write(|w| w.arlocf().set_bit().berrcf().set_bit()); return Err(Error::BUS); } if isr.nackf().bit_is_set() { self.i2c .icr .write(|w| w.stopcf().set_bit().nackcf().set_bit()); return Err(Error::NACK); } Ok(()) } fn send_byte(&self, byte: u8) -> Result<(), Error> { loop { let isr = self.i2c.isr.read(); self.check_and_clear_error_flags(&isr)?; if isr.txis().bit_is_set() { break; } } self.i2c.txdr.write(|w| unsafe { w.bits(u32::from(byte)) }); self.check_and_clear_error_flags(&self.i2c.isr.read())?; Ok(()) } fn recv_byte(&self) -> Result { loop { let isr = self.i2c.isr.read(); self.check_and_clear_error_flags(&isr)?; if isr.rxne().bit_is_set() { break; } } let value = self.i2c.rxdr.read().bits() as u8; Ok(value) } } impl WriteRead for I2c where I2C: Deref, { type Error = Error; fn write_read(&mut self, addr: u8, bytes: &[u8], buffer: &mut [u8]) -> Result<(), Error> { self.i2c.cr2.modify(|_, w| { w.sadd() .bits(u16::from(addr) << 1) .nbytes() .bits(bytes.len() as u8) .rd_wrn() .clear_bit() .autoend() .clear_bit() }); self.i2c.cr2.modify(|_, w| w.start().set_bit()); loop { let isr = self.i2c.isr.read(); self.check_and_clear_error_flags(&isr)?; if isr.txis().bit_is_set() || isr.tc().bit_is_set() { break; } } for c in bytes { self.send_byte(*c)?; } loop { let isr = self.i2c.isr.read(); self.check_and_clear_error_flags(&isr)?; if isr.tc().bit_is_set() { break; } } self.i2c.cr2.modify(|_, w| { w.sadd() .bits(u16::from(addr) << 1) .nbytes() .bits(buffer.len() as u8) .rd_wrn() .set_bit() }); self.i2c.cr2.modify(|_, w| w.start().set_bit()); self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); for c in buffer.iter_mut() { *c = self.recv_byte()?; } self.check_and_clear_error_flags(&self.i2c.isr.read())?; Ok(()) } } impl Read for I2c where I2C: Deref, { type Error = Error; fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Error> { self.i2c.cr2.modify(|_, w| { w.sadd() .bits(u16::from(addr) << 1) .nbytes() .bits(buffer.len() as u8) .rd_wrn() .set_bit() }); self.i2c.cr2.modify(|_, w| w.start().set_bit()); self.i2c.cr2.modify(|_, w| w.autoend().set_bit()); for c in buffer.iter_mut() { *c = self.recv_byte()?; } self.check_and_clear_error_flags(&self.i2c.isr.read())?; Ok(()) } } impl Write for I2c where I2C: Deref, { type Error = Error; fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> { self.i2c.cr2.modify(|_, w| { w.sadd() .bits(u16::from(addr) << 1) .nbytes() .bits(bytes.len() as u8) .rd_wrn() .clear_bit() .autoend() .set_bit() }); self.i2c.cr2.modify(|_, w| w.start().set_bit()); for c in bytes { self.send_byte(*c)?; } self.check_and_clear_error_flags(&self.i2c.isr.read())?; Ok(()) } } } #[cfg(feature = "device-selected")] pub mod prelude { pub use embedded_hal::prelude::*; pub use embedded_hal::watchdog::Watchdog as _stm32f0xx_hal_embedded_hal_watchdog_Watchdog; pub use embedded_hal::watchdog::WatchdogEnable as _stm32f0xx_hal_embedded_hal_watchdog_WatchdogEnable; pub use embedded_hal::adc::OneShot as _embedded_hal_adc_OneShot; pub use embedded_hal::digital::v2::InputPin as _embedded_hal_gpio_InputPin; pub use embedded_hal::digital::v2::OutputPin as _embedded_hal_gpio_OutputPin; pub use embedded_hal::digital::v2::StatefulOutputPin as _embedded_hal_gpio_StatefulOutputPin; pub use embedded_hal::digital::v2::ToggleableOutputPin as _embedded_hal_gpio_ToggleableOutputPin; pub use crate::gpio::GpioExt as _stm32f0xx_hal_gpio_GpioExt; pub use crate::rcc::RccExt as _stm32f0xx_hal_rcc_RccExt; pub use crate::time::U32Ext as _stm32f0xx_hal_time_U32Ext; } #[cfg(feature = "device-selected")] pub mod pwm { use cast::{u16, u32}; use core::{marker::PhantomData, mem::MaybeUninit}; use crate::rcc::Rcc; use crate::time::Hertz; use embedded_hal as hal; pub trait Pins { const C1: bool = false; const C2: bool = false; const C3: bool = false; const C4: bool = false; type Channels; } use crate::timers::PinC1; use crate::timers::PinC2; use crate::timers::PinC3; use crate::timers::PinC4; pub struct C1; pub struct C2; pub struct C3; pub struct C4; pub struct PwmChannels { _channel: PhantomData, _tim: PhantomData, } #[allow(unused_parens)] impl Pins for (P1, P2, P3, P4) where P1: PinC1, P2: PinC2, P3: PinC3, P4: PinC4, { const C1: bool = true; const C2: bool = true; const C3: bool = true; const C4: bool = true; type Channels = ( PwmChannels, PwmChannels, PwmChannels, PwmChannels, ); } #[allow(unused_parens)] impl Pins for (P2, P3, P4) where P2: PinC2, P3: PinC3, P4: PinC4, { const C2: bool = true; const C3: bool = true; const C4: bool = true; type Channels = ( PwmChannels, PwmChannels, PwmChannels, ); } #[allow(unused_parens)] impl Pins for (P1, P3, P4) where P1: PinC1, P3: PinC3, P4: PinC4, { const C1: bool = true; const C3: bool = true; const C4: bool = true; type Channels = ( PwmChannels, PwmChannels, PwmChannels, ); } #[allow(unused_parens)] impl Pins for (P1, P2, P4) where P1: PinC1, P2: PinC2, P4: PinC4, { const C1: bool = true; const C2: bool = true; const C4: bool = true; type Channels = ( PwmChannels, PwmChannels, PwmChannels, ); } #[allow(unused_parens)] impl Pins for (P1, P2, P3) where P1: PinC1, P2: PinC2, P3: PinC3, { const C1: bool = true; const C2: bool = true; const C3: bool = true; type Channels = ( PwmChannels, PwmChannels, PwmChannels, ); } #[allow(unused_parens)] impl Pins for (P3, P4) where P3: PinC3, P4: PinC4, { const C3: bool = true; const C4: bool = true; type Channels = (PwmChannels, PwmChannels); } #[allow(unused_parens)] impl Pins for (P2, P4) where P2: PinC2, P4: PinC4, { const C2: bool = true; const C4: bool = true; type Channels = (PwmChannels, PwmChannels); } #[allow(unused_parens)] impl Pins for (P2, P3) where P2: PinC2, P3: PinC3, { const C2: bool = true; const C3: bool = true; type Channels = (PwmChannels, PwmChannels); } #[allow(unused_parens)] impl Pins for (P1, P4) where P1: PinC1, P4: PinC4, { const C1: bool = true; const C4: bool = true; type Channels = (PwmChannels, PwmChannels); } #[allow(unused_parens)] impl Pins for (P1, P3) where P1: PinC1, P3: PinC3, { const C1: bool = true; const C3: bool = true; type Channels = (PwmChannels, PwmChannels); } #[allow(unused_parens)] impl Pins for (P1, P2) where P1: PinC1, P2: PinC2, { const C1: bool = true; const C2: bool = true; type Channels = (PwmChannels, PwmChannels); } #[allow(unused_parens)] impl Pins for (P1) where P1: PinC1, { const C1: bool = true; type Channels = (PwmChannels); } #[allow(unused_parens)] impl Pins for (P2) where P2: PinC2, { const C2: bool = true; type Channels = (PwmChannels); } #[allow(unused_parens)] impl Pins for (P3) where P3: PinC3, { const C3: bool = true; type Channels = (PwmChannels); } #[allow(unused_parens)] impl Pins for (P4) where P4: PinC4, { const C4: bool = true; type Channels = (PwmChannels); } impl, P2: PinC1> PinC1 for (P1, P2) {} impl, P2: PinC2> PinC2 for (P1, P2) {} impl, P2: PinC3> PinC3 for (P1, P2) {} impl, P2: PinC4> PinC4 for (P1, P2) {} impl, P2: PinC1, P3: PinC1> PinC1 for (P1, P2, P3) {} impl, P2: PinC2, P3: PinC2> PinC2 for (P1, P2, P3) {} impl, P2: PinC3, P3: PinC3> PinC3 for (P1, P2, P3) {} impl, P2: PinC4, P3: PinC4> PinC4 for (P1, P2, P3) {} impl, P2: PinC1, P3: PinC1, P4: PinC1> PinC1 for (P1, P2, P3, P4) { } impl, P2: PinC2, P3: PinC2, P4: PinC2> PinC2 for (P1, P2, P3, P4) { } impl, P2: PinC3, P3: PinC3, P4: PinC3> PinC3 for (P1, P2, P3, P4) { } impl, P2: PinC4, P3: PinC4, P4: PinC4> PinC4 for (P1, P2, P3, P4) { } use crate::pac::*; pub fn tim1(tim: TIM1, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels where PINS: Pins, T: Into, { rcc.regs.apb2enr.modify(|_, w| w.tim1en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().clear_bit()); if PINS::C1 { tim.ccmr1_output() .modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1()); } if PINS::C2 { tim.ccmr1_output() .modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1()); } if PINS::C3 { tim.ccmr2_output() .modify(|_, w| w.oc3pe().set_bit().oc3m().pwm_mode1()); } if PINS::C4 { tim.ccmr2_output() .modify(|_, w| w.oc4pe().set_bit().oc4m().pwm_mode1()); } let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 { rcc.clocks.pclk().0 } else { rcc.clocks.pclk().0 * 2 }; let ticks = tclk / freq.into().0; let psc = u16((ticks - 1) / (1 << 16)).unwrap(); tim.psc.write(|w| w.psc().bits(psc)); let arr = u16(ticks / u32(psc + 1)).unwrap(); tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); tim.cr1.modify(|_, w| w.arpe().set_bit()); tim.cr1.modify(|_, w| w.urs().set_bit()); tim.egr.write(|w| w.ug().set_bit()); tim.cr1.modify(|_, w| w.urs().clear_bit()); tim.bdtr.modify(|_, w| w.aoe().set_bit()); tim.cr1.write(|w| { w.cms() .bits(0b00) .dir() .clear_bit() .opm() .clear_bit() .cen() .set_bit() }); unsafe { MaybeUninit::uninit().assume_init() } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).ccr1.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM1::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc2e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc2e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).ccr2.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM1::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) } } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc3e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc3e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).ccr3.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM1::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) } } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc4e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM1::ptr())).ccer.modify(|_, w| w.cc4e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).ccr4.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM1::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM1::ptr()).ccr4.write(|w| w.ccr().bits(duty.into())) } } } pub fn tim3(tim: TIM3, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels where PINS: Pins, T: Into, { rcc.regs.apb1enr.modify(|_, w| w.tim3en().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().clear_bit()); if PINS::C1 { tim.ccmr1_output() .modify(|_, w| w.oc1pe().set_bit().oc1m().pwm_mode1()); } if PINS::C2 { tim.ccmr1_output() .modify(|_, w| w.oc2pe().set_bit().oc2m().pwm_mode1()); } if PINS::C3 { tim.ccmr2_output() .modify(|_, w| w.oc3pe().set_bit().oc3m().pwm_mode1()); } if PINS::C4 { tim.ccmr2_output() .modify(|_, w| w.oc4pe().set_bit().oc4m().pwm_mode1()); } let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 { rcc.clocks.pclk().0 } else { rcc.clocks.pclk().0 * 2 }; let ticks = tclk / freq.into().0; let psc = u16((ticks - 1) / (1 << 16)).unwrap(); tim.psc.write(|w| w.psc().bits(psc)); let arr = u16(ticks / u32(psc + 1)).unwrap(); tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); tim.cr1.modify(|_, w| w.arpe().set_bit()); tim.cr1.modify(|_, w| w.urs().set_bit()); tim.egr.write(|w| w.ug().set_bit()); tim.cr1.modify(|_, w| w.urs().clear_bit()); tim.cr1.write(|w| { w.cms() .bits(0b00) .dir() .clear_bit() .opm() .clear_bit() .cen() .set_bit() }); unsafe { MaybeUninit::uninit().assume_init() } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).ccr1.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM3::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc2e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc2e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).ccr2.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM3::ptr()).ccr2.write(|w| w.ccr().bits(duty.into())) } } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc3e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc3e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).ccr3.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM3::ptr()).ccr3.write(|w| w.ccr().bits(duty.into())) } } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc4e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM3::ptr())).ccer.modify(|_, w| w.cc4e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).ccr4.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM3::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM3::ptr()).ccr4.write(|w| w.ccr().bits(duty.into())) } } } pub fn tim14(tim: TIM14, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels where PINS: Pins, T: Into, { rcc.regs.apb1enr.modify(|_, w| w.tim14en().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().clear_bit()); if PINS::C1 { tim.ccmr1_output() .modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6)); } let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 { rcc.clocks.pclk().0 } else { rcc.clocks.pclk().0 * 2 }; let ticks = tclk / freq.into().0; let psc = u16((ticks - 1) / (1 << 16)).unwrap(); tim.psc.write(|w| w.psc().bits(psc)); let arr = u16(ticks / u32(psc + 1)).unwrap(); tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); tim.cr1.modify(|_, w| w.arpe().set_bit()); tim.cr1.modify(|_, w| w.urs().set_bit()); tim.egr.write(|w| w.ug().set_bit()); tim.cr1.modify(|_, w| w.urs().clear_bit()); tim.cr1.write(|w| w.cen().set_bit()); unsafe { MaybeUninit::uninit().assume_init() } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM14::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM14::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM14::ptr()).ccr1.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM14::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM14::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } } } pub fn tim16(tim: TIM16, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels where PINS: Pins, T: Into, { rcc.regs.apb2enr.modify(|_, w| w.tim16en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().clear_bit()); if PINS::C1 { tim.ccmr1_output() .modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6)); } let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 { rcc.clocks.pclk().0 } else { rcc.clocks.pclk().0 * 2 }; let ticks = tclk / freq.into().0; let psc = u16((ticks - 1) / (1 << 16)).unwrap(); tim.psc.write(|w| w.psc().bits(psc)); let arr = u16(ticks / u32(psc + 1)).unwrap(); tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); tim.cr1.modify(|_, w| w.arpe().set_bit()); tim.cr1.modify(|_, w| w.urs().set_bit()); tim.egr.write(|w| w.ug().set_bit()); tim.cr1.modify(|_, w| w.urs().clear_bit()); tim.bdtr.modify(|_, w| w.aoe().set_bit()); tim.cr1.write(|w| w.opm().clear_bit().cen().set_bit()); unsafe { MaybeUninit::uninit().assume_init() } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM16::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM16::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM16::ptr()).ccr1.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM16::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM16::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } } } pub fn tim17(tim: TIM17, _pins: PINS, rcc: &mut Rcc, freq: T) -> PINS::Channels where PINS: Pins, T: Into, { rcc.regs.apb2enr.modify(|_, w| w.tim17en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().clear_bit()); if PINS::C1 { tim.ccmr1_output() .modify(|_, w| w.oc1pe().set_bit().oc1m().bits(6)); } let tclk = if rcc.clocks.hclk().0 == rcc.clocks.pclk().0 { rcc.clocks.pclk().0 } else { rcc.clocks.pclk().0 * 2 }; let ticks = tclk / freq.into().0; let psc = u16((ticks - 1) / (1 << 16)).unwrap(); tim.psc.write(|w| w.psc().bits(psc)); let arr = u16(ticks / u32(psc + 1)).unwrap(); tim.arr.write(|w| unsafe { w.bits(u32(arr)) }); tim.cr1.modify(|_, w| w.arpe().set_bit()); tim.cr1.modify(|_, w| w.urs().set_bit()); tim.egr.write(|w| w.ug().set_bit()); tim.cr1.modify(|_, w| w.urs().clear_bit()); tim.bdtr.modify(|_, w| w.aoe().set_bit()); tim.cr1.write(|w| w.opm().clear_bit().cen().set_bit()); unsafe { MaybeUninit::uninit().assume_init() } } impl hal::PwmPin for PwmChannels { type Duty = u16; fn disable(&mut self) { unsafe { (*(TIM17::ptr())).ccer.modify(|_, w| w.cc1e().clear_bit()) }; } fn enable(&mut self) { unsafe { (*(TIM17::ptr())).ccer.modify(|_, w| w.cc1e().set_bit()) }; } fn get_duty(&self) -> u16 { unsafe { (*TIM17::ptr()).ccr1.read().ccr().bits() as u16 } } fn get_max_duty(&self) -> u16 { unsafe { (*TIM17::ptr()).arr.read().arr().bits() as u16 } } fn set_duty(&mut self, duty: u16) { unsafe { (*TIM17::ptr()).ccr1.write(|w| w.ccr().bits(duty.into())) } } } } #[cfg(feature = "device-selected")] pub mod rcc { use crate::pac::RCC; use crate::time::Hertz; /// Extension trait that sets up the `RCC` peripheral pub trait RccExt { /// Configure the clocks of the RCC peripheral fn configure(self) -> CFGR; } impl RccExt for RCC { fn configure(self) -> CFGR { CFGR { hclk: None, pclk: None, sysclk: None, clock_src: SysClkSource::HSI, #[cfg(feature = "stm32f070")] usb_src: USBClockSource::Disabled, rcc: self, } } } /// Constrained RCC peripheral pub struct Rcc { pub clocks: Clocks, pub(crate) regs: RCC, } pub enum HSEBypassMode { /// Not bypassed: for crystals NotBypassed, /// Bypassed: for external clock sources Bypassed, } #[cfg(any( feature = "stm32f042", feature = "stm32f048", feature = "stm32f070", feature = "stm32f072", feature = "stm32f078", ))] pub enum USBClockSource { #[cfg(feature = "stm32f070")] /// USB peripheral's tranceiver is disabled Disabled, /// PLL output is used as USB peripheral tranceiver clock PLL, } /// RCC for F0x0 devices #[cfg(any(feature = "stm32f030", feature = "stm32f070",))] mod inner { use crate::pac::{rcc::cfgr::SW_A, RCC}; pub(super) const HSI: u32 = 8_000_000; #[cfg(any( feature = "stm32f030x4", feature = "stm32f030x6", feature = "stm32f030x8", feature = "stm32f070", feature = "stm32f030xc" ))] pub(super) const RCC_PLLSRC_PREDIV1_SUPPORT: bool = false; pub(super) enum SysClkSource { HSI, /// High-speed external clock(freq,bypassed) HSE(u32, super::HSEBypassMode), } pub(super) fn get_freq(c_src: &SysClkSource) -> u32 { match c_src { SysClkSource::HSE(freq, _) => *freq, _ => HSI, } } pub(super) fn enable_clock(rcc: &mut RCC, c_src: &SysClkSource) { match c_src { SysClkSource::HSE(_, bypassed) => { match bypassed { super::HSEBypassMode::NotBypassed => { rcc.cr .modify(|_, w| w.csson().on().hseon().on().hsebyp().not_bypassed()); } super::HSEBypassMode::Bypassed => { rcc.cr .modify(|_, w| w.csson().on().hseon().on().hsebyp().bypassed()); } } while !rcc.cr.read().hserdy().bit_is_set() {} } SysClkSource::HSI => { rcc.cr.write(|w| w.hsion().set_bit()); while rcc.cr.read().hsirdy().bit_is_clear() {} } } } pub(super) fn enable_pll( rcc: &mut RCC, c_src: &SysClkSource, pllmul_bits: u8, ppre_bits: u8, hpre_bits: u8, ) { let pllsrc_bit: bool = match c_src { SysClkSource::HSI => false, SysClkSource::HSE(_, _) => true, }; rcc.cfgr .modify(|_, w| w.pllsrc().bit(pllsrc_bit).pllmul().bits(pllmul_bits)); rcc.cr.modify(|_, w| w.pllon().set_bit()); while rcc.cr.read().pllrdy().bit_is_clear() {} rcc.cfgr.modify(|_, w| unsafe { w.ppre().bits(ppre_bits).hpre().bits(hpre_bits).sw().pll() }); } pub(super) fn get_sww(c_src: &SysClkSource) -> SW_A { match c_src { SysClkSource::HSI => SW_A::HSI, SysClkSource::HSE(_, _) => SW_A::HSE, } } } use self::inner::SysClkSource; pub struct CFGR { hclk: Option, pclk: Option, sysclk: Option, clock_src: SysClkSource, #[cfg(any( feature = "stm32f042", feature = "stm32f048", feature = "stm32f070", feature = "stm32f072", feature = "stm32f078", ))] usb_src: USBClockSource, rcc: RCC, } impl CFGR { pub fn hse(mut self, freq: F, bypass: HSEBypassMode) -> Self where F: Into, { self.clock_src = SysClkSource::HSE(freq.into().0, bypass); self } pub fn hclk(mut self, freq: F) -> Self where F: Into, { self.hclk = Some(freq.into().0); self } pub fn pclk(mut self, freq: F) -> Self where F: Into, { self.pclk = Some(freq.into().0); self } pub fn sysclk(mut self, freq: F) -> Self where F: Into, { self.sysclk = Some(freq.into().0); self } #[cfg(any( feature = "stm32f042", feature = "stm32f048", feature = "stm32f070", feature = "stm32f072", feature = "stm32f078", ))] /// Set the USB clock source (only valid for STM32F0xx with USB) pub fn usbsrc(mut self, src: USBClockSource) -> Self { self.usb_src = src; self } pub fn freeze(mut self, flash: &mut crate::pac::FLASH) -> Rcc { let sysclk = self.sysclk.unwrap_or(self::inner::HSI); let r_sysclk; let pllmul_bits; let src_clk_freq = self::inner::get_freq(&self.clock_src); if sysclk == src_clk_freq { pllmul_bits = None; r_sysclk = src_clk_freq; } else { let pllprediv = match (&self.clock_src, self::inner::RCC_PLLSRC_PREDIV1_SUPPORT) { (self::inner::SysClkSource::HSI, false) => 2, (_, _) => 1, }; let pllmul = (2 * pllprediv * self.sysclk.unwrap_or(src_clk_freq) + src_clk_freq) / src_clk_freq / 2; let pllmul = core::cmp::min(core::cmp::max(pllmul, 2), 16); r_sysclk = pllmul * src_clk_freq / pllprediv; pllmul_bits = Some(pllmul as u8 - 2) } let hpre_bits = self .hclk .map(|hclk| match r_sysclk / hclk { 0 => ::core::panicking::panic("internal error: entered unreachable code"), 1 => 0b0111, 2 => 0b1000, 3..=5 => 0b1001, 6..=11 => 0b1010, 12..=39 => 0b1011, 40..=95 => 0b1100, 96..=191 => 0b1101, 192..=383 => 0b1110, _ => 0b1111, }) .unwrap_or(0b0111); let hclk = r_sysclk / (1 << (hpre_bits - 0b0111)); let ppre_bits = self .pclk .map(|pclk| match hclk / pclk { 0 => ::core::panicking::panic("internal error: entered unreachable code"), 1 => 0b011, 2 => 0b100, 3..=5 => 0b101, 6..=11 => 0b110, _ => 0b111, }) .unwrap_or(0b011); let ppre: u8 = 1 << (ppre_bits - 0b011); let pclk = hclk / cast::u32(ppre); unsafe { flash.acr.write(|w| { w.latency().bits(if r_sysclk <= 24_000_000 { 0b000 } else if r_sysclk <= 48_000_000 { 0b001 } else { 0b010 }) }) } self::inner::enable_clock(&mut self.rcc, &self.clock_src); #[cfg(feature = "stm32f070")] { match self.usb_src { USBClockSource::Disabled => self.rcc.cfgr3.modify(|_, w| w.usbsw().clear_bit()), USBClockSource::PLL => self.rcc.cfgr3.modify(|_, w| w.usbsw().set_bit()), } } if let Some(pllmul_bits) = pllmul_bits { self::inner::enable_pll( &mut self.rcc, &self.clock_src, pllmul_bits, ppre_bits, hpre_bits, ); } else { let sw_var = self::inner::get_sww(&self.clock_src); self.rcc.cfgr.modify(|_, w| unsafe { w.ppre() .bits(ppre_bits) .hpre() .bits(hpre_bits) .sw() .variant(sw_var) }); } Rcc { clocks: Clocks { hclk: Hertz(hclk), pclk: Hertz(pclk), sysclk: Hertz(sysclk), }, regs: self.rcc, } } } /// Frozen clock frequencies /// /// The existence of this value indicates that the clock configuration can no longer be changed pub struct Clocks { hclk: Hertz, pclk: Hertz, sysclk: Hertz, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for Clocks { #[inline] fn clone(&self) -> Clocks { { let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for Clocks {} impl Clocks { /// Returns the frequency of the AHB pub fn hclk(&self) -> Hertz { self.hclk } /// Returns the frequency of the APB pub fn pclk(&self) -> Hertz { self.pclk } /// Returns the system (core) frequency pub fn sysclk(&self) -> Hertz { self.sysclk } } } #[cfg(feature = "device-selected")] pub mod serial { //! API for the integrated USART ports //! //! This only implements the usual asynchronous bidirectional 8-bit transfers. //! //! It's possible to use a read-only/write-only serial implementation with //! `usartXrx`/`usartXtx`. //! //! # Examples //! Echo //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::prelude::*; //! use crate::hal::serial::Serial; //! use crate::hal::pac; //! //! use nb::block; //! //! cortex_m::interrupt::free(|cs| { //! let rcc = p.RCC.configure().sysclk(48.mhz()).freeze(); //! //! let gpioa = p.GPIOA.split(&mut rcc); //! //! let tx = gpioa.pa9.into_alternate_af1(cs); //! let rx = gpioa.pa10.into_alternate_af1(cs); //! //! let mut serial = Serial::usart1(p.USART1, (tx, rx), 115_200.bps(), &mut rcc); //! //! loop { //! let received = block!(serial.read()).unwrap(); //! block!(serial.write(received)).ok(); //! } //! }); //! ``` //! //! Hello World //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::prelude::*; //! use crate::hal::serial::Serial; //! use crate::hal::pac; //! //! use nb::block; //! //! cortex_m::interrupt::free(|cs| { //! let rcc = p.RCC.configure().sysclk(48.mhz()).freeze(); //! //! let gpioa = p.GPIOA.split(&mut rcc); //! //! let tx = gpioa.pa9.into_alternate_af1(cs); //! //! let mut serial = Serial::usart1tx(p.USART1, tx, 115_200.bps(), &mut rcc); //! //! loop { //! serial.write_str("Hello World!\r\n"); //! } //! }); //! ``` use core::{ convert::Infallible, fmt::{Result, Write}, ops::Deref, }; use embedded_hal::prelude::*; use crate::{gpio::*, rcc::Rcc, time::Bps}; use core::marker::PhantomData; /// Serial error #[non_exhaustive] pub enum Error { /// Framing error Framing, /// Noise error Noise, /// RX buffer overrun Overrun, /// Parity check error Parity, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for Error { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&Error::Framing,) => ::core::fmt::Formatter::write_str(f, "Framing"), (&Error::Noise,) => ::core::fmt::Formatter::write_str(f, "Noise"), (&Error::Overrun,) => ::core::fmt::Formatter::write_str(f, "Overrun"), (&Error::Parity,) => ::core::fmt::Formatter::write_str(f, "Parity"), } } } /// Interrupt event pub enum Event { /// New data has been received Rxne, /// New data can be sent Txe, /// Idle line state detected Idle, } pub trait TxPin {} pub trait RxPin {} impl TxPin for gpioa::PA9> {} impl TxPin for gpiob::PB6> {} impl RxPin for gpioa::PA10> {} impl RxPin for gpiob::PB7> {} impl TxPin for gpioa::PA2> {} impl TxPin for gpioa::PA14> {} impl RxPin for gpioa::PA3> {} impl RxPin for gpioa::PA15> {} /// Serial abstraction pub struct Serial { usart: USART, pins: (TXPIN, RXPIN), } type SerialRegisterBlock = crate::pac::usart1::RegisterBlock; /// Serial receiver pub struct Rx { usart: *const SerialRegisterBlock, _instance: PhantomData, } unsafe impl Send for Rx {} /// Serial transmitter pub struct Tx { usart: *const SerialRegisterBlock, _instance: PhantomData, } unsafe impl Send for Tx {} use crate::pac::USART1; impl Serial where TXPIN: TxPin, RXPIN: RxPin, { /// Creates a new serial instance pub fn usart1(usart: USART1, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self { let mut serial = Serial { usart, pins }; serial.configure(baud_rate, rcc); serial .usart .cr1 .modify(|_, w| w.te().set_bit().re().set_bit().ue().set_bit()); serial } } impl Serial where TXPIN: TxPin, { /// Creates a new tx-only serial instance pub fn usart1tx(usart: USART1, txpin: TXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self { let rxpin = (); let mut serial = Serial { usart, pins: (txpin, rxpin), }; serial.configure(baud_rate, rcc); serial .usart .cr1 .modify(|_, w| w.te().set_bit().ue().set_bit()); serial } } impl Serial where RXPIN: RxPin, { /// Creates a new rx-only serial instance pub fn usart1rx(usart: USART1, rxpin: RXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self { let txpin = (); let mut serial = Serial { usart, pins: (txpin, rxpin), }; serial.configure(baud_rate, rcc); serial .usart .cr1 .modify(|_, w| w.re().set_bit().ue().set_bit()); serial } } impl Serial { fn configure(&mut self, baud_rate: Bps, rcc: &mut Rcc) { rcc.regs.apb2enr.modify(|_, w| w.usart1en().set_bit()); let brr = rcc.clocks.pclk().0 / baud_rate.0; self.usart.brr.write(|w| unsafe { w.bits(brr) }); self.usart.cr2.reset(); self.usart.cr3.reset(); } /// Starts listening for an interrupt event pub fn listen(&mut self, event: Event) { match event { Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().set_bit()), Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().set_bit()), Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().set_bit()), } } /// Stop listening for an interrupt event pub fn unlisten(&mut self, event: Event) { match event { Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().clear_bit()), Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().clear_bit()), Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().clear_bit()), } } } use crate::pac::USART2; impl Serial where TXPIN: TxPin, RXPIN: RxPin, { /// Creates a new serial instance pub fn usart2(usart: USART2, pins: (TXPIN, RXPIN), baud_rate: Bps, rcc: &mut Rcc) -> Self { let mut serial = Serial { usart, pins }; serial.configure(baud_rate, rcc); serial .usart .cr1 .modify(|_, w| w.te().set_bit().re().set_bit().ue().set_bit()); serial } } impl Serial where TXPIN: TxPin, { /// Creates a new tx-only serial instance pub fn usart2tx(usart: USART2, txpin: TXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self { let rxpin = (); let mut serial = Serial { usart, pins: (txpin, rxpin), }; serial.configure(baud_rate, rcc); serial .usart .cr1 .modify(|_, w| w.te().set_bit().ue().set_bit()); serial } } impl Serial where RXPIN: RxPin, { /// Creates a new rx-only serial instance pub fn usart2rx(usart: USART2, rxpin: RXPIN, baud_rate: Bps, rcc: &mut Rcc) -> Self { let txpin = (); let mut serial = Serial { usart, pins: (txpin, rxpin), }; serial.configure(baud_rate, rcc); serial .usart .cr1 .modify(|_, w| w.re().set_bit().ue().set_bit()); serial } } impl Serial { fn configure(&mut self, baud_rate: Bps, rcc: &mut Rcc) { rcc.regs.apb1enr.modify(|_, w| w.usart2en().set_bit()); let brr = rcc.clocks.pclk().0 / baud_rate.0; self.usart.brr.write(|w| unsafe { w.bits(brr) }); self.usart.cr2.reset(); self.usart.cr3.reset(); } /// Starts listening for an interrupt event pub fn listen(&mut self, event: Event) { match event { Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().set_bit()), Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().set_bit()), Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().set_bit()), } } /// Stop listening for an interrupt event pub fn unlisten(&mut self, event: Event) { match event { Event::Rxne => self.usart.cr1.modify(|_, w| w.rxneie().clear_bit()), Event::Txe => self.usart.cr1.modify(|_, w| w.txeie().clear_bit()), Event::Idle => self.usart.cr1.modify(|_, w| w.idleie().clear_bit()), } } } impl embedded_hal::serial::Read for Rx where USART: Deref, { type Error = Error; /// Tries to read a byte from the uart fn read(&mut self) -> nb::Result { read(self.usart) } } impl embedded_hal::serial::Read for Serial where USART: Deref, RXPIN: RxPin, { type Error = Error; /// Tries to read a byte from the uart fn read(&mut self) -> nb::Result { read(&*self.usart) } } impl embedded_hal::serial::Write for Tx where USART: Deref, { type Error = Infallible; /// Ensures that none of the previously written words are still buffered fn flush(&mut self) -> nb::Result<(), Self::Error> { flush(self.usart) } /// Tries to write a byte to the uart /// Fails if the transmit buffer is full fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { write(self.usart, byte) } } impl embedded_hal::serial::Write for Serial where USART: Deref, TXPIN: TxPin, { type Error = Infallible; /// Ensures that none of the previously written words are still buffered fn flush(&mut self) -> nb::Result<(), Self::Error> { flush(&*self.usart) } /// Tries to write a byte to the uart /// Fails if the transmit buffer is full fn write(&mut self, byte: u8) -> nb::Result<(), Self::Error> { write(&*self.usart, byte) } } impl Serial where USART: Deref, { /// Splits the UART Peripheral in a Tx and an Rx part /// This is required for sending/receiving pub fn split(self) -> (Tx, Rx) where TXPIN: TxPin, RXPIN: RxPin, { ( Tx { usart: &*self.usart, _instance: PhantomData, }, Rx { usart: &*self.usart, _instance: PhantomData, }, ) } pub fn release(self) -> (USART, (TXPIN, RXPIN)) { (self.usart, self.pins) } } impl Write for Tx where Tx: embedded_hal::serial::Write, { fn write_str(&mut self, s: &str) -> Result { s.as_bytes() .iter() .try_for_each(|c| loop { #[allow(unreachable_patterns)] match self.write(*c) { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }) .map_err(|_| core::fmt::Error) } } impl Write for Serial where USART: Deref, TXPIN: TxPin, { fn write_str(&mut self, s: &str) -> Result { s.as_bytes() .iter() .try_for_each(|c| loop { #[allow(unreachable_patterns)] match self.write(*c) { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }) .map_err(|_| core::fmt::Error) } } /// Ensures that none of the previously written words are still buffered fn flush(usart: *const SerialRegisterBlock) -> nb::Result<(), Infallible> { let isr = unsafe { (*usart).isr.read() }; if isr.tc().bit_is_set() { Ok(()) } else { Err(nb::Error::WouldBlock) } } /// Tries to write a byte to the UART /// Returns `Err(WouldBlock)` if the transmit buffer is full fn write(usart: *const SerialRegisterBlock, byte: u8) -> nb::Result<(), Infallible> { let isr = unsafe { (*usart).isr.read() }; if isr.txe().bit_is_set() { unsafe { (*usart).tdr.write(|w| w.tdr().bits(byte as u16)) } Ok(()) } else { Err(nb::Error::WouldBlock) } } /// Tries to read a byte from the UART fn read(usart: *const SerialRegisterBlock) -> nb::Result { let isr = unsafe { (*usart).isr.read() }; let icr = unsafe { &(*usart).icr }; if isr.pe().bit_is_set() { icr.write(|w| w.pecf().set_bit()); Err(nb::Error::Other(Error::Parity)) } else if isr.fe().bit_is_set() { icr.write(|w| w.fecf().set_bit()); Err(nb::Error::Other(Error::Framing)) } else if isr.nf().bit_is_set() { icr.write(|w| w.ncf().set_bit()); Err(nb::Error::Other(Error::Noise)) } else if isr.ore().bit_is_set() { icr.write(|w| w.orecf().set_bit()); Err(nb::Error::Other(Error::Overrun)) } else if isr.rxne().bit_is_set() { Ok(unsafe { (*usart).rdr.read().rdr().bits() as u8 }) } else { Err(nb::Error::WouldBlock) } } } #[cfg(feature = "device-selected")] pub mod spi { //! API for the integrate SPI peripherals //! //! The spi bus acts as the master (generating the clock) and you need to handle the CS separately. //! //! The most significant bit is transmitted first & only 8-bit transfers are supported //! //! # Example //! Echo incoming data in the next transfer //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::pac; //! use crate::hal::prelude::*; //! use crate::hal::spi::{Spi, Mode, Phase, Polarity}; //! //! cortex_m::interrupt::free(|cs| { //! let mut p = pac::Peripherals::take().unwrap(); //! let mut rcc = p.RCC.constrain().freeze(&mut p.FLASH); //! //! let gpioa = p.GPIOA.split(&mut rcc); //! //! // Configure pins for SPI //! let sck = gpioa.pa5.into_alternate_af0(cs); //! let miso = gpioa.pa6.into_alternate_af0(cs); //! let mosi = gpioa.pa7.into_alternate_af0(cs); //! //! // Configure SPI with 1MHz rate //! let mut spi = Spi::spi1(p.SPI1, (sck, miso, mosi), Mode { //! polarity: Polarity::IdleHigh, //! phase: Phase::CaptureOnSecondTransition, //! }, 1.mhz(), &mut rcc); //! //! let mut data = [0]; //! loop { //! spi.transfer(&mut data).unwrap(); //! } //! }); //! ``` use core::marker::PhantomData; use core::{ops::Deref, ptr}; pub use embedded_hal::spi::{Mode, Phase, Polarity}; use crate::pac::SPI1; use crate::gpio::*; use crate::rcc::{Clocks, Rcc}; use crate::time::Hertz; /// Typestate for 8-bit transfer size pub struct EightBit; /// Typestate for 16-bit transfer size pub struct SixteenBit; /// SPI error #[non_exhaustive] pub enum Error { /// Overrun occurred Overrun, /// Mode fault occurred ModeFault, /// CRC error Crc, } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::fmt::Debug for Error { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match (&*self,) { (&Error::Overrun,) => ::core::fmt::Formatter::write_str(f, "Overrun"), (&Error::ModeFault,) => ::core::fmt::Formatter::write_str(f, "ModeFault"), (&Error::Crc,) => ::core::fmt::Formatter::write_str(f, "Crc"), } } } /// SPI abstraction pub struct Spi { spi: SPI, pins: (SCKPIN, MISOPIN, MOSIPIN), _width: PhantomData, } pub trait SckPin {} pub trait MisoPin {} pub trait MosiPin {} impl SckPin for gpioa::PA5> {} impl SckPin for gpiob::PB3> {} impl MisoPin for gpioa::PA6> {} impl MisoPin for gpiob::PB4> {} impl MosiPin for gpioa::PA7> {} impl MosiPin for gpiob::PB5> {} impl Spi { /// Creates a new spi instance pub fn spi1( spi: SPI1, pins: (SCKPIN, MISOPIN, MOSIPIN), mode: Mode, speed: F, rcc: &mut Rcc, ) -> Self where SCKPIN: SckPin, MISOPIN: MisoPin, MOSIPIN: MosiPin, F: Into, { rcc.regs.apb2enr.modify(|_, w| w.spi1en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.spi1rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.spi1rst().clear_bit()); Spi:: { spi, pins, _width: PhantomData, } .spi_init(mode, speed, rcc.clocks) .into_8bit_width() } } #[allow(dead_code)] type SpiRegisterBlock = crate::pac::spi1::RegisterBlock; impl Spi where SPI: Deref, { fn spi_init(self, mode: Mode, speed: F, clocks: Clocks) -> Self where F: Into, { self.spi.cr1.modify(|_, w| w.spe().clear_bit()); let br = match clocks.pclk().0 / speed.into().0 { 0 => ::core::panicking::panic("internal error: entered unreachable code"), 1..=2 => 0b000, 3..=5 => 0b001, 6..=11 => 0b010, 12..=23 => 0b011, 24..=47 => 0b100, 48..=95 => 0b101, 96..=191 => 0b110, _ => 0b111, }; self.spi.cr1.write(|w| { w.cpha() .bit(mode.phase == Phase::CaptureOnSecondTransition) .cpol() .bit(mode.polarity == Polarity::IdleHigh) .mstr() .set_bit() .br() .bits(br) .lsbfirst() .clear_bit() .ssm() .set_bit() .ssi() .set_bit() .rxonly() .clear_bit() .bidimode() .clear_bit() .spe() .set_bit() }); self } pub fn into_8bit_width(self) -> Spi { self.spi .cr2 .write(|w| w.frxth().set_bit().ds().eight_bit().ssoe().clear_bit()); Spi { spi: self.spi, pins: self.pins, _width: PhantomData, } } pub fn into_16bit_width(self) -> Spi { self.spi .cr2 .write(|w| w.frxth().set_bit().ds().sixteen_bit().ssoe().clear_bit()); Spi { spi: self.spi, pins: self.pins, _width: PhantomData, } } fn set_send_only(&mut self) { self.spi .cr1 .modify(|_, w| w.bidimode().set_bit().bidioe().set_bit()); } fn set_bidi(&mut self) { self.spi .cr1 .modify(|_, w| w.bidimode().clear_bit().bidioe().clear_bit()); } fn check_read(&mut self) -> nb::Result<(), Error> { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { nb::Error::Other(Error::Overrun) } else if sr.modf().bit_is_set() { nb::Error::Other(Error::ModeFault) } else if sr.crcerr().bit_is_set() { nb::Error::Other(Error::Crc) } else if sr.rxne().bit_is_set() { return Ok(()); } else { nb::Error::WouldBlock }) } fn send_buffer_size(&mut self) -> u8 { match self.spi.sr.read().ftlvl().bits() { 0 => 4, 1 => 3, 2 => 2, _ => 0, } } fn check_send(&mut self) -> nb::Result<(), Error> { let sr = self.spi.sr.read(); Err(if sr.ovr().bit_is_set() { nb::Error::Other(Error::Overrun) } else if sr.modf().bit_is_set() { nb::Error::Other(Error::ModeFault) } else if sr.crcerr().bit_is_set() { nb::Error::Other(Error::Crc) } else if sr.txe().bit_is_set() && sr.bsy().bit_is_clear() { return Ok(()); } else { nb::Error::WouldBlock }) } fn read_u8(&mut self) -> u8 { unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const u8) } } fn send_u8(&mut self, byte: u8) { unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u8, byte) } } fn read_u16(&mut self) -> u16 { unsafe { ptr::read_volatile(&self.spi.dr as *const _ as *const u16) } } fn send_u16(&mut self, byte: u16) { unsafe { ptr::write_volatile(&self.spi.dr as *const _ as *mut u16, byte) } } pub fn release(self) -> (SPI, (SCKPIN, MISOPIN, MOSIPIN)) { (self.spi, self.pins) } } impl ::embedded_hal::blocking::spi::Transfer for Spi where SPI: Deref, { type Error = Error; fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { self.set_bidi(); for word in words.iter_mut() { loop { #[allow(unreachable_patterns)] match self.check_send() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }?; self.send_u8(*word); loop { #[allow(unreachable_patterns)] match self.check_read() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }?; *word = self.read_u8(); } Ok(words) } } impl ::embedded_hal::blocking::spi::Write for Spi where SPI: Deref, { type Error = Error; fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { let mut bufcap: u8 = 0; self.set_send_only(); loop { #[allow(unreachable_patterns)] match self.check_send() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }?; for word in words { while bufcap == 0 { bufcap = self.send_buffer_size(); } self.send_u8(*word); bufcap -= 1; } loop { #[allow(unreachable_patterns)] match self.check_send() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } } .ok(); Ok(()) } } impl ::embedded_hal::blocking::spi::Transfer for Spi where SPI: Deref, { type Error = Error; fn transfer<'w>(&mut self, words: &'w mut [u16]) -> Result<&'w [u16], Self::Error> { self.set_bidi(); for word in words.iter_mut() { loop { #[allow(unreachable_patterns)] match self.check_send() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }?; self.send_u16(*word); loop { #[allow(unreachable_patterns)] match self.check_read() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }?; *word = self.read_u16(); } Ok(words) } } impl ::embedded_hal::blocking::spi::Write for Spi where SPI: Deref, { type Error = Error; fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> { self.set_send_only(); for word in words { loop { #[allow(unreachable_patterns)] match self.check_send() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } }?; self.send_u16(*word); } loop { #[allow(unreachable_patterns)] match self.check_send() { Err(::nb::Error::Other(e)) => { #[allow(unreachable_code)] break Err(e) } Err(::nb::Error::WouldBlock) => {} Ok(x) => break Ok(x), } } .ok(); Ok(()) } } } #[cfg(feature = "device-selected")] pub mod time { /// Bits per second pub struct Bps(pub u32); impl ::core::marker::StructuralPartialEq for Bps {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for Bps { #[inline] fn eq(&self, other: &Bps) -> bool { match *other { Bps(ref __self_1_0) => match *self { Bps(ref __self_0_0) => (*__self_0_0) == (*__self_1_0), }, } } #[inline] fn ne(&self, other: &Bps) -> bool { match *other { Bps(ref __self_1_0) => match *self { Bps(ref __self_0_0) => (*__self_0_0) != (*__self_1_0), }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialOrd for Bps { #[inline] fn partial_cmp(&self, other: &Bps) -> ::core::option::Option<::core::cmp::Ordering> { match *other { Bps(ref __self_1_0) => match *self { Bps(ref __self_0_0) => { match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } cmp => cmp, } } }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for Bps { #[inline] fn clone(&self) -> Bps { { let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for Bps {} pub struct Hertz(pub u32); impl ::core::marker::StructuralPartialEq for Hertz {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for Hertz { #[inline] fn eq(&self, other: &Hertz) -> bool { match *other { Hertz(ref __self_1_0) => match *self { Hertz(ref __self_0_0) => (*__self_0_0) == (*__self_1_0), }, } } #[inline] fn ne(&self, other: &Hertz) -> bool { match *other { Hertz(ref __self_1_0) => match *self { Hertz(ref __self_0_0) => (*__self_0_0) != (*__self_1_0), }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialOrd for Hertz { #[inline] fn partial_cmp(&self, other: &Hertz) -> ::core::option::Option<::core::cmp::Ordering> { match *other { Hertz(ref __self_1_0) => match *self { Hertz(ref __self_0_0) => { match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } cmp => cmp, } } }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for Hertz { #[inline] fn clone(&self) -> Hertz { { let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for Hertz {} pub struct KiloHertz(pub u32); impl ::core::marker::StructuralPartialEq for KiloHertz {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for KiloHertz { #[inline] fn eq(&self, other: &KiloHertz) -> bool { match *other { KiloHertz(ref __self_1_0) => match *self { KiloHertz(ref __self_0_0) => (*__self_0_0) == (*__self_1_0), }, } } #[inline] fn ne(&self, other: &KiloHertz) -> bool { match *other { KiloHertz(ref __self_1_0) => match *self { KiloHertz(ref __self_0_0) => (*__self_0_0) != (*__self_1_0), }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialOrd for KiloHertz { #[inline] fn partial_cmp(&self, other: &KiloHertz) -> ::core::option::Option<::core::cmp::Ordering> { match *other { KiloHertz(ref __self_1_0) => match *self { KiloHertz(ref __self_0_0) => { match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } cmp => cmp, } } }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for KiloHertz { #[inline] fn clone(&self) -> KiloHertz { { let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for KiloHertz {} pub struct MegaHertz(pub u32); impl ::core::marker::StructuralPartialEq for MegaHertz {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for MegaHertz { #[inline] fn eq(&self, other: &MegaHertz) -> bool { match *other { MegaHertz(ref __self_1_0) => match *self { MegaHertz(ref __self_0_0) => (*__self_0_0) == (*__self_1_0), }, } } #[inline] fn ne(&self, other: &MegaHertz) -> bool { match *other { MegaHertz(ref __self_1_0) => match *self { MegaHertz(ref __self_0_0) => (*__self_0_0) != (*__self_1_0), }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialOrd for MegaHertz { #[inline] fn partial_cmp(&self, other: &MegaHertz) -> ::core::option::Option<::core::cmp::Ordering> { match *other { MegaHertz(ref __self_1_0) => match *self { MegaHertz(ref __self_0_0) => { match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } cmp => cmp, } } }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for MegaHertz { #[inline] fn clone(&self) -> MegaHertz { { let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for MegaHertz {} /// 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; } 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) } } impl Into for KiloHertz { fn into(self) -> Hertz { Hertz(self.0 * 1_000) } } impl Into for MegaHertz { fn into(self) -> Hertz { Hertz(self.0 * 1_000_000) } } impl Into for MegaHertz { fn into(self) -> KiloHertz { KiloHertz(self.0 * 1_000) } } } #[cfg(feature = "device-selected")] pub mod timers { //! API for the integrated timers //! //! This only implements basic functions, a lot of things are missing //! //! # Example //! Blink the led with 1Hz //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::pac; //! use crate::hal::prelude::*; //! use crate::hal::time::*; //! use crate::hal::timers::*; //! use nb::block; //! //! cortex_m::interrupt::free(|cs| { //! let mut p = pac::Peripherals::take().unwrap(); //! let mut rcc = p.RCC.configure().freeze(&mut p.FLASH); //! //! let gpioa = p.GPIOA.split(&mut rcc); //! //! let mut led = gpioa.pa1.into_push_pull_pull_output(cs); //! //! let mut timer = Timer::tim1(p.TIM1, Hertz(1), &mut rcc); //! loop { //! led.toggle(); //! block!(timer.wait()).ok(); //! } //! }); //! ``` use cortex_m::peripheral::syst::SystClkSource; use cortex_m::peripheral::SYST; use crate::rcc::{Clocks, Rcc}; use crate::time::Hertz; use embedded_hal::timer::{CountDown, Periodic}; use void::Void; /// Hardware timers pub struct Timer { clocks: Clocks, tim: TIM, } /// Interrupt events pub enum Event { /// Timer timed out / count down ended TimeOut, } impl Timer { /// Configures the SYST clock as a periodic count down timer pub fn syst(mut syst: SYST, timeout: T, rcc: &Rcc) -> Self where T: Into, { syst.set_clock_source(SystClkSource::Core); let mut timer = Timer { tim: syst, clocks: rcc.clocks, }; timer.start(timeout); timer } /// Starts listening for an `event` pub fn listen(&mut self, event: &Event) { match event { Event::TimeOut => self.tim.enable_interrupt(), } } /// Stops listening for an `event` pub fn unlisten(&mut self, event: &Event) { match event { Event::TimeOut => self.tim.disable_interrupt(), } } } /// Use the systick as a timer /// /// Be aware that intervals less than 4 Hertz may not function properly impl CountDown for Timer { type Time = Hertz; /// Start the timer with a `timeout` fn start(&mut self, timeout: T) where T: Into, { let rvr = self.clocks.sysclk().0 / timeout.into().0 - 1; if !(rvr < (1 << 24)) { ::core::panicking::panic("assertion failed: rvr < (1 << 24)") }; self.tim.set_reload(rvr); self.tim.clear_current(); self.tim.enable_counter(); } /// Return `Ok` if the timer has wrapped /// Automatically clears the flag and restarts the time fn wait(&mut self) -> nb::Result<(), Void> { if self.tim.has_wrapped() { Ok(()) } else { Err(nb::Error::WouldBlock) } } } impl Periodic for Timer {} use crate::pac::TIM1; impl Timer { /// Configures a TIM peripheral as a periodic count down timer pub fn tim1(tim: TIM1, timeout: T, rcc: &mut Rcc) -> Self where T: Into, { rcc.regs.apb2enr.modify(|_, w| w.tim1en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim1rst().clear_bit()); let mut timer = Timer { clocks: rcc.clocks, tim, }; timer.start(timeout); timer } /// Starts listening for an `event` pub fn listen(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().set_bit()); } } } /// Stops listening for an `event` pub fn unlisten(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().clear_bit()); } } } /// Releases the TIM peripheral pub fn release(self) -> TIM1 { let rcc = unsafe { &(*crate::pac::RCC::ptr()) }; self.tim.cr1.modify(|_, w| w.cen().clear_bit()); rcc.apb2enr.modify(|_, w| w.tim1en().clear_bit()); self.tim } } impl CountDown for Timer { type Time = Hertz; /// Start the timer with a `timeout` fn start(&mut self, timeout: T) where T: Into, { self.tim.cr1.modify(|_, w| w.cen().clear_bit()); self.tim.cnt.reset(); let frequency = timeout.into().0; let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 { self.clocks.pclk().0 } else { self.clocks.pclk().0 * 2 }; let ticks = tclk / frequency; let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| w.psc().bits(psc)); let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap(); self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) }); self.tim.cr1.modify(|_, w| w.cen().set_bit()); } /// Return `Ok` if the timer has wrapped /// Automatically clears the flag and restarts the time fn wait(&mut self) -> nb::Result<(), Void> { if self.tim.sr.read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { self.tim.sr.modify(|_, w| w.uif().clear_bit()); Ok(()) } } } impl Periodic for Timer {} use crate::pac::TIM3; impl Timer { /// Configures a TIM peripheral as a periodic count down timer pub fn tim3(tim: TIM3, timeout: T, rcc: &mut Rcc) -> Self where T: Into, { rcc.regs.apb1enr.modify(|_, w| w.tim3en().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim3rst().clear_bit()); let mut timer = Timer { clocks: rcc.clocks, tim, }; timer.start(timeout); timer } /// Starts listening for an `event` pub fn listen(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().set_bit()); } } } /// Stops listening for an `event` pub fn unlisten(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().clear_bit()); } } } /// Releases the TIM peripheral pub fn release(self) -> TIM3 { let rcc = unsafe { &(*crate::pac::RCC::ptr()) }; self.tim.cr1.modify(|_, w| w.cen().clear_bit()); rcc.apb1enr.modify(|_, w| w.tim3en().clear_bit()); self.tim } } impl CountDown for Timer { type Time = Hertz; /// Start the timer with a `timeout` fn start(&mut self, timeout: T) where T: Into, { self.tim.cr1.modify(|_, w| w.cen().clear_bit()); self.tim.cnt.reset(); let frequency = timeout.into().0; let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 { self.clocks.pclk().0 } else { self.clocks.pclk().0 * 2 }; let ticks = tclk / frequency; let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| w.psc().bits(psc)); let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap(); self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) }); self.tim.cr1.modify(|_, w| w.cen().set_bit()); } /// Return `Ok` if the timer has wrapped /// Automatically clears the flag and restarts the time fn wait(&mut self) -> nb::Result<(), Void> { if self.tim.sr.read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { self.tim.sr.modify(|_, w| w.uif().clear_bit()); Ok(()) } } } impl Periodic for Timer {} use crate::pac::TIM14; impl Timer { /// Configures a TIM peripheral as a periodic count down timer pub fn tim14(tim: TIM14, timeout: T, rcc: &mut Rcc) -> Self where T: Into, { rcc.regs.apb1enr.modify(|_, w| w.tim14en().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().set_bit()); rcc.regs.apb1rstr.modify(|_, w| w.tim14rst().clear_bit()); let mut timer = Timer { clocks: rcc.clocks, tim, }; timer.start(timeout); timer } /// Starts listening for an `event` pub fn listen(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().set_bit()); } } } /// Stops listening for an `event` pub fn unlisten(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().clear_bit()); } } } /// Releases the TIM peripheral pub fn release(self) -> TIM14 { let rcc = unsafe { &(*crate::pac::RCC::ptr()) }; self.tim.cr1.modify(|_, w| w.cen().clear_bit()); rcc.apb1enr.modify(|_, w| w.tim14en().clear_bit()); self.tim } } impl CountDown for Timer { type Time = Hertz; /// Start the timer with a `timeout` fn start(&mut self, timeout: T) where T: Into, { self.tim.cr1.modify(|_, w| w.cen().clear_bit()); self.tim.cnt.reset(); let frequency = timeout.into().0; let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 { self.clocks.pclk().0 } else { self.clocks.pclk().0 * 2 }; let ticks = tclk / frequency; let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| w.psc().bits(psc)); let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap(); self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) }); self.tim.cr1.modify(|_, w| w.cen().set_bit()); } /// Return `Ok` if the timer has wrapped /// Automatically clears the flag and restarts the time fn wait(&mut self) -> nb::Result<(), Void> { if self.tim.sr.read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { self.tim.sr.modify(|_, w| w.uif().clear_bit()); Ok(()) } } } impl Periodic for Timer {} use crate::pac::TIM16; impl Timer { /// Configures a TIM peripheral as a periodic count down timer pub fn tim16(tim: TIM16, timeout: T, rcc: &mut Rcc) -> Self where T: Into, { rcc.regs.apb2enr.modify(|_, w| w.tim16en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim16rst().clear_bit()); let mut timer = Timer { clocks: rcc.clocks, tim, }; timer.start(timeout); timer } /// Starts listening for an `event` pub fn listen(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().set_bit()); } } } /// Stops listening for an `event` pub fn unlisten(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().clear_bit()); } } } /// Releases the TIM peripheral pub fn release(self) -> TIM16 { let rcc = unsafe { &(*crate::pac::RCC::ptr()) }; self.tim.cr1.modify(|_, w| w.cen().clear_bit()); rcc.apb2enr.modify(|_, w| w.tim16en().clear_bit()); self.tim } } impl CountDown for Timer { type Time = Hertz; /// Start the timer with a `timeout` fn start(&mut self, timeout: T) where T: Into, { self.tim.cr1.modify(|_, w| w.cen().clear_bit()); self.tim.cnt.reset(); let frequency = timeout.into().0; let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 { self.clocks.pclk().0 } else { self.clocks.pclk().0 * 2 }; let ticks = tclk / frequency; let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| w.psc().bits(psc)); let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap(); self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) }); self.tim.cr1.modify(|_, w| w.cen().set_bit()); } /// Return `Ok` if the timer has wrapped /// Automatically clears the flag and restarts the time fn wait(&mut self) -> nb::Result<(), Void> { if self.tim.sr.read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { self.tim.sr.modify(|_, w| w.uif().clear_bit()); Ok(()) } } } impl Periodic for Timer {} use crate::pac::TIM17; impl Timer { /// Configures a TIM peripheral as a periodic count down timer pub fn tim17(tim: TIM17, timeout: T, rcc: &mut Rcc) -> Self where T: Into, { rcc.regs.apb2enr.modify(|_, w| w.tim17en().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().set_bit()); rcc.regs.apb2rstr.modify(|_, w| w.tim17rst().clear_bit()); let mut timer = Timer { clocks: rcc.clocks, tim, }; timer.start(timeout); timer } /// Starts listening for an `event` pub fn listen(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().set_bit()); } } } /// Stops listening for an `event` pub fn unlisten(&mut self, event: Event) { match event { Event::TimeOut => { self.tim.dier.write(|w| w.uie().clear_bit()); } } } /// Releases the TIM peripheral pub fn release(self) -> TIM17 { let rcc = unsafe { &(*crate::pac::RCC::ptr()) }; self.tim.cr1.modify(|_, w| w.cen().clear_bit()); rcc.apb2enr.modify(|_, w| w.tim17en().clear_bit()); self.tim } } impl CountDown for Timer { type Time = Hertz; /// Start the timer with a `timeout` fn start(&mut self, timeout: T) where T: Into, { self.tim.cr1.modify(|_, w| w.cen().clear_bit()); self.tim.cnt.reset(); let frequency = timeout.into().0; let tclk = if self.clocks.hclk().0 == self.clocks.pclk().0 { self.clocks.pclk().0 } else { self.clocks.pclk().0 * 2 }; let ticks = tclk / frequency; let psc = cast::u16((ticks - 1) / (1 << 16)).unwrap(); self.tim.psc.write(|w| w.psc().bits(psc)); let arr = cast::u16(ticks / cast::u32(psc + 1)).unwrap(); self.tim.arr.write(|w| unsafe { w.bits(cast::u32(arr)) }); self.tim.cr1.modify(|_, w| w.cen().set_bit()); } /// Return `Ok` if the timer has wrapped /// Automatically clears the flag and restarts the time fn wait(&mut self) -> nb::Result<(), Void> { if self.tim.sr.read().uif().bit_is_clear() { Err(nb::Error::WouldBlock) } else { self.tim.sr.modify(|_, w| w.uif().clear_bit()); Ok(()) } } } impl Periodic for Timer {} use crate::gpio::{AF0, AF1, AF2, AF4, AF5}; use crate::gpio::{gpioa::*, gpiob::*, Alternate}; pub trait PinC1 {} pub trait PinC2 {} pub trait PinC3 {} pub trait PinC4 {} impl PinC1 for PA8> {} impl PinC2 for PA9> {} impl PinC3 for PA10> {} impl PinC4 for PA11> {} impl PinC1 for PA6> {} impl PinC2 for PA7> {} impl PinC1 for PB4> {} impl PinC2 for PB5> {} impl PinC3 for PB0> {} impl PinC4 for PB1> {} impl PinC1 for PA4> {} impl PinC1 for PA7> {} impl PinC1 for PB1> {} impl PinC1 for PA6> {} impl PinC1 for PB8> {} impl PinC1 for PA7> {} impl PinC1 for PB9> {} #[cfg(any( feature = "stm32f030", feature = "stm32f051", feature = "stm32f058", feature = "stm32f070", feature = "stm32f071", feature = "stm32f072", feature = "stm32f078", feature = "stm32f091", feature = "stm32f098" ))] use crate::gpio::gpioc::*; impl PinC1 for PC6> {} impl PinC2 for PC7> {} impl PinC3 for PC8> {} impl PinC4 for PC9> {} } #[cfg(feature = "device-selected")] pub mod watchdog { //! API for the IWDG //! //! You can activate the watchdog by calling `start` or the setting appropriate //! device option bit when programming. //! //! After activating the watchdog, you'll have to regularly `feed` the watchdog. //! If more time than `timeout` has gone by since the last `feed`, your //! microcontroller will be reset. //! //! This is useful if you fear that your program may get stuck. In that case it //! won't feed the watchdog anymore, the watchdog will reset the microcontroller //! and thus your program will function again. //! //! **Attention**: //! //! The IWDG runs on a separate 40kHz low-accuracy clock (30kHz-60kHz). You may //! want to some buffer in your interval. //! //! Per default the iwdg continues to run even when you stopped execution of code via a debugger. //! You may want to disable the watchdog when the cpu is stopped //! //! ``` ignore //! let dbgmcu = p.DBGMCU; //! dbgmcu.apb1_fz.modify(|_, w| w.dbg_iwdg_stop().set_bit()); //! ``` //! //! # Example //! ``` no_run //! use stm32f0xx_hal as hal; //! //! use crate::hal::pac; //! use crate::hal::prelude::*; //! use crate::hal:watchdog::Watchdog; //! use crate::hal:time::Hertz; //! //! let mut p = pac::Peripherals::take().unwrap(); //! //! let mut iwdg = Watchdog::new(p.iwdg); //! iwdg.start(Hertz(100)); //! loop {} //! // Whoops, got stuck, the watchdog issues a reset after 10 ms //! iwdg.feed(); //! ``` use embedded_hal::watchdog; use crate::pac::IWDG; use crate::time::Hertz; /// Watchdog instance pub struct Watchdog { iwdg: IWDG, } impl watchdog::Watchdog for Watchdog { /// Feed the watchdog, so that at least one `period` goes by before the next /// reset fn feed(&mut self) { self.iwdg.kr.write(|w| w.key().reset()); } } /// Timeout configuration for the IWDG pub struct IwdgTimeout { psc: u8, reload: u16, } impl ::core::marker::StructuralPartialEq for IwdgTimeout {} #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialEq for IwdgTimeout { #[inline] fn eq(&self, other: &IwdgTimeout) -> bool { match *other { IwdgTimeout { psc: ref __self_1_0, reload: ref __self_1_1, } => match *self { IwdgTimeout { psc: ref __self_0_0, reload: ref __self_0_1, } => (*__self_0_0) == (*__self_1_0) && (*__self_0_1) == (*__self_1_1), }, } } #[inline] fn ne(&self, other: &IwdgTimeout) -> bool { match *other { IwdgTimeout { psc: ref __self_1_0, reload: ref __self_1_1, } => match *self { IwdgTimeout { psc: ref __self_0_0, reload: ref __self_0_1, } => (*__self_0_0) != (*__self_1_0) || (*__self_0_1) != (*__self_1_1), }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::cmp::PartialOrd for IwdgTimeout { #[inline] fn partial_cmp( &self, other: &IwdgTimeout, ) -> ::core::option::Option<::core::cmp::Ordering> { match *other { IwdgTimeout { psc: ref __self_1_0, reload: ref __self_1_1, } => match *self { IwdgTimeout { psc: ref __self_0_0, reload: ref __self_0_1, } => match ::core::cmp::PartialOrd::partial_cmp(&(*__self_0_0), &(*__self_1_0)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => { match ::core::cmp::PartialOrd::partial_cmp( &(*__self_0_1), &(*__self_1_1), ) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } cmp => cmp, } } cmp => cmp, }, }, } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::clone::Clone for IwdgTimeout { #[inline] fn clone(&self) -> IwdgTimeout { { let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone; *self } } } #[automatically_derived] #[allow(unused_qualifications)] impl ::core::marker::Copy for IwdgTimeout {} impl Into for Hertz { /// This converts the value so it's usable by the IWDG /// Due to conversion losses, the specified frequency is a maximum /// /// It can also only represent values < 10000 Hertz fn into(self) -> IwdgTimeout { let mut time = 40_000 / 4 / self.0; let mut psc = 0; let mut reload = 0; while psc < 7 { reload = time; if reload < 0x1000 { break; } psc += 1; time /= 2; } let reload = reload as u16; IwdgTimeout { psc, reload } } } impl Watchdog { pub fn new(iwdg: IWDG) -> Self { Self { iwdg } } } impl watchdog::WatchdogEnable for Watchdog { type Time = IwdgTimeout; fn start(&mut self, period: T) where T: Into, { let time: IwdgTimeout = period.into(); self.iwdg.kr.write(|w| w.key().reset()); self.iwdg.kr.write(|w| w.key().start()); self.iwdg.kr.write(|w| w.key().enable()); while self.iwdg.sr.read().pvu().bit() {} self.iwdg.pr.write(|w| w.pr().bits(time.psc)); while self.iwdg.sr.read().rvu().bit() {} self.iwdg.rlr.write(|w| w.rl().bits(time.reload)); while self.iwdg.sr.read().bits() != 0 {} self.iwdg.kr.write(|w| w.key().reset()); } } } #[cfg(feature = "device-selected")] #[deprecated(since = "0.17.0", note = "please use `pac` instead")] pub use pac as stm32;