Initial implementation of GPIO traits

features/pwm
HarkonenBade 5 years ago
parent aca43e3a11
commit 0006281d59

@ -11,6 +11,13 @@ pub trait GpioExt {
fn split(self) -> Self::Parts;
}
pub trait Gpio {
fn in_low(&self, pos: u8) -> bool;
fn out_low(&self, pos: u8) -> bool;
fn set_high(&self, pos: u8);
fn set_low(&self, pos:u8);
}
pub struct AF0;
pub struct AF1;
pub struct AF2;
@ -53,10 +60,9 @@ use crate::stm32;
use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin};
/// Fully erased pin
// We can just pretend it's gpioa. It's modified using the bits and it can only be constructed out of already existing pins
pub struct Pin<MODE> {
i: u8,
port: *const stm32::gpioa::RegisterBlock,
port: *const Gpio,
_mode: PhantomData<MODE>,
}
@ -66,20 +72,17 @@ impl<MODE> StatefulOutputPin for Pin<Output<MODE>> {
}
fn is_set_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*self.port).odr.read().bits() & (1 << self.i) == 0 }
unsafe { (*self.port).out_low(self.i) }
}
}
impl<MODE> OutputPin for Pin<Output<MODE>> {
fn set_high(&mut self) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { (*self.port).bsrr.write(|w| w.bits(1 << self.i)) }
unsafe { (*self.port).set_high(self.i) }
}
fn set_low(&mut self) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { (*self.port).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
unsafe { (*self.port).set_low(self.i) }
}
}
@ -89,8 +92,7 @@ impl InputPin for Pin<Output<OpenDrain>> {
}
fn is_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*self.port).idr.read().bits() & (1 << self.i) == 0 }
unsafe { (*self.port).in_low(self.i) }
}
}
@ -100,8 +102,7 @@ impl<MODE> InputPin for Pin<Input<MODE>> {
}
fn is_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*self.port).idr.read().bits() & (1 << self.i) == 0 }
unsafe { (*self.port).in_low(self.i) }
}
}
@ -115,11 +116,13 @@ macro_rules! gpio {
use embedded_hal::digital::{InputPin, OutputPin, StatefulOutputPin, toggleable};
use crate::stm32::$GPIOX;
use crate::stm32::$gpiox::RegisterBlock;
use crate::stm32::RCC;
use super::{
Alternate, Floating, GpioExt, Input, OpenDrain, Output,
PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7, Pin
PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7,
Pin, Gpio,
};
/// GPIO parts
@ -146,86 +149,25 @@ macro_rules! gpio {
}
}
/// Partially erased pin
pub struct $PXx<MODE> {
i: u8,
_mode: PhantomData<MODE>,
}
impl<MODE> StatefulOutputPin for $PXx<Output<MODE>> {
fn is_set_high(&self) -> bool {
!self.is_set_low()
impl Gpio for RegisterBlock {
fn in_low(&self, pos :u8) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { self.idr.read().bits() & (1 << pos) == 0 }
}
fn is_set_low(&self) -> bool {
fn out_low(&self, pos: u8) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << self.i) == 0 }
unsafe { self.odr.read().bits() & (1 << pos) == 0 }
}
}
impl<MODE> OutputPin for $PXx<Output<MODE>> {
fn set_high(&mut self) {
fn set_high(&self, pos: u8) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
unsafe { self.bsrr.write(|w| w.bits(1 << pos)) }
}
fn set_low(&mut self) {
fn set_low(&self, pos: u8) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
}
}
impl<MODE> toggleable::Default for $PXx<Output<MODE>> {}
impl InputPin for $PXx<Output<OpenDrain>> {
fn is_high(&self) -> bool {
!self.is_low()
}
fn is_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
}
}
impl<MODE> InputPin for $PXx<Input<MODE>> {
fn is_high(&self) -> bool {
!self.is_low()
}
fn is_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
}
}
impl<MODE> $PXx<Input<MODE>> {
/// Erases the port 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<Input<MODE>> {
use crate::stm32::gpioa;
Pin {
i: self.i,
port: $GPIOX::ptr() as * const gpioa::RegisterBlock,
_mode: self._mode,
}
}
}
impl<MODE> $PXx<Output<MODE>> {
/// Erases the port 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<Output<MODE>> {
use crate::stm32::gpioa;
Pin {
i: self.i,
port: $GPIOX::ptr() as * const gpioa::RegisterBlock,
_mode: self._mode,
}
unsafe { self.bsrr.write(|w| w.bits(1 << (pos + 16))) }
}
}
@ -479,9 +421,10 @@ macro_rules! gpio {
///
/// 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) -> $PXx<Output<MODE>> {
$PXx {
pub fn downgrade(self) -> Pin<Output<MODE>> {
Pin {
i: $i,
port: $GPIOX::ptr() as *const Gpio,
_mode: self._mode,
}
}
@ -493,20 +436,17 @@ macro_rules! gpio {
}
fn is_set_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
(*$GPIOX::ptr()).out_low($i)
}
}
impl<MODE> OutputPin for $PXi<Output<MODE>> {
fn set_high(&mut self) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
(*$GPIOX::ptr()).set_high($i)
}
fn set_low(&mut self) {
// NOTE(unsafe) atomic write to a stateless register
unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) }
(*$GPIOX::ptr()).set_low($i)
}
}
@ -518,8 +458,7 @@ macro_rules! gpio {
}
fn is_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
(*$GPIOX::ptr()).in_low($i)
}
}
@ -528,9 +467,10 @@ macro_rules! gpio {
///
/// 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) -> $PXx<Input<MODE>> {
$PXx {
pub fn downgrade(self) -> Pin<Input<MODE>> {
Pin {
i: $i,
port: $GPIOX::ptr() as *const Gpio,
_mode: self._mode,
}
}
@ -542,18 +482,10 @@ macro_rules! gpio {
}
fn is_low(&self) -> bool {
// NOTE(unsafe) atomic read with no side effects
unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
(*$GPIOX::ptr()).in_low($i)
}
}
)+
impl<TYPE> $PXx<TYPE> {
pub fn get_id (&self) -> u8
{
self.i
}
}
}
}
}

Loading…
Cancel
Save