/// 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) }) } } }