Skip to main content

mpfs_hal/
gpio.rs

1//! The MPFS broadly uses 2 GPIO interfaces: the MSS GPIO interface and the FPGA Core GPIO interface.
2//!
3//! By default, on the BeagleV-Fire, P8_3 through P8_30 use the MSS GPIO interface. The remainder use the FPGA Core GPIO interface. Both interfaces are routed through the FPGA and thus depend on the FPGA configuration to work correctly. See the [Default cape gateware](https://git.beagleboard.org/beaglev-fire/gateware/-/tree/main/sources/FPGA-design/script_support/components/CAPE/DEFAULT) for the expected configuration. Note that if you want to use interrupts for the Core GPIO interface, "fixed config" needs to be disabled, or the interrupts need to be otherwise configured in the gateware. The [CoreGPIO_LCD.tcl](https://git.beagleboard.org/beaglev-fire/gateware/-/blob/main/sources/FPGA-design/script_support/components/CAPE/DEFAULT/CoreGPIO_LCD.tcl?ref_type=heads#L7) file controls this config for the P8 pins, while [CoreGPIO_P9.tcl](https://git.beagleboard.org/beaglev-fire/gateware/-/blob/main/sources/FPGA-design/script_support/components/CAPE/DEFAULT/CoreGPIO_P9.tcl?ref_type=heads)
4//!
5//! This module provides a unified interface to both GPIO interfaces. It also provides a way to define custom Pins and Input/Output peripherals so that any user can define their own GPIO depending on the given FPGA programming.
6
7extern crate alloc;
8
9use paste::paste;
10
11use core::convert::Infallible;
12use core::future::Future;
13use core::task::{Context, Poll, Waker};
14
15use crate::Peripheral;
16use crate::pac;
17
18const MSS_GPIO_INTERRUPT_COUNT: usize = 38;
19unsafe fn base_init() {
20    unsafe {
21        pac::MSS_GPIO_init(pac::GPIO0_LO);
22        pac::MSS_GPIO_init(pac::GPIO1_LO);
23        pac::MSS_GPIO_init(pac::GPIO2_LO);
24        // Interrupts are configured for GPIO0 and GPIO1 by default
25        // GPIO2 interrupts are initialized when a Pin is taken
26        (*pac::SYSREG).GPIO_INTERRUPT_FAB_CR = 0x0;
27
28        for i in 0..MSS_GPIO_INTERRUPT_COUNT {
29            pac::PLIC_SetPriority(
30                pac::PLIC_IRQn_Type_PLIC_GPIO0_BIT0_or_GPIO2_BIT0_INT_OFFSET + i as u32,
31                2,
32            );
33        }
34        for i in
35            pac::PLIC_IRQn_Type_PLIC_F2M_0_INT_OFFSET..=pac::PLIC_IRQn_Type_PLIC_F2M_63_INT_OFFSET
36        {
37            pac::PLIC_SetPriority(i, 2);
38        }
39    }
40}
41
42//-------------------------------------
43// MARK: Interrupts
44//-------------------------------------
45
46#[derive(Default, Debug)]
47struct GpioInterruptData {
48    waker: Option<Waker>,
49    triggered: bool,
50}
51
52const NUM_INTERRUPTS: usize = 38 + 64; // 38 MSS GPIO interrupts + 64 F2M interrupts
53static mut GPIO_INTERRUPTS: [GpioInterruptData; NUM_INTERRUPTS] = [const {
54    GpioInterruptData {
55        waker: None,
56        triggered: false,
57    }
58}; NUM_INTERRUPTS];
59
60#[repr(u8)]
61#[derive(Default, Copy, Clone, Debug, PartialEq)]
62#[doc(hidden)]
63pub enum InterruptTrigger {
64    #[default]
65    LevelHigh = pac::GPIO_IRQ_LEVEL_HIGH as u8,
66    LevelLow = pac::GPIO_IRQ_LEVEL_LOW as u8,
67    EdgePositive = pac::GPIO_IRQ_EDGE_POSITIVE as u8,
68    EdgeNegative = pac::GPIO_IRQ_EDGE_NEGATIVE as u8,
69    EdgeBoth = pac::GPIO_IRQ_EDGE_BOTH as u8,
70}
71
72#[doc(hidden)]
73#[derive(Debug, Clone, Copy)]
74pub struct Interrupt {
75    interrupt_idx: u8,
76    plic_idx: u8,
77}
78
79impl Interrupt {
80    pub const NONE: Self = Self {
81        interrupt_idx: 255,
82        plic_idx: 255,
83    };
84
85    unsafe fn triggered(&self) -> bool {
86        unsafe { GPIO_INTERRUPTS[self.interrupt_idx as usize].triggered }
87    }
88
89    unsafe fn set_waker(&mut self, waker: Waker) {
90        unsafe {
91            GPIO_INTERRUPTS[self.interrupt_idx as usize].waker = Some(waker);
92        }
93    }
94
95    fn is_none(&self) -> bool {
96        self.interrupt_idx == 255 && self.plic_idx == 255
97    }
98}
99
100pub trait GpioInterrupt: 'static {
101    #[doc(hidden)]
102    fn address(&self) -> Interrupt;
103}
104
105macro_rules! impl_gpio_interrupt {
106    ($interrupt:ident, $interrupt_idx:expr, $interrupt_handler:ident, $plic_idx:expr) => {
107        paste! {
108            impl_gpio_interrupt!($interrupt, [<$interrupt _TAKEN>], $interrupt_idx, $interrupt_handler, $plic_idx);
109        }
110    };
111
112    ($interrupt:ident, $interrupt_idx:expr, $interrupt_handler:ident) => {
113        impl_gpio_interrupt!($interrupt, $interrupt_idx, $interrupt_handler, 255);
114    };
115
116    ($INTERRUPT:ident, $INTERRUPT_TAKEN:ident, $interrupt_idx:expr, $interrupt_handler:ident, $plic_idx:expr) => {
117        #[allow(non_camel_case_types)]
118        pub struct $INTERRUPT {
119            _private: (),
120        }
121        static mut $INTERRUPT_TAKEN: bool = false;
122
123        impl crate::Peripheral for $INTERRUPT {
124            fn take() -> Option<Self> {
125                critical_section::with(|_| unsafe {
126                    if $INTERRUPT_TAKEN {
127                        None
128                    } else {
129                        $INTERRUPT_TAKEN = true;
130                        Some(Self { _private: () })
131                    }
132                })
133            }
134
135            unsafe fn steal() -> Self {
136                Self { _private: () }
137            }
138        }
139
140        impl GpioInterrupt for $INTERRUPT {
141            fn address(&self) -> Interrupt {
142                Interrupt {
143                    interrupt_idx: $interrupt_idx,
144                    plic_idx: $plic_idx as u8,
145                }
146            }
147        }
148
149        #[unsafe(no_mangle)]
150        extern "C" fn $interrupt_handler() -> u8 {
151            let interrupt = unsafe { &mut GPIO_INTERRUPTS[$interrupt_idx] };
152            trace!("GPIO interrupt {} triggered: {:?}", $interrupt_idx, interrupt);
153            if let Some(waker) = interrupt.waker.take() {
154                interrupt.triggered = true;
155                waker.wake();
156            }
157            pac::EXT_IRQ_DISABLE as u8
158        }
159    };
160}
161
162impl_gpio_interrupt!(
163    GPIO0_0_OR_GPIO2_0_INT,
164    0,
165    // The first 14 GPIO2 handlers are misnamed
166    // This one handles GPIO2[0]
167    PLIC_gpio0_bit0_or_gpio2_bit13_IRQHandler
168);
169impl_gpio_interrupt!(
170    GPIO0_1_OR_GPIO2_1_INT,
171    1,
172    PLIC_gpio0_bit1_or_gpio2_bit13_IRQHandler
173);
174impl_gpio_interrupt!(
175    GPIO0_2_OR_GPIO2_2_INT,
176    2,
177    PLIC_gpio0_bit2_or_gpio2_bit13_IRQHandler
178);
179impl_gpio_interrupt!(
180    GPIO0_3_OR_GPIO2_3_INT,
181    3,
182    PLIC_gpio0_bit3_or_gpio2_bit13_IRQHandler
183);
184impl_gpio_interrupt!(
185    GPIO0_4_OR_GPIO2_4_INT,
186    4,
187    PLIC_gpio0_bit4_or_gpio2_bit13_IRQHandler
188);
189impl_gpio_interrupt!(
190    GPIO0_5_OR_GPIO2_5_INT,
191    5,
192    PLIC_gpio0_bit5_or_gpio2_bit13_IRQHandler
193);
194impl_gpio_interrupt!(
195    GPIO0_6_OR_GPIO2_6_INT,
196    6,
197    PLIC_gpio0_bit6_or_gpio2_bit13_IRQHandler
198);
199impl_gpio_interrupt!(
200    GPIO0_7_OR_GPIO2_7_INT,
201    7,
202    PLIC_gpio0_bit7_or_gpio2_bit13_IRQHandler
203);
204impl_gpio_interrupt!(
205    GPIO0_8_OR_GPIO2_8_INT,
206    8,
207    PLIC_gpio0_bit8_or_gpio2_bit13_IRQHandler
208);
209impl_gpio_interrupt!(
210    GPIO0_9_OR_GPIO2_9_INT,
211    9,
212    PLIC_gpio0_bit9_or_gpio2_bit13_IRQHandler
213);
214impl_gpio_interrupt!(
215    GPIO0_10_OR_GPIO2_10_INT,
216    10,
217    PLIC_gpio0_bit10_or_gpio2_bit13_IRQHandler
218);
219impl_gpio_interrupt!(
220    GPIO0_11_OR_GPIO2_11_INT,
221    11,
222    PLIC_gpio0_bit11_or_gpio2_bit13_IRQHandler
223);
224impl_gpio_interrupt!(
225    GPIO0_12_OR_GPIO2_12_INT,
226    12,
227    PLIC_gpio0_bit12_or_gpio2_bit13_IRQHandler
228);
229impl_gpio_interrupt!(
230    GPIO0_13_OR_GPIO2_13_INT,
231    13,
232    PLIC_gpio0_bit13_or_gpio2_bit13_IRQHandler
233);
234impl_gpio_interrupt!(
235    GPIO1_0_OR_GPIO2_14_INT,
236    14,
237    PLIC_gpio1_bit0_or_gpio2_bit14_IRQHandler
238);
239impl_gpio_interrupt!(
240    GPIO1_1_OR_GPIO2_15_INT,
241    15,
242    PLIC_gpio1_bit1_or_gpio2_bit15_IRQHandler
243);
244impl_gpio_interrupt!(
245    GPIO1_2_OR_GPIO2_16_INT,
246    16,
247    PLIC_gpio1_bit2_or_gpio2_bit16_IRQHandler
248);
249impl_gpio_interrupt!(
250    GPIO1_3_OR_GPIO2_17_INT,
251    17,
252    PLIC_gpio1_bit3_or_gpio2_bit17_IRQHandler
253);
254impl_gpio_interrupt!(
255    GPIO1_4_OR_GPIO2_18_INT,
256    18,
257    PLIC_gpio1_bit4_or_gpio2_bit18_IRQHandler
258);
259impl_gpio_interrupt!(
260    GPIO1_5_OR_GPIO2_19_INT,
261    19,
262    PLIC_gpio1_bit5_or_gpio2_bit19_IRQHandler
263);
264impl_gpio_interrupt!(
265    GPIO1_6_OR_GPIO2_20_INT,
266    20,
267    PLIC_gpio1_bit6_or_gpio2_bit20_IRQHandler
268);
269impl_gpio_interrupt!(
270    GPIO1_7_OR_GPIO2_21_INT,
271    21,
272    PLIC_gpio1_bit7_or_gpio2_bit21_IRQHandler
273);
274impl_gpio_interrupt!(
275    GPIO1_8_OR_GPIO2_22_INT,
276    22,
277    PLIC_gpio1_bit8_or_gpio2_bit22_IRQHandler
278);
279impl_gpio_interrupt!(
280    GPIO1_9_OR_GPIO2_23_INT,
281    23,
282    PLIC_gpio1_bit9_or_gpio2_bit23_IRQHandler
283);
284impl_gpio_interrupt!(
285    GPIO1_10_OR_GPIO2_24_INT,
286    24,
287    PLIC_gpio1_bit10_or_gpio2_bit24_IRQHandler
288);
289impl_gpio_interrupt!(
290    GPIO1_11_OR_GPIO2_25_INT,
291    25,
292    PLIC_gpio1_bit11_or_gpio2_bit25_IRQHandler
293);
294impl_gpio_interrupt!(
295    GPIO1_12_OR_GPIO2_26_INT,
296    26,
297    PLIC_gpio1_bit12_or_gpio2_bit26_IRQHandler
298);
299impl_gpio_interrupt!(
300    GPIO1_13_OR_GPIO2_27_INT,
301    27,
302    PLIC_gpio1_bit13_or_gpio2_bit27_IRQHandler
303);
304impl_gpio_interrupt!(
305    GPIO1_14_OR_GPIO2_28_INT,
306    28,
307    PLIC_gpio1_bit14_or_gpio2_bit28_IRQHandler
308);
309impl_gpio_interrupt!(
310    GPIO1_15_OR_GPIO2_29_INT,
311    29,
312    PLIC_gpio1_bit15_or_gpio2_bit29_IRQHandler
313);
314impl_gpio_interrupt!(
315    GPIO1_16_OR_GPIO2_30_INT,
316    30,
317    PLIC_gpio1_bit16_or_gpio2_bit30_IRQHandler
318);
319impl_gpio_interrupt!(
320    GPIO1_17_OR_GPIO2_31_INT,
321    31,
322    PLIC_gpio1_bit17_or_gpio2_bit31_IRQHandler
323);
324impl_gpio_interrupt!(GPIO1_18_INT, 32, PLIC_gpio1_bit18_IRQHandler);
325impl_gpio_interrupt!(GPIO1_19_INT, 33, PLIC_gpio1_bit19_IRQHandler);
326impl_gpio_interrupt!(GPIO1_20_INT, 34, PLIC_gpio1_bit20_IRQHandler);
327impl_gpio_interrupt!(GPIO1_21_INT, 35, PLIC_gpio1_bit21_IRQHandler);
328impl_gpio_interrupt!(GPIO1_22_INT, 36, PLIC_gpio1_bit22_IRQHandler);
329impl_gpio_interrupt!(GPIO1_23_INT, 37, PLIC_gpio1_bit23_IRQHandler);
330
331macro_rules! impl_f2m_interrupt {
332    ($num:expr) => {
333        paste! {
334            impl_gpio_interrupt!([<F2M_ $num _INT>], 38 + $num, [<PLIC_f2m_ $num _IRQHandler>], pac::[<PLIC_IRQn_Type_PLIC_F2M_ $num _INT_OFFSET>]);
335        }
336    };
337}
338
339impl_f2m_interrupt!(0);
340impl_f2m_interrupt!(1);
341impl_f2m_interrupt!(2);
342impl_f2m_interrupt!(3);
343impl_f2m_interrupt!(4);
344impl_f2m_interrupt!(5);
345impl_f2m_interrupt!(6);
346impl_f2m_interrupt!(7);
347impl_f2m_interrupt!(8);
348impl_f2m_interrupt!(9);
349impl_f2m_interrupt!(10);
350impl_f2m_interrupt!(11);
351impl_f2m_interrupt!(12);
352impl_f2m_interrupt!(13);
353impl_f2m_interrupt!(14);
354impl_f2m_interrupt!(15);
355impl_f2m_interrupt!(16);
356impl_f2m_interrupt!(17);
357impl_f2m_interrupt!(18);
358impl_f2m_interrupt!(19);
359impl_f2m_interrupt!(20);
360impl_f2m_interrupt!(21);
361impl_f2m_interrupt!(22);
362impl_f2m_interrupt!(23);
363impl_f2m_interrupt!(24);
364impl_f2m_interrupt!(25);
365impl_f2m_interrupt!(26);
366impl_f2m_interrupt!(27);
367impl_f2m_interrupt!(28);
368impl_f2m_interrupt!(29);
369impl_f2m_interrupt!(30);
370impl_f2m_interrupt!(31);
371impl_f2m_interrupt!(32);
372impl_f2m_interrupt!(33);
373impl_f2m_interrupt!(34);
374impl_f2m_interrupt!(35);
375impl_f2m_interrupt!(36);
376impl_f2m_interrupt!(37);
377impl_f2m_interrupt!(38);
378impl_f2m_interrupt!(39);
379impl_f2m_interrupt!(40);
380impl_f2m_interrupt!(41);
381impl_f2m_interrupt!(42);
382impl_f2m_interrupt!(43);
383impl_f2m_interrupt!(44);
384impl_f2m_interrupt!(45);
385impl_f2m_interrupt!(46);
386impl_f2m_interrupt!(47);
387impl_f2m_interrupt!(48);
388impl_f2m_interrupt!(49);
389impl_f2m_interrupt!(50);
390impl_f2m_interrupt!(51);
391impl_f2m_interrupt!(52);
392impl_f2m_interrupt!(53);
393impl_f2m_interrupt!(54);
394impl_f2m_interrupt!(55);
395impl_f2m_interrupt!(56);
396impl_f2m_interrupt!(57);
397impl_f2m_interrupt!(58);
398impl_f2m_interrupt!(59);
399impl_f2m_interrupt!(60);
400impl_f2m_interrupt!(61);
401impl_f2m_interrupt!(62);
402impl_f2m_interrupt!(63);
403
404//-------------------------------------
405// MARK: Pins
406//-------------------------------------
407
408#[derive(Debug, Clone, Copy)]
409#[allow(dead_code)]
410#[doc(hidden)]
411pub enum GpioPeripheral {
412    Mss(*mut pac::GPIO_TypeDef),
413    FpgaCore(pac::gpio_instance_t),
414}
415
416impl GpioPeripheral {
417    pub fn is_gpio2(&self) -> bool {
418        if let GpioPeripheral::Mss(gpio) = self {
419            gpio == &pac::GPIO2_LO
420        } else {
421            false
422        }
423    }
424}
425
426#[doc(hidden)]
427#[derive(Debug, Clone, Copy)]
428pub struct Pin {
429    number: u8,
430    peripheral: GpioPeripheral,
431    interrupt: Interrupt,
432}
433
434impl Pin {
435    // Meant to be used only by board-support code
436    #[doc(hidden)]
437    pub fn new(number: u8, peripheral: GpioPeripheral, interrupt: Interrupt) -> Self {
438        Self {
439            number,
440            peripheral,
441            interrupt,
442        }
443    }
444
445    #[doc(hidden)]
446    pub fn config_output(&self) {
447        unsafe {
448            match self.peripheral {
449                GpioPeripheral::Mss(typedef) => {
450                    trace!("Configuring MSS GPIO {:?} to output", self);
451                    pac::MSS_GPIO_config(typedef, self.number as u32, pac::MSS_GPIO_OUTPUT_MODE);
452                }
453                GpioPeripheral::FpgaCore(address) => {
454                    let mut address = address;
455                    trace!("Configuring FPGA Core GPIO {:?} to output", self);
456                    pac::GPIO_config(&mut address, self.number as u32, pac::MSS_GPIO_OUTPUT_MODE);
457                }
458            }
459        }
460    }
461
462    #[doc(hidden)]
463    pub fn config_input(&self, config: InterruptTrigger) {
464        unsafe {
465            match self.peripheral {
466                GpioPeripheral::Mss(typedef) => {
467                    trace!(
468                        "Configuring MSS GPIO {:?} to input with trigger {:?}",
469                        self,
470                        config
471                    );
472                    pac::MSS_GPIO_config(
473                        typedef,
474                        self.number as u32,
475                        pac::MSS_GPIO_INPUT_MODE | config as u32,
476                    );
477                }
478                GpioPeripheral::FpgaCore(address) => {
479                    let mut address = address;
480                    trace!(
481                        "Configuring FPGA Core GPIO {:?} to input with trigger {:?}",
482                        self,
483                        config
484                    );
485                    pac::GPIO_config(
486                        &mut address,
487                        self.number as u32,
488                        pac::MSS_GPIO_INPUT_MODE | config as u32,
489                    );
490                }
491            }
492        }
493    }
494
495    #[doc(hidden)]
496    pub fn set_high(&self) {
497        unsafe {
498            match self.peripheral {
499                GpioPeripheral::Mss(typedef) => {
500                    trace!("Setting MSS GPIO {:?} to high", self);
501                    pac::MSS_GPIO_set_output(typedef, self.number as u32, 1);
502                }
503                GpioPeripheral::FpgaCore(address) => {
504                    let mut address = address;
505                    let mut gpio_outputs = pac::GPIO_get_outputs(&mut address);
506                    gpio_outputs |= 1 << self.number;
507                    trace!(
508                        "Setting FPGA Core GPIO {:?} to high with value {:?}",
509                        self,
510                        gpio_outputs
511                    );
512                    pac::GPIO_set_outputs(&mut address, gpio_outputs);
513                }
514            }
515        }
516    }
517
518    #[doc(hidden)]
519    pub fn set_low(&self) {
520        unsafe {
521            match self.peripheral {
522                GpioPeripheral::Mss(typedef) => {
523                    trace!("Setting MSS GPIO {:?} to low", self);
524                    pac::MSS_GPIO_set_output(typedef, self.number as u32, 0);
525                }
526                GpioPeripheral::FpgaCore(address) => {
527                    let mut address = address;
528                    let mut gpio_outputs = pac::GPIO_get_outputs(&mut address);
529                    gpio_outputs &= !(1 << self.number);
530                    trace!(
531                        "Setting FPGA Core GPIO {:?} to low with value {:?}",
532                        self,
533                        gpio_outputs
534                    );
535                    pac::GPIO_set_outputs(&mut address, gpio_outputs);
536                }
537            }
538        }
539    }
540
541    #[doc(hidden)]
542    pub fn is_high(&self) -> bool {
543        unsafe {
544            match self.peripheral {
545                GpioPeripheral::Mss(typedef) => {
546                    let inputs = (*typedef).GPIO_IN;
547                    inputs & (1 << self.number) != 0
548                }
549                GpioPeripheral::FpgaCore(address) => {
550                    let mut address = address;
551                    let inputs = pac::GPIO_get_inputs(&mut address);
552                    inputs & (1 << self.number) != 0
553                }
554            }
555        }
556    }
557
558    fn enable_interrupt(&self) {
559        unsafe {
560            match self.peripheral {
561                GpioPeripheral::Mss(typedef) => {
562                    pac::MSS_GPIO_enable_irq(typedef, self.number as u32);
563                }
564                GpioPeripheral::FpgaCore(address) => {
565                    let mut address = address;
566                    pac::GPIO_enable_irq(&mut address, self.number as u32);
567                    pac::PLIC_EnableIRQ(self.interrupt.plic_idx as u32);
568                }
569            }
570        }
571    }
572
573    fn clear_triggered(&self) {
574        critical_section::with(|_| unsafe {
575            GPIO_INTERRUPTS[self.interrupt.interrupt_idx as usize].triggered = false;
576        });
577    }
578
579    fn clear_interrupt(peripheral: GpioPeripheral, number: u8) {
580        unsafe {
581            match peripheral {
582                GpioPeripheral::Mss(addr) => {
583                    pac::MSS_GPIO_clear_irq(addr, number as u32);
584                }
585                GpioPeripheral::FpgaCore(addr) => {
586                    let mut address = addr;
587                    pac::GPIO_clear_irq(&mut address, number as u32);
588                }
589            }
590        }
591    }
592
593    fn disable_interrupt(peripheral: GpioPeripheral, number: u8) {
594        unsafe {
595            match peripheral {
596                GpioPeripheral::Mss(addr) => {
597                    pac::MSS_GPIO_disable_irq(addr, number as u32);
598                }
599                GpioPeripheral::FpgaCore(addr) => {
600                    let mut address = addr;
601                    pac::GPIO_disable_irq(&mut address, number as u32);
602                }
603            }
604        }
605    }
606}
607
608/// All GPIO pins implement this trait
609pub trait GpioPin: 'static {
610    #[doc(hidden)]
611    fn address(&self) -> Pin;
612}
613
614pub struct Output {
615    pub pin: Pin,
616}
617
618//----------------------------------------------------------------------
619// Output
620
621impl Output {
622    pub fn new<P: GpioPin>(pin: P) -> Self {
623        let address = pin.address();
624        address.config_output();
625        Self { pin: address }
626    }
627}
628
629impl embedded_hal::digital::ErrorType for Output {
630    type Error = Infallible;
631}
632
633impl embedded_hal::digital::OutputPin for Output {
634    fn set_high(&mut self) -> Result<(), Self::Error> {
635        self.pin.set_high();
636        Ok(())
637    }
638
639    fn set_low(&mut self) -> Result<(), Self::Error> {
640        self.pin.set_low();
641        Ok(())
642    }
643}
644
645//----------------------------------------------------------------------
646// Input
647
648pub struct Input {
649    pub pin: Pin,
650}
651
652impl Input {
653    pub fn new<P: GpioPin>(pin: P) -> Self {
654        let address = pin.address();
655        if address.interrupt.is_none() {
656            panic!(
657                "Cannot create an input pin with no interrupt: {:?}",
658                address
659            );
660        }
661        address.config_input(InterruptTrigger::default());
662        Self { pin: address }
663    }
664}
665
666impl embedded_hal::digital::ErrorType for Input {
667    type Error = core::convert::Infallible;
668}
669
670impl embedded_hal::digital::InputPin for Input {
671    fn is_high(&mut self) -> Result<bool, Self::Error> {
672        Ok(self.pin.is_high())
673    }
674
675    fn is_low(&mut self) -> Result<bool, Self::Error> {
676        Ok(!self.pin.is_high())
677    }
678}
679
680//----------------------------------------------------------------------
681// Interrupt
682
683#[doc(hidden)]
684pub struct InputFuture {
685    pin: Pin,
686    trigger: InterruptTrigger,
687}
688
689impl InputFuture {
690    pub fn new(pin: Pin, interrupt_trigger: InterruptTrigger) -> Self {
691        critical_section::with(|_| unsafe {
692            GPIO_INTERRUPTS[pin.interrupt.interrupt_idx as usize].triggered = false;
693        });
694        pin.config_input(interrupt_trigger);
695        pin.enable_interrupt();
696        Self {
697            pin,
698            trigger: interrupt_trigger,
699        }
700    }
701}
702
703impl Future for InputFuture {
704    type Output = Result<(), Infallible>;
705
706    fn poll(mut self: core::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
707        let trigger = critical_section::with(|_| unsafe {
708            self.as_mut().pin.interrupt.set_waker(cx.waker().clone());
709            self.as_mut().pin.interrupt.triggered()
710        });
711
712        if ((self.trigger == InterruptTrigger::EdgePositive
713            || self.trigger == InterruptTrigger::LevelHigh)
714            && self.as_mut().pin.is_high())
715            || ((self.trigger == InterruptTrigger::EdgeNegative
716                || self.trigger == InterruptTrigger::LevelLow)
717                && !self.as_mut().pin.is_high())
718        {
719            // Check to see if the pin is in the state we're looking for, even if the interrupt wasn't triggered
720            Poll::Ready(Ok(()))
721        } else if trigger {
722            if ((self.trigger == InterruptTrigger::EdgePositive
723                || self.trigger == InterruptTrigger::LevelHigh)
724                && !self.as_mut().pin.is_high())
725                || ((self.trigger == InterruptTrigger::EdgeNegative
726                    || self.trigger == InterruptTrigger::LevelLow)
727                    && self.as_mut().pin.is_high())
728            {
729                // The interrupt was triggered, but the pin is not in the correct state
730                // so we reset the interrupt and wait for the next one
731                self.as_mut().pin.clear_triggered();
732                self.as_mut().pin.enable_interrupt();
733                return Poll::Pending;
734            }
735            self.as_mut().pin.clear_triggered();
736            Pin::clear_interrupt(self.as_mut().pin.peripheral, self.as_mut().pin.number);
737            Pin::disable_interrupt(self.as_mut().pin.peripheral, self.as_mut().pin.number);
738            Poll::Ready(Ok(()))
739        } else {
740            Poll::Pending
741        }
742    }
743}
744
745impl embedded_hal_async::digital::Wait for Input {
746    async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
747        if !self.pin.is_high() {
748            InputFuture::new(self.pin, InterruptTrigger::LevelHigh).await
749        } else {
750            Ok(())
751        }
752    }
753
754    async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
755        if self.pin.is_high() {
756            InputFuture::new(self.pin, InterruptTrigger::LevelLow).await
757        } else {
758            Ok(())
759        }
760    }
761
762    async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
763        InputFuture::new(self.pin, InterruptTrigger::EdgePositive).await
764    }
765
766    async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
767        InputFuture::new(self.pin, InterruptTrigger::EdgeNegative).await
768    }
769
770    async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
771        InputFuture::new(self.pin, InterruptTrigger::EdgeBoth).await
772    }
773}
774
775//----------------------------------------------------------------------
776// MARK: Macros
777//----------------------------------------------------------------------
778
779#[macro_export]
780/// This macro is used to define a GPIO pin.
781///
782/// It does not actually guard against defining the same resource multiple times, so be careful.
783macro_rules! impl_gpio_pin {
784    ($pin:ident, $peripheral:expr, $n:expr, $interrupt:ident) => {
785        paste::paste! {
786            impl_gpio_pin!($pin, [<$pin _TAKEN>], $peripheral, $n, $interrupt);
787        }
788    };
789
790    ($PIN:ident, $PIN_TAKEN:ident, $peripheral:expr, $num:expr, NONE) => {
791        #[allow(non_camel_case_types)]
792        pub struct $PIN {
793            _private: (),
794        }
795        static mut $PIN_TAKEN: bool = false;
796
797        impl $crate::Peripheral for $PIN {
798            fn take() -> Option<Self> {
799                critical_section::with(|_| unsafe {
800                    if $PIN_TAKEN {
801                        None
802                    } else {
803                        $PIN_TAKEN = true;
804                        Some(Self { _private: () })
805                    }
806                })
807            }
808
809            unsafe fn steal() -> Self {
810                Self { _private: () }
811            }
812        }
813
814        impl $crate::gpio::GpioPin for $PIN {
815            fn address(&self) -> $crate::gpio::Pin {
816                $crate::gpio::Pin::new($num, $peripheral, $crate::gpio::Interrupt::NONE)
817            }
818        }
819    };
820
821    ($PIN:ident, $PIN_TAKEN:ident, $peripheral:expr, $num:expr, $interrupt:ident) => {
822        #[allow(non_camel_case_types)]
823        pub struct $PIN {
824            _private: (),
825        }
826        static mut $PIN_TAKEN: bool = false;
827
828        impl $crate::Peripheral for $PIN {
829            fn take() -> Option<Self> {
830                critical_section::with(|_| unsafe {
831                    if $PIN_TAKEN {
832                        None
833                    } else {
834                        if $interrupt::take().is_some() {
835                            $PIN_TAKEN = true;
836                            if $peripheral.is_gpio2() {
837                                // Enable GPIO2 interrupt
838                                (*$crate::pac::SYSREG).GPIO_INTERRUPT_FAB_CR |= 1 << $num;
839                                trace!(
840                                    "Enabled GPIO2 interrupt for pin {}; {:x?}",
841                                    $num,
842                                    (*$crate::pac::SYSREG).GPIO_INTERRUPT_FAB_CR
843                                );
844                            }
845                            Some(Self { _private: () })
846                        } else {
847                            None
848                        }
849                    }
850                })
851            }
852
853            unsafe fn steal() -> Self {
854                Self { _private: () }
855            }
856        }
857
858        impl $crate::gpio::GpioPin for $PIN {
859            fn address(&self) -> $crate::gpio::Pin {
860                $crate::gpio::Pin::new($num, $peripheral, unsafe {
861                    $crate::gpio::GpioInterrupt::address(&$interrupt::steal())
862                })
863            }
864        }
865    };
866}
867
868#[macro_export]
869macro_rules! impl_input_peripheral {
870    ($perif:ident, $pin:ident) => {
871        paste::paste! {
872            impl_input_peripheral!($perif, [<$perif _TAKEN>], $pin);
873        }
874    };
875
876    ($PERIF:ident, $PERIF_TAKEN:ident, $pin:ident) => {
877        #[allow(non_camel_case_types)]
878        pub struct $PERIF {
879            pub pin: $crate::gpio::Input,
880        }
881        #[allow(non_upper_case_globals)]
882        static mut $PERIF_TAKEN: bool = false;
883
884        impl $crate::Peripheral for $PERIF {
885            fn take() -> Option<Self> {
886                critical_section::with(|_| unsafe {
887                    if $PERIF_TAKEN {
888                        None
889                    } else {
890                        if $pin::take().is_some() {
891                            $PERIF_TAKEN = true;
892                            Some(Self {
893                                pin: $crate::gpio::Input::new($pin::steal()),
894                            })
895                        } else {
896                            None
897                        }
898                    }
899                })
900            }
901
902            unsafe fn steal() -> Self {
903                unsafe {
904                    Self {
905                        pin: $crate::gpio::Input::new($pin::steal()),
906                    }
907                }
908            }
909        }
910
911        impl embedded_hal::digital::ErrorType for $PERIF {
912            type Error = core::convert::Infallible;
913        }
914
915        impl embedded_hal::digital::InputPin for $PERIF {
916            fn is_high(&mut self) -> Result<bool, Self::Error> {
917                self.pin.is_high()
918            }
919
920            fn is_low(&mut self) -> Result<bool, Self::Error> {
921                self.pin.is_low()
922            }
923        }
924
925        impl embedded_hal_async::digital::Wait for $PERIF {
926            async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
927                self.pin.wait_for_high().await
928            }
929
930            async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
931                self.pin.wait_for_low().await
932            }
933
934            async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
935                self.pin.wait_for_rising_edge().await
936            }
937
938            async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
939                self.pin.wait_for_falling_edge().await
940            }
941
942            async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
943                self.pin.wait_for_any_edge().await
944            }
945        }
946    };
947}
948
949#[macro_export]
950macro_rules! impl_output_peripheral {
951    ($perif:ident, $pin:ident) => {
952        paste::paste! {
953            impl_output_peripheral!($perif, [<$perif _TAKEN>], $pin);
954        }
955    };
956
957    ($PERIF:ident, $PERIF_TAKEN:ident, $pin:ident) => {
958        #[allow(non_camel_case_types)]
959        pub struct $PERIF {
960            pub pin: $crate::gpio::Output,
961        }
962        #[allow(non_upper_case_globals)]
963        static mut $PERIF_TAKEN: bool = false;
964
965        impl $crate::Peripheral for $PERIF {
966            fn take() -> Option<Self> {
967                critical_section::with(|_| unsafe {
968                    if $PERIF_TAKEN {
969                        None
970                    } else {
971                        if $pin::take().is_some() {
972                            $PERIF_TAKEN = true;
973                            Some(Self {
974                                pin: $crate::gpio::Output::new($pin::steal()),
975                            })
976                        } else {
977                            None
978                        }
979                    }
980                })
981            }
982
983            unsafe fn steal() -> Self {
984                unsafe {
985                    Self {
986                        pin: $crate::gpio::Output::new($pin::steal()),
987                    }
988                }
989            }
990        }
991
992        impl embedded_hal::digital::ErrorType for $PERIF {
993            type Error = core::convert::Infallible;
994        }
995
996        impl embedded_hal::digital::OutputPin for $PERIF {
997            fn set_low(&mut self) -> Result<(), Self::Error> {
998                self.pin.set_low()
999            }
1000
1001            fn set_high(&mut self) -> Result<(), Self::Error> {
1002                self.pin.set_high()
1003            }
1004        }
1005    };
1006}
1007
1008//----------------------------------------------------------------------
1009// MARK: Beaglev Fire
1010//-------------------------------------
1011
1012#[cfg(feature = "beaglev-fire")]
1013pub use beaglev_fire::*;
1014#[cfg(feature = "beaglev-fire")]
1015mod beaglev_fire {
1016    use super::*;
1017    use crate::pac;
1018
1019    use embedded_hal::digital::InputPin;
1020    use embedded_hal_async::digital::Wait;
1021    use mutually_exclusive_features::exactly_one_of;
1022
1023    exactly_one_of!(
1024        "beaglev-fire-default-cape",
1025        "beaglev-fire-gpio-cape",
1026        "beaglev-fire-no-cape"
1027    );
1028
1029    /// To be called before using any GPIO pins
1030    pub fn init() {
1031        unsafe {
1032            base_init();
1033            #[cfg(any(
1034                feature = "beaglev-fire-gpio-cape",
1035                feature = "beaglev-fire-default-cape"
1036            ))]
1037            beaglev_fire_default_cape::cape_init();
1038        }
1039    }
1040
1041    // IO that is always available
1042
1043    impl_gpio_pin!(
1044        SD_DETECT,
1045        GpioPeripheral::Mss(pac::GPIO2_LO),
1046        31,
1047        GPIO1_17_OR_GPIO2_31_INT
1048    );
1049    impl_input_peripheral!(SdDetect, SD_DETECT);
1050
1051    impl SdDetect {
1052        pub fn is_inserted(&mut self) -> bool {
1053            self.is_low().unwrap()
1054        }
1055
1056        pub async fn wait_for_inserted(
1057            &mut self,
1058        ) -> Result<(), <Self as embedded_hal::digital::ErrorType>::Error> {
1059            self.wait_for_low().await
1060        }
1061
1062        pub async fn wait_for_removed(
1063            &mut self,
1064        ) -> Result<(), <Self as embedded_hal::digital::ErrorType>::Error> {
1065            self.wait_for_high().await
1066        }
1067    }
1068
1069    impl_gpio_pin!(SD_CHIP_SELECT, GpioPeripheral::Mss(pac::GPIO0_LO), 12, NONE);
1070    impl_output_peripheral!(SdChipSelect, SD_CHIP_SELECT);
1071
1072    impl_gpio_pin!(
1073        USER_BUTTON,
1074        GpioPeripheral::Mss(pac::GPIO0_LO),
1075        13,
1076        GPIO0_13_OR_GPIO2_13_INT
1077    );
1078    impl_input_peripheral!(UserButton, USER_BUTTON);
1079
1080    //-------------------------------------------------------------
1081    // Cape GPIOs
1082
1083    // From the Cape documentation: https://git.beagleboard.org/beaglev-fire/gateware/-/blob/main/sources/FPGA-design/script_support/components/CAPE/DEFAULT/Readme.md
1084    // https://git.beagleboard.org/beaglev-fire/gateware/-/blob/main/sources/FPGA-design/script_support/components/CAPE/GPIOS/Readme.md
1085    /*
1086    | P8_3   | MSS GPIO_2[0]              |   53  | User LED 0  |
1087    | P8_4   | MSS GPIO_2[1]              |   53  | User LED 1  |
1088    | P8_5   | MSS GPIO_2[2]              |   53  | User LED 2  |
1089    | P8_6   | MSS GPIO_2[3]              |   53  | User LED 3  |
1090    | P8_7   | MSS GPIO_2[4]              |   53  | User LED 4  |
1091    | P8_8   | MSS GPIO_2[5]              |   53  | User LED 5  |
1092    | P8_9   | MSS GPIO_2[6]              |   53  | User LED 6  |
1093    | P8_10  | MSS GPIO_2[7]              |   53  | User LED 7  |
1094    | P8_11  | MSS GPIO_2[8]              |   53  | User LED 8  |
1095    | P8_12  | MSS GPIO_2[9]              |   53  | User LED 9  |
1096    | P8_13  | MSS GPIO_2[10]             |   53  | User LED 10 | // ONLY ON GPIO CAPE
1097    | P8_14  | MSS GPIO_2[11]             |   53  | User LED 11 |
1098    | P8_15  | MSS GPIO_2[12]             |   53  | GPIO        |
1099    | P8_16  | MSS GPIO_2[13]             |   53  | GPIO        |
1100    | P8_17  | MSS GPIO_2[14]             |   53  | GPIO        |
1101    | P8_18  | MSS GPIO_2[15]             |   53  | GPIO        |
1102    | P8_19  | MSS GPIO_2[16]             |   53  | GPIO        | // ONLY ON GPIO CAPE
1103    | P8_20  | MSS GPIO_2[17]             |   53  | GPIO        |
1104    | P8_21  | MSS GPIO_2[18]             |   53  | GPIO        |
1105    | P8_22  | MSS GPIO_2[19]             |   53  | GPIO        |
1106    | P8_23  | MSS GPIO_2[20]             |   53  | GPIO        |
1107    | P8_24  | MSS GPIO_2[21]             |   53  | GPIO        |
1108    | P8_25  | MSS GPIO_2[22]             |   53  | GPIO        |
1109    | P8_26  | MSS GPIO_2[23]             |   53  | GPIO        |
1110    | P8_27  | MSS GPIO_2[24]             |   53  | GPIO        |
1111    | P8_28  | MSS GPIO_2[25]             |   53  | GPIO        |
1112    | P8_29  | MSS GPIO_2[26]             |   53  | GPIO        |
1113    | P8_30  | MSS GPIO_2[27]             |   53  | GPIO        |
1114    | P8_31  | core_gpio[0] @ 0x41100000  |  126  | GPIO        |
1115    | P8_32  | core_gpio[1] @ 0x41100000  |  127  | GPIO        |
1116    | P8_33  | core_gpio[2] @ 0x41100000  |  128  | GPIO        |
1117    | P8_34  | core_gpio[3] @ 0x41100000  |  129  | GPIO        |
1118    | P8_35  | core_gpio[4] @ 0x41100000  |  130  | GPIO        |
1119    | P8_36  | core_gpio[5] @ 0x41100000  |  131  | GPIO        |
1120    | P8_37  | core_gpio[6] @ 0x41100000  |  132  | GPIO        |
1121    | P8_38  | core_gpio[7] @ 0x41100000  |  133  | GPIO        |
1122    | P8_39  | core_gpio[8] @ 0x41100000  |  134  | GPIO        |
1123    | P8_40  | core_gpio[9] @ 0x41100000  |  135  | GPIO        |
1124    | P8_41  | core_gpio[10] @ 0x41100000 |  136  | GPIO        |
1125    | P8_42  | core_gpio[11] @ 0x41100000 |  137  | GPIO        |
1126    | P8_43  | core_gpio[12] @ 0x41100000 |  138  | GPIO        |
1127    | P8_44  | core_gpio[13] @ 0x41100000 |  139  | GPIO        |
1128    | P8_45  | core_gpio[14] @ 0x41100000 |  140  | GPIO        |
1129    | P8_46  | core_gpio[15] @ 0x41100000 |  141  | GPIO        |
1130    -------------------------------------------------------------
1131    | P9_11  | core_gpio[0] @ 0x41200000  |  142  | GPIO        | // ONLY ON GPIO CAPE
1132    | P9_12  | core_gpio[1] @ 0x41200000  |  143  | GPIO        |
1133    | P9_13  | core_gpio[2] @ 0x41200000  |  144  | GPIO        | // ONLY ON GPIO CAPE
1134    | P9_15  | core_gpio[4] @ 0x41200000  |  146  | GPIO        |
1135    | P9_16  | core_gpio[5] @ 0x41200000  |  147  | GPIO        | // ONLY ON GPIO CAPE
1136    | P9_17  | core_gpio[6] @ 0x41200000  |  148  | GPIO        | // ONLY ON GPIO CAPE
1137    | P9_18  | core_gpio[7] @ 0x41200000  |  149  | GPIO        | // ONLY ON GPIO CAPE
1138    | P9_21  | core_gpio[8] @ 0x41200000  |  150  | GPIO        | // ONLY ON GPIO CAPE
1139    | P9_22  | core_gpio[9] @ 0x41200000  |  151  | GPIO        | // ONLY ON GPIO CAPE
1140    | P9_23  | core_gpio[10] @ 0x41200000 |  152  | GPIO        |
1141    | P9_24  | core_gpio[11] @ 0x41200000 |  153  | GPIO        | // ONLY ON GPIO CAPE
1142    | P9_25  | core_gpio[12] @ 0x41200000 |  154  | GPIO        |
1143    | P9_26  | core_gpio[13] @ 0x41200000 |  155  | GPIO        | // ONLY ON GPIO CAPE
1144    | P9_27  | core_gpio[14] @ 0x41200000 |  156  | GPIO        |
1145    | P9_28  | core_gpio[15] @ 0x41200000 |  157  | GPIO        | // ONLY ON GPIO CAPE
1146    | P9_29  | core_gpio[16] @ 0x41200000 |  158  | GPIO        | // ONLY ON GPIO CAPE
1147    | P9_30  | core_gpio[17] @ 0x41200000 |  159  | GPIO        |
1148    | P9_31  | core_gpio[18] @ 0x41200000 |  160  | GPIO        | // ONLY ON GPIO CAPE
1149    | P9_41  | core_gpio[19] @ 0x41200000 |  161  | GPIO        |
1150    | P9_42  | core_gpio[20] @ 0x41200000 |  162  | GPIO        | // ONLY ON GPIO CAPE
1151    */
1152
1153    #[cfg(any(
1154        feature = "beaglev-fire-gpio-cape",
1155        feature = "beaglev-fire-default-cape"
1156    ))]
1157    pub use beaglev_fire_default_cape::*;
1158
1159    #[cfg(any(
1160        feature = "beaglev-fire-gpio-cape",
1161        feature = "beaglev-fire-default-cape"
1162    ))]
1163    mod beaglev_fire_default_cape {
1164        use super::*;
1165        use crate::pac;
1166
1167        pub(crate) unsafe fn cape_init() {
1168            unsafe {
1169                // FPGA Core GPIO initialization
1170                let mut p8: pac::gpio_instance_t = P8_CORE_GPIO;
1171                trace!("Initializing FPGA Core GPIO {:?}", p8);
1172                pac::GPIO_init(&mut p8, P8_CORE_GPIO.base_addr, P8_CORE_GPIO.apb_bus_width);
1173                let mut p9: pac::gpio_instance_t = P9_CORE_GPIO;
1174                trace!("Initializing FPGA Core GPIO {:?}", p9);
1175                pac::GPIO_init(&mut p9, P9_CORE_GPIO.base_addr, P9_CORE_GPIO.apb_bus_width);
1176            }
1177        }
1178
1179        pub const P8_CORE_GPIO: pac::gpio_instance_t = pac::gpio_instance_t {
1180            base_addr: 0x4110_0000,
1181            apb_bus_width: pac::__gpio_apb_width_t_GPIO_APB_32_BITS_BUS,
1182        };
1183
1184        pub const P9_CORE_GPIO: pac::gpio_instance_t = pac::gpio_instance_t {
1185            base_addr: 0x41200000,
1186            apb_bus_width: pac::__gpio_apb_width_t_GPIO_APB_32_BITS_BUS,
1187        };
1188
1189        impl_gpio_pin!(
1190            P8_3,
1191            GpioPeripheral::Mss(pac::GPIO2_LO),
1192            0,
1193            GPIO0_0_OR_GPIO2_0_INT
1194        );
1195        impl_gpio_pin!(
1196            P8_4,
1197            GpioPeripheral::Mss(pac::GPIO2_LO),
1198            1,
1199            GPIO0_1_OR_GPIO2_1_INT
1200        );
1201        impl_gpio_pin!(
1202            P8_5,
1203            GpioPeripheral::Mss(pac::GPIO2_LO),
1204            2,
1205            GPIO0_2_OR_GPIO2_2_INT
1206        );
1207        impl_gpio_pin!(
1208            P8_6,
1209            GpioPeripheral::Mss(pac::GPIO2_LO),
1210            3,
1211            GPIO0_3_OR_GPIO2_3_INT
1212        );
1213        impl_gpio_pin!(
1214            P8_7,
1215            GpioPeripheral::Mss(pac::GPIO2_LO),
1216            4,
1217            GPIO0_4_OR_GPIO2_4_INT
1218        );
1219        impl_gpio_pin!(
1220            P8_8,
1221            GpioPeripheral::Mss(pac::GPIO2_LO),
1222            5,
1223            GPIO0_5_OR_GPIO2_5_INT
1224        );
1225        impl_gpio_pin!(
1226            P8_9,
1227            GpioPeripheral::Mss(pac::GPIO2_LO),
1228            6,
1229            GPIO0_6_OR_GPIO2_6_INT
1230        );
1231        impl_gpio_pin!(
1232            P8_10,
1233            GpioPeripheral::Mss(pac::GPIO2_LO),
1234            7,
1235            GPIO0_7_OR_GPIO2_7_INT
1236        );
1237        impl_gpio_pin!(
1238            P8_11,
1239            GpioPeripheral::Mss(pac::GPIO2_LO),
1240            8,
1241            GPIO0_8_OR_GPIO2_8_INT
1242        );
1243        impl_gpio_pin!(
1244            P8_12,
1245            GpioPeripheral::Mss(pac::GPIO2_LO),
1246            9,
1247            GPIO0_9_OR_GPIO2_9_INT
1248        );
1249        impl_gpio_pin!(
1250            P8_14,
1251            GpioPeripheral::Mss(pac::GPIO2_LO),
1252            11,
1253            GPIO0_11_OR_GPIO2_11_INT
1254        );
1255        impl_gpio_pin!(
1256            P8_15,
1257            GpioPeripheral::Mss(pac::GPIO2_LO),
1258            12,
1259            GPIO0_12_OR_GPIO2_12_INT
1260        );
1261        impl_gpio_pin!(
1262            P8_16,
1263            GpioPeripheral::Mss(pac::GPIO2_LO),
1264            13,
1265            GPIO0_13_OR_GPIO2_13_INT
1266        );
1267        impl_gpio_pin!(
1268            P8_17,
1269            GpioPeripheral::Mss(pac::GPIO2_LO),
1270            14,
1271            GPIO1_0_OR_GPIO2_14_INT
1272        );
1273        impl_gpio_pin!(
1274            P8_18,
1275            GpioPeripheral::Mss(pac::GPIO2_LO),
1276            15,
1277            GPIO1_1_OR_GPIO2_15_INT
1278        );
1279        impl_gpio_pin!(
1280            P8_20,
1281            GpioPeripheral::Mss(pac::GPIO2_LO),
1282            17,
1283            GPIO1_3_OR_GPIO2_17_INT
1284        );
1285        impl_gpio_pin!(
1286            P8_21,
1287            GpioPeripheral::Mss(pac::GPIO2_LO),
1288            18,
1289            GPIO1_4_OR_GPIO2_18_INT
1290        );
1291        impl_gpio_pin!(
1292            P8_22,
1293            GpioPeripheral::Mss(pac::GPIO2_LO),
1294            19,
1295            GPIO1_5_OR_GPIO2_19_INT
1296        );
1297        impl_gpio_pin!(
1298            P8_23,
1299            GpioPeripheral::Mss(pac::GPIO2_LO),
1300            20,
1301            GPIO1_6_OR_GPIO2_20_INT
1302        );
1303        impl_gpio_pin!(
1304            P8_24,
1305            GpioPeripheral::Mss(pac::GPIO2_LO),
1306            21,
1307            GPIO1_7_OR_GPIO2_21_INT
1308        );
1309        impl_gpio_pin!(
1310            P8_25,
1311            GpioPeripheral::Mss(pac::GPIO2_LO),
1312            22,
1313            GPIO1_8_OR_GPIO2_22_INT
1314        );
1315        impl_gpio_pin!(
1316            P8_26,
1317            GpioPeripheral::Mss(pac::GPIO2_LO),
1318            23,
1319            GPIO1_9_OR_GPIO2_23_INT
1320        );
1321        impl_gpio_pin!(
1322            P8_27,
1323            GpioPeripheral::Mss(pac::GPIO2_LO),
1324            24,
1325            GPIO1_10_OR_GPIO2_24_INT
1326        );
1327        impl_gpio_pin!(
1328            P8_28,
1329            GpioPeripheral::Mss(pac::GPIO2_LO),
1330            25,
1331            GPIO1_11_OR_GPIO2_25_INT
1332        );
1333        impl_gpio_pin!(
1334            P8_29,
1335            GpioPeripheral::Mss(pac::GPIO2_LO),
1336            26,
1337            GPIO1_12_OR_GPIO2_26_INT
1338        );
1339        impl_gpio_pin!(
1340            P8_30,
1341            GpioPeripheral::Mss(pac::GPIO2_LO),
1342            27,
1343            GPIO1_13_OR_GPIO2_27_INT
1344        );
1345
1346        impl_gpio_pin!(P8_31, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 0, F2M_8_INT);
1347        impl_gpio_pin!(P8_32, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 1, F2M_9_INT);
1348        impl_gpio_pin!(P8_33, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 2, F2M_10_INT);
1349        impl_gpio_pin!(P8_34, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 3, F2M_11_INT);
1350        impl_gpio_pin!(P8_35, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 4, F2M_12_INT);
1351        impl_gpio_pin!(P8_36, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 5, F2M_13_INT);
1352        impl_gpio_pin!(P8_37, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 6, F2M_14_INT);
1353        impl_gpio_pin!(P8_38, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 7, F2M_15_INT);
1354        impl_gpio_pin!(P8_39, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 8, F2M_16_INT);
1355        impl_gpio_pin!(P8_40, GpioPeripheral::FpgaCore(P8_CORE_GPIO), 9, F2M_17_INT);
1356        impl_gpio_pin!(
1357            P8_41,
1358            GpioPeripheral::FpgaCore(P8_CORE_GPIO),
1359            10,
1360            F2M_18_INT
1361        );
1362        impl_gpio_pin!(
1363            P8_42,
1364            GpioPeripheral::FpgaCore(P8_CORE_GPIO),
1365            11,
1366            F2M_19_INT
1367        );
1368        impl_gpio_pin!(
1369            P8_43,
1370            GpioPeripheral::FpgaCore(P8_CORE_GPIO),
1371            12,
1372            F2M_20_INT
1373        );
1374        impl_gpio_pin!(
1375            P8_44,
1376            GpioPeripheral::FpgaCore(P8_CORE_GPIO),
1377            13,
1378            F2M_21_INT
1379        );
1380        impl_gpio_pin!(
1381            P8_45,
1382            GpioPeripheral::FpgaCore(P8_CORE_GPIO),
1383            14,
1384            F2M_22_INT
1385        );
1386        impl_gpio_pin!(
1387            P8_46,
1388            GpioPeripheral::FpgaCore(P8_CORE_GPIO),
1389            15,
1390            F2M_23_INT
1391        );
1392        impl_gpio_pin!(P9_12, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 1, F2M_25_INT);
1393        impl_gpio_pin!(P9_15, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 4, F2M_28_INT);
1394        impl_gpio_pin!(
1395            P9_23,
1396            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1397            10,
1398            F2M_34_INT
1399        );
1400        impl_gpio_pin!(
1401            P9_25,
1402            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1403            12,
1404            F2M_36_INT
1405        );
1406        impl_gpio_pin!(
1407            P9_27,
1408            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1409            14,
1410            F2M_38_INT
1411        );
1412        impl_gpio_pin!(
1413            P9_30,
1414            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1415            17,
1416            F2M_41_INT
1417        );
1418        impl_gpio_pin!(
1419            P9_41,
1420            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1421            19,
1422            F2M_43_INT
1423        );
1424
1425        impl_output_peripheral!(Led0, P8_3);
1426        impl_output_peripheral!(Led1, P8_4);
1427        impl_output_peripheral!(Led2, P8_5);
1428        impl_output_peripheral!(Led3, P8_6);
1429        impl_output_peripheral!(Led4, P8_7);
1430        impl_output_peripheral!(Led5, P8_8);
1431        impl_output_peripheral!(Led6, P8_9);
1432        impl_output_peripheral!(Led7, P8_10);
1433        impl_output_peripheral!(Led8, P8_11);
1434        impl_output_peripheral!(Led9, P8_12);
1435        impl_output_peripheral!(Led11, P8_14);
1436
1437        use embedded_hal::digital::{OutputPin, PinState};
1438        pub struct Leds {
1439            pub led0: Led0,
1440            pub led1: Led1,
1441            pub led2: Led2,
1442            pub led3: Led3,
1443            pub led4: Led4,
1444            pub led5: Led5,
1445            pub led6: Led6,
1446            pub led7: Led7,
1447            pub led8: Led8,
1448            pub led9: Led9,
1449            #[cfg(feature = "beaglev-fire-gpio-cape")]
1450            pub led10: Led10,
1451            pub led11: Led11,
1452        }
1453
1454        impl Leds {
1455            pub fn set_led(&mut self, led_num: usize, on: bool) {
1456                let pin_state = if on { PinState::High } else { PinState::Low };
1457                match led_num {
1458                    0 => self.led0.set_state(pin_state),
1459                    1 => self.led1.set_state(pin_state),
1460                    2 => self.led2.set_state(pin_state),
1461                    3 => self.led3.set_state(pin_state),
1462                    4 => self.led4.set_state(pin_state),
1463                    5 => self.led5.set_state(pin_state),
1464                    6 => self.led6.set_state(pin_state),
1465                    7 => self.led7.set_state(pin_state),
1466                    8 => self.led8.set_state(pin_state),
1467                    9 => self.led9.set_state(pin_state),
1468                    #[cfg(feature = "beaglev-fire-gpio-cape")]
1469                    10 => self.led10.set_state(pin_state),
1470                    #[cfg(not(feature = "beaglev-fire-gpio-cape"))]
1471                    10 => Ok(()),
1472                    11 => self.led11.set_state(pin_state),
1473                    _ => panic!("Invalid LED number: {}", led_num),
1474                }
1475                .unwrap();
1476            }
1477        }
1478
1479        impl crate::Peripheral for Leds {
1480            fn take() -> Option<Self> {
1481                let led0 = Led0::take();
1482                let led1 = Led1::take();
1483                let led2 = Led2::take();
1484                let led3 = Led3::take();
1485                let led4 = Led4::take();
1486                let led5 = Led5::take();
1487                let led6 = Led6::take();
1488                let led7 = Led7::take();
1489                let led8 = Led8::take();
1490                let led9 = Led9::take();
1491                #[cfg(feature = "beaglev-fire-gpio-cape")]
1492                let led10 = Led10::take();
1493                let led11 = Led11::take();
1494
1495                #[cfg(feature = "beaglev-fire-default-cape")]
1496                {
1497                    if let (
1498                        Some(led0),
1499                        Some(led1),
1500                        Some(led2),
1501                        Some(led3),
1502                        Some(led4),
1503                        Some(led5),
1504                        Some(led6),
1505                        Some(led7),
1506                        Some(led8),
1507                        Some(led9),
1508                        Some(led11),
1509                    ) = (
1510                        led0, led1, led2, led3, led4, led5, led6, led7, led8, led9, led11,
1511                    ) {
1512                        Some(Self {
1513                            led0,
1514                            led1,
1515                            led2,
1516                            led3,
1517                            led4,
1518                            led5,
1519                            led6,
1520                            led7,
1521                            led8,
1522                            led9,
1523                            led11,
1524                        })
1525                    } else {
1526                        None
1527                    }
1528                }
1529                #[cfg(feature = "beaglev-fire-gpio-cape")]
1530                {
1531                    if let (
1532                        Some(led0),
1533                        Some(led1),
1534                        Some(led2),
1535                        Some(led3),
1536                        Some(led4),
1537                        Some(led5),
1538                        Some(led6),
1539                        Some(led7),
1540                        Some(led8),
1541                        Some(led9),
1542                        Some(led10),
1543                        Some(led11),
1544                    ) = (
1545                        led0, led1, led2, led3, led4, led5, led6, led7, led8, led9, led10, led11,
1546                    ) {
1547                        Some(Self {
1548                            led0,
1549                            led1,
1550                            led2,
1551                            led3,
1552                            led4,
1553                            led5,
1554                            led6,
1555                            led7,
1556                            led8,
1557                            led9,
1558                            led10,
1559                            led11,
1560                        })
1561                    } else {
1562                        None
1563                    }
1564                }
1565            }
1566
1567            unsafe fn steal() -> Self {
1568                unsafe {
1569                    Self {
1570                        led0: Led0::steal(),
1571                        led1: Led1::steal(),
1572                        led2: Led2::steal(),
1573                        led3: Led3::steal(),
1574                        led4: Led4::steal(),
1575                        led5: Led5::steal(),
1576                        led6: Led6::steal(),
1577                        led7: Led7::steal(),
1578                        led8: Led8::steal(),
1579                        led9: Led9::steal(),
1580                        #[cfg(feature = "beaglev-fire-gpio-cape")]
1581                        led10: Led10::steal(),
1582                        led11: Led11::steal(),
1583                    }
1584                }
1585            }
1586        }
1587    }
1588
1589    #[cfg(feature = "beaglev-fire-gpio-cape")]
1590    pub use beaglev_fire_gpio_cape::*;
1591
1592    #[cfg(feature = "beaglev-fire-gpio-cape")]
1593    mod beaglev_fire_gpio_cape {
1594        use super::*;
1595        use crate::pac;
1596        impl_gpio_pin!(
1597            P8_13,
1598            GpioPeripheral::Mss(pac::GPIO2_LO),
1599            10,
1600            GPIO0_10_OR_GPIO2_10_INT
1601        );
1602
1603        impl_output_peripheral!(Led10, P8_13);
1604
1605        impl_gpio_pin!(
1606            P8_19,
1607            GpioPeripheral::Mss(pac::GPIO2_LO),
1608            16,
1609            GPIO1_2_OR_GPIO2_16_INT
1610        );
1611
1612        impl_gpio_pin!(P9_11, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 0, F2M_24_INT);
1613        impl_gpio_pin!(P9_13, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 2, F2M_26_INT);
1614        impl_gpio_pin!(P9_16, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 5, F2M_29_INT);
1615        impl_gpio_pin!(P9_17, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 6, F2M_30_INT);
1616        impl_gpio_pin!(P9_18, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 7, F2M_31_INT);
1617        impl_gpio_pin!(P9_21, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 8, F2M_32_INT);
1618        impl_gpio_pin!(P9_22, GpioPeripheral::FpgaCore(P9_CORE_GPIO), 9, F2M_33_INT);
1619        impl_gpio_pin!(
1620            P9_24,
1621            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1622            11,
1623            F2M_35_INT
1624        );
1625        impl_gpio_pin!(
1626            P9_26,
1627            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1628            13,
1629            F2M_37_INT
1630        );
1631        impl_gpio_pin!(
1632            P9_28,
1633            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1634            15,
1635            F2M_39_INT
1636        );
1637        impl_gpio_pin!(
1638            P9_29,
1639            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1640            16,
1641            F2M_40_INT
1642        );
1643        impl_gpio_pin!(
1644            P9_31,
1645            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1646            18,
1647            F2M_42_INT
1648        );
1649        impl_gpio_pin!(
1650            P9_41,
1651            GpioPeripheral::FpgaCore(P9_CORE_GPIO),
1652            19,
1653            F2M_44_INT
1654        );
1655    }
1656}