use crate::pac;
use core::marker::PhantomData;
mod erased;
pub use erased::{AnyPin, ErasedPin};
mod partially_erased;
pub use partially_erased::{PEPin, PartiallyErasedPin};
mod hal_02;
mod hal_1;
pub trait PinExt {
type Mode;
fn pin_id(&self) -> u8;
fn port_id(&self) -> u8;
}
pub trait GpioExt {
type Parts;
fn split(self) -> Self::Parts;
unsafe fn split_without_reset(self) -> Self::Parts;
}
pub trait Active {}
#[derive(Default)]
pub struct Input<PULL = Floating>(PhantomData<PULL>);
impl<PULL> Active for Input<PULL> {}
#[derive(Default)]
pub struct Debugger;
#[derive(Default)]
pub struct Floating;
#[derive(Default)]
pub struct PullDown;
#[derive(Default)]
pub struct PullUp;
#[derive(Default)]
pub struct Output<Otype = PushPull>(PhantomData<Otype>);
impl<MODE> Active for Output<MODE> {}
#[derive(Default)]
pub struct OpenDrain;
#[derive(Default)]
pub struct PushPull;
#[derive(Default)]
pub struct Analog;
impl Active for Analog {}
#[derive(Default)]
pub struct Alternate<AF>(PhantomData<AF>);
impl<AF> Active for Alternate<AF> {}
#[derive(Default)]
pub struct AF0;
#[derive(Default)]
pub struct AF1;
#[derive(Default)]
pub struct AF2;
#[derive(Default)]
pub struct AF3;
#[derive(Default)]
pub struct AF4;
#[derive(Default)]
pub struct AF5;
#[derive(Default)]
pub struct AF6;
#[derive(Default)]
pub struct AF7;
#[derive(Default)]
pub struct AF8;
#[derive(Default)]
pub struct AF9;
#[derive(Default)]
pub struct AF10;
#[derive(Default)]
pub struct AF11;
#[derive(Default)]
pub struct AF12;
#[derive(Default)]
pub struct AF13;
#[derive(Default)]
pub struct AF14;
#[derive(Default)]
pub struct AF15;
pub use embedded_hal_02::digital::v2::PinState;
#[allow(non_camel_case_types)]
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Edge {
Rising,
Falling,
RisingFalling,
}
mod sealed {
pub trait Interruptable {}
pub trait PinMode: Default {
const CNF: super::Cnf;
const MODE: super::Mode;
const PULL: Option<bool> = None;
const AF: Option<super::Af> = None;
}
}
use crate::pac::gpioa::{afrl::AFSEL0_A as Af, moder::MODE0_A as Mode, otyper::OT0_A as Cnf};
use sealed::Interruptable;
pub(crate) use sealed::PinMode;
impl<MODE> Interruptable for Input<MODE> {}
impl Interruptable for Dynamic {}
pub trait ExtiPin {
fn make_interrupt_source(&mut self, exti: &mut pac::EXTI);
fn trigger_on_edge(&mut self, exti: &mut pac::EXTI, level: Edge);
fn enable_interrupt(&mut self, exti: &mut pac::EXTI);
fn disable_interrupt(&mut self, exti: &mut pac::EXTI);
fn clear_interrupt_pending_bit(&mut self);
fn check_interrupt(&self) -> bool;
}
impl<PIN> ExtiPin for PIN
where
PIN: PinExt,
PIN::Mode: Interruptable,
{
fn make_interrupt_source(&mut self, exti: &mut pac::EXTI) {
let pin_number = self.pin_id();
let offset = 8 * (pin_number % 4);
let port = match self.port_id() {
b'A' => 0,
b'B' => 1,
b'C' | b'F' => 2,
_ => unreachable!(),
};
match pin_number {
0..=3 => {
exti.exticr1.modify(|r, w| unsafe {
w.bits((r.bits() & !(0xf << offset)) | (port << offset))
});
}
4 => {
exti.exticr2.modify(|r, w| unsafe {
w.bits((r.bits() & !(0xf << offset)) | (port << offset))
});
}
5..=7 => {
exti.exticr2
.modify(|r, w| unsafe { w.bits(r.bits() | (port << offset)) });
}
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
8 => {
exti.exticr3
.modify(|r, w| unsafe { w.bits(r.bits() | (port << offset)) });
}
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
9..=15 => {}
_ => unreachable!(),
}
}
fn trigger_on_edge(&mut self, exti: &mut pac::EXTI, edge: Edge) {
let pin_number = self.pin_id();
match edge {
Edge::Rising => {
exti.rtsr
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
exti.ftsr
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << pin_number)) });
}
Edge::Falling => {
exti.rtsr
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << pin_number)) });
exti.ftsr
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
}
Edge::RisingFalling => {
exti.rtsr
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
exti.ftsr
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << pin_number)) });
}
}
}
fn enable_interrupt(&mut self, exti: &mut pac::EXTI) {
exti.imr
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << self.pin_id())) });
}
fn disable_interrupt(&mut self, exti: &mut pac::EXTI) {
exti.imr
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << self.pin_id())) });
}
fn clear_interrupt_pending_bit(&mut self) {
unsafe { (*pac::EXTI::ptr()).pr.write(|w| w.bits(1 << self.pin_id())) };
}
fn check_interrupt(&self) -> bool {
unsafe { ((*pac::EXTI::ptr()).pr.read().bits() & (1 << self.pin_id())) != 0 }
}
}
pub enum Dynamic {
InputFloating,
InputPullUp,
InputPullDown,
OutputPushPull,
OutputOpenDrain,
}
impl Default for Dynamic {
fn default() -> Self {
Dynamic::InputFloating
}
}
impl Active for Dynamic {}
#[derive(Debug, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PinModeError {
IncorrectMode,
}
impl Dynamic {
fn is_input(&self) -> bool {
use Dynamic::*;
match self {
InputFloating | InputPullUp | InputPullDown | OutputOpenDrain => true,
OutputPushPull => false,
}
}
fn is_output(&self) -> bool {
use Dynamic::*;
match self {
InputFloating | InputPullUp | InputPullDown => false,
OutputPushPull | OutputOpenDrain => true,
}
}
}
macro_rules! gpio {
($GPIOX:ident, $gpiox:ident, $PXx:ident, $port_id:expr, [
$($PXi:ident: ($pxi:ident, $pin_number:expr $(, $MODE:ty)?),)+
]) => {
pub mod $gpiox {
use crate::{
rcc::{Enable, Reset},
pac::RCC,
pac::$GPIOX
};
use super::{
Active, PartiallyErasedPin, ErasedPin, Floating, GpioExt, Input,
Pin,
};
#[allow(unused)]
use super::Debugger;
pub struct Parts {
$(
pub $pxi: $PXi $(<$MODE>)?,
)+
}
$(
pub type $PXi<MODE = Input<Floating>> = Pin<$port_id, $pin_number, MODE>;
)+
impl GpioExt for $GPIOX {
type Parts = Parts;
fn split(self) -> Parts {
let rcc = unsafe { &(*RCC::ptr()) };
$GPIOX::enable(rcc);
$GPIOX::reset(rcc);
Parts {
$(
$pxi: $PXi::new(),
)+
}
}
unsafe fn split_without_reset(self) -> Parts {
let rcc = unsafe { &(*RCC::ptr()) };
$GPIOX::enable(rcc);
Parts {
$(
$pxi: $PXi::new(),
)+
}
}
}
impl<MODE> PartiallyErasedPin<$port_id, MODE> {
pub fn erase(self) -> ErasedPin<MODE> {
ErasedPin::$PXx(self)
}
}
impl<const N: u8, MODE> Pin<$port_id, N, MODE>
where
MODE: Active,
{
pub fn erase(self) -> ErasedPin<MODE> {
self.erase_number().erase()
}
}
}
pub use $gpiox::{ $($PXi,)+ };
}
}
pub struct Pin<const P: char, const N: u8, MODE = Input<Floating>> {
mode: MODE,
}
impl<const P: char, const N: u8, MODE: Default> Pin<P, N, MODE> {
fn new() -> Self {
Self {
mode: Default::default(),
}
}
}
impl<const P: char, const N: u8, MODE: Default> PinExt for Pin<P, N, MODE> {
type Mode = MODE;
fn pin_id(&self) -> u8 {
N
}
fn port_id(&self) -> u8 {
P as u8
}
}
impl<const P: char, const N: u8> Pin<P, N, Debugger> {
#[allow(dead_code)]
pub(crate) unsafe fn activate(self) -> Pin<P, N, Input<Floating>> {
Pin::new()
}
}
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
#[inline(always)]
fn _set_state(&mut self, state: PinState) {
match state {
PinState::High => self._set_high(),
PinState::Low => self._set_low(),
}
}
#[inline(always)]
fn _set_high(&mut self) {
let gpio = unsafe { &(*gpiox::<P>()) };
unsafe { gpio.bsrr.write(|w| w.bits(1 << N)) }
}
#[inline(always)]
fn _set_low(&mut self) {
let gpio = unsafe { &(*gpiox::<P>()) };
unsafe { gpio.bsrr.write(|w| w.bits(1 << (N + 16))) }
}
#[inline(always)]
fn _is_set_low(&self) -> bool {
let gpio = unsafe { &(*gpiox::<P>()) };
gpio.odr.read().bits() & (1 << N) == 0
}
#[inline(always)]
fn _is_low(&self) -> bool {
let gpio = unsafe { &(*gpiox::<P>()) };
gpio.idr.read().bits() & (1 << N) != 0
}
}
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
where
MODE: Active,
{
#[inline]
pub fn erase_number(self) -> PartiallyErasedPin<P, MODE> {
PartiallyErasedPin::new(N)
}
}
impl<const P: char, const N: u8, MODE> Pin<P, N, Output<MODE>> {
#[inline]
pub fn set_high(&mut self) {
self._set_high()
}
#[inline]
pub fn set_low(&mut self) {
self._set_low()
}
#[inline(always)]
pub fn get_state(&self) -> PinState {
if self._is_set_low() {
PinState::Low
} else {
PinState::High
}
}
#[inline(always)]
pub fn set_state(&mut self, state: PinState) {
self._set_state(state)
}
#[inline]
pub fn is_set_high(&self) -> bool {
!self._is_set_low()
}
#[inline]
pub fn is_set_low(&self) -> bool {
self._is_set_low()
}
#[inline]
pub fn toggle(&mut self) {
if self._is_set_low() {
self._set_high()
} else {
self._set_low()
}
}
}
impl<const P: char, const N: u8, MODE> Pin<P, N, Input<MODE>> {
#[inline]
pub fn is_high(&self) -> bool {
!self._is_low()
}
#[inline]
pub fn is_low(&self) -> bool {
self._is_low()
}
}
impl<const P: char, const N: u8> Pin<P, N, Output<OpenDrain>> {
#[inline]
pub fn is_high(&self) -> bool {
!self._is_low()
}
#[inline]
pub fn is_low(&self) -> bool {
self._is_low()
}
}
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
where
MODE: Active,
{
#[inline]
pub fn into_floating_input(self) -> Pin<P, N, Input<Floating>> {
self.into_mode()
}
#[inline]
pub fn into_pull_down_input(self) -> Pin<P, N, Input<PullDown>> {
self.into_mode()
}
#[inline]
pub fn into_pull_up_input(self) -> Pin<P, N, Input<PullUp>> {
self.into_mode()
}
#[inline]
pub fn into_open_drain_output(self) -> Pin<P, N, Output<OpenDrain>> {
self.into_open_drain_output_with_state(PinState::Low)
}
#[inline]
pub fn into_open_drain_output_with_state(
mut self,
initial_state: PinState,
) -> Pin<P, N, Output<OpenDrain>> {
self._set_state(initial_state);
self.into_mode()
}
#[inline]
pub fn into_push_pull_output(self) -> Pin<P, N, Output<PushPull>> {
self.into_push_pull_output_with_state(PinState::Low)
}
#[inline]
pub fn into_push_pull_output_with_state(
mut self,
initial_state: PinState,
) -> Pin<P, N, Output<PushPull>> {
self._set_state(initial_state);
self.into_mode()
}
#[inline]
pub fn into_push_pull_output_with_current_state(self) -> Pin<P, N, Output<PushPull>> {
self.into_mode()
}
#[inline]
pub fn into_analog(self) -> Pin<P, N, Analog> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af0(self) -> Pin<P, N, Alternate<AF0>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af1(self) -> Pin<P, N, Alternate<AF1>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af2(self) -> Pin<P, N, Alternate<AF2>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af3(self) -> Pin<P, N, Alternate<AF3>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af4(self) -> Pin<P, N, Alternate<AF4>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af5(self) -> Pin<P, N, Alternate<AF5>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af6(self) -> Pin<P, N, Alternate<AF6>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af7(self) -> Pin<P, N, Alternate<AF7>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af8(self) -> Pin<P, N, Alternate<AF8>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af9(self) -> Pin<P, N, Alternate<AF9>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af10(self) -> Pin<P, N, Alternate<AF10>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af11(self) -> Pin<P, N, Alternate<AF11>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af12(self) -> Pin<P, N, Alternate<AF12>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af13(self) -> Pin<P, N, Alternate<AF13>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af14(self) -> Pin<P, N, Alternate<AF14>> {
self.into_mode()
}
#[inline]
pub fn into_alternate_af15(self) -> Pin<P, N, Alternate<AF15>> {
self.into_mode()
}
#[inline]
pub fn into_dynamic(mut self) -> Pin<P, N, Dynamic> {
self.mode::<Input<Floating>>();
Pin::new()
}
}
macro_rules! impl_temp_output {
($fn_name:ident, $stateful_fn_name:ident, $mode:ty) => {
#[inline]
pub fn $fn_name(&mut self, mut f: impl FnMut(&mut Pin<P, N, $mode>)) {
self.mode::<$mode>();
let mut temp = Pin::<P, N, $mode>::new();
f(&mut temp);
self.mode::<$mode>();
Self::new();
}
#[inline]
pub fn $stateful_fn_name(
&mut self,
state: PinState,
mut f: impl FnMut(&mut Pin<P, N, $mode>),
) {
self._set_state(state);
self.mode::<$mode>();
let mut temp = Pin::<P, N, $mode>::new();
f(&mut temp);
self.mode::<$mode>();
Self::new();
}
};
}
macro_rules! impl_temp_input {
($fn_name:ident, $mode:ty) => {
#[inline]
pub fn $fn_name(&mut self, mut f: impl FnMut(&mut Pin<P, N, $mode>)) {
self.mode::<$mode>();
let mut temp = Pin::<P, N, $mode>::new();
f(&mut temp);
self.mode::<$mode>();
Self::new();
}
};
}
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
where
MODE: Active + PinMode,
{
impl_temp_output!(
as_push_pull_output,
as_push_pull_output_with_state,
Output<PushPull>
);
impl_temp_output!(
as_open_drain_output,
as_open_drain_output_with_state,
Output<OpenDrain>
);
impl_temp_input!(as_floating_input, Input<Floating>);
impl_temp_input!(as_pull_up_input, Input<PullUp>);
impl_temp_input!(as_pull_down_input, Input<PullDown>);
}
impl<const P: char, const N: u8> Pin<P, N, Dynamic> {
#[inline]
pub fn make_pull_up_input(&mut self) {
self.mode::<Input<PullUp>>();
self.mode = Dynamic::InputPullUp;
}
#[inline]
pub fn make_pull_down_input(&mut self) {
self.mode::<Input<PullDown>>();
self.mode = Dynamic::InputPullDown;
}
#[inline]
pub fn make_floating_input(&mut self) {
self.mode::<Input<Floating>>();
self.mode = Dynamic::InputFloating;
}
#[inline]
pub fn make_push_pull_output(&mut self) {
self.mode::<Output<PushPull>>();
self.mode = Dynamic::OutputPushPull;
}
#[inline]
pub fn make_open_drain_output(&mut self) {
self.mode::<Output<OpenDrain>>();
self.mode = Dynamic::OutputOpenDrain;
}
}
impl PinMode for Analog {
const MODE: Mode = Mode::Analog;
const CNF: Cnf = Cnf::PushPull;
}
impl PinMode for Input<Floating> {
const MODE: Mode = Mode::Input;
const CNF: Cnf = Cnf::PushPull;
}
impl PinMode for Input<PullDown> {
const MODE: Mode = Mode::Input;
const CNF: Cnf = Cnf::PushPull;
const PULL: Option<bool> = Some(false);
}
impl PinMode for Input<PullUp> {
const MODE: Mode = Mode::Input;
const CNF: Cnf = Cnf::PushPull;
const PULL: Option<bool> = Some(true);
}
impl PinMode for Output<PushPull> {
const MODE: Mode = Mode::Output;
const CNF: Cnf = Cnf::PushPull;
}
impl PinMode for Output<OpenDrain> {
const MODE: Mode = Mode::Output;
const CNF: Cnf = Cnf::OpenDrain;
}
impl PinMode for Alternate<AF0> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af0);
}
impl PinMode for Alternate<AF1> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af1);
}
impl PinMode for Alternate<AF2> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af2);
}
impl PinMode for Alternate<AF3> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af3);
}
impl PinMode for Alternate<AF4> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af4);
}
impl PinMode for Alternate<AF5> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af5);
}
impl PinMode for Alternate<AF6> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af6);
}
impl PinMode for Alternate<AF7> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af7);
}
impl PinMode for Alternate<AF8> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af8);
}
impl PinMode for Alternate<AF9> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af9);
}
impl PinMode for Alternate<AF10> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af10);
}
impl PinMode for Alternate<AF11> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af11);
}
impl PinMode for Alternate<AF12> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af12);
}
impl PinMode for Alternate<AF13> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af13);
}
impl PinMode for Alternate<AF14> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af14);
}
impl PinMode for Alternate<AF15> {
const MODE: Mode = Mode::Alternate;
const CNF: Cnf = Cnf::PushPull;
const AF: Option<Af> = Some(Af::Af15);
}
impl<const P: char, const N: u8, M> Pin<P, N, M> {
fn mode<MODE: PinMode>(&mut self) {
let gpio = unsafe { &(*gpiox::<P>()) };
let offset2 = 2 * N;
if let Some(pull) = MODE::PULL {
let pupdv = if pull { 0b01 } else { 0b11 };
unsafe {
gpio.pupdr
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset2)) | (pupdv << offset2)))
};
}
let mv: u8 = MODE::MODE.into();
unsafe {
gpio.moder
.modify(|r, w| w.bits((r.bits() & !(0b11 << offset2)) | ((mv as u32) << offset2)))
};
if MODE::MODE == Mode::Output {
let otv = match MODE::CNF {
Cnf::OpenDrain => 0b1,
Cnf::PushPull => 0b0,
};
gpio.otyper
.modify(|r, w| unsafe { w.bits((r.bits() & !(0b1 << N)) | (otv << N)) });
}
if let Some(af) = MODE::AF {
let afv: u8 = af.into();
unsafe {
if N < 8 {
let offset4 = N * 4;
gpio.afrl.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << offset4)) | ((afv as u32) << offset4))
});
} else {
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
{
let offset4 = (N - 8) * 4;
gpio.afrh.modify(|r, w| {
w.bits((r.bits() & !(0b1111 << offset4)) | ((afv as u32) << offset4))
});
}
#[cfg(feature = "py32f002b")]
{
unreachable!();
}
}
}
}
}
#[inline]
pub(crate) fn into_mode<MODE: PinMode>(mut self) -> Pin<P, N, MODE> {
self.mode::<MODE>();
Pin::new()
}
}
impl Analog {
pub fn new<const P: char, const N: u8, MODE>(pin: Pin<P, N, MODE>) -> Pin<P, N, Self>
where
Self: PinMode,
{
pin.into_mode()
}
}
impl<PULL> Input<PULL> {
pub fn new<const P: char, const N: u8, MODE>(
pin: Pin<P, N, MODE>,
_pull: PULL,
) -> Pin<P, N, Self>
where
Self: PinMode,
{
pin.into_mode()
}
}
impl<Otype> Output<Otype> {
pub fn new<const P: char, const N: u8, MODE>(
mut pin: Pin<P, N, MODE>,
state: PinState,
) -> Pin<P, N, Self>
where
Self: PinMode,
{
pin._set_state(state);
pin.into_mode()
}
}
impl<AF> Alternate<AF> {
pub fn new<const P: char, const N: u8, MODE>(pin: Pin<P, N, MODE>) -> Pin<P, N, Self>
where
Self: PinMode,
{
pin.into_mode()
}
}
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
gpio!(GPIOA, gpioa, PAx, 'A', [
PA0: (pa0, 0),
PA1: (pa1, 1),
PA2: (pa2, 2),
PA3: (pa3, 3),
PA4: (pa4, 4),
PA5: (pa5, 5),
PA6: (pa6, 6),
PA7: (pa7, 7),
PA8: (pa8, 8),
PA9: (pa9, 9),
PA10: (pa10, 10),
PA11: (pa11, 11),
PA12: (pa12, 12),
PA13: (pa13, 13, Debugger),
PA14: (pa14, 14, Debugger),
PA15: (pa15, 15),
]);
#[cfg(feature = "py32f002b")]
gpio!(GPIOA, gpioa, PAx, 'A', [
PA0: (pa0, 0),
PA1: (pa1, 1),
PA2: (pa2, 2, Debugger),
PA3: (pa3, 3),
PA4: (pa4, 4),
PA5: (pa5, 5),
PA6: (pa6, 6),
PA7: (pa7, 7),
]);
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
gpio!(GPIOB, gpiob, PBx, 'B', [
PB0: (pb0, 0),
PB1: (pb1, 1),
PB2: (pb2, 2),
PB3: (pb3, 3),
PB4: (pb4, 4),
PB5: (pb5, 5),
PB6: (pb6, 6),
PB7: (pb7, 7),
PB8: (pb8, 8),
]);
#[cfg(feature = "py32f002b")]
gpio!(GPIOB, gpiob, PBx, 'B', [
PB0: (pb0, 0),
PB1: (pb1, 1),
PB2: (pb2, 2),
PB3: (pb3, 3),
PB4: (pb4, 4),
PB5: (pb5, 5),
PB6: (pb6, 6, Debugger),
PB7: (pb7, 7),
PB8: (pb8, 8),
]);
#[cfg(feature = "py32f002b")]
gpio!(GPIOC, gpioc, PCx, 'C', [
PC0: (pc0, 0),
PC1: (pc1, 1),
]);
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
gpio!(GPIOF, gpiof, PFx, 'F', [
PF0: (pf0, 0),
PF1: (pf1, 1),
PF2: (pf2, 2),
PF3: (pf3, 3),
PF4: (pf4, 4),
]);
const fn gpiox<const P: char>() -> *const crate::pac::gpioa::RegisterBlock {
match P {
'A' => crate::pac::GPIOA::ptr(),
'B' => crate::pac::GPIOB::ptr() as _,
#[cfg(feature = "py32f002b")]
'C' => crate::pac::GPIOC::ptr() as _,
#[cfg(any(feature = "py32f030", feature = "py32f003", feature = "py32f002a"))]
'F' => crate::pac::GPIOF::ptr() as _,
_ => unreachable!(),
}
}