#![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 gpio { //! General Purpose Input / Output use core::convert::Infallible; use core::marker::PhantomData; use crate::rcc::Rcc; /// Extension trait to split a GPIO peripheral in independent pins and registers pub trait GpioExt { /// The parts to split the GPIO into type Parts; /// Splits the GPIO block into independent pins and registers fn split(self, rcc: &mut Rcc) -> Self::Parts; } trait GpioRegExt { fn is_low(&self, pos: u8) -> bool; fn is_set_low(&self, pos: u8) -> bool; fn set_high(&self, pos: u8); fn set_low(&self, pos: u8); } /// Alternate function 0 pub struct AF0; /// Alternate function 1 pub struct AF1; /// Alternate function 2 pub struct AF2; /// Alternate function 3 pub struct AF3; /// Alternate function 4 pub struct AF4; /// Alternate function 5 pub struct AF5; /// Alternate function 6 pub struct AF6; /// Alternate function 7 pub struct AF7; /// Alternate function mode (type state) pub struct Alternate { _mode: PhantomData, } /// Input mode (type state) pub struct Input { _mode: PhantomData, } /// Floating input (type state) pub struct Floating; /// Pulled down input (type state) pub struct PullDown; /// Pulled up input (type state) pub struct PullUp; /// Open drain input or output (type state) pub struct OpenDrain; /// Analog mode (type state) pub struct Analog; /// Output mode (type state) pub struct Output { _mode: PhantomData, } /// Push pull output (type state) pub struct PushPull; use embedded_hal::digital::v2::{toggleable, InputPin, OutputPin, StatefulOutputPin}; /// Fully erased pin pub struct Pin { i: u8, port: *const dyn GpioRegExt, _mode: PhantomData, } unsafe impl Sync for Pin {} unsafe impl Send for Pin {} impl StatefulOutputPin for Pin> { #[inline(always)] fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } #[inline(always)] fn is_set_low(&self) -> Result { Ok(unsafe { (*self.port).is_set_low(self.i) }) } } impl OutputPin for Pin> { type Error = Infallible; #[inline(always)] fn set_high(&mut self) -> Result<(), Self::Error> { unsafe { (*self.port).set_high(self.i) }; Ok(()) } #[inline(always)] fn set_low(&mut self) -> Result<(), Self::Error> { unsafe { (*self.port).set_low(self.i) } Ok(()) } } impl toggleable::Default for Pin> {} impl InputPin for Pin> { type Error = Infallible; #[inline(always)] fn is_high(&self) -> Result { self.is_low().map(|v| !v) } #[inline(always)] fn is_low(&self) -> Result { Ok(unsafe { (*self.port).is_low(self.i) }) } } impl InputPin for Pin> { type Error = Infallible; #[inline(always)] fn is_high(&self) -> Result { self.is_low().map(|v| !v) } #[inline(always)] fn is_low(&self) -> Result { Ok(unsafe { (*self.port).is_low(self.i) }) } } impl GpioRegExt for crate::pac::gpioa::RegisterBlock { fn is_low(&self, pos: u8) -> bool { self.idr.read().bits() & (1 << pos) == 0 } fn is_set_low(&self, pos: u8) -> bool { self.odr.read().bits() & (1 << pos) == 0 } fn set_high(&self, pos: u8) { unsafe { self.bsrr.write(|w| w.bits(1 << pos)) } } fn set_low(&self, pos: u8) { unsafe { self.bsrr.write(|w| w.bits(1 << (pos + 16))) } } } impl GpioRegExt for crate::pac::gpiof::RegisterBlock { fn is_low(&self, pos: u8) -> bool { self.idr.read().bits() & (1 << pos) == 0 } fn is_set_low(&self, pos: u8) -> bool { self.odr.read().bits() & (1 << pos) == 0 } fn set_high(&self, pos: u8) { unsafe { self.bsrr.write(|w| w.bits(1 << pos)) } } fn set_low(&self, pos: u8) { unsafe { self.bsrr.write(|w| w.bits(1 << (pos + 16))) } } } /// GPIO #[cfg(any(feature = "device-selected"))] pub mod gpioa { use core::marker::PhantomData; use core::convert::Infallible; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::{rcc::Rcc, pac::GPIOA}; use cortex_m::interrupt::CriticalSection; use super::{ Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output, PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin, GpioRegExt, }; /// GPIO parts pub struct Parts { /// Pin pub pa0: PA0>, /// Pin pub pa1: PA1>, /// Pin pub pa2: PA2>, /// Pin pub pa3: PA3>, /// Pin pub pa4: PA4>, /// Pin pub pa5: PA5>, /// Pin pub pa6: PA6>, /// Pin pub pa7: PA7>, /// Pin pub pa8: PA8>, /// Pin pub pa9: PA9>, /// Pin pub pa10: PA10>, /// Pin pub pa11: PA11>, /// Pin pub pa12: PA12>, /// Pin pub pa13: PA13>, /// Pin pub pa14: PA14>, /// Pin pub pa15: PA15>, } impl GpioExt for GPIOA { type Parts = Parts; fn split(self, rcc: &mut Rcc) -> Parts { rcc.regs.ahbenr.modify(|_, w| w.iopaen().set_bit()); Parts { pa0: PA0 { _mode: PhantomData }, pa1: PA1 { _mode: PhantomData }, pa2: PA2 { _mode: PhantomData }, pa3: PA3 { _mode: PhantomData }, pa4: PA4 { _mode: PhantomData }, pa5: PA5 { _mode: PhantomData }, pa6: PA6 { _mode: PhantomData }, pa7: PA7 { _mode: PhantomData }, pa8: PA8 { _mode: PhantomData }, pa9: PA9 { _mode: PhantomData }, pa10: PA10 { _mode: PhantomData }, pa11: PA11 { _mode: PhantomData }, pa12: PA12 { _mode: PhantomData }, pa13: PA13 { _mode: PhantomData }, pa14: PA14 { _mode: PhantomData }, pa15: PA15 { _mode: PhantomData }, } } } fn _set_alternate_mode(index: usize, mode: u32) { let offset = 2 * index; let offset2 = 4 * index; unsafe { let reg = &(*GPIOA::ptr()); if offset2 < 32 { reg.afrl.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; reg.afrh.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); } } /// Pin pub struct PA0 { _mode: PhantomData, } impl PA0 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 0); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 1); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 2); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 3); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 4); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 5); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 6); PA0 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA0> { _set_alternate_mode(0, 7); PA0 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA0 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA0 { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA0 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA0 { _mode: PhantomData } } } impl PA0> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA0> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA0> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 0; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA0> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(0) }) } } impl OutputPin for PA0> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(0) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(0) }) } } impl toggleable::Default for PA0> {} impl InputPin for PA0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(0) }) } } impl PA0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(0) }) } } /// Pin pub struct PA1 { _mode: PhantomData, } impl PA1 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 0); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 1); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 2); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 3); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 4); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 5); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 6); PA1 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA1> { _set_alternate_mode(1, 7); PA1 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA1 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA1 { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA1 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA1 { _mode: PhantomData } } } impl PA1> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA1> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA1> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 1; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA1> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(1) }) } } impl OutputPin for PA1> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(1) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(1) }) } } impl toggleable::Default for PA1> {} impl InputPin for PA1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(1) }) } } impl PA1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(1) }) } } /// Pin pub struct PA2 { _mode: PhantomData, } impl PA2 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 0); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 1); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 2); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 3); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 4); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 5); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 6); PA2 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA2> { _set_alternate_mode(2, 7); PA2 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA2 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA2 { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA2 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA2 { _mode: PhantomData } } } impl PA2> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA2> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA2> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 2; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA2> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(2) }) } } impl OutputPin for PA2> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(2) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(2) }) } } impl toggleable::Default for PA2> {} impl InputPin for PA2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(2) }) } } impl PA2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(2) }) } } /// Pin pub struct PA3 { _mode: PhantomData, } impl PA3 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 0); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 1); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 2); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 3); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 4); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 5); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 6); PA3 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA3> { _set_alternate_mode(3, 7); PA3 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA3 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA3 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA3 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA3 { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA3 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA3 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA3 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA3 { _mode: PhantomData } } } impl PA3> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 3; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA3> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 3; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA3> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 3; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA3> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 3, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA3> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(3) }) } } impl OutputPin for PA3> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(3) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(3) }) } } impl toggleable::Default for PA3> {} impl InputPin for PA3> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(3) }) } } impl PA3> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 3, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA3> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(3) }) } } /// Pin pub struct PA4 { _mode: PhantomData, } impl PA4 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 0); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 1); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 2); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 3); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 4); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 5); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 6); PA4 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA4> { _set_alternate_mode(4, 7); PA4 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA4 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA4 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA4 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA4 { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA4 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA4 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA4 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA4 { _mode: PhantomData } } } impl PA4> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 4; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA4> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 4; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA4> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 4; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA4> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 4, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA4> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(4) }) } } impl OutputPin for PA4> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(4) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(4) }) } } impl toggleable::Default for PA4> {} impl InputPin for PA4> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(4) }) } } impl PA4> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 4, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA4> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(4) }) } } /// Pin pub struct PA5 { _mode: PhantomData, } impl PA5 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 0); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 1); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 2); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 3); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 4); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 5); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 6); PA5 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA5> { _set_alternate_mode(5, 7); PA5 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA5 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA5 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA5 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA5 { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA5 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA5 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA5 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA5 { _mode: PhantomData } } } impl PA5> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 5; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA5> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 5; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA5> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 5; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA5> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 5, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA5> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(5) }) } } impl OutputPin for PA5> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(5) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(5) }) } } impl toggleable::Default for PA5> {} impl InputPin for PA5> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(5) }) } } impl PA5> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 5, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA5> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(5) }) } } /// Pin pub struct PA6 { _mode: PhantomData, } impl PA6 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 0); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 1); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 2); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 3); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 4); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 5); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 6); PA6 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA6> { _set_alternate_mode(6, 7); PA6 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA6 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA6 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA6 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA6 { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA6 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA6 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA6 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA6 { _mode: PhantomData } } } impl PA6> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 6; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA6> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 6; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA6> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 6; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA6> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 6, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA6> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(6) }) } } impl OutputPin for PA6> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(6) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(6) }) } } impl toggleable::Default for PA6> {} impl InputPin for PA6> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(6) }) } } impl PA6> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 6, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA6> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(6) }) } } /// Pin pub struct PA7 { _mode: PhantomData, } impl PA7 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 0); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 1); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 2); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 3); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 4); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 5); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 6); PA7 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA7> { _set_alternate_mode(7, 7); PA7 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA7 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA7 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA7 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA7 { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA7 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA7 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA7 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA7 { _mode: PhantomData } } } impl PA7> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 7; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA7> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 7; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA7> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 7; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA7> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 7, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA7> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(7) }) } } impl OutputPin for PA7> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(7) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(7) }) } } impl toggleable::Default for PA7> {} impl InputPin for PA7> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(7) }) } } impl PA7> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 7, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA7> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(7) }) } } /// Pin pub struct PA8 { _mode: PhantomData, } impl PA8 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 0); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 1); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 2); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 3); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 4); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 5); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 6); PA8 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA8> { _set_alternate_mode(8, 7); PA8 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA8 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA8 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA8 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA8 { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA8 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA8 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA8 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA8 { _mode: PhantomData } } } impl PA8> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 8; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA8> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 8; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA8> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 8; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA8> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 8, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA8> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(8) }) } } impl OutputPin for PA8> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(8) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(8) }) } } impl toggleable::Default for PA8> {} impl InputPin for PA8> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(8) }) } } impl PA8> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 8, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA8> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(8) }) } } /// Pin pub struct PA9 { _mode: PhantomData, } impl PA9 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 0); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 1); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 2); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 3); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 4); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 5); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 6); PA9 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA9> { _set_alternate_mode(9, 7); PA9 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA9 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA9 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA9 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA9 { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA9 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA9 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA9 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA9 { _mode: PhantomData } } } impl PA9> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 9; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA9> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 9; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA9> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 9; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA9> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 9, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA9> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(9) }) } } impl OutputPin for PA9> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(9) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(9) }) } } impl toggleable::Default for PA9> {} impl InputPin for PA9> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(9) }) } } impl PA9> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 9, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA9> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(9) }) } } /// Pin pub struct PA10 { _mode: PhantomData, } impl PA10 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 0); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 1); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 2); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 3); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 4); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 5); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 6); PA10 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA10> { _set_alternate_mode(10, 7); PA10 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA10 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA10 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA10 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA10 { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA10 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA10 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA10 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA10 { _mode: PhantomData } } } impl PA10> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 10; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA10> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 10; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA10> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 10; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA10> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 10, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA10> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(10) }) } } impl OutputPin for PA10> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(10) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(10) }) } } impl toggleable::Default for PA10> {} impl InputPin for PA10> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(10) }) } } impl PA10> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 10, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA10> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(10) }) } } /// Pin pub struct PA11 { _mode: PhantomData, } impl PA11 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 0); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 1); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 2); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 3); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 4); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 5); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 6); PA11 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA11> { _set_alternate_mode(11, 7); PA11 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA11 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA11 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA11 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA11 { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA11 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA11 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA11 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA11 { _mode: PhantomData } } } impl PA11> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 11; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA11> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 11; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA11> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 11; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA11> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 11, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA11> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(11) }) } } impl OutputPin for PA11> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(11) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(11) }) } } impl toggleable::Default for PA11> {} impl InputPin for PA11> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(11) }) } } impl PA11> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 11, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA11> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(11) }) } } /// Pin pub struct PA12 { _mode: PhantomData, } impl PA12 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 0); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 1); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 2); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 3); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 4); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 5); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 6); PA12 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA12> { _set_alternate_mode(12, 7); PA12 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA12 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA12 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA12 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA12 { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA12 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA12 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA12 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA12 { _mode: PhantomData } } } impl PA12> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 12; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA12> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 12; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA12> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 12; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA12> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 12, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA12> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(12) }) } } impl OutputPin for PA12> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(12) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(12) }) } } impl toggleable::Default for PA12> {} impl InputPin for PA12> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(12) }) } } impl PA12> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 12, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA12> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(12) }) } } /// Pin pub struct PA13 { _mode: PhantomData, } impl PA13 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 0); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 1); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 2); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 3); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 4); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 5); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 6); PA13 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA13> { _set_alternate_mode(13, 7); PA13 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA13 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA13 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA13 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA13 { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA13 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA13 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA13 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA13 { _mode: PhantomData } } } impl PA13> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 13; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA13> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 13; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA13> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 13; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA13> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 13, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA13> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(13) }) } } impl OutputPin for PA13> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(13) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(13) }) } } impl toggleable::Default for PA13> {} impl InputPin for PA13> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(13) }) } } impl PA13> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 13, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA13> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(13) }) } } /// Pin pub struct PA14 { _mode: PhantomData, } impl PA14 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 0); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 1); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 2); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 3); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 4); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 5); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 6); PA14 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA14> { _set_alternate_mode(14, 7); PA14 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA14 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA14 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA14 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA14 { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA14 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA14 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA14 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA14 { _mode: PhantomData } } } impl PA14> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 14; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA14> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 14; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA14> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 14; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA14> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 14, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA14> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(14) }) } } impl OutputPin for PA14> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(14) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(14) }) } } impl toggleable::Default for PA14> {} impl InputPin for PA14> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(14) }) } } impl PA14> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 14, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA14> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(14) }) } } /// Pin pub struct PA15 { _mode: PhantomData, } impl PA15 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 0); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 1); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 2); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 3); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 4); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 5); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 6); PA15 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PA15> { _set_alternate_mode(15, 7); PA15 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PA15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA15 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PA15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA15 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PA15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PA15 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PA15 { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PA15 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PA15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA15 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PA15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA15 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PA15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PA15 { _mode: PhantomData } } } impl PA15> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 15; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PA15> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 15; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOA::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PA15> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 15; unsafe { let reg = &(*GPIOA::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PA15> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 15, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PA15> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_set_low(15) }) } } impl OutputPin for PA15> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_high(15) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOA::ptr()).set_low(15) }) } } impl toggleable::Default for PA15> {} impl InputPin for PA15> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(15) }) } } impl PA15> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 15, port: GPIOA::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PA15> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOA::ptr()).is_low(15) }) } } } /// GPIO #[cfg(any(feature = "device-selected"))] pub mod gpiob { use core::marker::PhantomData; use core::convert::Infallible; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::{rcc::Rcc, pac::GPIOB}; use cortex_m::interrupt::CriticalSection; use super::{ Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output, PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin, GpioRegExt, }; /// GPIO parts pub struct Parts { /// Pin pub pb0: PB0>, /// Pin pub pb1: PB1>, /// Pin pub pb2: PB2>, /// Pin pub pb3: PB3>, /// Pin pub pb4: PB4>, /// Pin pub pb5: PB5>, /// Pin pub pb6: PB6>, /// Pin pub pb7: PB7>, /// Pin pub pb8: PB8>, /// Pin pub pb9: PB9>, /// Pin pub pb10: PB10>, /// Pin pub pb11: PB11>, /// Pin pub pb12: PB12>, /// Pin pub pb13: PB13>, /// Pin pub pb14: PB14>, /// Pin pub pb15: PB15>, } impl GpioExt for GPIOB { type Parts = Parts; fn split(self, rcc: &mut Rcc) -> Parts { rcc.regs.ahbenr.modify(|_, w| w.iopben().set_bit()); Parts { pb0: PB0 { _mode: PhantomData }, pb1: PB1 { _mode: PhantomData }, pb2: PB2 { _mode: PhantomData }, pb3: PB3 { _mode: PhantomData }, pb4: PB4 { _mode: PhantomData }, pb5: PB5 { _mode: PhantomData }, pb6: PB6 { _mode: PhantomData }, pb7: PB7 { _mode: PhantomData }, pb8: PB8 { _mode: PhantomData }, pb9: PB9 { _mode: PhantomData }, pb10: PB10 { _mode: PhantomData }, pb11: PB11 { _mode: PhantomData }, pb12: PB12 { _mode: PhantomData }, pb13: PB13 { _mode: PhantomData }, pb14: PB14 { _mode: PhantomData }, pb15: PB15 { _mode: PhantomData }, } } } fn _set_alternate_mode(index: usize, mode: u32) { let offset = 2 * index; let offset2 = 4 * index; unsafe { let reg = &(*GPIOB::ptr()); if offset2 < 32 { reg.afrl.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; reg.afrh.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); } } /// Pin pub struct PB0 { _mode: PhantomData, } impl PB0 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 0); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 1); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 2); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 3); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 4); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 5); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 6); PB0 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB0> { _set_alternate_mode(0, 7); PB0 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB0 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB0 { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB0 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB0 { _mode: PhantomData } } } impl PB0> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB0> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB0> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 0; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB0> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(0) }) } } impl OutputPin for PB0> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(0) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(0) }) } } impl toggleable::Default for PB0> {} impl InputPin for PB0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(0) }) } } impl PB0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(0) }) } } /// Pin pub struct PB1 { _mode: PhantomData, } impl PB1 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 0); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 1); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 2); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 3); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 4); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 5); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 6); PB1 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB1> { _set_alternate_mode(1, 7); PB1 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB1 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB1 { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB1 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB1 { _mode: PhantomData } } } impl PB1> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB1> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB1> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 1; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB1> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(1) }) } } impl OutputPin for PB1> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(1) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(1) }) } } impl toggleable::Default for PB1> {} impl InputPin for PB1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(1) }) } } impl PB1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(1) }) } } /// Pin pub struct PB2 { _mode: PhantomData, } impl PB2 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 0); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 1); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 2); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 3); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 4); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 5); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 6); PB2 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB2> { _set_alternate_mode(2, 7); PB2 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB2 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB2 { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB2 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB2 { _mode: PhantomData } } } impl PB2> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB2> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB2> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 2; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB2> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(2) }) } } impl OutputPin for PB2> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(2) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(2) }) } } impl toggleable::Default for PB2> {} impl InputPin for PB2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(2) }) } } impl PB2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(2) }) } } /// Pin pub struct PB3 { _mode: PhantomData, } impl PB3 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 0); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 1); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 2); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 3); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 4); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 5); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 6); PB3 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB3> { _set_alternate_mode(3, 7); PB3 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB3 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB3 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB3 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB3 { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB3 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB3 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB3 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB3 { _mode: PhantomData } } } impl PB3> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 3; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB3> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 3; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB3> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 3; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB3> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 3, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB3> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(3) }) } } impl OutputPin for PB3> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(3) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(3) }) } } impl toggleable::Default for PB3> {} impl InputPin for PB3> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(3) }) } } impl PB3> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 3, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB3> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(3) }) } } /// Pin pub struct PB4 { _mode: PhantomData, } impl PB4 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 0); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 1); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 2); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 3); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 4); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 5); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 6); PB4 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB4> { _set_alternate_mode(4, 7); PB4 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB4 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB4 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB4 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB4 { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB4 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB4 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB4 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB4 { _mode: PhantomData } } } impl PB4> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 4; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB4> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 4; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB4> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 4; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB4> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 4, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB4> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(4) }) } } impl OutputPin for PB4> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(4) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(4) }) } } impl toggleable::Default for PB4> {} impl InputPin for PB4> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(4) }) } } impl PB4> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 4, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB4> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(4) }) } } /// Pin pub struct PB5 { _mode: PhantomData, } impl PB5 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 0); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 1); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 2); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 3); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 4); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 5); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 6); PB5 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB5> { _set_alternate_mode(5, 7); PB5 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB5 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB5 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB5 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB5 { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB5 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB5 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB5 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB5 { _mode: PhantomData } } } impl PB5> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 5; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB5> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 5; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB5> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 5; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB5> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 5, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB5> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(5) }) } } impl OutputPin for PB5> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(5) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(5) }) } } impl toggleable::Default for PB5> {} impl InputPin for PB5> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(5) }) } } impl PB5> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 5, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB5> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(5) }) } } /// Pin pub struct PB6 { _mode: PhantomData, } impl PB6 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 0); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 1); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 2); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 3); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 4); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 5); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 6); PB6 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB6> { _set_alternate_mode(6, 7); PB6 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB6 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB6 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB6 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB6 { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB6 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB6 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB6 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB6 { _mode: PhantomData } } } impl PB6> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 6; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB6> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 6; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB6> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 6; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB6> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 6, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB6> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(6) }) } } impl OutputPin for PB6> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(6) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(6) }) } } impl toggleable::Default for PB6> {} impl InputPin for PB6> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(6) }) } } impl PB6> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 6, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB6> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(6) }) } } /// Pin pub struct PB7 { _mode: PhantomData, } impl PB7 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 0); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 1); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 2); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 3); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 4); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 5); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 6); PB7 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB7> { _set_alternate_mode(7, 7); PB7 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB7 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB7 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB7 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB7 { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB7 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB7 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB7 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB7 { _mode: PhantomData } } } impl PB7> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 7; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB7> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 7; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB7> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 7; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB7> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 7, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB7> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(7) }) } } impl OutputPin for PB7> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(7) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(7) }) } } impl toggleable::Default for PB7> {} impl InputPin for PB7> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(7) }) } } impl PB7> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 7, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB7> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(7) }) } } /// Pin pub struct PB8 { _mode: PhantomData, } impl PB8 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 0); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 1); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 2); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 3); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 4); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 5); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 6); PB8 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB8> { _set_alternate_mode(8, 7); PB8 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB8 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB8 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB8 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB8 { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB8 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB8 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB8 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB8 { _mode: PhantomData } } } impl PB8> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 8; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB8> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 8; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB8> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 8; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB8> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 8, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB8> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(8) }) } } impl OutputPin for PB8> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(8) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(8) }) } } impl toggleable::Default for PB8> {} impl InputPin for PB8> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(8) }) } } impl PB8> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 8, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB8> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(8) }) } } /// Pin pub struct PB9 { _mode: PhantomData, } impl PB9 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 0); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 1); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 2); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 3); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 4); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 5); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 6); PB9 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB9> { _set_alternate_mode(9, 7); PB9 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB9 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB9 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB9 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB9 { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB9 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB9 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB9 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB9 { _mode: PhantomData } } } impl PB9> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 9; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB9> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 9; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB9> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 9; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB9> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 9, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB9> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(9) }) } } impl OutputPin for PB9> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(9) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(9) }) } } impl toggleable::Default for PB9> {} impl InputPin for PB9> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(9) }) } } impl PB9> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 9, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB9> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(9) }) } } /// Pin pub struct PB10 { _mode: PhantomData, } impl PB10 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 0); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 1); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 2); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 3); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 4); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 5); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 6); PB10 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB10> { _set_alternate_mode(10, 7); PB10 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB10 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB10 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB10 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB10 { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB10 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB10 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB10 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB10 { _mode: PhantomData } } } impl PB10> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 10; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB10> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 10; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB10> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 10; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB10> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 10, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB10> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(10) }) } } impl OutputPin for PB10> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(10) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(10) }) } } impl toggleable::Default for PB10> {} impl InputPin for PB10> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(10) }) } } impl PB10> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 10, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB10> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(10) }) } } /// Pin pub struct PB11 { _mode: PhantomData, } impl PB11 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 0); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 1); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 2); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 3); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 4); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 5); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 6); PB11 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB11> { _set_alternate_mode(11, 7); PB11 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB11 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB11 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB11 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB11 { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB11 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB11 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB11 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB11 { _mode: PhantomData } } } impl PB11> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 11; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB11> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 11; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB11> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 11; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB11> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 11, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB11> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(11) }) } } impl OutputPin for PB11> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(11) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(11) }) } } impl toggleable::Default for PB11> {} impl InputPin for PB11> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(11) }) } } impl PB11> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 11, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB11> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(11) }) } } /// Pin pub struct PB12 { _mode: PhantomData, } impl PB12 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 0); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 1); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 2); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 3); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 4); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 5); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 6); PB12 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB12> { _set_alternate_mode(12, 7); PB12 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB12 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB12 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB12 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB12 { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB12 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB12 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB12 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB12 { _mode: PhantomData } } } impl PB12> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 12; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB12> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 12; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB12> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 12; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB12> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 12, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB12> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(12) }) } } impl OutputPin for PB12> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(12) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(12) }) } } impl toggleable::Default for PB12> {} impl InputPin for PB12> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(12) }) } } impl PB12> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 12, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB12> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(12) }) } } /// Pin pub struct PB13 { _mode: PhantomData, } impl PB13 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 0); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 1); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 2); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 3); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 4); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 5); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 6); PB13 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB13> { _set_alternate_mode(13, 7); PB13 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB13 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB13 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB13 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB13 { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB13 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB13 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB13 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB13 { _mode: PhantomData } } } impl PB13> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 13; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB13> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 13; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB13> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 13; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB13> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 13, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB13> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(13) }) } } impl OutputPin for PB13> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(13) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(13) }) } } impl toggleable::Default for PB13> {} impl InputPin for PB13> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(13) }) } } impl PB13> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 13, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB13> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(13) }) } } /// Pin pub struct PB14 { _mode: PhantomData, } impl PB14 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 0); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 1); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 2); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 3); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 4); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 5); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 6); PB14 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB14> { _set_alternate_mode(14, 7); PB14 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB14 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB14 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB14 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB14 { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB14 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB14 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB14 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB14 { _mode: PhantomData } } } impl PB14> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 14; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB14> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 14; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB14> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 14; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB14> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 14, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB14> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(14) }) } } impl OutputPin for PB14> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(14) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(14) }) } } impl toggleable::Default for PB14> {} impl InputPin for PB14> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(14) }) } } impl PB14> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 14, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB14> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(14) }) } } /// Pin pub struct PB15 { _mode: PhantomData, } impl PB15 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 0); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 1); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 2); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 3); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 4); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 5); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 6); PB15 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PB15> { _set_alternate_mode(15, 7); PB15 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PB15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB15 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PB15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB15 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PB15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PB15 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PB15 { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PB15 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PB15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB15 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PB15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB15 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PB15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PB15 { _mode: PhantomData } } } impl PB15> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 15; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PB15> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 15; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOB::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PB15> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 15; unsafe { let reg = &(*GPIOB::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PB15> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 15, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PB15> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_set_low(15) }) } } impl OutputPin for PB15> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_high(15) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOB::ptr()).set_low(15) }) } } impl toggleable::Default for PB15> {} impl InputPin for PB15> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(15) }) } } impl PB15> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 15, port: GPIOB::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PB15> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOB::ptr()).is_low(15) }) } } } /// GPIO #[cfg(any( feature = "stm32f030", feature = "stm32f051", feature = "stm32f058", feature = "stm32f070", feature = "stm32f071", feature = "stm32f072", feature = "stm32f078", feature = "stm32f091", feature = "stm32f098" ))] pub mod gpioc { use core::marker::PhantomData; use core::convert::Infallible; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::{rcc::Rcc, pac::GPIOC}; use cortex_m::interrupt::CriticalSection; use super::{ Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output, PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin, GpioRegExt, }; /// GPIO parts pub struct Parts { /// Pin pub pc0: PC0>, /// Pin pub pc1: PC1>, /// Pin pub pc2: PC2>, /// Pin pub pc3: PC3>, /// Pin pub pc4: PC4>, /// Pin pub pc5: PC5>, /// Pin pub pc6: PC6>, /// Pin pub pc7: PC7>, /// Pin pub pc8: PC8>, /// Pin pub pc9: PC9>, /// Pin pub pc10: PC10>, /// Pin pub pc11: PC11>, /// Pin pub pc12: PC12>, /// Pin pub pc13: PC13>, /// Pin pub pc14: PC14>, /// Pin pub pc15: PC15>, } impl GpioExt for GPIOC { type Parts = Parts; fn split(self, rcc: &mut Rcc) -> Parts { rcc.regs.ahbenr.modify(|_, w| w.iopcen().set_bit()); Parts { pc0: PC0 { _mode: PhantomData }, pc1: PC1 { _mode: PhantomData }, pc2: PC2 { _mode: PhantomData }, pc3: PC3 { _mode: PhantomData }, pc4: PC4 { _mode: PhantomData }, pc5: PC5 { _mode: PhantomData }, pc6: PC6 { _mode: PhantomData }, pc7: PC7 { _mode: PhantomData }, pc8: PC8 { _mode: PhantomData }, pc9: PC9 { _mode: PhantomData }, pc10: PC10 { _mode: PhantomData }, pc11: PC11 { _mode: PhantomData }, pc12: PC12 { _mode: PhantomData }, pc13: PC13 { _mode: PhantomData }, pc14: PC14 { _mode: PhantomData }, pc15: PC15 { _mode: PhantomData }, } } } fn _set_alternate_mode(index: usize, mode: u32) { let offset = 2 * index; let offset2 = 4 * index; unsafe { let reg = &(*GPIOC::ptr()); if offset2 < 32 { reg.afrl.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; reg.afrh.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); } } /// Pin pub struct PC0 { _mode: PhantomData, } impl PC0 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 0); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 1); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 2); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 3); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 4); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 5); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 6); PC0 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC0> { _set_alternate_mode(0, 7); PC0 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC0 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC0 { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC0 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC0 { _mode: PhantomData } } } impl PC0> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC0> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC0> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 0; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC0> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(0) }) } } impl OutputPin for PC0> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(0) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(0) }) } } impl toggleable::Default for PC0> {} impl InputPin for PC0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(0) }) } } impl PC0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(0) }) } } /// Pin pub struct PC1 { _mode: PhantomData, } impl PC1 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 0); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 1); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 2); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 3); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 4); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 5); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 6); PC1 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC1> { _set_alternate_mode(1, 7); PC1 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC1 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC1 { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC1 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC1 { _mode: PhantomData } } } impl PC1> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC1> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC1> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 1; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC1> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(1) }) } } impl OutputPin for PC1> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(1) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(1) }) } } impl toggleable::Default for PC1> {} impl InputPin for PC1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(1) }) } } impl PC1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(1) }) } } /// Pin pub struct PC2 { _mode: PhantomData, } impl PC2 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 0); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 1); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 2); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 3); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 4); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 5); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 6); PC2 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC2> { _set_alternate_mode(2, 7); PC2 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC2 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC2 { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC2 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC2 { _mode: PhantomData } } } impl PC2> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC2> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC2> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 2; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC2> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(2) }) } } impl OutputPin for PC2> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(2) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(2) }) } } impl toggleable::Default for PC2> {} impl InputPin for PC2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(2) }) } } impl PC2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(2) }) } } /// Pin pub struct PC3 { _mode: PhantomData, } impl PC3 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 0); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 1); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 2); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 3); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 4); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 5); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 6); PC3 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC3> { _set_alternate_mode(3, 7); PC3 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC3 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC3 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC3 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC3 { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC3 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC3 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC3 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC3> { let offset = 2 * 3; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 3))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC3 { _mode: PhantomData } } } impl PC3> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 3; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC3> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 3; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC3> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 3; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC3> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 3, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC3> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(3) }) } } impl OutputPin for PC3> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(3) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(3) }) } } impl toggleable::Default for PC3> {} impl InputPin for PC3> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(3) }) } } impl PC3> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 3, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC3> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(3) }) } } /// Pin pub struct PC4 { _mode: PhantomData, } impl PC4 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 0); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 1); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 2); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 3); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 4); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 5); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 6); PC4 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC4> { _set_alternate_mode(4, 7); PC4 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC4 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC4 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC4 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC4 { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC4 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC4 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC4 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC4> { let offset = 2 * 4; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 4))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC4 { _mode: PhantomData } } } impl PC4> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 4; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC4> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 4; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC4> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 4; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC4> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 4, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC4> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(4) }) } } impl OutputPin for PC4> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(4) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(4) }) } } impl toggleable::Default for PC4> {} impl InputPin for PC4> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(4) }) } } impl PC4> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 4, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC4> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(4) }) } } /// Pin pub struct PC5 { _mode: PhantomData, } impl PC5 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 0); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 1); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 2); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 3); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 4); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 5); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 6); PC5 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC5> { _set_alternate_mode(5, 7); PC5 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC5 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC5 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC5 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC5 { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC5 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC5 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC5 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC5> { let offset = 2 * 5; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 5))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC5 { _mode: PhantomData } } } impl PC5> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 5; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC5> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 5; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC5> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 5; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC5> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 5, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC5> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(5) }) } } impl OutputPin for PC5> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(5) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(5) }) } } impl toggleable::Default for PC5> {} impl InputPin for PC5> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(5) }) } } impl PC5> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 5, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC5> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(5) }) } } /// Pin pub struct PC6 { _mode: PhantomData, } impl PC6 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 0); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 1); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 2); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 3); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 4); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 5); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 6); PC6 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC6> { _set_alternate_mode(6, 7); PC6 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC6 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC6 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC6 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC6 { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC6 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC6 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC6 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC6> { let offset = 2 * 6; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 6))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC6 { _mode: PhantomData } } } impl PC6> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 6; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC6> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 6; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC6> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 6; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC6> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 6, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC6> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(6) }) } } impl OutputPin for PC6> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(6) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(6) }) } } impl toggleable::Default for PC6> {} impl InputPin for PC6> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(6) }) } } impl PC6> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 6, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC6> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(6) }) } } /// Pin pub struct PC7 { _mode: PhantomData, } impl PC7 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 0); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 1); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 2); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 3); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 4); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 5); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 6); PC7 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC7> { _set_alternate_mode(7, 7); PC7 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC7 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC7 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC7 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC7 { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC7 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC7 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC7 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC7> { let offset = 2 * 7; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 7))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC7 { _mode: PhantomData } } } impl PC7> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 7; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC7> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 7; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC7> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 7; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC7> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 7, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC7> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(7) }) } } impl OutputPin for PC7> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(7) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(7) }) } } impl toggleable::Default for PC7> {} impl InputPin for PC7> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(7) }) } } impl PC7> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 7, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC7> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(7) }) } } /// Pin pub struct PC8 { _mode: PhantomData, } impl PC8 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 0); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 1); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 2); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 3); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 4); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 5); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 6); PC8 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC8> { _set_alternate_mode(8, 7); PC8 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC8 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC8 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC8 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC8 { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC8 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC8 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC8 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC8> { let offset = 2 * 8; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 8))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC8 { _mode: PhantomData } } } impl PC8> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 8; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC8> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 8; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC8> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 8; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC8> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 8, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC8> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(8) }) } } impl OutputPin for PC8> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(8) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(8) }) } } impl toggleable::Default for PC8> {} impl InputPin for PC8> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(8) }) } } impl PC8> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 8, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC8> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(8) }) } } /// Pin pub struct PC9 { _mode: PhantomData, } impl PC9 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 0); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 1); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 2); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 3); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 4); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 5); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 6); PC9 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC9> { _set_alternate_mode(9, 7); PC9 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC9 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC9 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC9 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC9 { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC9 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC9 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC9 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC9> { let offset = 2 * 9; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 9))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC9 { _mode: PhantomData } } } impl PC9> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 9; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC9> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 9; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC9> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 9; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC9> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 9, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC9> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(9) }) } } impl OutputPin for PC9> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(9) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(9) }) } } impl toggleable::Default for PC9> {} impl InputPin for PC9> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(9) }) } } impl PC9> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 9, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC9> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(9) }) } } /// Pin pub struct PC10 { _mode: PhantomData, } impl PC10 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 0); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 1); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 2); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 3); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 4); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 5); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 6); PC10 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC10> { _set_alternate_mode(10, 7); PC10 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC10 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC10 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC10 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC10 { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC10 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC10 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC10 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC10> { let offset = 2 * 10; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 10))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC10 { _mode: PhantomData } } } impl PC10> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 10; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC10> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 10; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC10> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 10; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC10> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 10, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC10> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(10) }) } } impl OutputPin for PC10> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(10) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(10) }) } } impl toggleable::Default for PC10> {} impl InputPin for PC10> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(10) }) } } impl PC10> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 10, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC10> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(10) }) } } /// Pin pub struct PC11 { _mode: PhantomData, } impl PC11 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 0); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 1); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 2); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 3); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 4); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 5); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 6); PC11 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC11> { _set_alternate_mode(11, 7); PC11 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC11 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC11 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC11 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC11 { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC11 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC11 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC11 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC11> { let offset = 2 * 11; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 11))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC11 { _mode: PhantomData } } } impl PC11> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 11; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC11> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 11; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC11> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 11; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC11> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 11, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC11> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(11) }) } } impl OutputPin for PC11> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(11) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(11) }) } } impl toggleable::Default for PC11> {} impl InputPin for PC11> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(11) }) } } impl PC11> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 11, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC11> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(11) }) } } /// Pin pub struct PC12 { _mode: PhantomData, } impl PC12 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 0); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 1); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 2); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 3); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 4); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 5); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 6); PC12 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC12> { _set_alternate_mode(12, 7); PC12 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC12 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC12 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC12 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC12 { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC12 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC12 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC12 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC12> { let offset = 2 * 12; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 12))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC12 { _mode: PhantomData } } } impl PC12> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 12; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC12> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 12; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC12> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 12; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC12> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 12, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC12> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(12) }) } } impl OutputPin for PC12> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(12) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(12) }) } } impl toggleable::Default for PC12> {} impl InputPin for PC12> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(12) }) } } impl PC12> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 12, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC12> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(12) }) } } /// Pin pub struct PC13 { _mode: PhantomData, } impl PC13 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 0); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 1); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 2); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 3); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 4); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 5); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 6); PC13 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC13> { _set_alternate_mode(13, 7); PC13 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC13 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC13 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC13 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC13 { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC13 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC13 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC13 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC13> { let offset = 2 * 13; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 13))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC13 { _mode: PhantomData } } } impl PC13> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 13; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC13> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 13; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC13> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 13; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC13> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 13, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC13> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(13) }) } } impl OutputPin for PC13> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(13) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(13) }) } } impl toggleable::Default for PC13> {} impl InputPin for PC13> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(13) }) } } impl PC13> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 13, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC13> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(13) }) } } /// Pin pub struct PC14 { _mode: PhantomData, } impl PC14 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 0); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 1); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 2); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 3); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 4); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 5); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 6); PC14 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC14> { _set_alternate_mode(14, 7); PC14 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC14 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC14 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC14 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC14 { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC14 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC14 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC14 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC14> { let offset = 2 * 14; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 14))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC14 { _mode: PhantomData } } } impl PC14> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 14; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC14> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 14; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC14> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 14; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC14> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 14, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC14> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(14) }) } } impl OutputPin for PC14> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(14) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(14) }) } } impl toggleable::Default for PC14> {} impl InputPin for PC14> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(14) }) } } impl PC14> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 14, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC14> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(14) }) } } /// Pin pub struct PC15 { _mode: PhantomData, } impl PC15 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 0); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 1); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 2); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 3); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 4); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 5); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 6); PC15 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PC15> { _set_alternate_mode(15, 7); PC15 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PC15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC15 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PC15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC15 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PC15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PC15 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PC15 { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PC15 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PC15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC15 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PC15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC15 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PC15> { let offset = 2 * 15; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 15))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PC15 { _mode: PhantomData } } } impl PC15> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 15; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PC15> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 15; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOC::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PC15> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 15; unsafe { let reg = &(*GPIOC::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PC15> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 15, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PC15> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_set_low(15) }) } } impl OutputPin for PC15> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_high(15) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOC::ptr()).set_low(15) }) } } impl toggleable::Default for PC15> {} impl InputPin for PC15> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(15) }) } } impl PC15> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 15, port: GPIOC::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PC15> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOC::ptr()).is_low(15) }) } } } /// GPIO #[cfg(any( feature = "stm32f030", feature = "stm32f051", feature = "stm32f058", feature = "stm32f070" ))] pub mod gpiod { use core::marker::PhantomData; use core::convert::Infallible; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::{rcc::Rcc, pac::GPIOD}; use cortex_m::interrupt::CriticalSection; use super::{ Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output, PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin, GpioRegExt, }; /// GPIO parts pub struct Parts { /// Pin pub pd2: PD2>, } impl GpioExt for GPIOD { type Parts = Parts; fn split(self, rcc: &mut Rcc) -> Parts { rcc.regs.ahbenr.modify(|_, w| w.iopden().set_bit()); Parts { pd2: PD2 { _mode: PhantomData }, } } } fn _set_alternate_mode(index: usize, mode: u32) { let offset = 2 * index; let offset2 = 4 * index; unsafe { let reg = &(*GPIOD::ptr()); if offset2 < 32 { reg.afrl.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; reg.afrh.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); } } /// Pin pub struct PD2 { _mode: PhantomData, } impl PD2 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 0); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 1); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 2); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 3); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 4); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 5); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 6); PD2 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PD2> { _set_alternate_mode(2, 7); PD2 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PD2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PD2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PD2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PD2 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PD2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PD2 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PD2 { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PD2 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PD2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PD2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PD2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PD2 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PD2> { let offset = 2 * 2; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 2))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PD2 { _mode: PhantomData } } } impl PD2> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PD2> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 2; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOD::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PD2> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 2; unsafe { let reg = &(*GPIOD::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PD2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOD::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PD2> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOD::ptr()).is_set_low(2) }) } } impl OutputPin for PD2> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOD::ptr()).set_high(2) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOD::ptr()).set_low(2) }) } } impl toggleable::Default for PD2> {} impl InputPin for PD2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOD::ptr()).is_low(2) }) } } impl PD2> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 2, port: GPIOD::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PD2> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOD::ptr()).is_low(2) }) } } } /// GPIO #[cfg(any(feature = "stm32f030xc", feature = "stm32f070"))] pub mod gpiof { use core::marker::PhantomData; use core::convert::Infallible; use embedded_hal::digital::v2::{InputPin, OutputPin, StatefulOutputPin, toggleable}; use crate::{rcc::Rcc, pac::GPIOF}; use cortex_m::interrupt::CriticalSection; use super::{ Alternate, Analog, Floating, GpioExt, Input, OpenDrain, Output, PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin, GpioRegExt, }; /// GPIO parts pub struct Parts { /// Pin pub pf0: PF0>, /// Pin pub pf1: PF1>, } impl GpioExt for GPIOF { type Parts = Parts; fn split(self, rcc: &mut Rcc) -> Parts { rcc.regs.ahbenr.modify(|_, w| w.iopfen().set_bit()); Parts { pf0: PF0 { _mode: PhantomData }, pf1: PF1 { _mode: PhantomData }, } } } fn _set_alternate_mode(index: usize, mode: u32) { let offset = 2 * index; let offset2 = 4 * index; unsafe { let reg = &(*GPIOF::ptr()); if offset2 < 32 { reg.afrl.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } else { let offset2 = offset2 - 32; reg.afrh.modify(|r, w| { w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2)) }); } reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); } } /// Pin pub struct PF0 { _mode: PhantomData, } impl PF0 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 0); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 1); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 2); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 3); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 4); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 5); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 6); PF0 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PF0> { _set_alternate_mode(0, 7); PF0 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PF0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PF0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PF0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PF0 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PF0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PF0 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PF0 { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PF0 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PF0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PF0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PF0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PF0 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PF0> { let offset = 2 * 0; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 0))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PF0 { _mode: PhantomData } } } impl PF0> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PF0> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 0; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PF0> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 0; unsafe { let reg = &(*GPIOF::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PF0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOF::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PF0> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOF::ptr()).is_set_low(0) }) } } impl OutputPin for PF0> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOF::ptr()).set_high(0) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOF::ptr()).set_low(0) }) } } impl toggleable::Default for PF0> {} impl InputPin for PF0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOF::ptr()).is_low(0) }) } } impl PF0> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 0, port: GPIOF::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PF0> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOF::ptr()).is_low(0) }) } } /// Pin pub struct PF1 { _mode: PhantomData, } impl PF1 { /// Configures the pin to operate in AF0 mode pub fn into_alternate_af0(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 0); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF1 mode pub fn into_alternate_af1(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 1); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF2 mode pub fn into_alternate_af2(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 2); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF3 mode pub fn into_alternate_af3(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 3); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF4 mode pub fn into_alternate_af4(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 4); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF5 mode pub fn into_alternate_af5(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 5); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF6 mode pub fn into_alternate_af6(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 6); PF1 { _mode: PhantomData } } /// Configures the pin to operate in AF7 mode pub fn into_alternate_af7(self, _cs: &CriticalSection) -> PF1> { _set_alternate_mode(1, 7); PF1 { _mode: PhantomData } } /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self, _cs: &CriticalSection) -> PF1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PF1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self, _cs: &CriticalSection) -> PF1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PF1 { _mode: PhantomData } } /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self, _cs: &CriticalSection) -> PF1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); } PF1 { _mode: PhantomData } } /// Configures the pin to operate as an analog pin pub fn into_analog(self, _cs: &CriticalSection) -> PF1 { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b11 << offset))); } PF1 { _mode: PhantomData } } /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self, _cs: &CriticalSection) -> PF1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() | (0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PF1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self, _cs: &CriticalSection) -> PF1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PF1 { _mode: PhantomData } } /// Configures the pin to operate as an push pull output pin with quick fall /// and rise times pub fn into_push_pull_output_hs(self, _cs: &CriticalSection) -> PF1> { let offset = 2 * 1; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))); reg.otyper.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.ospeedr.modify(|r, w| w.bits(r.bits() & !(0b1 << 1))); reg.moder .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))); } PF1 { _mode: PhantomData } } } impl PF1> { /// Enables / disables the internal pull up pub fn internal_pull_up(&mut self, _cs: &CriticalSection, on: bool) { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } } } impl PF1> { /// Enables / disables the internal pull up pub fn internal_pull_up(self, _cs: &CriticalSection, on: bool) -> Self { let offset = 2 * 1; let value = if on { 0b01 } else { 0b00 }; unsafe { let reg = &(*GPIOF::ptr()); reg.pupdr .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (value << offset))); } self } } impl PF1> { /// Turns pin alternate configuration pin into open drain pub fn set_open_drain(self, _cs: &CriticalSection) -> Self { let offset = 1; unsafe { let reg = &(*GPIOF::ptr()); reg.otyper.modify(|r, w| w.bits(r.bits() | (1 << offset))); } self } } impl PF1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOF::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl StatefulOutputPin for PF1> { fn is_set_high(&self) -> Result { self.is_set_low().map(|v| !v) } fn is_set_low(&self) -> Result { Ok(unsafe { (*GPIOF::ptr()).is_set_low(1) }) } } impl OutputPin for PF1> { type Error = Infallible; fn set_high(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOF::ptr()).set_high(1) }) } fn set_low(&mut self) -> Result<(), Self::Error> { Ok(unsafe { (*GPIOF::ptr()).set_low(1) }) } } impl toggleable::Default for PF1> {} impl InputPin for PF1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOF::ptr()).is_low(1) }) } } impl PF1> { /// Erases the pin number from the type /// /// This is useful when you want to collect the pins into an array where you /// need all the elements to have the same type pub fn downgrade(self) -> Pin> { Pin { i: 1, port: GPIOF::ptr() as *const dyn GpioRegExt, _mode: self._mode, } } } impl InputPin for PF1> { type Error = Infallible; fn is_high(&self) -> Result { self.is_low().map(|v| !v) } fn is_low(&self) -> Result { Ok(unsafe { (*GPIOF::ptr()).is_low(1) }) } } } } #[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;