@@ -41,6 +41,63 @@ pub struct Output<MODE> {
41
41
/// Push pull output (type state)
42
42
pub struct PushPull ;
43
43
44
+ mod sealed {
45
+ pub trait Sealed { }
46
+ }
47
+
48
+ /// Marker trait for valid pin modes (type state).
49
+ ///
50
+ /// It can not be implemented by outside types.
51
+ pub trait PinMode : sealed:: Sealed {
52
+ // These constants are used to implement the pin configuration code.
53
+ // They are not part of public API.
54
+
55
+ #[ doc( hidden) ]
56
+ const PUPDR : u8 ;
57
+ #[ doc( hidden) ]
58
+ const MODER : u8 ;
59
+ #[ doc( hidden) ]
60
+ const OTYPER : Option < u8 > = None ;
61
+ }
62
+
63
+ impl sealed:: Sealed for Input < Floating > { }
64
+ impl PinMode for Input < Floating > {
65
+ const PUPDR : u8 = 0b00 ;
66
+ const MODER : u8 = 0b00 ;
67
+ }
68
+
69
+ impl sealed:: Sealed for Input < PullDown > { }
70
+ impl PinMode for Input < PullDown > {
71
+ const PUPDR : u8 = 0b10 ;
72
+ const MODER : u8 = 0b00 ;
73
+ }
74
+
75
+ impl sealed:: Sealed for Input < PullUp > { }
76
+ impl PinMode for Input < PullUp > {
77
+ const PUPDR : u8 = 0b01 ;
78
+ const MODER : u8 = 0b00 ;
79
+ }
80
+
81
+ impl sealed:: Sealed for Analog { }
82
+ impl PinMode for Analog {
83
+ const PUPDR : u8 = 0b00 ;
84
+ const MODER : u8 = 0b11 ;
85
+ }
86
+
87
+ impl sealed:: Sealed for Output < OpenDrain > { }
88
+ impl PinMode for Output < OpenDrain > {
89
+ const PUPDR : u8 = 0b00 ;
90
+ const MODER : u8 = 0b01 ;
91
+ const OTYPER : Option < u8 > = Some ( 0b1 ) ;
92
+ }
93
+
94
+ impl sealed:: Sealed for Output < PushPull > { }
95
+ impl PinMode for Output < PushPull > {
96
+ const PUPDR : u8 = 0b00 ;
97
+ const MODER : u8 = 0b01 ;
98
+ const OTYPER : Option < u8 > = Some ( 0b0 ) ;
99
+ }
100
+
44
101
/// GPIO Pin speed selection
45
102
#[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
46
103
pub enum Speed {
@@ -85,7 +142,8 @@ macro_rules! gpio {
85
142
use crate :: rcc:: Rcc ;
86
143
use super :: {
87
144
Floating , GpioExt , Input , OpenDrain , Output , Speed ,
88
- PullDown , PullUp , PushPull , AltMode , Analog , Port
145
+ PullDown , PullUp , PushPull , AltMode , Analog , Port ,
146
+ PinMode ,
89
147
} ;
90
148
91
149
/// GPIO parts
@@ -218,122 +276,91 @@ macro_rules! gpio {
218
276
}
219
277
}
220
278
221
- impl <MODE > $PXi<MODE > {
222
- /// Configures the pin to operate as a floating input pin
223
- pub fn into_floating_input(
224
- self ,
225
- ) -> $PXi<Input <Floating >> {
279
+ impl <MODE : PinMode > $PXi<MODE > {
280
+ /// Puts `self` into mode `M`.
281
+ ///
282
+ /// This violates the type state constraints from `MODE`, so callers must
283
+ /// ensure they use this properly.
284
+ fn mode<M : PinMode >( & mut self ) {
226
285
let offset = 2 * $i;
227
286
unsafe {
228
287
& ( * $GPIOX:: ptr( ) ) . pupdr. modify( |r, w| {
229
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
288
+ w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( u32 :: from ( M :: PUPDR ) << offset) )
230
289
} ) ;
290
+
291
+ if let Some ( otyper) = M :: OTYPER {
292
+ & ( * $GPIOX:: ptr( ) ) . otyper. modify( |r, w| {
293
+ w. bits( r. bits( ) & !( 0b1 << $i) | ( u32 :: from( otyper) << $i) )
294
+ } ) ;
295
+ }
296
+
231
297
& ( * $GPIOX:: ptr( ) ) . moder. modify( |r, w| {
232
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
233
- } )
234
- } ;
298
+ w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( u32 :: from( M :: MODER ) << offset) )
299
+ } ) ;
300
+ }
301
+ }
302
+
303
+ /// Configures the pin to operate as a floating input pin.
304
+ pub fn into_floating_input(
305
+ mut self ,
306
+ ) -> $PXi<Input <Floating >> {
307
+ self . mode:: <Input <Floating >>( ) ;
235
308
$PXi {
236
309
_mode: PhantomData
237
310
}
238
311
}
239
312
240
- /// Configures the pin to operate as a pulled down input pin
313
+ /// Configures the pin to operate as a pulled down input pin.
241
314
pub fn into_pull_down_input(
242
- self ,
243
- ) -> $PXi<Input <PullDown >> {
244
- let offset = 2 * $i;
245
- unsafe {
246
- & ( * $GPIOX:: ptr( ) ) . pupdr. modify( |r, w| {
247
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b10 << offset) )
248
- } ) ;
249
- & ( * $GPIOX:: ptr( ) ) . moder. modify( |r, w| {
250
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
251
- } )
252
- } ;
315
+ mut self ,
316
+ ) -> $PXi<Input <PullDown >> {
317
+ self . mode:: <Input <Floating >>( ) ;
253
318
$PXi {
254
319
_mode: PhantomData
255
320
}
256
321
}
257
322
258
- /// Configures the pin to operate as a pulled up input pin
323
+ /// Configures the pin to operate as a pulled up input pin.
259
324
pub fn into_pull_up_input(
260
- self ,
325
+ mut self ,
261
326
) -> $PXi<Input <PullUp >> {
262
- let offset = 2 * $i;
263
- unsafe {
264
- & ( * $GPIOX:: ptr( ) ) . pupdr. modify( |r, w| {
265
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b01 << offset) )
266
- } ) ;
267
- & ( * $GPIOX:: ptr( ) ) . moder. modify( |r, w| {
268
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
269
- } )
270
- } ;
327
+ self . mode:: <Input <PullUp >>( ) ;
271
328
$PXi {
272
329
_mode: PhantomData
273
330
}
274
331
}
275
332
276
- /// Configures the pin to operate as an analog pin
333
+ /// Configures the pin to operate as an analog pin.
277
334
pub fn into_analog(
278
- self ,
335
+ mut self ,
279
336
) -> $PXi<Analog > {
280
- let offset = 2 * $i;
281
- unsafe {
282
- & ( * $GPIOX:: ptr( ) ) . pupdr. modify( |r, w| {
283
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
284
- } ) ;
285
- & ( * $GPIOX:: ptr( ) ) . moder. modify( |r, w| {
286
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b11 << offset) )
287
- } ) ;
288
- }
337
+ self . mode:: <Analog >( ) ;
289
338
$PXi {
290
339
_mode: PhantomData
291
340
}
292
341
}
293
342
294
- /// Configures the pin to operate as an open drain output pin
343
+ /// Configures the pin to operate as an open drain output pin.
295
344
pub fn into_open_drain_output(
296
- self ,
345
+ mut self ,
297
346
) -> $PXi<Output <OpenDrain >> {
298
- let offset = 2 * $i;
299
- unsafe {
300
- & ( * $GPIOX:: ptr( ) ) . pupdr. modify( |r, w| {
301
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
302
- } ) ;
303
- & ( * $GPIOX:: ptr( ) ) . otyper. modify( |r, w| {
304
- w. bits( r. bits( ) | ( 0b1 << $i) )
305
- } ) ;
306
- & ( * $GPIOX:: ptr( ) ) . moder. modify( |r, w| {
307
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b01 << offset) )
308
- } )
309
- } ;
347
+ self . mode:: <Output <OpenDrain >>( ) ;
310
348
$PXi {
311
349
_mode: PhantomData
312
350
}
313
351
}
314
352
315
- /// Configures the pin to operate as an push pull output pin
353
+ /// Configures the pin to operate as an push pull output pin.
316
354
pub fn into_push_pull_output(
317
- self ,
355
+ mut self ,
318
356
) -> $PXi<Output <PushPull >> {
319
- let offset = 2 * $i;
320
- unsafe {
321
- & ( * $GPIOX:: ptr( ) ) . pupdr. modify( |r, w| {
322
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b00 << offset) )
323
- } ) ;
324
- & ( * $GPIOX:: ptr( ) ) . otyper. modify( |r, w| {
325
- w. bits( r. bits( ) & !( 0b1 << $i) )
326
- } ) ;
327
- & ( * $GPIOX:: ptr( ) ) . moder. modify( |r, w| {
328
- w. bits( ( r. bits( ) & !( 0b11 << offset) ) | ( 0b01 << offset) )
329
- } )
330
- } ;
357
+ self . mode:: <Output <PushPull >>( ) ;
331
358
$PXi {
332
359
_mode: PhantomData
333
360
}
334
361
}
335
362
336
- /// Set pin speed
363
+ /// Set pin speed.
337
364
pub fn set_speed( self , speed: Speed ) -> Self {
338
365
let offset = 2 * $i;
339
366
unsafe {
0 commit comments