18
18
//! Some pins that could be configured here may be missing from actual MCU
19
19
//! depending on the package.
20
20
21
+ use hal:: pin:: { Gpio , GpioDirection , GpioLevel } ;
21
22
use super :: peripheral_clock;
22
23
use core:: intrinsics:: abort;
23
24
@@ -68,12 +69,9 @@ impl Port {
68
69
}
69
70
}
70
71
71
- /// Pin configuration.
72
- ///
73
- /// This structure shouldn't be used directly, pinmap.rs, available via pin::map
74
- /// has all possible pin configurations.
72
+ /// Pin configuration
75
73
#[ derive( Clone , Copy ) ]
76
- pub struct PinConf {
74
+ pub struct Pin {
77
75
/// Pin port, mcu-specific.
78
76
pub port : Port ,
79
77
/// Pin number.
@@ -82,58 +80,33 @@ pub struct PinConf {
82
80
pub function : Function ,
83
81
}
84
82
85
- impl PinConf {
83
+ impl Pin {
86
84
/// Setup the pin.
87
85
#[ inline( always) ]
88
86
pub fn setup ( & self ) {
89
87
use self :: Function :: * ;
88
+ use self :: reg:: GPIO_moder_mode as RegMode ;
90
89
91
90
self . port . clock ( ) . enable ( ) ; // TODO(farcaller): should be done once per port
92
91
93
- let offset: u32 = self . pin as u32 * 2 ;
92
+ let offset = self . pin as usize ;
94
93
let gpreg = self . get_reg ( ) ;
95
94
96
- let bits : u32 = match self . function {
97
- GPIOOut => 0b01 << offset as usize ,
98
- GPIOIn => 0b00 << offset as usize ,
95
+ let val = match self . function {
96
+ GPIOOut => RegMode :: Output ,
97
+ GPIOIn => RegMode :: Input ,
99
98
_ => unsafe { abort ( ) } , // FIXME(farcaller): not implemented
100
99
} ;
101
- let mask: u32 = !( 0b11 << offset as usize ) ;
102
- let val: u32 = gpreg. MODER ( ) ;
103
100
104
- gpreg. set_MODER ( val & mask | bits) ;
105
- }
106
-
107
- /// Sets output GPIO value to high.
108
- pub fn set_high ( & self ) {
109
- let bit: u32 = 1 << self . pin as usize ;
110
- self . get_reg ( ) . set_BSRR ( bit) ;
111
- }
112
-
113
- /// Sets output GPIO value to low.
114
- pub fn set_low ( & self ) {
115
- let bit: u32 = 1 << ( self . pin as usize + 16 ) ;
116
- self . get_reg ( ) . set_BSRR ( bit) ;
101
+ gpreg. moder . set_mode ( offset, val) ;
117
102
}
118
103
119
104
/// Toggles the GPIO value
120
105
pub fn toggle ( & self ) {
121
- let bit: u32 = 1 << self . pin as usize ;
122
106
let reg = self . get_reg ( ) ;
123
- let val : u32 = reg . ODR ( ) ;
107
+ let offset = self . pin as usize ;
124
108
125
- reg. set_ODR ( val ^ bit) ;
126
- }
127
-
128
- /// Returns input GPIO level.
129
- pub fn level ( & self ) -> :: hal:: pin:: GpioLevel {
130
- let bit: u32 = 1 << ( self . pin as usize ) ;
131
- let reg = self . get_reg ( ) ;
132
-
133
- match reg. IDR ( ) & bit {
134
- 0 => :: hal:: pin:: Low ,
135
- _ => :: hal:: pin:: High ,
136
- }
109
+ reg. odr . set_od ( offset, !reg. odr . od ( offset) ) ;
137
110
}
138
111
139
112
fn get_reg ( & self ) -> & reg:: GPIO {
@@ -151,21 +124,103 @@ impl PinConf {
151
124
}
152
125
}
153
126
127
+ impl Gpio for Pin {
128
+ /// Sets output GPIO value to high.
129
+ fn set_high ( & self ) {
130
+ let offset = self . pin as usize ;
131
+ self . get_reg ( ) . bsrr . set_bs ( offset, true ) ;
132
+ }
133
+
134
+ /// Sets output GPIO value to low.
135
+ fn set_low ( & self ) {
136
+ let offset = self . pin as usize ;
137
+ self . get_reg ( ) . bsrr . set_br ( offset, true ) ;
138
+ }
139
+
140
+ /// Returns input GPIO level.
141
+ fn level ( & self ) -> GpioLevel {
142
+ let offset = self . pin as usize ;
143
+ let reg = self . get_reg ( ) ;
144
+
145
+ match reg. idr . id ( offset) {
146
+ false => GpioLevel :: Low ,
147
+ _ => GpioLevel :: High ,
148
+ }
149
+ }
150
+
151
+ /// Sets output GPIO direction.
152
+ fn set_direction ( & self , new_mode : GpioDirection ) {
153
+ // TODO(darayus): Verify that this works
154
+ // TODO(darayus): Change the Pin.function field to the new mode
155
+ use self :: reg:: GPIO_moder_mode as RegMode ;
156
+ let offset = self . pin as usize ;
157
+ let reg = self . get_reg ( ) ;
158
+
159
+ let val = match new_mode {
160
+ GpioDirection :: Out => RegMode :: Output ,
161
+ GpioDirection :: In => RegMode :: Input ,
162
+ } ;
163
+
164
+ reg. moder . set_mode ( offset, val) ;
165
+ }
166
+ }
167
+
154
168
#[ allow( dead_code) ]
155
169
mod reg {
170
+ use core:: ops:: Drop ;
156
171
use volatile_cell:: VolatileCell ;
157
172
158
- ioreg_old ! ( GPIO : u32 , MODER , OTYPER , OSPEEDER , PUPDR , IDR , ODR , BSRR , LCKR , AFRL , AFRH ) ;
159
- reg_rw ! ( GPIO , u32 , MODER , set_MODER, MODER ) ;
160
- reg_rw ! ( GPIO , u32 , OTYPER , set_OTYPER, OTYPER ) ;
161
- reg_rw ! ( GPIO , u32 , OSPEEDER , set_OSPEEDER, OSPEEDER ) ;
162
- reg_rw ! ( GPIO , u32 , PUPDR , set_PUPDR, PUPDR ) ;
163
- reg_rw ! ( GPIO , u32 , IDR , set_IDR, IDR ) ;
164
- reg_rw ! ( GPIO , u32 , ODR , set_ODR, ODR ) ;
165
- reg_rw ! ( GPIO , u32 , BSRR , set_BSRR, BSRR ) ;
166
- reg_rw ! ( GPIO , u32 , LCKR , set_LCKR, LCKR ) ;
167
- reg_rw ! ( GPIO , u32 , AFRL , set_AFRL, AFRL ) ;
168
- reg_rw ! ( GPIO , u32 , AFRH , set_AFRH, AFRH ) ;
173
+ ioregs ! ( GPIO = {
174
+ 0x0 => reg32 moder {
175
+ 0 ..31 => mode[ 16 ] {
176
+ 0 => Input ,
177
+ 1 => Output ,
178
+ 3 => Alternate ,
179
+ 4 => Analog
180
+ }
181
+ }
182
+ 0x04 => reg32 otyper {
183
+ 0 ..15 => ot[ 16 ] {
184
+ 0 => PushPull ,
185
+ 1 => OpenDrain
186
+ }
187
+ }
188
+ 0x08 => reg32 ospeedr {
189
+ 0 ..31 => ospeed[ 16 ] {
190
+ 0 => Low ,
191
+ 1 => Medium ,
192
+ 2 => Fast ,
193
+ 3 => High
194
+ }
195
+ }
196
+ 0x0c => reg32 pupdr {
197
+ 0 ..31 => pupd[ 16 ] {
198
+ 0 => None ,
199
+ 1 => PullUp ,
200
+ 2 => PullDown
201
+ }
202
+ }
203
+ 0x10 => reg32 idr {
204
+ 0 ..15 => id[ 16 ] : ro
205
+ }
206
+ 0x14 => reg32 odr {
207
+ 0 ..15 => od[ 16 ]
208
+ }
209
+ 0x18 => reg32 bsrr {
210
+ 0 ..15 => bs[ 16 ] : wo,
211
+ 16 ..31 => br[ 16 ] : wo
212
+ }
213
+ 0x1c => reg32 lckr {
214
+ 0 ..15 => lck[ 16 ] ,
215
+ 16 => lckk
216
+ }
217
+ 0x20 => reg32 afrl {
218
+ 0 ..31 => afrl[ 8 ]
219
+ }
220
+ 0x24 => reg32 afrh {
221
+ 0 ..31 => afrh[ 8 ]
222
+ }
223
+ } ) ;
169
224
170
225
extern {
171
226
#[ link_name="stm32f4_iomem_GPIOA" ] pub static GPIO_A : GPIO ;
0 commit comments