Skip to content

Commit

Permalink
Add all possible PINs to TIM3 channels
Browse files Browse the repository at this point in the history
  • Loading branch information
rblaze committed Nov 3, 2024
1 parent 7be9236 commit 9484196
Show file tree
Hide file tree
Showing 3 changed files with 221 additions and 144 deletions.
325 changes: 196 additions & 129 deletions src/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ use core::marker::PhantomData;

use paste::paste;

use crate::pac::{EXTI, GPIOA, GPIOB};
use crate::pac::{EXTI, GPIOA, GPIOB, GPIOC};
use crate::rcc::{Rcc, ResetEnable};

#[cfg(feature = "stm32g0b1")]
use crate::pac::GPIOE;

/// Extension trait to split a GPIO peripheral in independent pins and registers
pub trait GpioExt {
/// The parts to split the GPIO into
Expand Down Expand Up @@ -54,6 +57,7 @@ pub struct Analog;
/// Alternate function mode
pub struct Alternate<const N: u8>;

/// Alternate function numbers
pub(crate) enum AltFunction {
AF0 = 0,
AF1 = 1,
Expand Down Expand Up @@ -135,109 +139,175 @@ mod marker {
impl<MODE> Interruptable for super::Output<MODE> {}
}

macro_rules! gpio {
macro_rules! gpio_common {
($GPIO:ident, $port:ident, [$($PXi:ident: (
$i:literal, $default_mode:ty,
$afreg:ident, $afval:ident,
$muxreg:ident, $muxbits:ident),)+]) => {
$i:literal, $default_mode:ty,
$afreg:ident, $afval:ident),)+]) => {
use paste::paste;
paste! {
pub mod [<$GPIO:lower>] {
use super::{GpioExt, ResetEnable, Rcc, EXTI, $GPIO};
use super::{Output, PushPull, OpenDrain};
use super::{Input, Floating, PullUp, PullDown};
use super::{Analog, Alternate, AltFunction};
use super::SignalEdge;
use super::marker::{AF, Interruptable};

use core::marker::PhantomData;

impl GpioExt for $GPIO {
type Parts = Parts;

fn split(self, rcc: &Rcc) -> Self::Parts {
$GPIO::enable(rcc);
$GPIO::reset(rcc);

Self::Parts{
$(
[<$PXi:lower>]: $PXi { _mode: PhantomData },
)+
}
use super::{GpioExt, ResetEnable, Rcc, EXTI, $GPIO};
use super::{Output, PushPull, OpenDrain};
use super::{Input, Floating, PullUp, PullDown};
use super::{Analog, Alternate, AltFunction};
use super::SignalEdge;
use super::marker::{AF, Interruptable};

use core::marker::PhantomData;

impl GpioExt for $GPIO {
type Parts = Parts;

fn split(self, rcc: &Rcc) -> Self::Parts {
$GPIO::enable(rcc);
$GPIO::reset(rcc);

Self::Parts{
$(
[<$PXi:lower>]: $PXi { _mode: PhantomData },
)+
}
}
}

pub struct Parts {
$(
pub [<$PXi:lower>]: $PXi<$default_mode>,
)+
pub struct Parts {
$(
pub [<$PXi:lower>]: $PXi<$default_mode>,
)+
}

$(
pub struct $PXi<MODE> {
_mode: PhantomData<MODE>,
}

$(
pub struct $PXi<MODE> {
_mode: PhantomData<MODE>,
#[allow(unsafe_code)]
impl<MODE> $PXi<MODE> {
pub fn into_push_pull_output(self) -> $PXi<Output<PushPull>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.otyper().modify(|_, w| w.[<ot $i>]().push_pull());
rb.moder().modify(|_, w| w.[<moder $i>]().output());
$PXi { _mode: PhantomData }
}

#[allow(unsafe_code)]
impl<MODE> $PXi<MODE> {
pub fn into_push_pull_output(self) -> $PXi<Output<PushPull>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.otyper().modify(|_, w| w.[<ot $i>]().push_pull());
rb.moder().modify(|_, w| w.[<moder $i>]().output());
$PXi { _mode: PhantomData }
}
pub fn into_open_drain_output(self) -> $PXi<Output<OpenDrain>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.otyper().modify(|_, w| w.[<ot $i>]().open_drain());
rb.moder().modify(|_, w| w.[<moder $i>]().output());
$PXi { _mode: PhantomData }
}

pub fn into_open_drain_output(self) -> $PXi<Output<OpenDrain>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.otyper().modify(|_, w| w.[<ot $i>]().open_drain());
rb.moder().modify(|_, w| w.[<moder $i>]().output());
$PXi { _mode: PhantomData }
}
pub fn into_floating_input(self) -> $PXi<Input<Floating>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.moder().modify(|_, w| w.[<moder $i>]().input());
$PXi { _mode: PhantomData }
}

pub fn into_floating_input(self) -> $PXi<Input<Floating>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.moder().modify(|_, w| w.[<moder $i>]().input());
$PXi { _mode: PhantomData }
}
pub fn into_pulldown_input(self) -> $PXi<Input<PullDown>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().pull_down());
rb.moder().modify(|_, w| w.[<moder $i>]().input());
$PXi { _mode: PhantomData }
}

pub fn into_pulldown_input(self) -> $PXi<Input<PullDown>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().pull_down());
rb.moder().modify(|_, w| w.[<moder $i>]().input());
$PXi { _mode: PhantomData }
}
pub fn into_pullup_input(self) -> $PXi<Input<PullUp>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().pull_up());
rb.moder().modify(|_, w| w.[<moder $i>]().input());
$PXi { _mode: PhantomData }
}

pub fn into_pullup_input(self) -> $PXi<Input<PullUp>> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().pull_up());
rb.moder().modify(|_, w| w.[<moder $i>]().input());
$PXi { _mode: PhantomData }
}
pub fn into_analog(self) -> $PXi<Analog> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.moder().modify(|_, w| w.[<moder $i>]().analog());
$PXi { _mode: PhantomData }
}

pub fn into_analog(self) -> $PXi<Analog> {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.pupdr().modify(|_, w| w.[<pupdr $i>]().floating());
rb.moder().modify(|_, w| w.[<moder $i>]().analog());
$PXi { _mode: PhantomData }
}
pub fn into_alternate_function<const N: u8>(self) -> $PXi<Alternate<N>>
where Alternate<N> : AF {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.$afreg().modify(|_, w| w.[<afrel $i>]().variant(<Alternate<N>>::$afval));
rb.moder().modify(|_, w| w.[<moder $i>]().alternate());
$PXi { _mode: PhantomData }
}

pub(crate) fn set_alternate_function_mode(&self, mode: AltFunction) {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.$afreg().modify(|_, w| w.[<afrel $i>]().variant(mode.into()));
rb.moder().modify(|_, w| w.[<moder $i>]().alternate());
}
}

impl<MODE> embedded_hal::digital::ErrorType for $PXi<MODE> {
type Error = core::convert::Infallible;
}

impl<MODE> embedded_hal::digital::InputPin for $PXi<Input<MODE>> {
#[allow(unsafe_code)]
fn is_high(&mut self) -> Result<bool, Self::Error> {
let rb = unsafe { &(*$GPIO::ptr()) };
Ok(rb.idr().read().[<idr $i>]().is_high())
}

pub fn into_alternate_function<const N: u8>(self) -> $PXi<Alternate<N>>
where Alternate<N> : AF {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.$afreg().modify(|_, w| w.[<afrel $i>]().variant(<Alternate<N>>::$afval));
rb.moder().modify(|_, w| w.[<moder $i>]().alternate());
$PXi { _mode: PhantomData }
fn is_low(&mut self) -> Result<bool, Self::Error> {
self.is_high().map(|v| !v)
}
}

#[allow(unsafe_code)]
impl<MODE> embedded_hal::digital::OutputPin for $PXi<Output<MODE>> {
fn set_high(&mut self) -> Result<(), Self::Error> {
unsafe {
let rb = &(*$GPIO::ptr());
Ok(rb.bsrr().write(|w| w.[<bs $i>]().set_bit()))
}
}

pub(crate) fn set_alternate_function_mode(&self, mode: AltFunction) {
let rb = unsafe { &(*$GPIO::ptr()) };
rb.$afreg().modify(|_, w| w.[<afrel $i>]().variant(mode.into()));
rb.moder().modify(|_, w| w.[<moder $i>]().alternate());
fn set_low(&mut self) -> Result<(), Self::Error> {
unsafe {
let rb = &(*$GPIO::ptr());
Ok(rb.bsrr().write(|w| w.[<br $i>]().set_bit()))
}
}
}

impl<MODE> embedded_hal::digital::StatefulOutputPin for $PXi<Output<MODE>> {
#[allow(unsafe_code)]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
let rb = unsafe { &(*$GPIO::ptr()) };
Ok(rb.odr().read().[<odr $i>]().is_high())
}

fn is_set_low(&mut self) -> Result<bool, Self::Error> {
self.is_set_high().map(|v| !v)
}
}
)+
}
};
}

macro_rules! gpio {
($GPIO:ident, $port:ident, [$($PXi:ident: (
$i:literal, $default_mode:ty,
$afreg:ident, $afval:ident),)+]) => {
paste! {
pub mod [<$GPIO:lower>] {
gpio_common!($GPIO, $port, [$($PXi: ($i, $default_mode,$afreg, $afval),)+]);
}
}
};
($GPIO:ident, $port:ident, [$($PXi:ident: (
$i:literal, $default_mode:ty,
$afreg:ident, $afval:ident,
$muxreg:ident, $muxbits:ident),)+]) => {
paste! {
pub mod [<$GPIO:lower>] {
gpio_common!($GPIO, $port, [$($PXi: ($i, $default_mode,$afreg, $afval),)+]);
$(
impl<MODE> $PXi<MODE> where MODE: Interruptable {
pub fn make_interrupt_source(&mut self, exti: &mut EXTI) {
exti.$muxreg().modify(|_, w| w.$muxbits().$port());
Expand Down Expand Up @@ -267,51 +337,6 @@ macro_rules! gpio {
}
}
}

impl<MODE> embedded_hal::digital::ErrorType for $PXi<MODE> {
type Error = core::convert::Infallible;
}

impl<MODE> embedded_hal::digital::InputPin for $PXi<Input<MODE>> {
#[allow(unsafe_code)]
fn is_high(&mut self) -> Result<bool, Self::Error> {
let rb = unsafe { &(*$GPIO::ptr()) };
Ok(rb.idr().read().[<idr $i>]().is_high())
}

fn is_low(&mut self) -> Result<bool, Self::Error> {
self.is_high().map(|v| !v)
}
}

#[allow(unsafe_code)]
impl<MODE> embedded_hal::digital::OutputPin for $PXi<Output<MODE>> {
fn set_high(&mut self) -> Result<(), Self::Error> {
unsafe {
let rb = &(*$GPIO::ptr());
Ok(rb.bsrr().write(|w| w.[<bs $i>]().set_bit()))
}
}

fn set_low(&mut self) -> Result<(), Self::Error> {
unsafe {
let rb = &(*$GPIO::ptr());
Ok(rb.bsrr().write(|w| w.[<br $i>]().set_bit()))
}
}
}

impl<MODE> embedded_hal::digital::StatefulOutputPin for $PXi<Output<MODE>> {
#[allow(unsafe_code)]
fn is_set_high(&mut self) -> Result<bool, Self::Error> {
let rb = unsafe { &(*$GPIO::ptr()) };
Ok(rb.odr().read().[<odr $i>]().is_high())
}

fn is_set_low(&mut self) -> Result<bool, Self::Error> {
self.is_set_high().map(|v| !v)
}
}
)+
}
}
Expand Down Expand Up @@ -357,3 +382,45 @@ gpio!(GPIOB, pb, [
PB14: (14, Analog, afrh, AF_B_H, exticr4, exti16_23),
PB15: (15, Analog, afrh, AF_B_H, exticr4, exti24_31),
]);

gpio!(GPIOC, pc, [
// Pin: (pin, default_mode, bits...)
PC0: (0, Analog, afrl, AF_B_L, exticr1, exti0_7 ),
PC1: (1, Analog, afrl, AF_B_L, exticr1, exti8_15 ),
PC2: (2, Analog, afrl, AF_B_L, exticr1, exti16_23),
PC3: (3, Analog, afrl, AF_B_L, exticr1, exti24_31),
PC4: (4, Analog, afrl, AF_B_L, exticr2, exti0_7 ),
PC5: (5, Analog, afrl, AF_B_L, exticr2, exti8_15 ),
PC6: (6, Analog, afrl, AF_B_L, exticr2, exti16_23),
PC7: (7, Analog, afrl, AF_B_L, exticr2, exti24_31),
PC8: (8, Analog, afrh, AF_B_H, exticr3, exti0_7 ),
PC9: (9, Analog, afrh, AF_B_H, exticr3, exti8_15 ),
PC10: (10, Analog, afrh, AF_B_H, exticr3, exti16_23),
PC11: (11, Analog, afrh, AF_B_H, exticr3, exti24_31),
PC12: (12, Analog, afrh, AF_B_H, exticr4, exti0_7 ),
PC13: (13, Analog, afrh, AF_B_H, exticr4, exti8_15 ),
PC14: (14, Analog, afrh, AF_B_H, exticr4, exti16_23),
PC15: (15, Analog, afrh, AF_B_H, exticr4, exti24_31),
]);

// GPIOE can't be used as EXTI interrupt source
#[cfg(feature = "stm32g0b1")]
gpio!(GPIOE, pe, [
// Pin: (pin, default_mode, bits...)
PE0: (0, Analog, afrl, AF_B_L),
PE1: (1, Analog, afrl, AF_B_L),
PE2: (2, Analog, afrl, AF_B_L),
PE3: (3, Analog, afrl, AF_B_L),
PE4: (4, Analog, afrl, AF_B_L),
PE5: (5, Analog, afrl, AF_B_L),
PE6: (6, Analog, afrl, AF_B_L),
PE7: (7, Analog, afrl, AF_B_L),
PE8: (8, Analog, afrh, AF_B_H),
PE9: (9, Analog, afrh, AF_B_H),
PE10: (10, Analog, afrh, AF_B_H),
PE11: (11, Analog, afrh, AF_B_H),
PE12: (12, Analog, afrh, AF_B_H),
PE13: (13, Analog, afrh, AF_B_H),
PE14: (14, Analog, afrh, AF_B_H),
PE15: (15, Analog, afrh, AF_B_H),
]);
5 changes: 5 additions & 0 deletions src/rcc/reset_enable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use crate::pac::{
ADC, DMA1, GPIOA, GPIOB, GPIOC, GPIOD, GPIOF, I2C1, I2C2, LPTIM1, LPTIM2, TIM1, TIM2, TIM3,
};

#[cfg(feature = "stm32g0b1")]
use crate::pac::GPIOE;

use super::{Rcc, ResetEnable};

macro_rules! reset_enable_bus {
Expand Down Expand Up @@ -86,4 +89,6 @@ reset_enable!(GPIOC, GPIO, gpiocen, gpiocrst); // 2
#[cfg(feature = "stm32g0b1")]
reset_enable!(GPIOD, GPIO, gpioden, gpiodrst); // 3
#[cfg(feature = "stm32g0b1")]
reset_enable!(GPIOE, GPIO, gpioeen, gpioerst); // 5
#[cfg(feature = "stm32g0b1")]
reset_enable!(GPIOF, GPIO, gpiofen, gpiofrst); // 5
Loading

0 comments on commit 9484196

Please sign in to comment.