embedded_c_sdk_bind_hal/gpio/
port.rs

1use crate::ll_api::{ll_cmd::*, GpioInitFlag, PortNum};
2use core::marker::PhantomData;
3
4#[derive(Clone, Copy, PartialEq, Eq, Debug)]
5pub enum PortModeInput {
6    InFloating,
7    InPullUp,
8    InPullDown,
9}
10
11impl PortModeInput {
12    fn to_flag(&self) -> u32 {
13        match self {
14            PortModeInput::InFloating => GpioInitFlag::InFloating as u32,
15            PortModeInput::InPullUp => GpioInitFlag::InPU as u32,
16            PortModeInput::InPullDown => GpioInitFlag::InPD as u32,
17        }
18    }
19}
20
21pub enum PortModeOutput {
22    OutOD,
23    OutPP,
24}
25
26impl PortModeOutput {
27    fn to_flag(&self) -> u32 {
28        match self {
29            PortModeOutput::OutOD => GpioInitFlag::OutOD as u32,
30            PortModeOutput::OutPP => GpioInitFlag::OutPP as u32,
31        }
32    }
33}
34
35#[derive(Clone, Copy, PartialEq, Eq, Debug)]
36#[repr(C)]
37pub struct PortReg {
38    /// Port input data register
39    pub idr: *mut u16,
40    /// Port output data register
41    pub odr: *mut u16,
42    /// Port bit set register
43    pub bsr: *mut u16,
44    /// Port bit reset register
45    pub bcr: *mut u16,
46}
47
48unsafe impl Send for PortReg {}
49unsafe impl Sync for PortReg {}
50
51pub struct InputPort;
52pub struct OutputPort;
53
54#[derive(Clone, Copy, Debug)]
55pub struct Port<MODE> {
56    gpio: PortNum,
57    mask: u16,
58    regs: &'static PortReg,
59    _mode: PhantomData<MODE>,
60}
61
62impl Port<()> {
63    /// Creates a new GPIO port instance.
64    ///
65    /// # Arguments
66    /// * `gpio` - The port number.
67    /// * `mask` - A bit mask specifying which pins are part of this port.
68    ///
69    /// # Returns
70    /// A new `Port` instance with uninitialized mode.
71    pub fn new(gpio: PortNum, mask: u16, regs: &'static PortReg) -> Self {
72        let port = Port {
73            gpio,
74            mask,
75            regs,
76            _mode: PhantomData,
77        };
78
79        port
80    }
81
82    /// Converts the port to an input mode.
83    ///
84    /// # Arguments
85    /// * `mode` - The input mode configuration.
86    ///
87    /// # Returns
88    /// A new `Port` instance configured as an input port.
89    pub fn into_input(&self, mode: PortModeInput) -> Port<InputPort> {
90        let pin_mode = mode.to_flag();
91        self.port_init(pin_mode);
92
93        Port {
94            gpio: self.gpio,
95            mask: self.mask,
96            regs: self.regs,
97            _mode: PhantomData,
98        }
99    }
100
101    /// Converts the port to an output mode.
102    ///
103    /// # Arguments
104    /// * `mode` - The output mode configuration.
105    ///
106    /// # Returns
107    /// A new `Port` instance configured as an output port.
108    pub fn into_output(&self, mode: PortModeOutput) -> Port<OutputPort> {
109        let pin_mode = mode.to_flag();
110        self.port_init(pin_mode);
111
112        Port {
113            gpio: self.gpio,
114            mask: self.mask,
115            regs: self.regs,
116            _mode: PhantomData,
117        }
118    }
119
120    /// Initializes individual pins on the port according to the given mode.
121    ///
122    /// # Arguments
123    /// * `mode` - The initialization flag for the pins.
124    fn port_init(&self, mode: u32) {
125        for pin in 0..16 {
126            if (self.mask & (1 << pin)) > 0 {
127                ll_invoke_inner!(INVOKE_ID_GPIO_INIT, self.gpio, pin, mode);
128            }
129        }
130    }
131}
132
133impl Port<OutputPort> {
134    /// Sets the specified bits of the output register without checking bounds or validity.
135    ///
136    /// # Safety
137    /// This function must only be called when it is safe to modify the output register directly.
138    #[inline]
139    pub unsafe fn set_bits_uncheck(&mut self, bits: u16) {
140        core::ptr::write_volatile(self.regs.bsr, bits)
141    }
142
143    /// Clears the specified bits of the output register without checking bounds or validity.
144    ///
145    /// # Safety
146    /// This function must only be called when it is safe to modify the output register directly.
147    #[inline]
148    pub unsafe fn clr_bits_uncheck(&mut self, bits: u16) {
149        core::ptr::write_volatile(self.regs.bcr, bits);
150    }
151
152    /// Reads the current value of the output register without checking bounds or validity.
153    ///
154    /// # Safety
155    /// This function must only be called when it is safe to read from the output register directly.
156    #[inline]
157    pub unsafe fn read_output_bits_uncheck(&mut self) -> u16 {
158        core::ptr::read_volatile(self.regs.odr)
159    }
160
161    /// Writes a value to the output register without checking bounds or validity.
162    ///
163    /// # Safety
164    /// This function must only be called when it is safe to modify the output register directly.
165    #[inline]
166    pub unsafe fn write_bits_uncheck(&mut self, bits: u16) {
167        core::ptr::write_volatile(self.regs.odr, bits);
168    }
169
170    /// Sets the specified bits of the output register, applying the bit mask.
171    pub fn set_bits(&mut self, bits: u16) {
172        if !self.regs.bsr.is_null() {
173            unsafe { self.set_bits_uncheck(bits & self.mask) }
174        } else {
175            let read = self.read_output_bits();
176            self.write_bits(bits | read);
177        }
178    }
179
180    /// Clears the specified bits of the output register, applying the bit mask.
181    pub fn clr_bits(&mut self, bits: u16) {
182        if !self.regs.bcr.is_null() {
183            unsafe { self.clr_bits_uncheck(bits & self.mask) }
184        } else {
185            let read = self.read_output_bits();
186            self.write_bits(!bits & read);
187        }
188    }
189
190    /// Reads the current value of the output register, applying the bit mask.
191    pub fn read_output_bits(&mut self) -> u16 {
192        if !self.regs.odr.is_null() {
193            return unsafe { self.read_output_bits_uncheck() } & self.mask;
194        }
195        return 0;
196    }
197
198    /// Writes a value to the output register, applying the bit mask.
199    pub fn write_bits(&mut self, bits: u16) {
200        if !self.regs.odr.is_null() {
201            unsafe {
202                let read = self.read_output_bits_uncheck() & !self.mask;
203                self.write_bits_uncheck((bits & self.mask) | read);
204            }
205        }
206    }
207
208    /// Reads the current value of the input register, applying the bit mask.
209    pub fn read_input_bits(&mut self) -> u16 {
210        if !self.regs.idr.is_null() {
211            return unsafe { core::ptr::read_volatile(self.regs.idr) } & self.mask;
212        }
213        return 0;
214    }
215}
216
217impl Port<InputPort> {
218    /// Reads the current value of the input register without checking bounds or validity.
219    ///
220    /// # Safety
221    /// This function must only be called when it is safe to read from the input register directly.
222    #[inline]
223    pub unsafe fn read_input_bits_uncheck(&mut self) -> u16 {
224        core::ptr::read_volatile(self.regs.idr)
225    }
226
227    /// Reads the current value of the input register, applying the bit mask.
228    pub fn read_input_bits(&mut self) -> u16 {
229        if !self.regs.idr.is_null() {
230            return unsafe { self.read_input_bits_uncheck() } & self.mask;
231        }
232        return 0;
233    }
234}
235
236impl<MODE> embedded_hal::digital::ErrorType for Port<MODE> {
237    type Error = core::convert::Infallible;
238}
239
240impl embedded_hal::digital::OutputPin for Port<OutputPort> {
241    #[inline(always)]
242    fn set_high(&mut self) -> Result<(), Self::Error> {
243        self.set_bits(self.mask);
244        Ok(())
245    }
246
247    #[inline(always)]
248    fn set_low(&mut self) -> Result<(), Self::Error> {
249        self.clr_bits(self.mask);
250        Ok(())
251    }
252}
253
254impl embedded_hal::digital::StatefulOutputPin for Port<OutputPort> {
255    #[inline(always)]
256    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
257        Ok(self.read_output_bits() > 0)
258    }
259
260    #[inline(always)]
261    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
262        Ok(self.read_output_bits() == 0)
263    }
264}
265
266impl embedded_hal::digital::InputPin for Port<InputPort> {
267    #[inline(always)]
268    fn is_high(&mut self) -> Result<bool, Self::Error> {
269        Ok(self.read_input_bits() > 0)
270    }
271
272    #[inline(always)]
273    fn is_low(&mut self) -> Result<bool, Self::Error> {
274        Ok(self.read_input_bits() == 0)
275    }
276}
277
278impl embedded_hal::digital::InputPin for Port<OutputPort> {
279    #[inline(always)]
280    fn is_high(&mut self) -> Result<bool, Self::Error> {
281        Ok(self.read_input_bits() > 0)
282    }
283
284    #[inline(always)]
285    fn is_low(&mut self) -> Result<bool, Self::Error> {
286        Ok(self.read_input_bits() == 0)
287    }
288}