aboutsummaryrefslogtreecommitdiff
path: root/embassy-nxp/src/gpio/lpc55.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-nxp/src/gpio/lpc55.rs')
-rw-r--r--embassy-nxp/src/gpio/lpc55.rs677
1 files changed, 677 insertions, 0 deletions
diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs
new file mode 100644
index 000000000..94cd8b7f8
--- /dev/null
+++ b/embassy-nxp/src/gpio/lpc55.rs
@@ -0,0 +1,677 @@
1use embassy_hal_internal::{impl_peripheral, PeripheralType};
2
3use crate::{peripherals, Peri};
4
5pub(crate) fn init() {
6 // Enable clocks for GPIO, PINT, and IOCON
7 syscon_reg()
8 .ahbclkctrl0
9 .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable());
10}
11
12/// The GPIO pin level for pins set on "Digital" mode.
13#[derive(Debug, Eq, PartialEq, Clone, Copy)]
14pub enum Level {
15 /// Logical low. Corresponds to 0V.
16 Low,
17 /// Logical high. Corresponds to VDD.
18 High,
19}
20
21/// Pull setting for a GPIO input set on "Digital" mode.
22#[derive(Debug, Clone, Copy, Eq, PartialEq)]
23pub enum Pull {
24 /// No pull.
25 None,
26 /// Internal pull-up resistor.
27 Up,
28 /// Internal pull-down resistor.
29 Down,
30}
31
32/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks.
33#[derive(Debug, Eq, PartialEq, Clone, Copy)]
34pub enum Bank {
35 Bank0 = 0,
36 Bank1 = 1,
37}
38
39/// GPIO output driver. Internally, this is a specialized [Flex] pin.
40pub struct Output<'d> {
41 pub(crate) pin: Flex<'d>,
42}
43
44impl<'d> Output<'d> {
45 /// Create GPIO output driver for a [Pin] with the provided [initial output](Level).
46 #[inline]
47 pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
48 let mut pin = Flex::new(pin);
49 pin.set_as_output();
50 let mut result = Self { pin };
51
52 match initial_output {
53 Level::High => result.set_high(),
54 Level::Low => result.set_low(),
55 };
56
57 result
58 }
59
60 pub fn set_high(&mut self) {
61 gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
62 }
63
64 pub fn set_low(&mut self) {
65 gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
66 }
67
68 pub fn toggle(&mut self) {
69 gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
70 }
71
72 /// Get the current output level of the pin. Note that the value returned by this function is
73 /// the voltage level reported by the pin, not the value set by the output driver.
74 pub fn level(&self) -> Level {
75 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits();
76 if bits & self.pin.bit() != 0 {
77 Level::High
78 } else {
79 Level::Low
80 }
81 }
82}
83
84/// GPIO input driver. Internally, this is a specialized [Flex] pin.
85pub struct Input<'d> {
86 pub(crate) pin: Flex<'d>,
87}
88
89impl<'d> Input<'d> {
90 /// Create GPIO output driver for a [Pin] with the provided [Pull].
91 #[inline]
92 pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
93 let mut pin = Flex::new(pin);
94 pin.set_as_input();
95 let mut result = Self { pin };
96 result.set_pull(pull);
97
98 result
99 }
100
101 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None].
102 pub fn set_pull(&mut self, pull: Pull) {
103 match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), {
104 register.modify(|_, w| match pull {
105 Pull::None => w.mode().inactive(),
106 Pull::Up => w.mode().pull_up(),
107 Pull::Down => w.mode().pull_down(),
108 });
109 });
110 }
111
112 /// Get the current input level of the pin.
113 pub fn read(&self) -> Level {
114 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits();
115 if bits & self.pin.bit() != 0 {
116 Level::High
117 } else {
118 Level::Low
119 }
120 }
121}
122
123/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a
124/// reference to a type-erased pin called ["AnyPin"](AnyPin).
125pub struct Flex<'d> {
126 pub(crate) pin: Peri<'d, AnyPin>,
127}
128
129impl<'d> Flex<'d> {
130 /// Wrap the pin in a `Flex`.
131 ///
132 /// Note: you cannot assume that the pin will be in Digital mode after this call.
133 #[inline]
134 pub fn new(pin: Peri<'d, impl Pin>) -> Self {
135 Self { pin: pin.into() }
136 }
137
138 /// Get the bank of this pin. See also [Bank].
139 ///
140 /// # Example
141 ///
142 /// ```
143 /// use embassy_nxp::gpio::{Bank, Flex};
144 ///
145 /// let p = embassy_nxp::init(Default::default());
146 /// let pin = Flex::new(p.PIO1_15);
147 ///
148 /// assert_eq!(pin.pin_bank(), Bank::Bank1);
149 /// ```
150 pub fn pin_bank(&self) -> Bank {
151 self.pin.pin_bank()
152 }
153
154 /// Get the number of this pin within its bank. See also [Bank].
155 ///
156 /// # Example
157 ///
158 /// ```
159 /// use embassy_nxp::gpio::Flex;
160 ///
161 /// let p = embassy_nxp::init(Default::default());
162 /// let pin = Flex::new(p.PIO1_15);
163 ///
164 /// assert_eq!(pin.pin_number(), 15 as u8);
165 /// ```
166 pub fn pin_number(&self) -> u8 {
167 self.pin.pin_number()
168 }
169
170 /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note:
171 /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc.
172 ///
173 /// # Example
174 ///
175 /// ```
176 /// use embassy_nxp::gpio::Flex;
177 ///
178 /// let p = embassy_nxp::init(Default::default());
179 /// let pin = Flex::new(p.PIO1_3);
180 ///
181 /// assert_eq!(pin.bit(), 0b0000_1000);
182 /// ```
183 pub fn bit(&self) -> u32 {
184 1 << self.pin.pin_number()
185 }
186
187 /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default
188 /// setting for pins is (usually) non-digital.
189 fn set_as_digital(&mut self) {
190 match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), {
191 register.modify(|_, w| w.digimode().digital());
192 });
193 }
194
195 /// Set the pin in output mode. This implies setting the pin to digital mode, which this
196 /// function handles itself.
197 pub fn set_as_output(&mut self) {
198 self.set_as_digital();
199 gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) })
200 }
201
202 pub fn set_as_input(&mut self) {
203 self.set_as_digital();
204 gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) })
205 }
206}
207
208/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate.
209pub(crate) trait SealedPin: Sized {
210 fn pin_bank(&self) -> Bank;
211 fn pin_number(&self) -> u8;
212}
213
214/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an
215/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the
216/// `embassy-nxp` crate due to the [SealedPin] trait.
217#[allow(private_bounds)]
218pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
219 /// Returns the pin number within a bank
220 #[inline]
221 fn pin(&self) -> u8 {
222 self.pin_number()
223 }
224
225 /// Returns the bank of this pin
226 #[inline]
227 fn bank(&self) -> Bank {
228 self.pin_bank()
229 }
230}
231
232/// Type-erased GPIO pin.
233pub struct AnyPin {
234 pin_bank: Bank,
235 pin_number: u8,
236}
237
238impl AnyPin {
239 /// Unsafely create a new type-erased pin.
240 ///
241 /// # Safety
242 ///
243 /// You must ensure that you’re only using one instance of this type at a time.
244 pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> {
245 Peri::new_unchecked(Self { pin_bank, pin_number })
246 }
247}
248
249impl_peripheral!(AnyPin);
250
251impl Pin for AnyPin {}
252impl SealedPin for AnyPin {
253 #[inline]
254 fn pin_bank(&self) -> Bank {
255 self.pin_bank
256 }
257
258 #[inline]
259 fn pin_number(&self) -> u8 {
260 self.pin_number
261 }
262}
263
264/// Get the GPIO register block. This is used to configure all GPIO pins.
265///
266/// # Safety
267/// Due to the type system of peripherals, access to the settings of a single pin is possible only
268/// by a single thread at a time. Read/Write operations on a single registers are NOT atomic. You
269/// must ensure that the GPIO registers are not accessed concurrently by multiple threads.
270pub(crate) fn gpio_reg() -> &'static lpc55_pac::gpio::RegisterBlock {
271 unsafe { &*lpc55_pac::GPIO::ptr() }
272}
273
274/// Get the IOCON register block.
275///
276/// # Safety
277/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
278/// registers are not accessed concurrently by multiple threads.
279pub(crate) fn iocon_reg() -> &'static lpc55_pac::iocon::RegisterBlock {
280 unsafe { &*lpc55_pac::IOCON::ptr() }
281}
282
283/// Get the INPUTMUX register block.
284///
285/// # Safety
286/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
287/// registers are not accessed concurrently by multiple threads.
288pub(crate) fn inputmux_reg() -> &'static lpc55_pac::inputmux::RegisterBlock {
289 unsafe { &*lpc55_pac::INPUTMUX::ptr() }
290}
291
292/// Get the SYSCON register block.
293///
294/// # Safety
295/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
296/// registers are not accessed concurrently by multiple threads.
297pub(crate) fn syscon_reg() -> &'static lpc55_pac::syscon::RegisterBlock {
298 unsafe { &*lpc55_pac::SYSCON::ptr() }
299}
300
301/// Get the PINT register block.
302///
303/// # Safety
304/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
305/// registers are not accessed concurrently by multiple threads.
306pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock {
307 unsafe { &*lpc55_pac::PINT::ptr() }
308}
309
310/// Match the pin bank and number of a pin to the corresponding IOCON register.
311///
312/// # Example
313/// ```
314/// use embassy_nxp::gpio::Bank;
315/// use embassy_nxp::pac_utils::{iocon_reg, match_iocon};
316///
317/// // Make pin PIO1_6 digital and set it to pull-down mode.
318/// match_iocon!(register, iocon_reg(), Bank::Bank1, 6, {
319/// register.modify(|_, w| w.mode().pull_down().digimode().digital());
320/// });
321/// ```
322macro_rules! match_iocon {
323 ($register:ident, $iocon_register:expr, $pin_bank:expr, $pin_number:expr, $action:expr) => {
324 match ($pin_bank, $pin_number) {
325 (Bank::Bank0, 0) => {
326 let $register = &($iocon_register).pio0_0;
327 $action;
328 }
329 (Bank::Bank0, 1) => {
330 let $register = &($iocon_register).pio0_1;
331 $action;
332 }
333 (Bank::Bank0, 2) => {
334 let $register = &($iocon_register).pio0_2;
335 $action;
336 }
337 (Bank::Bank0, 3) => {
338 let $register = &($iocon_register).pio0_3;
339 $action;
340 }
341 (Bank::Bank0, 4) => {
342 let $register = &($iocon_register).pio0_4;
343 $action;
344 }
345 (Bank::Bank0, 5) => {
346 let $register = &($iocon_register).pio0_5;
347 $action;
348 }
349 (Bank::Bank0, 6) => {
350 let $register = &($iocon_register).pio0_6;
351 $action;
352 }
353 (Bank::Bank0, 7) => {
354 let $register = &($iocon_register).pio0_7;
355 $action;
356 }
357 (Bank::Bank0, 8) => {
358 let $register = &($iocon_register).pio0_8;
359 $action;
360 }
361 (Bank::Bank0, 9) => {
362 let $register = &($iocon_register).pio0_9;
363 $action;
364 }
365 (Bank::Bank0, 10) => {
366 let $register = &($iocon_register).pio0_10;
367 $action;
368 }
369 (Bank::Bank0, 11) => {
370 let $register = &($iocon_register).pio0_11;
371 $action;
372 }
373 (Bank::Bank0, 12) => {
374 let $register = &($iocon_register).pio0_12;
375 $action;
376 }
377 (Bank::Bank0, 13) => {
378 let $register = &($iocon_register).pio0_13;
379 $action;
380 }
381 (Bank::Bank0, 14) => {
382 let $register = &($iocon_register).pio0_14;
383 $action;
384 }
385 (Bank::Bank0, 15) => {
386 let $register = &($iocon_register).pio0_15;
387 $action;
388 }
389 (Bank::Bank0, 16) => {
390 let $register = &($iocon_register).pio0_16;
391 $action;
392 }
393 (Bank::Bank0, 17) => {
394 let $register = &($iocon_register).pio0_17;
395 $action;
396 }
397 (Bank::Bank0, 18) => {
398 let $register = &($iocon_register).pio0_18;
399 $action;
400 }
401 (Bank::Bank0, 19) => {
402 let $register = &($iocon_register).pio0_19;
403 $action;
404 }
405 (Bank::Bank0, 20) => {
406 let $register = &($iocon_register).pio0_20;
407 $action;
408 }
409 (Bank::Bank0, 21) => {
410 let $register = &($iocon_register).pio0_21;
411 $action;
412 }
413 (Bank::Bank0, 22) => {
414 let $register = &($iocon_register).pio0_22;
415 $action;
416 }
417 (Bank::Bank0, 23) => {
418 let $register = &($iocon_register).pio0_23;
419 $action;
420 }
421 (Bank::Bank0, 24) => {
422 let $register = &($iocon_register).pio0_24;
423 $action;
424 }
425 (Bank::Bank0, 25) => {
426 let $register = &($iocon_register).pio0_25;
427 $action;
428 }
429 (Bank::Bank0, 26) => {
430 let $register = &($iocon_register).pio0_26;
431 $action;
432 }
433 (Bank::Bank0, 27) => {
434 let $register = &($iocon_register).pio0_27;
435 $action;
436 }
437 (Bank::Bank0, 28) => {
438 let $register = &($iocon_register).pio0_28;
439 $action;
440 }
441 (Bank::Bank0, 29) => {
442 let $register = &($iocon_register).pio0_29;
443 $action;
444 }
445 (Bank::Bank0, 30) => {
446 let $register = &($iocon_register).pio0_30;
447 $action;
448 }
449 (Bank::Bank0, 31) => {
450 let $register = &($iocon_register).pio0_31;
451 $action;
452 }
453 (Bank::Bank1, 0) => {
454 let $register = &($iocon_register).pio1_0;
455 $action;
456 }
457 (Bank::Bank1, 1) => {
458 let $register = &($iocon_register).pio1_1;
459 $action;
460 }
461 (Bank::Bank1, 2) => {
462 let $register = &($iocon_register).pio1_2;
463 $action;
464 }
465 (Bank::Bank1, 3) => {
466 let $register = &($iocon_register).pio1_3;
467 $action;
468 }
469 (Bank::Bank1, 4) => {
470 let $register = &($iocon_register).pio1_4;
471 $action;
472 }
473 (Bank::Bank1, 5) => {
474 let $register = &($iocon_register).pio1_5;
475 $action;
476 }
477 (Bank::Bank1, 6) => {
478 let $register = &($iocon_register).pio1_6;
479 $action;
480 }
481 (Bank::Bank1, 7) => {
482 let $register = &($iocon_register).pio1_7;
483 $action;
484 }
485 (Bank::Bank1, 8) => {
486 let $register = &($iocon_register).pio1_8;
487 $action;
488 }
489 (Bank::Bank1, 9) => {
490 let $register = &($iocon_register).pio1_9;
491 $action;
492 }
493 (Bank::Bank1, 10) => {
494 let $register = &($iocon_register).pio1_10;
495 $action;
496 }
497 (Bank::Bank1, 11) => {
498 let $register = &($iocon_register).pio1_11;
499 $action;
500 }
501 (Bank::Bank1, 12) => {
502 let $register = &($iocon_register).pio1_12;
503 $action;
504 }
505 (Bank::Bank1, 13) => {
506 let $register = &($iocon_register).pio1_13;
507 $action;
508 }
509 (Bank::Bank1, 14) => {
510 let $register = &($iocon_register).pio1_14;
511 $action;
512 }
513 (Bank::Bank1, 15) => {
514 let $register = &($iocon_register).pio1_15;
515 $action;
516 }
517 (Bank::Bank1, 16) => {
518 let $register = &($iocon_register).pio1_16;
519 $action;
520 }
521 (Bank::Bank1, 17) => {
522 let $register = &($iocon_register).pio1_17;
523 $action;
524 }
525 (Bank::Bank1, 18) => {
526 let $register = &($iocon_register).pio1_18;
527 $action;
528 }
529 (Bank::Bank1, 19) => {
530 let $register = &($iocon_register).pio1_19;
531 $action;
532 }
533 (Bank::Bank1, 20) => {
534 let $register = &($iocon_register).pio1_20;
535 $action;
536 }
537 (Bank::Bank1, 21) => {
538 let $register = &($iocon_register).pio1_21;
539 $action;
540 }
541 (Bank::Bank1, 22) => {
542 let $register = &($iocon_register).pio1_22;
543 $action;
544 }
545 (Bank::Bank1, 23) => {
546 let $register = &($iocon_register).pio1_23;
547 $action;
548 }
549 (Bank::Bank1, 24) => {
550 let $register = &($iocon_register).pio1_24;
551 $action;
552 }
553 (Bank::Bank1, 25) => {
554 let $register = &($iocon_register).pio1_25;
555 $action;
556 }
557 (Bank::Bank1, 26) => {
558 let $register = &($iocon_register).pio1_26;
559 $action;
560 }
561 (Bank::Bank1, 27) => {
562 let $register = &($iocon_register).pio1_27;
563 $action;
564 }
565 (Bank::Bank1, 28) => {
566 let $register = &($iocon_register).pio1_28;
567 $action;
568 }
569 (Bank::Bank1, 29) => {
570 let $register = &($iocon_register).pio1_29;
571 $action;
572 }
573 (Bank::Bank1, 30) => {
574 let $register = &($iocon_register).pio1_30;
575 $action;
576 }
577 (Bank::Bank1, 31) => {
578 let $register = &($iocon_register).pio1_31;
579 $action;
580 }
581 _ => unreachable!(),
582 }
583 };
584}
585
586pub(crate) use match_iocon;
587
588macro_rules! impl_pin {
589 ($name:ident, $bank:expr, $pin_num:expr) => {
590 impl Pin for peripherals::$name {}
591 impl SealedPin for peripherals::$name {
592 #[inline]
593 fn pin_bank(&self) -> Bank {
594 $bank
595 }
596
597 #[inline]
598 fn pin_number(&self) -> u8 {
599 $pin_num
600 }
601 }
602
603 impl From<peripherals::$name> for crate::gpio::AnyPin {
604 fn from(val: peripherals::$name) -> Self {
605 Self {
606 pin_bank: val.pin_bank(),
607 pin_number: val.pin_number(),
608 }
609 }
610 }
611 };
612}
613
614impl_pin!(PIO0_0, Bank::Bank0, 0);
615impl_pin!(PIO0_1, Bank::Bank0, 1);
616impl_pin!(PIO0_2, Bank::Bank0, 2);
617impl_pin!(PIO0_3, Bank::Bank0, 3);
618impl_pin!(PIO0_4, Bank::Bank0, 4);
619impl_pin!(PIO0_5, Bank::Bank0, 5);
620impl_pin!(PIO0_6, Bank::Bank0, 6);
621impl_pin!(PIO0_7, Bank::Bank0, 7);
622impl_pin!(PIO0_8, Bank::Bank0, 8);
623impl_pin!(PIO0_9, Bank::Bank0, 9);
624impl_pin!(PIO0_10, Bank::Bank0, 10);
625impl_pin!(PIO0_11, Bank::Bank0, 11);
626impl_pin!(PIO0_12, Bank::Bank0, 12);
627impl_pin!(PIO0_13, Bank::Bank0, 13);
628impl_pin!(PIO0_14, Bank::Bank0, 14);
629impl_pin!(PIO0_15, Bank::Bank0, 15);
630impl_pin!(PIO0_16, Bank::Bank0, 16);
631impl_pin!(PIO0_17, Bank::Bank0, 17);
632impl_pin!(PIO0_18, Bank::Bank0, 18);
633impl_pin!(PIO0_19, Bank::Bank0, 19);
634impl_pin!(PIO0_20, Bank::Bank0, 20);
635impl_pin!(PIO0_21, Bank::Bank0, 21);
636impl_pin!(PIO0_22, Bank::Bank0, 22);
637impl_pin!(PIO0_23, Bank::Bank0, 23);
638impl_pin!(PIO0_24, Bank::Bank0, 24);
639impl_pin!(PIO0_25, Bank::Bank0, 25);
640impl_pin!(PIO0_26, Bank::Bank0, 26);
641impl_pin!(PIO0_27, Bank::Bank0, 27);
642impl_pin!(PIO0_28, Bank::Bank0, 28);
643impl_pin!(PIO0_29, Bank::Bank0, 29);
644impl_pin!(PIO0_30, Bank::Bank0, 30);
645impl_pin!(PIO0_31, Bank::Bank0, 31);
646impl_pin!(PIO1_0, Bank::Bank1, 0);
647impl_pin!(PIO1_1, Bank::Bank1, 1);
648impl_pin!(PIO1_2, Bank::Bank1, 2);
649impl_pin!(PIO1_3, Bank::Bank1, 3);
650impl_pin!(PIO1_4, Bank::Bank1, 4);
651impl_pin!(PIO1_5, Bank::Bank1, 5);
652impl_pin!(PIO1_6, Bank::Bank1, 6);
653impl_pin!(PIO1_7, Bank::Bank1, 7);
654impl_pin!(PIO1_8, Bank::Bank1, 8);
655impl_pin!(PIO1_9, Bank::Bank1, 9);
656impl_pin!(PIO1_10, Bank::Bank1, 10);
657impl_pin!(PIO1_11, Bank::Bank1, 11);
658impl_pin!(PIO1_12, Bank::Bank1, 12);
659impl_pin!(PIO1_13, Bank::Bank1, 13);
660impl_pin!(PIO1_14, Bank::Bank1, 14);
661impl_pin!(PIO1_15, Bank::Bank1, 15);
662impl_pin!(PIO1_16, Bank::Bank1, 16);
663impl_pin!(PIO1_17, Bank::Bank1, 17);
664impl_pin!(PIO1_18, Bank::Bank1, 18);
665impl_pin!(PIO1_19, Bank::Bank1, 19);
666impl_pin!(PIO1_20, Bank::Bank1, 20);
667impl_pin!(PIO1_21, Bank::Bank1, 21);
668impl_pin!(PIO1_22, Bank::Bank1, 22);
669impl_pin!(PIO1_23, Bank::Bank1, 23);
670impl_pin!(PIO1_24, Bank::Bank1, 24);
671impl_pin!(PIO1_25, Bank::Bank1, 25);
672impl_pin!(PIO1_26, Bank::Bank1, 26);
673impl_pin!(PIO1_27, Bank::Bank1, 27);
674impl_pin!(PIO1_28, Bank::Bank1, 28);
675impl_pin!(PIO1_29, Bank::Bank1, 29);
676impl_pin!(PIO1_30, Bank::Bank1, 30);
677impl_pin!(PIO1_31, Bank::Bank1, 31);