@@ -11,6 +11,13 @@ pub trait GpioExt {
11
11
fn split ( self ) -> Self :: Parts ;
12
12
}
13
13
14
+ trait GpioRegExt {
15
+ fn is_low ( & self , pos : u8 ) -> bool ;
16
+ fn is_set_low ( & self , pos : u8 ) -> bool ;
17
+ fn set_high ( & self , pos : u8 ) ;
18
+ fn set_low ( & self , pos : u8 ) ;
19
+ }
20
+
14
21
pub struct AF0 ;
15
22
pub struct AF1 ;
16
23
pub struct AF2 ;
@@ -49,6 +56,86 @@ pub struct Output<MODE> {
49
56
/// Push pull output (type state)
50
57
pub struct PushPull ;
51
58
59
+ use embedded_hal:: digital:: { toggleable, InputPin , OutputPin , StatefulOutputPin } ;
60
+
61
+ /// Fully erased pin
62
+ pub struct Pin < MODE > {
63
+ i : u8 ,
64
+ port : * const GpioRegExt ,
65
+ _mode : PhantomData < MODE > ,
66
+ }
67
+
68
+ impl < MODE > StatefulOutputPin for Pin < Output < MODE > > {
69
+ fn is_set_high ( & self ) -> bool {
70
+ !self . is_set_low ( )
71
+ }
72
+
73
+ fn is_set_low ( & self ) -> bool {
74
+ unsafe { ( * self . port ) . is_set_low ( self . i ) }
75
+ }
76
+ }
77
+
78
+ impl < MODE > OutputPin for Pin < Output < MODE > > {
79
+ fn set_high ( & mut self ) {
80
+ unsafe { ( * self . port ) . set_high ( self . i ) }
81
+ }
82
+
83
+ fn set_low ( & mut self ) {
84
+ unsafe { ( * self . port ) . set_low ( self . i ) }
85
+ }
86
+ }
87
+
88
+ impl < MODE > toggleable:: Default for Pin < Output < MODE > > { }
89
+
90
+ impl InputPin for Pin < Output < OpenDrain > > {
91
+ fn is_high ( & self ) -> bool {
92
+ !self . is_low ( )
93
+ }
94
+
95
+ fn is_low ( & self ) -> bool {
96
+ unsafe { ( * self . port ) . is_low ( self . i ) }
97
+ }
98
+ }
99
+
100
+ impl < MODE > InputPin for Pin < Input < MODE > > {
101
+ fn is_high ( & self ) -> bool {
102
+ !self . is_low ( )
103
+ }
104
+
105
+ fn is_low ( & self ) -> bool {
106
+ unsafe { ( * self . port ) . is_low ( self . i ) }
107
+ }
108
+ }
109
+
110
+ macro_rules! gpio_trait {
111
+ ( $gpiox: ident) => {
112
+ impl GpioRegExt for crate :: stm32:: $gpiox:: RegisterBlock {
113
+ fn is_low( & self , pos: u8 ) -> bool {
114
+ // NOTE(unsafe) atomic read with no side effects
115
+ self . idr. read( ) . bits( ) & ( 1 << pos) == 0
116
+ }
117
+
118
+ fn is_set_low( & self , pos: u8 ) -> bool {
119
+ // NOTE(unsafe) atomic read with no side effects
120
+ self . odr. read( ) . bits( ) & ( 1 << pos) == 0
121
+ }
122
+
123
+ fn set_high( & self , pos: u8 ) {
124
+ // NOTE(unsafe) atomic write to a stateless register
125
+ unsafe { self . bsrr. write( |w| w. bits( 1 << pos) ) }
126
+ }
127
+
128
+ fn set_low( & self , pos: u8 ) {
129
+ // NOTE(unsafe) atomic write to a stateless register
130
+ unsafe { self . bsrr. write( |w| w. bits( 1 << ( pos + 16 ) ) ) }
131
+ }
132
+ }
133
+ } ;
134
+ }
135
+
136
+ gpio_trait ! ( gpioa) ;
137
+ gpio_trait ! ( gpiof) ;
138
+
52
139
macro_rules! gpio {
53
140
( $GPIOX: ident, $gpiox: ident, $iopxenr: ident, $PXx: ident, [
54
141
$( $PXi: ident: ( $pxi: ident, $i: expr, $MODE: ty) , ) +
@@ -64,6 +151,7 @@ macro_rules! gpio {
64
151
use super :: {
65
152
Alternate , Floating , GpioExt , Input , OpenDrain , Output ,
66
153
PullDown , PullUp , PushPull , AF0 , AF1 , AF2 , AF3 , AF4 , AF5 , AF6 , AF7 ,
154
+ Pin , GpioRegExt ,
67
155
} ;
68
156
69
157
/// GPIO parts
@@ -90,48 +178,6 @@ macro_rules! gpio {
90
178
}
91
179
}
92
180
93
- /// Partially erased pin
94
- pub struct $PXx<MODE > {
95
- i: u8 ,
96
- _mode: PhantomData <MODE >,
97
- }
98
-
99
- impl <MODE > StatefulOutputPin for $PXx<Output <MODE >> {
100
- fn is_set_high( & self ) -> bool {
101
- !self . is_set_low( )
102
- }
103
-
104
- fn is_set_low( & self ) -> bool {
105
- // NOTE(unsafe) atomic read with no side effects
106
- unsafe { ( * $GPIOX:: ptr( ) ) . odr. read( ) . bits( ) & ( 1 << self . i) == 0 }
107
- }
108
- }
109
-
110
- impl <MODE > OutputPin for $PXx<Output <MODE >> {
111
- fn set_high( & mut self ) {
112
- // NOTE(unsafe) atomic write to a stateless register
113
- unsafe { ( * $GPIOX:: ptr( ) ) . bsrr. write( |w| w. bits( 1 << self . i) ) }
114
- }
115
-
116
- fn set_low( & mut self ) {
117
- // NOTE(unsafe) atomic write to a stateless register
118
- unsafe { ( * $GPIOX:: ptr( ) ) . bsrr. write( |w| w. bits( 1 << ( self . i + 16 ) ) ) }
119
- }
120
- }
121
-
122
- impl <MODE > toggleable:: Default for $PXx<Output <MODE >> { }
123
-
124
- impl <MODE > InputPin for $PXx<Input <MODE >> {
125
- fn is_high( & self ) -> bool {
126
- !self . is_low( )
127
- }
128
-
129
- fn is_low( & self ) -> bool {
130
- // NOTE(unsafe) atomic read with no side effects
131
- unsafe { ( * $GPIOX:: ptr( ) ) . idr. read( ) . bits( ) & ( 1 << self . i) == 0 }
132
- }
133
- }
134
-
135
181
fn _set_alternate_mode ( index: usize , mode: u32 )
136
182
{
137
183
let offset = 2 * index;
@@ -382,9 +428,10 @@ macro_rules! gpio {
382
428
///
383
429
/// This is useful when you want to collect the pins into an array where you
384
430
/// need all the elements to have the same type
385
- pub fn downgrade( self ) -> $PXx <Output <MODE >> {
386
- $PXx {
431
+ pub fn downgrade( self ) -> Pin <Output <MODE >> {
432
+ Pin {
387
433
i: $i,
434
+ port: $GPIOX:: ptr( ) as * const GpioRegExt ,
388
435
_mode: self . _mode,
389
436
}
390
437
}
@@ -396,33 +443,41 @@ macro_rules! gpio {
396
443
}
397
444
398
445
fn is_set_low( & self ) -> bool {
399
- // NOTE(unsafe) atomic read with no side effects
400
- unsafe { ( * $GPIOX:: ptr( ) ) . odr. read( ) . bits( ) & ( 1 << $i) == 0 }
446
+ unsafe { ( * $GPIOX:: ptr( ) ) . is_set_low( $i) }
401
447
}
402
448
}
403
449
404
450
impl <MODE > OutputPin for $PXi<Output <MODE >> {
405
451
fn set_high( & mut self ) {
406
- // NOTE(unsafe) atomic write to a stateless register
407
- unsafe { ( * $GPIOX:: ptr( ) ) . bsrr. write( |w| w. bits( 1 << $i) ) }
452
+ unsafe { ( * $GPIOX:: ptr( ) ) . set_high( $i) }
408
453
}
409
454
410
455
fn set_low( & mut self ) {
411
- // NOTE(unsafe) atomic write to a stateless register
412
- unsafe { ( * $GPIOX:: ptr( ) ) . bsrr. write( |w| w. bits( 1 << ( $i + 16 ) ) ) }
456
+ unsafe { ( * $GPIOX:: ptr( ) ) . set_low( $i) }
413
457
}
414
458
}
415
459
416
460
impl <MODE > toggleable:: Default for $PXi<Output <MODE >> { }
417
461
462
+ impl InputPin for $PXi<Output <OpenDrain >> {
463
+ fn is_high( & self ) -> bool {
464
+ !self . is_low( )
465
+ }
466
+
467
+ fn is_low( & self ) -> bool {
468
+ unsafe { ( * $GPIOX:: ptr( ) ) . is_low( $i) }
469
+ }
470
+ }
471
+
418
472
impl <MODE > $PXi<Input <MODE >> {
419
473
/// Erases the pin number from the type
420
474
///
421
475
/// This is useful when you want to collect the pins into an array where you
422
476
/// need all the elements to have the same type
423
- pub fn downgrade( self ) -> $PXx <Input <MODE >> {
424
- $PXx {
477
+ pub fn downgrade( self ) -> Pin <Input <MODE >> {
478
+ Pin {
425
479
i: $i,
480
+ port: $GPIOX:: ptr( ) as * const GpioRegExt ,
426
481
_mode: self . _mode,
427
482
}
428
483
}
@@ -434,18 +489,10 @@ macro_rules! gpio {
434
489
}
435
490
436
491
fn is_low( & self ) -> bool {
437
- // NOTE(unsafe) atomic read with no side effects
438
- unsafe { ( * $GPIOX:: ptr( ) ) . idr. read( ) . bits( ) & ( 1 << $i) == 0 }
492
+ unsafe { ( * $GPIOX:: ptr( ) ) . is_low( $i) }
439
493
}
440
494
}
441
495
) +
442
-
443
- impl <TYPE > $PXx<TYPE > {
444
- pub fn get_id ( & self ) -> u8
445
- {
446
- self . i
447
- }
448
- }
449
496
}
450
497
}
451
498
}
0 commit comments