corstone300_hal/
shield.rs

1// Copyright 2022 Arm Limited and/or its affiliates <open-source-office@arm.com>
2//
3// SPDX-License-Identifier: MIT
4
5use core::marker::PhantomData;
6
7use crate::pac::{gpio0, GPIO0_SECURE, GPIO1_SECURE, GPIO2_SECURE};
8
9pub trait PinMode {}
10
11pub enum Gpio {}
12impl PinMode for Gpio {}
13pub enum Uart {}
14impl PinMode for Uart {}
15pub enum Spi {}
16impl PinMode for Spi {}
17pub enum I2c {}
18impl PinMode for I2c {}
19
20pub struct Pin<const SHIELD_ID: usize, const PIN_ID: usize, Mode: PinMode> {
21    mode: PhantomData<Mode>,
22}
23impl<const SHIELD_ID: usize, const PIN_ID: usize, Mode: PinMode> Pin<SHIELD_ID, PIN_ID, Mode> {
24    fn block_and_mask(&self) -> (*const gpio0::RegisterBlock, u32) {
25        match (SHIELD_ID, PIN_ID) {
26            (0, 16) => (GPIO2_SECURE::PTR, 0b0001),
27            (0, 17) => (GPIO2_SECURE::PTR, 0b0010),
28            (1, 16) => (GPIO2_SECURE::PTR, 0b0100),
29            (1, 17) => (GPIO2_SECURE::PTR, 0b1000),
30            (0, pid) => (GPIO0_SECURE::PTR, 1 << pid),
31            (1, pid) => (GPIO1_SECURE::PTR, 1 << pid),
32            (_, _) => unreachable!(),
33        }
34    }
35}
36
37pub enum Pins {}
38impl Pins {
39    #[allow(clippy::type_complexity)]
40    pub fn get_pins_secure(
41        gpio0: GPIO0_SECURE,
42        gpio1: GPIO1_SECURE,
43        gpio2: GPIO2_SECURE,
44    ) -> (
45        Pin<0, 0, Gpio>,
46        Pin<0, 1, Gpio>,
47        Pin<0, 2, Gpio>,
48        Pin<0, 3, Gpio>,
49        Pin<0, 4, Gpio>,
50        Pin<0, 5, Gpio>,
51        Pin<0, 6, Gpio>,
52        Pin<0, 7, Gpio>,
53        Pin<0, 8, Gpio>,
54        Pin<0, 9, Gpio>,
55        Pin<0, 10, Gpio>,
56        Pin<0, 11, Gpio>,
57        Pin<0, 12, Gpio>,
58        Pin<0, 13, Gpio>,
59        Pin<0, 14, Gpio>,
60        Pin<0, 15, Gpio>,
61        Pin<0, 16, Gpio>,
62        Pin<0, 17, Gpio>,
63        Pin<1, 0, Gpio>,
64        Pin<1, 1, Gpio>,
65        Pin<1, 2, Gpio>,
66        Pin<1, 3, Gpio>,
67        Pin<1, 4, Gpio>,
68        Pin<1, 5, Gpio>,
69        Pin<1, 6, Gpio>,
70        Pin<1, 7, Gpio>,
71        Pin<1, 8, Gpio>,
72        Pin<1, 9, Gpio>,
73        Pin<1, 10, Gpio>,
74        Pin<1, 11, Gpio>,
75        Pin<1, 12, Gpio>,
76        Pin<1, 13, Gpio>,
77        Pin<1, 14, Gpio>,
78        Pin<1, 15, Gpio>,
79        Pin<1, 16, Gpio>,
80        Pin<1, 17, Gpio>,
81    ) {
82        // The pin types directly access the GPIO register from the GPIO block type.
83        // The pin types are responsible of ensuring their operations are atomic and won't colide
84        // with others.
85        let _ = (gpio0, gpio1, gpio2);
86        (
87            Pin { mode: PhantomData },
88            Pin { mode: PhantomData },
89            Pin { mode: PhantomData },
90            Pin { mode: PhantomData },
91            Pin { mode: PhantomData },
92            Pin { mode: PhantomData },
93            Pin { mode: PhantomData },
94            Pin { mode: PhantomData },
95            Pin { mode: PhantomData },
96            Pin { mode: PhantomData },
97            Pin { mode: PhantomData },
98            Pin { mode: PhantomData },
99            Pin { mode: PhantomData },
100            Pin { mode: PhantomData },
101            Pin { mode: PhantomData },
102            Pin { mode: PhantomData },
103            Pin { mode: PhantomData },
104            Pin { mode: PhantomData },
105            Pin { mode: PhantomData },
106            Pin { mode: PhantomData },
107            Pin { mode: PhantomData },
108            Pin { mode: PhantomData },
109            Pin { mode: PhantomData },
110            Pin { mode: PhantomData },
111            Pin { mode: PhantomData },
112            Pin { mode: PhantomData },
113            Pin { mode: PhantomData },
114            Pin { mode: PhantomData },
115            Pin { mode: PhantomData },
116            Pin { mode: PhantomData },
117            Pin { mode: PhantomData },
118            Pin { mode: PhantomData },
119            Pin { mode: PhantomData },
120            Pin { mode: PhantomData },
121            Pin { mode: PhantomData },
122            Pin { mode: PhantomData },
123        )
124    }
125}
126
127macro_rules! impl_into_mode {
128    ($(($shield:expr, $pin:expr) => $mode:ident)*) => {
129        $(
130            impl Pin<$shield, $pin, Gpio> {
131                #[doc = concat!("Turns the current GPIO pin into a ", stringify!($mode), " pin")]
132                pub fn into_mode(self) -> Pin<$shield, $pin, $mode> {
133                    let (block, mask) = self.block_and_mask();
134                    unsafe { &*block }.altfuncset.write(|w|unsafe { w.bits(mask) });
135                    Pin {
136                        mode: PhantomData
137                    }
138                }
139            }
140            impl Pin<$shield, $pin, $mode> {
141                #[doc = concat!("Turns the current ", stringify!($mode), " pin into a GPIO pin")]
142                pub fn into_mode(self) -> Pin<$shield, $pin, Gpio> {
143                    let (block, mask) = self.block_and_mask();
144                    unsafe { &*block }.altfuncclr.write(|w|unsafe { w.bits(mask) });
145                    Pin {
146                        mode: PhantomData
147                    }
148                }
149            }
150         )*
151    };
152}
153
154impl_into_mode! {
155    (0, 0) => Uart
156    (0, 1) => Uart
157    (0, 10) => Spi
158    (0, 11) => Spi
159    (0, 12) => Spi
160    (0, 13) => Spi
161    (0, 14) => I2c
162    (0, 15) => I2c
163    (1, 0) => Uart
164    (1, 1) => Uart
165    (1, 10) => Spi
166    (1, 11) => Spi
167    (1, 12) => Spi
168    (1, 13) => Spi
169    (1, 14) => I2c
170    (1, 15) => I2c
171}
172
173impl<const SHIELD_ID: usize, const PIN_ID: usize> embedded_hal::digital::v2::InputPin
174    for Pin<SHIELD_ID, PIN_ID, Gpio>
175{
176    type Error = core::convert::Infallible;
177
178    fn is_high(&self) -> Result<bool, core::convert::Infallible> {
179        let (block, mask) = self.block_and_mask();
180        Ok((unsafe { &*block }.data.read().bits() & mask) != 0)
181    }
182
183    fn is_low(&self) -> Result<bool, core::convert::Infallible> {
184        self.is_high().map(|b| !b)
185    }
186}