Skip to content

Commit c4171fb

Browse files
committed
generic DynPin
1 parent af4e596 commit c4171fb

File tree

8 files changed

+382
-375
lines changed

8 files changed

+382
-375
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2020
- FMPI2c APB timings [#770]
2121
- Fefactor FMPI2c `embedded-hal` implementations [#784]
2222
- remove `NoPin`, use `Option` instead [#813]
23+
- Make `DynPin` be generic over `Pin` and `AnyPin`
2324

2425
[#770]: https://github.com/stm32-rs/stm32f4xx-hal/pull/770
2526
[#784]: https://github.com/stm32-rs/stm32f4xx-hal/pull/784

src/gpio.rs

Lines changed: 170 additions & 131 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pub use erased::{AnyPin, ErasedPin};
6767
mod exti;
6868
pub use exti::ExtiPin;
6969
mod dynamic;
70-
pub use dynamic::{Dynamic, DynamicPin};
70+
pub use dynamic::*;
7171
mod hal_02;
7272
mod hal_1;
7373
pub mod outport;
@@ -324,22 +324,29 @@ where
324324
}
325325
}
326326

327+
macro_rules! speed {
328+
() => {
329+
/// Set pin speed
330+
pub fn set_speed(&mut self, speed: Speed) {
331+
unsafe { &*self.block() }
332+
.ospeedr()
333+
.modify(|_, w| w.ospeedr(self.pin_id()).variant(speed.into()));
334+
}
335+
336+
/// Set pin speed
337+
pub fn speed(mut self, speed: Speed) -> Self {
338+
self.set_speed(speed);
339+
self
340+
}
341+
};
342+
}
343+
use speed;
344+
327345
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
328346
where
329347
MODE: marker::OutputSpeed,
330348
{
331-
/// Set pin speed
332-
pub fn set_speed(&mut self, speed: Speed) {
333-
unsafe { &(*gpiox::<P>()) }
334-
.ospeedr()
335-
.modify(|_, w| w.ospeedr(N).variant(speed.into()));
336-
}
337-
338-
/// Set pin speed
339-
pub fn speed(mut self, speed: Speed) -> Self {
340-
self.set_speed(speed);
341-
self
342-
}
349+
speed!();
343350
}
344351

345352
impl<const P: char, const N: u8, MODE> PinPull for Pin<P, N, MODE>
@@ -352,40 +359,47 @@ where
352359
}
353360
}
354361

355-
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
356-
where
357-
MODE: marker::Active,
358-
{
359-
/// Set the internal pull-up and pull-down resistor
360-
pub fn set_internal_resistor(&mut self, resistor: Pull) {
361-
unsafe { &(*gpiox::<P>()) }
362-
.pupdr()
363-
.modify(|_, w| w.pupdr(N).variant(resistor.into()));
364-
}
362+
macro_rules! internal_resistor {
363+
() => {
364+
/// Set the internal pull-up and pull-down resistor
365+
pub fn set_internal_resistor(&mut self, resistor: Pull) {
366+
unsafe { &*self.block() }
367+
.pupdr()
368+
.modify(|_, w| w.pupdr(self.pin_id()).variant(resistor.into()));
369+
}
365370

366-
/// Set the internal pull-up and pull-down resistor
367-
pub fn internal_resistor(mut self, resistor: Pull) -> Self {
368-
self.set_internal_resistor(resistor);
369-
self
370-
}
371+
/// Set the internal pull-up and pull-down resistor
372+
pub fn internal_resistor(mut self, resistor: Pull) -> Self {
373+
self.set_internal_resistor(resistor);
374+
self
375+
}
371376

372-
/// Enables / disables the internal pull up
373-
pub fn internal_pull_up(self, on: bool) -> Self {
374-
if on {
375-
self.internal_resistor(Pull::Up)
376-
} else {
377-
self.internal_resistor(Pull::None)
377+
/// Enables / disables the internal pull up
378+
pub fn internal_pull_up(self, on: bool) -> Self {
379+
if on {
380+
self.internal_resistor(Pull::Up)
381+
} else {
382+
self.internal_resistor(Pull::None)
383+
}
378384
}
379-
}
380385

381-
/// Enables / disables the internal pull down
382-
pub fn internal_pull_down(self, on: bool) -> Self {
383-
if on {
384-
self.internal_resistor(Pull::Down)
385-
} else {
386-
self.internal_resistor(Pull::None)
386+
/// Enables / disables the internal pull down
387+
pub fn internal_pull_down(self, on: bool) -> Self {
388+
if on {
389+
self.internal_resistor(Pull::Down)
390+
} else {
391+
self.internal_resistor(Pull::None)
392+
}
387393
}
388-
}
394+
};
395+
}
396+
use internal_resistor;
397+
398+
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
399+
where
400+
MODE: marker::Active,
401+
{
402+
internal_resistor!();
389403
}
390404

391405
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
@@ -424,97 +438,132 @@ impl<const P: char, const N: u8, MODE> From<Pin<P, N, MODE>> for AnyPin<MODE> {
424438
}
425439
}
426440

427-
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
428-
/// Set the output of the pin regardless of its mode.
429-
/// Primarily used to set the output value of the pin
430-
/// before changing its mode to an output to avoid
431-
/// a short spike of an incorrect value
432-
#[inline(always)]
433-
fn _set_state(&mut self, state: PinState) {
434-
match state {
435-
PinState::High => self._set_high(),
436-
PinState::Low => self._set_low(),
441+
macro_rules! state_inner {
442+
() => {
443+
/// Set the output of the pin regardless of its mode.
444+
/// Primarily used to set the output value of the pin
445+
/// before changing its mode to an output to avoid
446+
/// a short spike of an incorrect value
447+
#[inline(always)]
448+
pub(crate) fn _set_state(&mut self, state: PinState) {
449+
match state {
450+
PinState::High => self._set_high(),
451+
PinState::Low => self._set_low(),
452+
}
437453
}
438-
}
439-
#[inline(always)]
440-
fn _set_high(&mut self) {
441-
// NOTE(unsafe) atomic write to a stateless register
442-
let gpio = unsafe { &(*gpiox::<P>()) };
443-
gpio.bsrr().write(|w| w.bs(N).set_bit());
444-
}
445-
#[inline(always)]
446-
fn _set_low(&mut self) {
447-
// NOTE(unsafe) atomic write to a stateless register
448-
let gpio = unsafe { &(*gpiox::<P>()) };
449-
gpio.bsrr().write(|w| w.br(N).set_bit());
450-
}
451-
#[inline(always)]
452-
fn _is_set_low(&self) -> bool {
453-
// NOTE(unsafe) atomic read with no side effects
454-
let gpio = unsafe { &(*gpiox::<P>()) };
455-
gpio.odr().read().odr(N).bit_is_clear()
456-
}
457-
#[inline(always)]
458-
fn _is_low(&self) -> bool {
459-
// NOTE(unsafe) atomic read with no side effects
460-
let gpio = unsafe { &(*gpiox::<P>()) };
461-
gpio.idr().read().idr(N).bit_is_clear()
462-
}
454+
#[inline(always)]
455+
pub(crate) fn _set_high(&mut self) {
456+
// NOTE(unsafe) atomic write to a stateless register
457+
let gpio = unsafe { &*self.block() };
458+
gpio.bsrr().write(|w| w.bs(self.pin_id()).set_bit());
459+
}
460+
#[inline(always)]
461+
pub(crate) fn _set_low(&mut self) {
462+
// NOTE(unsafe) atomic write to a stateless register
463+
let gpio = unsafe { &*self.block() };
464+
gpio.bsrr().write(|w| w.br(self.pin_id()).set_bit());
465+
}
466+
#[inline(always)]
467+
pub(crate) fn _is_set_low(&self) -> bool {
468+
// NOTE(unsafe) atomic read with no side effects
469+
let gpio = unsafe { &*self.block() };
470+
gpio.odr().read().odr(self.pin_id()).bit_is_clear()
471+
}
472+
#[inline(always)]
473+
pub(crate) fn _is_low(&self) -> bool {
474+
// NOTE(unsafe) atomic read with no side effects
475+
let gpio = unsafe { &*self.block() };
476+
gpio.idr().read().idr(self.pin_id()).bit_is_clear()
477+
}
478+
};
463479
}
480+
use state_inner;
481+
482+
macro_rules! state_output {
483+
() => {
484+
/// Drives the pin high
485+
#[inline(always)]
486+
pub fn set_high(&mut self) {
487+
self._set_high()
488+
}
464489

465-
impl<const P: char, const N: u8, MODE> Pin<P, N, Output<MODE>> {
466-
/// Drives the pin high
467-
#[inline(always)]
468-
pub fn set_high(&mut self) {
469-
self._set_high()
470-
}
490+
/// Drives the pin low
491+
#[inline(always)]
492+
pub fn set_low(&mut self) {
493+
self._set_low()
494+
}
471495

472-
/// Drives the pin low
473-
#[inline(always)]
474-
pub fn set_low(&mut self) {
475-
self._set_low()
476-
}
496+
/// Is the pin in drive high or low mode?
497+
#[inline(always)]
498+
pub fn get_state(&self) -> PinState {
499+
if self.is_set_low() {
500+
PinState::Low
501+
} else {
502+
PinState::High
503+
}
504+
}
477505

478-
/// Is the pin in drive high or low mode?
479-
#[inline(always)]
480-
pub fn get_state(&self) -> PinState {
481-
if self.is_set_low() {
482-
PinState::Low
483-
} else {
484-
PinState::High
506+
/// Drives the pin high or low depending on the provided value
507+
#[inline(always)]
508+
pub fn set_state(&mut self, state: PinState) {
509+
match state {
510+
PinState::Low => self.set_low(),
511+
PinState::High => self.set_high(),
512+
}
485513
}
486-
}
487514

488-
/// Drives the pin high or low depending on the provided value
489-
#[inline(always)]
490-
pub fn set_state(&mut self, state: PinState) {
491-
match state {
492-
PinState::Low => self.set_low(),
493-
PinState::High => self.set_high(),
515+
/// Is the pin in drive high mode?
516+
#[inline(always)]
517+
pub fn is_set_high(&self) -> bool {
518+
!self.is_set_low()
494519
}
495-
}
496520

497-
/// Is the pin in drive high mode?
498-
#[inline(always)]
499-
pub fn is_set_high(&self) -> bool {
500-
!self.is_set_low()
501-
}
521+
/// Is the pin in drive low mode?
522+
#[inline(always)]
523+
pub fn is_set_low(&self) -> bool {
524+
self._is_set_low()
525+
}
502526

503-
/// Is the pin in drive low mode?
504-
#[inline(always)]
505-
pub fn is_set_low(&self) -> bool {
506-
self._is_set_low()
507-
}
527+
/// Toggle pin output
528+
#[inline(always)]
529+
pub fn toggle(&mut self) {
530+
if self.is_set_low() {
531+
self.set_high()
532+
} else {
533+
self.set_low()
534+
}
535+
}
536+
};
537+
}
538+
use state_output;
539+
540+
macro_rules! state_input {
541+
() => {
542+
/// Is the input pin high?
543+
#[inline(always)]
544+
pub fn is_high(&self) -> bool {
545+
!self.is_low()
546+
}
508547

509-
/// Toggle pin output
510-
#[inline(always)]
511-
pub fn toggle(&mut self) {
512-
if self.is_set_low() {
513-
self.set_high()
514-
} else {
515-
self.set_low()
548+
/// Is the input pin low?
549+
#[inline(always)]
550+
pub fn is_low(&self) -> bool {
551+
self._is_low()
516552
}
553+
};
554+
}
555+
use state_input;
556+
557+
impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
558+
#[inline(always)]
559+
pub(crate) fn block(&self) -> *const crate::pac::gpioa::RegisterBlock {
560+
gpiox::<P>()
517561
}
562+
state_inner!();
563+
}
564+
565+
impl<const P: char, const N: u8, MODE> Pin<P, N, Output<MODE>> {
566+
state_output!();
518567
}
519568

520569
pub trait ReadPin {
@@ -539,17 +588,7 @@ impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
539588
where
540589
MODE: marker::Readable,
541590
{
542-
/// Is the input pin high?
543-
#[inline(always)]
544-
pub fn is_high(&self) -> bool {
545-
!self.is_low()
546-
}
547-
548-
/// Is the input pin low?
549-
#[inline(always)]
550-
pub fn is_low(&self) -> bool {
551-
self._is_low()
552-
}
591+
state_input!();
553592
}
554593

555594
macro_rules! gpio {

src/gpio/convert.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -112,14 +112,6 @@ impl<const P: char, const N: u8, MODE: PinMode> Pin<P, N, MODE> {
112112
self.into_mode()
113113
}
114114

115-
/// Configures the pin as a pin that can change between input
116-
/// and output without changing the type. It starts out
117-
/// as a floating input
118-
pub fn into_dynamic(self) -> DynamicPin<P, N> {
119-
self.into_floating_input();
120-
DynamicPin::new(Dynamic::InputFloating)
121-
}
122-
123115
/// Puts `self` into mode `M`.
124116
///
125117
/// This violates the type state constraints from `MODE`, so callers must
@@ -171,7 +163,7 @@ impl<MODE: PinMode> AnyPin<MODE> {
171163
#[inline(always)]
172164
pub(super) fn mode<M: PinMode>(&mut self) {
173165
let n = self.pin_id();
174-
change_mode!(self.block(), n);
166+
change_mode!((*self.block()), n);
175167
}
176168

177169
#[inline(always)]

0 commit comments

Comments
 (0)