1use core::marker::PhantomData;
4
5pub trait GpioExt {
7 type Parts;
9
10 fn split(self) -> Self::Parts;
12}
13
14pub struct AF0;
15pub struct AF1;
16pub struct AF2;
17pub struct AF3;
18pub struct AF4;
19pub struct AF5;
20pub struct AF6;
21pub struct AF7;
22
23pub struct Alternate<MODE> {
24 _mode: PhantomData<MODE>,
25}
26
27pub struct Input<MODE> {
29 _mode: PhantomData<MODE>,
30}
31
32pub struct Floating;
34
35pub struct PullDown;
37
38pub struct PullUp;
40
41pub struct OpenDrain;
43
44pub struct Output<MODE> {
46 _mode: PhantomData<MODE>,
47}
48
49pub struct PushPull;
51
52macro_rules! gpio {
53 ($GPIOX:ident, $gpiox:ident, $iopxenr:ident, $PXx:ident, [
54 $($PXi:ident: ($pxi:ident, $i:expr, $MODE:ty),)+
55 ]) => {
56 pub mod $gpiox {
58 use core::marker::PhantomData;
59
60 use hal::digital::{InputPin, OutputPin, StatefulOutputPin};
61 use stm32::$GPIOX;
62
63 use stm32::RCC;
64 use super::{
65 Alternate, Floating, GpioExt, Input, OpenDrain, Output,
66 PullDown, PullUp, PushPull, AF0, AF1, AF2, AF3, AF4, AF5, AF6, AF7,
67 };
68
69 pub struct Parts {
71 $(
72 pub $pxi: $PXi<$MODE>,
74 )+
75 }
76
77 impl GpioExt for $GPIOX {
78 type Parts = Parts;
79
80 fn split(self) -> Parts {
81 let rcc = unsafe { &(*RCC::ptr()) };
83 rcc.ahbenr.modify(|_, w| w.$iopxenr().set_bit());
84
85 Parts {
86 $(
87 $pxi: $PXi { _mode: PhantomData },
88 )+
89 }
90 }
91 }
92
93 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 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 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
114 }
115
116 fn set_low(&mut self) {
117 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (self.i + 16))) }
119 }
120 }
121
122 impl<MODE> InputPin for $PXx<Input<MODE>> {
123 fn is_high(&self) -> bool {
124 !self.is_low()
125 }
126
127 fn is_low(&self) -> bool {
128 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
130 }
131 }
132
133 fn _set_alternate_mode (index:usize, mode: u32)
134 {
135 let offset = 2 * index;
136 let offset2 = 4 * index;
137 unsafe {
138 if offset2 < 32 {
139 &(*$GPIOX::ptr()).afrl.modify(|r, w| {
140 w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
141 });
142 } else
143 {
144 let offset2 = offset2 - 32;
145 &(*$GPIOX::ptr()).afrh.modify(|r, w| {
146 w.bits((r.bits() & !(0b1111 << offset2)) | (mode << offset2))
147 });
148 }
149 &(*$GPIOX::ptr()).moder.modify(|r, w| {
150 w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
151 });
152 }
153 }
154
155 $(
156 pub struct $PXi<MODE> {
158 _mode: PhantomData<MODE>,
159 }
160
161 impl<MODE> $PXi<MODE> {
162 pub fn into_alternate_af0(
164 self,
165 ) -> $PXi<Alternate<AF0>> {
166 _set_alternate_mode($i, 0);
167 $PXi { _mode: PhantomData }
168 }
169
170 pub fn into_alternate_af1(
172 self,
173 ) -> $PXi<Alternate<AF1>> {
174 _set_alternate_mode($i, 1);
175 $PXi { _mode: PhantomData }
176 }
177
178 pub fn into_alternate_af2(
180 self,
181 ) -> $PXi<Alternate<AF2>> {
182 _set_alternate_mode($i, 2);
183 $PXi { _mode: PhantomData }
184 }
185
186 pub fn into_alternate_af3(
188 self,
189 ) -> $PXi<Alternate<AF3>> {
190 _set_alternate_mode($i, 3);
191 $PXi { _mode: PhantomData }
192 }
193
194 pub fn into_alternate_af4(
196 self,
197 ) -> $PXi<Alternate<AF4>> {
198 _set_alternate_mode($i, 4);
199 $PXi { _mode: PhantomData }
200 }
201
202 pub fn into_alternate_af5(
204 self,
205 ) -> $PXi<Alternate<AF5>> {
206 _set_alternate_mode($i, 5);
207 $PXi { _mode: PhantomData }
208 }
209
210 pub fn into_alternate_af6(
212 self,
213 ) -> $PXi<Alternate<AF6>> {
214 _set_alternate_mode($i, 6);
215 $PXi { _mode: PhantomData }
216 }
217
218 pub fn into_alternate_af7(
220 self,
221 ) -> $PXi<Alternate<AF7>> {
222 _set_alternate_mode($i, 7);
223 $PXi { _mode: PhantomData }
224 }
225
226 pub fn into_floating_input(
228 self,
229 ) -> $PXi<Input<Floating>> {
230 let offset = 2 * $i;
231 unsafe {
232 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
233 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
234 });
235 &(*$GPIOX::ptr()).moder.modify(|r, w| {
236 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
237 });
238 }
239 $PXi { _mode: PhantomData }
240 }
241
242 pub fn into_pull_down_input(
244 self,
245 ) -> $PXi<Input<PullDown>> {
246 let offset = 2 * $i;
247 unsafe {
248 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
249 w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset))
250 });
251 &(*$GPIOX::ptr()).moder.modify(|r, w| {
252 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
253 });
254 }
255 $PXi { _mode: PhantomData }
256 }
257
258 pub fn into_pull_up_input(
260 self,
261 ) -> $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 }
271 $PXi { _mode: PhantomData }
272 }
273
274 pub fn into_open_drain_output(
276 self,
277 ) -> $PXi<Output<OpenDrain>> {
278 let offset = 2 * $i;
279 unsafe {
280 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
281 w.bits((r.bits() & !(0b11 << offset)) | (0b00 << offset))
282 });
283 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
284 w.bits(r.bits() | (0b1 << $i))
285 });
286 &(*$GPIOX::ptr()).moder.modify(|r, w| {
287 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
288 });
289 }
290 $PXi { _mode: PhantomData }
291 }
292
293 pub fn into_push_pull_output(
295 self,
296 ) -> $PXi<Output<PushPull>> {
297 let offset = 2 * $i;
298
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 }
310 $PXi { _mode: PhantomData }
311 }
312
313 pub fn into_push_pull_output_hs(
316 self,
317 ) -> $PXi<Output<PushPull>> {
318 let offset = 2 * $i;
319
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()).ospeedr.modify(|r, w| {
328 w.bits(r.bits() & !(0b1 << $i))
329 });
330 &(*$GPIOX::ptr()).moder.modify(|r, w| {
331 w.bits((r.bits() & !(0b11 << offset)) | (0b01 << offset))
332 });
333 }
334
335 $PXi { _mode: PhantomData }
336 }
337 }
338
339 impl $PXi<Output<OpenDrain>> {
340 pub fn internal_pull_up(&mut self, on: bool) {
342 let offset = 2 * $i;
343 let value = if on { 0b01 } else { 0b00 };
344 unsafe {
345 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
346 w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
347 })};
348 }
349 }
350
351 impl<MODE> $PXi<Alternate<MODE>> {
352 pub fn internal_pull_up(self, on: bool) -> Self {
354 let offset = 2 * $i;
355 let value = if on { 0b01 } else { 0b00 };
356 unsafe {
357 &(*$GPIOX::ptr()).pupdr.modify(|r, w| {
358 w.bits((r.bits() & !(0b11 << offset)) | (value << offset))
359 })};
360
361 self
362 }
363 }
364
365 impl<MODE> $PXi<Alternate<MODE>> {
366 pub fn set_open_drain(self) -> Self {
368 let offset = $i;
369 unsafe {
370 &(*$GPIOX::ptr()).otyper.modify(|r, w| {
371 w.bits(r.bits() | (1 << offset))
372 })};
373
374 self
375 }
376 }
377
378 impl<MODE> $PXi<Output<MODE>> {
379 pub fn downgrade(self) -> $PXx<Output<MODE>> {
384 $PXx {
385 i: $i,
386 _mode: self._mode,
387 }
388 }
389 }
390
391 impl<MODE> StatefulOutputPin for $PXi<Output<MODE>> {
392 fn is_set_high(&self) -> bool {
393 !self.is_set_low()
394 }
395
396 fn is_set_low(&self) -> bool {
397 unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
399 }
400 }
401
402 impl<MODE> OutputPin for $PXi<Output<MODE>> {
403 fn set_high(&mut self) {
404 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
406 }
407
408 fn set_low(&mut self) {
409 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << ($i + 16))) }
411 }
412 }
413
414 impl<MODE> $PXi<Input<MODE>> {
415 pub fn downgrade(self) -> $PXx<Input<MODE>> {
420 $PXx {
421 i: $i,
422 _mode: self._mode,
423 }
424 }
425 }
426
427 impl<MODE> InputPin for $PXi<Input<MODE>> {
428 fn is_high(&self) -> bool {
429 !self.is_low()
430 }
431
432 fn is_low(&self) -> bool {
433 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
435 }
436 }
437 )+
438
439 impl<TYPE> $PXx<TYPE> {
440 pub fn get_id (&self) -> u8
441 {
442 self.i
443 }
444 }
445 }
446 }
447}
448
449gpio!(GPIOA, gpioa, iopaen, PA, [
450 PA0: (pa0, 0, Input<Floating>),
451 PA1: (pa1, 1, Input<Floating>),
452 PA2: (pa2, 2, Input<Floating>),
453 PA3: (pa3, 3, Input<Floating>),
454 PA4: (pa4, 4, Input<Floating>),
455 PA5: (pa5, 5, Input<Floating>),
456 PA6: (pa6, 6, Input<Floating>),
457 PA7: (pa7, 7, Input<Floating>),
458 PA8: (pa8, 8, Input<Floating>),
459 PA9: (pa9, 9, Input<Floating>),
460 PA10: (pa10, 10, Input<Floating>),
461 PA11: (pa11, 11, Input<Floating>),
462 PA12: (pa12, 12, Input<Floating>),
463 PA13: (pa13, 13, Input<Floating>),
464 PA14: (pa14, 14, Input<Floating>),
465 PA15: (pa15, 15, Input<Floating>),
466]);
467
468gpio!(GPIOB, gpiob, iopben, PB, [
469 PB0: (pb0, 0, Input<Floating>),
470 PB1: (pb1, 1, Input<Floating>),
471 PB2: (pb2, 2, Input<Floating>),
472 PB3: (pb3, 3, Input<Floating>),
473 PB4: (pb4, 4, Input<Floating>),
474 PB5: (pb5, 5, Input<Floating>),
475 PB6: (pb6, 6, Input<Floating>),
476 PB7: (pb7, 7, Input<Floating>),
477 PB8: (pb8, 8, Input<Floating>),
478 PB9: (pb9, 9, Input<Floating>),
479 PB10: (pb10, 10, Input<Floating>),
480 PB11: (pb11, 11, Input<Floating>),
481 PB12: (pb12, 12, Input<Floating>),
482 PB13: (pb13, 13, Input<Floating>),
483 PB14: (pb14, 14, Input<Floating>),
484 PB15: (pb15, 15, Input<Floating>),
485]);
486
487gpio!(GPIOC, gpioc, iopcen, PC, [
488 PC13: (pc13, 13, Input<Floating>),
489 PC14: (pc14, 14, Input<Floating>),
490 PC15: (pc15, 15, Input<Floating>),
491]);
492
493gpio!(GPIOF, gpiof, iopfen, PF, [
494 PF0: (pf0, 0, Input<Floating>),
495 PF1: (pf1, 1, Input<Floating>),
496 PF11: (pf11, 11, Input<Floating>),
497]);