mpfs_hal_embassy/
sd.rs

1#[cfg(feature = "beaglev-fire")]
2pub use beaglev_fire::*;
3#[cfg(feature = "beaglev-fire")]
4mod beaglev_fire {
5    use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
6    use mpfs_hal::{gpio, pac, qspi, Peripheral};
7
8    pub fn init() -> (
9        SdChipSelect,
10        &'static mut Mutex<CriticalSectionRawMutex, qspi::Qspi>,
11    ) {
12        unsafe {
13            gpio::init();
14            pac::MSS_GPIO_init(pac::GPIO0_LO);
15            SdChipSelect::steal().pin.config_output();
16            SdDetect::steal()
17                .pin
18                .config_input(gpio::InterruptTrigger::default());
19        }
20        let qspi_bus = crate::qspi::qspi_bus();
21        (SdChipSelect::take().unwrap(), qspi_bus)
22    }
23
24    //---------------------------------------------------------------------------
25
26    static mut SDCS_TAKEN: bool = false;
27
28    pub struct SdChipSelect {
29        pin: gpio::Pin,
30    }
31
32    impl Peripheral for SdChipSelect {
33        fn take() -> Option<Self> {
34            critical_section::with(|_| unsafe {
35                if SDCS_TAKEN {
36                    None
37                } else {
38                    SDCS_TAKEN = true;
39                    Some(Self {
40                        pin: gpio::Pin::new(
41                            12,
42                            gpio::GpioPeripheral::Mss(pac::GPIO0_LO),
43                            255, // Never used
44                            255, // Never used
45                        ),
46                    })
47                }
48            })
49        }
50
51        unsafe fn steal() -> Self {
52            Self {
53                pin: gpio::Pin::new(
54                    12,
55                    gpio::GpioPeripheral::Mss(pac::GPIO0_LO),
56                    255, // Never used
57                    255, // Never used
58                ),
59            }
60        }
61    }
62
63    impl embedded_hal::digital::OutputPin for SdChipSelect {
64        fn set_low(&mut self) -> Result<(), Self::Error> {
65            self.pin.set_low();
66            Ok(())
67        }
68        fn set_high(&mut self) -> Result<(), Self::Error> {
69            unsafe {
70                pac::MSS_GPIO_set_output(pac::GPIO0_LO, pac::mss_gpio_id_MSS_GPIO_12, 1);
71            }
72            Ok(())
73        }
74    }
75
76    impl embedded_hal::digital::ErrorType for SdChipSelect {
77        type Error = core::convert::Infallible;
78    }
79
80    //---------------------------------------------------------------------------
81
82    use embedded_hal::digital::InputPin;
83    use embedded_hal_async::digital::Wait;
84
85    static mut SD_DETECT_TAKEN: bool = false;
86
87    pub struct SdDetect {
88        pin: gpio::Pin,
89    }
90
91    impl Peripheral for SdDetect {
92        fn take() -> Option<Self> {
93            critical_section::with(|_| unsafe {
94                if SD_DETECT_TAKEN {
95                    None
96                } else {
97                    SD_DETECT_TAKEN = true;
98                    Some(Self {
99                        pin: gpio::Pin::new(
100                            31,
101                            gpio::GpioPeripheral::Mss(pac::GPIO2_LO),
102                            gpio::SD_DETECT_INTERRUPT_IDX,
103                            255,
104                        ),
105                    })
106                }
107            })
108        }
109
110        unsafe fn steal() -> Self {
111            Self {
112                pin: gpio::Pin::new(
113                    31,
114                    gpio::GpioPeripheral::Mss(pac::GPIO2_LO),
115                    gpio::SD_DETECT_INTERRUPT_IDX,
116                    255,
117                ),
118            }
119        }
120    }
121
122    impl embedded_hal::digital::ErrorType for SdDetect {
123        type Error = core::convert::Infallible;
124    }
125
126    impl embedded_hal::digital::InputPin for SdDetect {
127        fn is_high(&mut self) -> Result<bool, Self::Error> {
128            Ok(self.pin.is_high())
129        }
130
131        fn is_low(&mut self) -> Result<bool, Self::Error> {
132            Ok(!self.pin.is_high())
133        }
134    }
135
136    impl embedded_hal_async::digital::Wait for SdDetect {
137        async fn wait_for_high(&mut self) -> Result<(), Self::Error> {
138            if !self.pin.is_high() {
139                gpio::InputFuture::new(self.pin, gpio::InterruptTrigger::LevelHigh).await
140            } else {
141                Ok(())
142            }
143        }
144
145        async fn wait_for_low(&mut self) -> Result<(), Self::Error> {
146            if self.pin.is_high() {
147                gpio::InputFuture::new(self.pin, gpio::InterruptTrigger::LevelLow).await
148            } else {
149                Ok(())
150            }
151        }
152
153        async fn wait_for_rising_edge(&mut self) -> Result<(), Self::Error> {
154            gpio::InputFuture::new(self.pin, gpio::InterruptTrigger::EdgePositive).await
155        }
156
157        async fn wait_for_falling_edge(&mut self) -> Result<(), Self::Error> {
158            gpio::InputFuture::new(self.pin, gpio::InterruptTrigger::EdgeNegative).await
159        }
160
161        async fn wait_for_any_edge(&mut self) -> Result<(), Self::Error> {
162            gpio::InputFuture::new(self.pin, gpio::InterruptTrigger::EdgeBoth).await
163        }
164    }
165
166    impl SdDetect {
167        pub fn is_inserted(&mut self) -> bool {
168            self.is_low().unwrap()
169        }
170
171        pub async fn wait_for_inserted(
172            &mut self,
173        ) -> Result<(), <Self as embedded_hal::digital::ErrorType>::Error> {
174            self.wait_for_low().await
175        }
176
177        pub async fn wait_for_removed(
178            &mut self,
179        ) -> Result<(), <Self as embedded_hal::digital::ErrorType>::Error> {
180            self.wait_for_high().await
181        }
182    }
183}