aboutsummaryrefslogtreecommitdiff
path: root/embassy-imxrt/src/iopctl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-imxrt/src/iopctl.rs')
-rw-r--r--embassy-imxrt/src/iopctl.rs717
1 files changed, 717 insertions, 0 deletions
diff --git a/embassy-imxrt/src/iopctl.rs b/embassy-imxrt/src/iopctl.rs
new file mode 100644
index 000000000..a3b8b14d6
--- /dev/null
+++ b/embassy-imxrt/src/iopctl.rs
@@ -0,0 +1,717 @@
1//! IO Pad Controller (IOPCTL)
2//!
3//! Also known as IO Pin Configuration (IOCON)
4
5use crate::pac::{iopctl, Iopctl};
6
7// A generic pin of any type.
8//
9// The actual pin type used here is arbitrary,
10// as all PioM_N types provide the same methods.
11//
12// Merely need some pin type to cast a raw pointer
13// to in order to access the provided methods.
14#[allow(non_camel_case_types)]
15type PioM_N = iopctl::Pio0_0;
16
17/// Pin function number.
18#[derive(Debug, Copy, Clone, Eq, PartialEq)]
19#[cfg_attr(feature = "defmt", derive(defmt::Format))]
20pub enum Function {
21 /// Function 0
22 F0,
23 /// Function 1
24 F1,
25 /// Function 2
26 F2,
27 /// Function 3
28 F3,
29 /// Function 4
30 F4,
31 /// Function 5
32 F5,
33 /// Function 6
34 F6,
35 /// Function 7
36 F7,
37 /// Function 8
38 F8,
39}
40
41/// Internal pull-up/down resistors on a pin.
42#[derive(Debug, Copy, Clone, Eq, PartialEq)]
43#[cfg_attr(feature = "defmt", derive(defmt::Format))]
44pub enum Pull {
45 /// No pull-up or pull-down resistor selected
46 None,
47 /// Pull-up resistor
48 Up,
49 /// Pull-down resistor
50 Down,
51}
52
53/// Pin slew rate.
54#[derive(Debug, Copy, Clone, Eq, PartialEq)]
55#[cfg_attr(feature = "defmt", derive(defmt::Format))]
56pub enum SlewRate {
57 /// Standard slew rate
58 Standard,
59 /// Slow slew rate
60 Slow,
61}
62
63/// Output drive strength of a pin.
64#[derive(Debug, Copy, Clone, Eq, PartialEq)]
65#[cfg_attr(feature = "defmt", derive(defmt::Format))]
66pub enum DriveStrength {
67 /// Normal
68 Normal,
69 /// Full
70 Full,
71}
72
73/// Output drive mode of a pin.
74#[derive(Debug, Copy, Clone, Eq, PartialEq)]
75#[cfg_attr(feature = "defmt", derive(defmt::Format))]
76pub enum DriveMode {
77 /// Push-Pull
78 PushPull,
79 /// Pseudo Open-Drain
80 OpenDrain,
81}
82
83/// Input inverter of a pin.
84#[derive(Debug, Copy, Clone, Eq, PartialEq)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub enum Inverter {
87 /// No inverter
88 Disabled,
89 /// Enable input inverter on the input port. A low signal will be
90 /// seen as a high signal by the pin.
91 Enabled,
92}
93
94trait SealedPin {}
95trait ToAnyPin: SealedPin {
96 #[inline]
97 fn to_raw(port: u8, pin: u8) -> AnyPin {
98 // SAFETY: This is safe since this is only called from within the module,
99 // where the port and pin numbers have been verified to be correct.
100 unsafe { AnyPin::steal(port, pin) }
101 }
102}
103
104trait ToFC15Pin: SealedPin {
105 #[inline]
106 fn to_raw(pin: u8) -> FC15Pin {
107 // SAFETY: This is safe since this is only called from within the module,
108 // where the port and pin numbers have been verified to be correct.
109 unsafe { FC15Pin::steal(pin) }
110 }
111}
112
113/// A pin that can be configured via iopctl.
114#[allow(private_bounds)]
115pub trait IopctlPin: SealedPin {
116 /// Sets the function number of a pin.
117 ///
118 /// This number corresponds to a specific function that the pin supports.
119 ///
120 /// Typically, function 0 corresponds to GPIO while other numbers correspond to a special function.
121 ///
122 /// See Section 7.5.3 in reference manual for list of pins and their supported functions.
123 fn set_function(&self, function: Function) -> &Self;
124
125 /// Enables either a pull-up or pull-down resistor on a pin.
126 ///
127 /// Setting this to [`Pull::None`] will disable the resistor.
128 fn set_pull(&self, pull: Pull) -> &Self;
129
130 /// Enables the input buffer of a pin.
131 ///
132 /// This must be enabled for any pin acting as an input,
133 /// and some peripheral pins acting as output may need this enabled as well.
134 ///
135 /// If there is any doubt, it is best to enable the input buffer.
136 ///
137 /// See Section 7.4.2.3 of reference manual.
138 fn enable_input_buffer(&self) -> &Self;
139
140 /// Disables the input buffer of a pin.
141 fn disable_input_buffer(&self) -> &Self;
142
143 /// Sets the slew rate of a pin.
144 ///
145 /// This controls the speed at which a pin can toggle,
146 /// which is voltage and load dependent.
147 fn set_slew_rate(&self, slew_rate: SlewRate) -> &Self;
148
149 /// Sets the output drive strength of a pin.
150 ///
151 /// A drive strength of [`DriveStrength::Full`] has twice the
152 /// high and low drive capability of the [`DriveStrength::Normal`] setting.
153 fn set_drive_strength(&self, strength: DriveStrength) -> &Self;
154
155 /// Enables the analog multiplexer of a pin.
156 ///
157 /// This must be called to allow analog functionalities of a pin.
158 ///
159 /// To protect the analog input, [`IopctlPin::set_function`] should be
160 /// called with [`Function::F0`] to disable digital functions.
161 ///
162 /// Additionally, [`IopctlPin::disable_input_buffer`] and [`IopctlPin::set_pull`]
163 /// with [`Pull::None`] should be called.
164 fn enable_analog_multiplex(&self) -> &Self;
165
166 /// Disables the analog multiplexer of a pin.
167 fn disable_analog_multiplex(&self) -> &Self;
168
169 /// Sets the ouput drive mode of a pin.
170 ///
171 /// A pin configured as [`DriveMode::OpenDrain`] actually operates in
172 /// a "pseudo" open-drain mode which is somewhat different than true open-drain.
173 ///
174 /// See Section 7.4.2.7 of reference manual.
175 fn set_drive_mode(&self, mode: DriveMode) -> &Self;
176
177 /// Sets the input inverter of an input pin.
178 ///
179 /// Setting this to [`Inverter::Enabled`] will invert
180 /// the input signal.
181 fn set_input_inverter(&self, inverter: Inverter) -> &Self;
182
183 /// Returns a pin to its reset state.
184 fn reset(&self) -> &Self;
185}
186
187/// Represents a pin peripheral created at run-time from given port and pin numbers.
188pub struct AnyPin {
189 pin_port: u8,
190 reg: &'static PioM_N,
191}
192
193impl AnyPin {
194 /// Creates a pin from raw port and pin numbers which can then be configured.
195 ///
196 /// This should ONLY be called when there is no other choice
197 /// (e.g. from a type-erased GPIO pin).
198 ///
199 /// Otherwise, pin peripherals should be configured directly.
200 ///
201 /// # Safety
202 ///
203 /// The caller MUST ensure valid port and pin numbers are provided,
204 /// and that multiple instances of [`AnyPin`] with the same port
205 /// and pin combination are not being used simultaneously.
206 ///
207 /// Failure to uphold these requirements will result in undefined behavior.
208 ///
209 /// See Table 297 in reference manual for a list of valid
210 /// pin and port number combinations.
211 #[must_use]
212 pub unsafe fn steal(port: u8, pin: u8) -> Self {
213 // Calculates the offset from the beginning of the IOPCTL register block
214 // address to the register address representing the pin.
215 //
216 // See Table 297 in reference manual for how this offset is calculated.
217 let offset = ((port as usize) << 7) + ((pin as usize) << 2);
218
219 // SAFETY: This is safe assuming the caller of this function satisfies the safety requirements above.
220 let reg = unsafe { &*Iopctl::ptr().byte_offset(offset as isize).cast() };
221 Self {
222 pin_port: port * 32 + pin,
223 reg,
224 }
225 }
226
227 /// Returns the pin's port and pin combination.
228 #[must_use]
229 pub fn pin_port(&self) -> usize {
230 self.pin_port as usize
231 }
232}
233
234/// Represents a FC15 pin peripheral created at run-time from given pin number.
235pub struct FC15Pin {
236 reg: &'static PioM_N,
237}
238
239impl FC15Pin {
240 /// Creates an FC15 pin from raw pin number which can then be configured.
241 ///
242 /// This should ONLY be called when there is no other choice
243 /// (e.g. from a type-erased GPIO pin).
244 ///
245 /// Otherwise, pin peripherals should be configured directly.
246 ///
247 /// # Safety
248 ///
249 /// The caller MUST ensure valid port and pin numbers are provided,
250 /// and that multiple instances of [`AnyPin`] with the same port
251 /// and pin combination are not being used simultaneously.
252 ///
253 /// Failure to uphold these requirements will result in undefined behavior.
254 ///
255 /// See Table 297 in reference manual for a list of valid
256 /// pin and port number combinations.
257 #[must_use]
258 pub unsafe fn steal(pin: u8) -> Self {
259 // Table 297: FC15_I2C_SCL offset = 0x400, FC15_I2C_SCL offset = 0x404
260 let iopctl = unsafe { crate::pac::Iopctl::steal() };
261
262 let reg = if pin == 0 {
263 &*iopctl.fc15_i2c_scl().as_ptr().cast()
264 } else {
265 &*iopctl.fc15_i2c_sda().as_ptr().cast()
266 };
267
268 Self { reg }
269 }
270}
271
272// This allows AnyPin/FC15Pin to be used in HAL constructors that require types
273// which impl Peripheral. Used primarily by GPIO HAL to convert type-erased
274// GPIO pins back into an Output or Input pin specifically.
275embassy_hal_internal::impl_peripheral!(AnyPin);
276
277impl SealedPin for AnyPin {}
278
279embassy_hal_internal::impl_peripheral!(FC15Pin);
280
281impl SealedPin for FC15Pin {}
282
283macro_rules! impl_iopctlpin {
284 ($pintype:ident) => {
285 impl IopctlPin for $pintype {
286 fn set_function(&self, function: Function) -> &Self {
287 critical_section::with(|_| match function {
288 Function::F0 => {
289 self.reg.modify(|_, w| w.fsel().function_0());
290 }
291 Function::F1 => {
292 self.reg.modify(|_, w| w.fsel().function_1());
293 }
294 Function::F2 => {
295 self.reg.modify(|_, w| w.fsel().function_2());
296 }
297 Function::F3 => {
298 self.reg.modify(|_, w| w.fsel().function_3());
299 }
300 Function::F4 => {
301 self.reg.modify(|_, w| w.fsel().function_4());
302 }
303 Function::F5 => {
304 self.reg.modify(|_, w| w.fsel().function_5());
305 }
306 Function::F6 => {
307 self.reg.modify(|_, w| w.fsel().function_6());
308 }
309 Function::F7 => {
310 self.reg.modify(|_, w| w.fsel().function_7());
311 }
312 Function::F8 => {
313 self.reg.modify(|_, w| w.fsel().function_8());
314 }
315 });
316 self
317 }
318
319 fn set_pull(&self, pull: Pull) -> &Self {
320 critical_section::with(|_| {
321 match pull {
322 Pull::None => {
323 self.reg.modify(|_, w| w.pupdena().disabled());
324 }
325 Pull::Up => {
326 self.reg.modify(|_, w| w.pupdena().enabled().pupdsel().pull_up());
327 }
328 Pull::Down => {
329 self.reg
330 .modify(|_, w| w.pupdena().enabled().pupdsel().pull_down());
331 }
332 }
333 self
334 })
335 }
336
337 fn enable_input_buffer(&self) -> &Self {
338 critical_section::with(|_| self.reg.modify(|_, w| w.ibena().enabled()));
339 self
340 }
341
342 fn disable_input_buffer(&self) -> &Self {
343 critical_section::with(|_| self.reg.modify(|_, w| w.ibena().disabled()));
344 self
345 }
346
347 fn set_slew_rate(&self, slew_rate: SlewRate) -> &Self {
348 critical_section::with(|_| match slew_rate {
349 SlewRate::Standard => {
350 self.reg.modify(|_, w| w.slewrate().normal());
351 }
352 SlewRate::Slow => {
353 self.reg.modify(|_, w| w.slewrate().slow());
354 }
355 });
356 self
357 }
358
359 fn set_drive_strength(&self, strength: DriveStrength) -> &Self {
360 critical_section::with(|_| match strength {
361 DriveStrength::Normal => {
362 self.reg.modify(|_, w| w.fulldrive().normal_drive());
363 }
364 DriveStrength::Full => {
365 self.reg.modify(|_, w| w.fulldrive().full_drive());
366 }
367 });
368 self
369 }
370
371 fn enable_analog_multiplex(&self) -> &Self {
372 critical_section::with(|_| self.reg.modify(|_, w| w.amena().enabled()));
373 self
374 }
375
376 fn disable_analog_multiplex(&self) -> &Self {
377 critical_section::with(|_| self.reg.modify(|_, w| w.amena().disabled()));
378 self
379 }
380
381 fn set_drive_mode(&self, mode: DriveMode) -> &Self {
382 critical_section::with(|_| match mode {
383 DriveMode::PushPull => {
384 self.reg.modify(|_, w| w.odena().disabled());
385 }
386 DriveMode::OpenDrain => {
387 self.reg.modify(|_, w| w.odena().enabled());
388 }
389 });
390 self
391 }
392
393 fn set_input_inverter(&self, inverter: Inverter) -> &Self {
394 critical_section::with(|_| match inverter {
395 Inverter::Disabled => {
396 self.reg.modify(|_, w| w.iiena().disabled());
397 }
398 Inverter::Enabled => {
399 self.reg.modify(|_, w| w.iiena().enabled());
400 }
401 });
402 self
403 }
404
405 fn reset(&self) -> &Self {
406 self.reg.reset();
407 self
408 }
409 }
410 };
411}
412
413impl_iopctlpin!(AnyPin);
414impl_iopctlpin!(FC15Pin);
415
416macro_rules! impl_FC15pin {
417 ($pin_periph:ident, $pin_no:expr) => {
418 impl SealedPin for crate::peripherals::$pin_periph {}
419 impl ToFC15Pin for crate::peripherals::$pin_periph {}
420 impl IopctlPin for crate::peripherals::$pin_periph {
421 #[inline]
422 fn set_function(&self, _function: Function) -> &Self {
423 //No function configuration for FC15 pin
424 self
425 }
426
427 #[inline]
428 fn set_pull(&self, pull: Pull) -> &Self {
429 Self::to_raw($pin_no).set_pull(pull);
430 self
431 }
432
433 #[inline]
434 fn enable_input_buffer(&self) -> &Self {
435 Self::to_raw($pin_no).enable_input_buffer();
436 self
437 }
438
439 #[inline]
440 fn disable_input_buffer(&self) -> &Self {
441 Self::to_raw($pin_no).disable_input_buffer();
442 self
443 }
444
445 #[inline]
446 fn set_slew_rate(&self, slew_rate: SlewRate) -> &Self {
447 Self::to_raw($pin_no).set_slew_rate(slew_rate);
448 self
449 }
450
451 #[inline]
452 fn set_drive_strength(&self, strength: DriveStrength) -> &Self {
453 Self::to_raw($pin_no).set_drive_strength(strength);
454 self
455 }
456
457 #[inline]
458 fn enable_analog_multiplex(&self) -> &Self {
459 Self::to_raw($pin_no).enable_analog_multiplex();
460 self
461 }
462
463 #[inline]
464 fn disable_analog_multiplex(&self) -> &Self {
465 Self::to_raw($pin_no).disable_analog_multiplex();
466 self
467 }
468
469 #[inline]
470 fn set_drive_mode(&self, mode: DriveMode) -> &Self {
471 Self::to_raw($pin_no).set_drive_mode(mode);
472 self
473 }
474
475 #[inline]
476 fn set_input_inverter(&self, inverter: Inverter) -> &Self {
477 Self::to_raw($pin_no).set_input_inverter(inverter);
478 self
479 }
480
481 #[inline]
482 fn reset(&self) -> &Self {
483 Self::to_raw($pin_no).reset();
484 self
485 }
486 }
487 };
488}
489
490macro_rules! impl_pin {
491 ($pin_periph:ident, $pin_port:expr, $pin_no:expr) => {
492 impl SealedPin for crate::peripherals::$pin_periph {}
493 impl ToAnyPin for crate::peripherals::$pin_periph {}
494 impl IopctlPin for crate::peripherals::$pin_periph {
495 #[inline]
496 fn set_function(&self, function: Function) -> &Self {
497 Self::to_raw($pin_port, $pin_no).set_function(function);
498 self
499 }
500
501 #[inline]
502 fn set_pull(&self, pull: Pull) -> &Self {
503 Self::to_raw($pin_port, $pin_no).set_pull(pull);
504 self
505 }
506
507 #[inline]
508 fn enable_input_buffer(&self) -> &Self {
509 Self::to_raw($pin_port, $pin_no).enable_input_buffer();
510 self
511 }
512
513 #[inline]
514 fn disable_input_buffer(&self) -> &Self {
515 Self::to_raw($pin_port, $pin_no).disable_input_buffer();
516 self
517 }
518
519 #[inline]
520 fn set_slew_rate(&self, slew_rate: SlewRate) -> &Self {
521 Self::to_raw($pin_port, $pin_no).set_slew_rate(slew_rate);
522 self
523 }
524
525 #[inline]
526 fn set_drive_strength(&self, strength: DriveStrength) -> &Self {
527 Self::to_raw($pin_port, $pin_no).set_drive_strength(strength);
528 self
529 }
530
531 #[inline]
532 fn enable_analog_multiplex(&self) -> &Self {
533 Self::to_raw($pin_port, $pin_no).enable_analog_multiplex();
534 self
535 }
536
537 #[inline]
538 fn disable_analog_multiplex(&self) -> &Self {
539 Self::to_raw($pin_port, $pin_no).disable_analog_multiplex();
540 self
541 }
542
543 #[inline]
544 fn set_drive_mode(&self, mode: DriveMode) -> &Self {
545 Self::to_raw($pin_port, $pin_no).set_drive_mode(mode);
546 self
547 }
548
549 #[inline]
550 fn set_input_inverter(&self, inverter: Inverter) -> &Self {
551 Self::to_raw($pin_port, $pin_no).set_input_inverter(inverter);
552 self
553 }
554
555 #[inline]
556 fn reset(&self) -> &Self {
557 Self::to_raw($pin_port, $pin_no).reset();
558 self
559 }
560 }
561 };
562}
563
564impl_pin!(PIO0_0, 0, 0);
565impl_pin!(PIO0_1, 0, 1);
566impl_pin!(PIO0_2, 0, 2);
567impl_pin!(PIO0_3, 0, 3);
568impl_pin!(PIO0_4, 0, 4);
569impl_pin!(PIO0_5, 0, 5);
570impl_pin!(PIO0_6, 0, 6);
571impl_pin!(PIO0_7, 0, 7);
572impl_pin!(PIO0_8, 0, 8);
573impl_pin!(PIO0_9, 0, 9);
574impl_pin!(PIO0_10, 0, 10);
575impl_pin!(PIO0_11, 0, 11);
576impl_pin!(PIO0_12, 0, 12);
577impl_pin!(PIO0_13, 0, 13);
578impl_pin!(PIO0_14, 0, 14);
579impl_pin!(PIO0_15, 0, 15);
580impl_pin!(PIO0_16, 0, 16);
581impl_pin!(PIO0_17, 0, 17);
582impl_pin!(PIO0_18, 0, 18);
583impl_pin!(PIO0_19, 0, 19);
584impl_pin!(PIO0_20, 0, 20);
585impl_pin!(PIO0_21, 0, 21);
586impl_pin!(PIO0_22, 0, 22);
587impl_pin!(PIO0_23, 0, 23);
588impl_pin!(PIO0_24, 0, 24);
589impl_pin!(PIO0_25, 0, 25);
590impl_pin!(PIO0_26, 0, 26);
591impl_pin!(PIO0_27, 0, 27);
592impl_pin!(PIO0_28, 0, 28);
593impl_pin!(PIO0_29, 0, 29);
594impl_pin!(PIO0_30, 0, 30);
595impl_pin!(PIO0_31, 0, 31);
596impl_pin!(PIO1_0, 1, 0);
597impl_pin!(PIO1_1, 1, 1);
598impl_pin!(PIO1_2, 1, 2);
599impl_pin!(PIO1_3, 1, 3);
600impl_pin!(PIO1_4, 1, 4);
601impl_pin!(PIO1_5, 1, 5);
602impl_pin!(PIO1_6, 1, 6);
603impl_pin!(PIO1_7, 1, 7);
604impl_pin!(PIO1_8, 1, 8);
605impl_pin!(PIO1_9, 1, 9);
606impl_pin!(PIO1_10, 1, 10);
607impl_pin!(PIO1_11, 1, 11);
608impl_pin!(PIO1_12, 1, 12);
609impl_pin!(PIO1_13, 1, 13);
610impl_pin!(PIO1_14, 1, 14);
611impl_pin!(PIO1_15, 1, 15);
612impl_pin!(PIO1_16, 1, 16);
613impl_pin!(PIO1_17, 1, 17);
614impl_pin!(PIO1_18, 1, 18);
615impl_pin!(PIO1_19, 1, 19);
616impl_pin!(PIO1_20, 1, 20);
617impl_pin!(PIO1_21, 1, 21);
618impl_pin!(PIO1_22, 1, 22);
619impl_pin!(PIO1_23, 1, 23);
620impl_pin!(PIO1_24, 1, 24);
621impl_pin!(PIO1_25, 1, 25);
622impl_pin!(PIO1_26, 1, 26);
623impl_pin!(PIO1_27, 1, 27);
624impl_pin!(PIO1_28, 1, 28);
625impl_pin!(PIO1_29, 1, 29);
626impl_pin!(PIO1_30, 1, 30);
627impl_pin!(PIO1_31, 1, 31);
628impl_pin!(PIO2_0, 2, 0);
629impl_pin!(PIO2_1, 2, 1);
630impl_pin!(PIO2_2, 2, 2);
631impl_pin!(PIO2_3, 2, 3);
632impl_pin!(PIO2_4, 2, 4);
633impl_pin!(PIO2_5, 2, 5);
634impl_pin!(PIO2_6, 2, 6);
635impl_pin!(PIO2_7, 2, 7);
636impl_pin!(PIO2_8, 2, 8);
637impl_pin!(PIO2_9, 2, 9);
638impl_pin!(PIO2_10, 2, 10);
639impl_pin!(PIO2_11, 2, 11);
640impl_pin!(PIO2_12, 2, 12);
641impl_pin!(PIO2_13, 2, 13);
642impl_pin!(PIO2_14, 2, 14);
643impl_pin!(PIO2_15, 2, 15);
644impl_pin!(PIO2_16, 2, 16);
645impl_pin!(PIO2_17, 2, 17);
646impl_pin!(PIO2_18, 2, 18);
647impl_pin!(PIO2_19, 2, 19);
648impl_pin!(PIO2_20, 2, 20);
649impl_pin!(PIO2_21, 2, 21);
650impl_pin!(PIO2_22, 2, 22);
651impl_pin!(PIO2_23, 2, 23);
652impl_pin!(PIO2_24, 2, 24);
653
654// Note: These have have reset values of 0x41 to support SWD by default
655impl_pin!(PIO2_25, 2, 25);
656impl_pin!(PIO2_26, 2, 26);
657
658impl_pin!(PIO2_27, 2, 27);
659impl_pin!(PIO2_28, 2, 28);
660impl_pin!(PIO2_29, 2, 29);
661impl_pin!(PIO2_30, 2, 30);
662impl_pin!(PIO2_31, 2, 31);
663impl_pin!(PIO3_0, 3, 0);
664impl_pin!(PIO3_1, 3, 1);
665impl_pin!(PIO3_2, 3, 2);
666impl_pin!(PIO3_3, 3, 3);
667impl_pin!(PIO3_4, 3, 4);
668impl_pin!(PIO3_5, 3, 5);
669impl_pin!(PIO3_6, 3, 6);
670impl_pin!(PIO3_7, 3, 7);
671impl_pin!(PIO3_8, 3, 8);
672impl_pin!(PIO3_9, 3, 9);
673impl_pin!(PIO3_10, 3, 10);
674impl_pin!(PIO3_11, 3, 11);
675impl_pin!(PIO3_12, 3, 12);
676impl_pin!(PIO3_13, 3, 13);
677impl_pin!(PIO3_14, 3, 14);
678impl_pin!(PIO3_15, 3, 15);
679impl_pin!(PIO3_16, 3, 16);
680impl_pin!(PIO3_17, 3, 17);
681impl_pin!(PIO3_18, 3, 18);
682impl_pin!(PIO3_19, 3, 19);
683impl_pin!(PIO3_20, 3, 20);
684impl_pin!(PIO3_21, 3, 21);
685impl_pin!(PIO3_22, 3, 22);
686impl_pin!(PIO3_23, 3, 23);
687impl_pin!(PIO3_24, 3, 24);
688impl_pin!(PIO3_25, 3, 25);
689impl_pin!(PIO3_26, 3, 26);
690impl_pin!(PIO3_27, 3, 27);
691impl_pin!(PIO3_28, 3, 28);
692impl_pin!(PIO3_29, 3, 29);
693impl_pin!(PIO3_30, 3, 30);
694impl_pin!(PIO3_31, 3, 31);
695impl_pin!(PIO4_0, 4, 0);
696impl_pin!(PIO4_1, 4, 1);
697impl_pin!(PIO4_2, 4, 2);
698impl_pin!(PIO4_3, 4, 3);
699impl_pin!(PIO4_4, 4, 4);
700impl_pin!(PIO4_5, 4, 5);
701impl_pin!(PIO4_6, 4, 6);
702impl_pin!(PIO4_7, 4, 7);
703impl_pin!(PIO4_8, 4, 8);
704impl_pin!(PIO4_9, 4, 9);
705impl_pin!(PIO4_10, 4, 10);
706impl_pin!(PIO7_24, 7, 24);
707impl_pin!(PIO7_25, 7, 25);
708impl_pin!(PIO7_26, 7, 26);
709impl_pin!(PIO7_27, 7, 27);
710impl_pin!(PIO7_28, 7, 28);
711impl_pin!(PIO7_29, 7, 29);
712impl_pin!(PIO7_30, 7, 30);
713impl_pin!(PIO7_31, 7, 31);
714
715// FC15 pins
716impl_FC15pin!(PIOFC15_SCL, 0);
717impl_FC15pin!(PIOFC15_SDA, 1);