aboutsummaryrefslogtreecommitdiff
path: root/embassy-nxp
diff options
context:
space:
mode:
Diffstat (limited to 'embassy-nxp')
-rw-r--r--embassy-nxp/Cargo.toml6
-rw-r--r--embassy-nxp/src/chips/lpc55.rs70
-rw-r--r--embassy-nxp/src/gpio.rs357
-rw-r--r--embassy-nxp/src/gpio/lpc55.rs (renamed from embassy-nxp/src/pac_utils.rs)354
-rw-r--r--embassy-nxp/src/lib.rs90
-rw-r--r--embassy-nxp/src/pint.rs3
6 files changed, 451 insertions, 429 deletions
diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml
index 010607914..18e9d989c 100644
--- a/embassy-nxp/Cargo.toml
+++ b/embassy-nxp/Cargo.toml
@@ -22,5 +22,11 @@ rt = ["lpc55-pac?/rt"]
22## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. 22## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers.
23defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] 23defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"]
24 24
25## Reexport the PAC for the currently enabled chip at `embassy_nxp::pac` (unstable)
26unstable-pac = []
27# This is unstable because semver-minor (non-breaking) releases of embassy-nrf may major-bump (breaking) the PAC version.
28# If this is an issue for you, you're encouraged to directly depend on a fixed version of the PAC.
29# There are no plans to make this stable.
30
25#! ### Chip selection features 31#! ### Chip selection features
26lpc55 = ["lpc55-pac"] 32lpc55 = ["lpc55-pac"]
diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs
new file mode 100644
index 000000000..c95218af0
--- /dev/null
+++ b/embassy-nxp/src/chips/lpc55.rs
@@ -0,0 +1,70 @@
1pub use lpc55_pac as pac;
2
3embassy_hal_internal::peripherals! {
4 // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other
5 // peripheral types (e.g. I2C).
6 PIO0_0,
7 PIO0_1,
8 PIO0_2,
9 PIO0_3,
10 PIO0_4,
11 PIO0_5,
12 PIO0_6,
13 PIO0_7,
14 PIO0_8,
15 PIO0_9,
16 PIO0_10,
17 PIO0_11,
18 PIO0_12,
19 PIO0_13,
20 PIO0_14,
21 PIO0_15,
22 PIO0_16,
23 PIO0_17,
24 PIO0_18,
25 PIO0_19,
26 PIO0_20,
27 PIO0_21,
28 PIO0_22,
29 PIO0_23,
30 PIO0_24,
31 PIO0_25,
32 PIO0_26,
33 PIO0_27,
34 PIO0_28,
35 PIO0_29,
36 PIO0_30,
37 PIO0_31,
38 PIO1_0,
39 PIO1_1,
40 PIO1_2,
41 PIO1_3,
42 PIO1_4,
43 PIO1_5,
44 PIO1_6,
45 PIO1_7,
46 PIO1_8,
47 PIO1_9,
48 PIO1_10,
49 PIO1_11,
50 PIO1_12,
51 PIO1_13,
52 PIO1_14,
53 PIO1_15,
54 PIO1_16,
55 PIO1_17,
56 PIO1_18,
57 PIO1_19,
58 PIO1_20,
59 PIO1_21,
60 PIO1_22,
61 PIO1_23,
62 PIO1_24,
63 PIO1_25,
64 PIO1_26,
65 PIO1_27,
66 PIO1_28,
67 PIO1_29,
68 PIO1_30,
69 PIO1_31,
70}
diff --git a/embassy-nxp/src/gpio.rs b/embassy-nxp/src/gpio.rs
index c7c78ce61..809903d97 100644
--- a/embassy-nxp/src/gpio.rs
+++ b/embassy-nxp/src/gpio.rs
@@ -1,354 +1,5 @@
1use embassy_hal_internal::{impl_peripheral, PeripheralType}; 1//! General purpose input/output (GPIO) driver.
2 2
3use crate::pac_utils::*; 3#[cfg_attr(feature = "lpc55", path = "./gpio/lpc55.rs")]
4use crate::{peripherals, Peri}; 4mod inner;
5 5pub use inner::*;
6pub(crate) fn init() {
7 // Enable clocks for GPIO, PINT, and IOCON
8 syscon_reg()
9 .ahbclkctrl0
10 .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable());
11}
12
13/// The GPIO pin level for pins set on "Digital" mode.
14#[derive(Debug, Eq, PartialEq, Clone, Copy)]
15pub enum Level {
16 /// Logical low. Corresponds to 0V.
17 Low,
18 /// Logical high. Corresponds to VDD.
19 High,
20}
21
22/// Pull setting for a GPIO input set on "Digital" mode.
23#[derive(Debug, Clone, Copy, Eq, PartialEq)]
24pub enum Pull {
25 /// No pull.
26 None,
27 /// Internal pull-up resistor.
28 Up,
29 /// Internal pull-down resistor.
30 Down,
31}
32
33/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks.
34#[derive(Debug, Eq, PartialEq, Clone, Copy)]
35pub enum Bank {
36 Bank0 = 0,
37 Bank1 = 1,
38}
39
40/// GPIO output driver. Internally, this is a specialized [Flex] pin.
41pub struct Output<'d> {
42 pub(crate) pin: Flex<'d>,
43}
44
45impl<'d> Output<'d> {
46 /// Create GPIO output driver for a [Pin] with the provided [initial output](Level).
47 #[inline]
48 pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
49 let mut pin = Flex::new(pin);
50 pin.set_as_output();
51 let mut result = Self { pin };
52
53 match initial_output {
54 Level::High => result.set_high(),
55 Level::Low => result.set_low(),
56 };
57
58 result
59 }
60
61 pub fn set_high(&mut self) {
62 gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
63 }
64
65 pub fn set_low(&mut self) {
66 gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
67 }
68
69 pub fn toggle(&mut self) {
70 gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
71 }
72
73 /// Get the current output level of the pin. Note that the value returned by this function is
74 /// the voltage level reported by the pin, not the value set by the output driver.
75 pub fn level(&self) -> Level {
76 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits();
77 if bits & self.pin.bit() != 0 {
78 Level::High
79 } else {
80 Level::Low
81 }
82 }
83}
84
85/// GPIO input driver. Internally, this is a specialized [Flex] pin.
86pub struct Input<'d> {
87 pub(crate) pin: Flex<'d>,
88}
89
90impl<'d> Input<'d> {
91 /// Create GPIO output driver for a [Pin] with the provided [Pull].
92 #[inline]
93 pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
94 let mut pin = Flex::new(pin);
95 pin.set_as_input();
96 let mut result = Self { pin };
97 result.set_pull(pull);
98
99 result
100 }
101
102 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None].
103 pub fn set_pull(&mut self, pull: Pull) {
104 match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), {
105 register.modify(|_, w| match pull {
106 Pull::None => w.mode().inactive(),
107 Pull::Up => w.mode().pull_up(),
108 Pull::Down => w.mode().pull_down(),
109 });
110 });
111 }
112
113 /// Get the current input level of the pin.
114 pub fn read(&self) -> Level {
115 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits();
116 if bits & self.pin.bit() != 0 {
117 Level::High
118 } else {
119 Level::Low
120 }
121 }
122}
123
124/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a
125/// reference to a type-erased pin called ["AnyPin"](AnyPin).
126pub struct Flex<'d> {
127 pub(crate) pin: Peri<'d, AnyPin>,
128}
129
130impl<'d> Flex<'d> {
131 /// Wrap the pin in a `Flex`.
132 ///
133 /// Note: you cannot assume that the pin will be in Digital mode after this call.
134 #[inline]
135 pub fn new(pin: Peri<'d, impl Pin>) -> Self {
136 Self { pin: pin.into() }
137 }
138
139 /// Get the bank of this pin. See also [Bank].
140 ///
141 /// # Example
142 ///
143 /// ```
144 /// use embassy_nxp::gpio::{Bank, Flex};
145 ///
146 /// let p = embassy_nxp::init(Default::default());
147 /// let pin = Flex::new(p.PIO1_15);
148 ///
149 /// assert_eq!(pin.pin_bank(), Bank::Bank1);
150 /// ```
151 pub fn pin_bank(&self) -> Bank {
152 self.pin.pin_bank()
153 }
154
155 /// Get the number of this pin within its bank. See also [Bank].
156 ///
157 /// # Example
158 ///
159 /// ```
160 /// use embassy_nxp::gpio::Flex;
161 ///
162 /// let p = embassy_nxp::init(Default::default());
163 /// let pin = Flex::new(p.PIO1_15);
164 ///
165 /// assert_eq!(pin.pin_number(), 15 as u8);
166 /// ```
167 pub fn pin_number(&self) -> u8 {
168 self.pin.pin_number()
169 }
170
171 /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note:
172 /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc.
173 ///
174 /// # Example
175 ///
176 /// ```
177 /// use embassy_nxp::gpio::Flex;
178 ///
179 /// let p = embassy_nxp::init(Default::default());
180 /// let pin = Flex::new(p.PIO1_3);
181 ///
182 /// assert_eq!(pin.bit(), 0b0000_1000);
183 /// ```
184 pub fn bit(&self) -> u32 {
185 1 << self.pin.pin_number()
186 }
187
188 /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default
189 /// setting for pins is (usually) non-digital.
190 fn set_as_digital(&mut self) {
191 match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), {
192 register.modify(|_, w| w.digimode().digital());
193 });
194 }
195
196 /// Set the pin in output mode. This implies setting the pin to digital mode, which this
197 /// function handles itself.
198 pub fn set_as_output(&mut self) {
199 self.set_as_digital();
200 gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) })
201 }
202
203 pub fn set_as_input(&mut self) {
204 self.set_as_digital();
205 gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) })
206 }
207}
208
209/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate.
210pub(crate) trait SealedPin: Sized {
211 fn pin_bank(&self) -> Bank;
212 fn pin_number(&self) -> u8;
213}
214
215/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an
216/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the
217/// `embassy-nxp` crate due to the [SealedPin] trait.
218#[allow(private_bounds)]
219pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
220 /// Returns the pin number within a bank
221 #[inline]
222 fn pin(&self) -> u8 {
223 self.pin_number()
224 }
225
226 /// Returns the bank of this pin
227 #[inline]
228 fn bank(&self) -> Bank {
229 self.pin_bank()
230 }
231}
232
233/// Type-erased GPIO pin.
234pub struct AnyPin {
235 pin_bank: Bank,
236 pin_number: u8,
237}
238
239impl AnyPin {
240 /// Unsafely create a new type-erased pin.
241 ///
242 /// # Safety
243 ///
244 /// You must ensure that you’re only using one instance of this type at a time.
245 pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> {
246 Peri::new_unchecked(Self { pin_bank, pin_number })
247 }
248}
249
250impl_peripheral!(AnyPin);
251
252impl Pin for AnyPin {}
253impl SealedPin for AnyPin {
254 #[inline]
255 fn pin_bank(&self) -> Bank {
256 self.pin_bank
257 }
258
259 #[inline]
260 fn pin_number(&self) -> u8 {
261 self.pin_number
262 }
263}
264
265macro_rules! impl_pin {
266 ($name:ident, $bank:expr, $pin_num:expr) => {
267 impl Pin for peripherals::$name {}
268 impl SealedPin for peripherals::$name {
269 #[inline]
270 fn pin_bank(&self) -> Bank {
271 $bank
272 }
273
274 #[inline]
275 fn pin_number(&self) -> u8 {
276 $pin_num
277 }
278 }
279
280 impl From<peripherals::$name> for crate::gpio::AnyPin {
281 fn from(val: peripherals::$name) -> Self {
282 Self {
283 pin_bank: val.pin_bank(),
284 pin_number: val.pin_number(),
285 }
286 }
287 }
288 };
289}
290
291impl_pin!(PIO0_0, Bank::Bank0, 0);
292impl_pin!(PIO0_1, Bank::Bank0, 1);
293impl_pin!(PIO0_2, Bank::Bank0, 2);
294impl_pin!(PIO0_3, Bank::Bank0, 3);
295impl_pin!(PIO0_4, Bank::Bank0, 4);
296impl_pin!(PIO0_5, Bank::Bank0, 5);
297impl_pin!(PIO0_6, Bank::Bank0, 6);
298impl_pin!(PIO0_7, Bank::Bank0, 7);
299impl_pin!(PIO0_8, Bank::Bank0, 8);
300impl_pin!(PIO0_9, Bank::Bank0, 9);
301impl_pin!(PIO0_10, Bank::Bank0, 10);
302impl_pin!(PIO0_11, Bank::Bank0, 11);
303impl_pin!(PIO0_12, Bank::Bank0, 12);
304impl_pin!(PIO0_13, Bank::Bank0, 13);
305impl_pin!(PIO0_14, Bank::Bank0, 14);
306impl_pin!(PIO0_15, Bank::Bank0, 15);
307impl_pin!(PIO0_16, Bank::Bank0, 16);
308impl_pin!(PIO0_17, Bank::Bank0, 17);
309impl_pin!(PIO0_18, Bank::Bank0, 18);
310impl_pin!(PIO0_19, Bank::Bank0, 19);
311impl_pin!(PIO0_20, Bank::Bank0, 20);
312impl_pin!(PIO0_21, Bank::Bank0, 21);
313impl_pin!(PIO0_22, Bank::Bank0, 22);
314impl_pin!(PIO0_23, Bank::Bank0, 23);
315impl_pin!(PIO0_24, Bank::Bank0, 24);
316impl_pin!(PIO0_25, Bank::Bank0, 25);
317impl_pin!(PIO0_26, Bank::Bank0, 26);
318impl_pin!(PIO0_27, Bank::Bank0, 27);
319impl_pin!(PIO0_28, Bank::Bank0, 28);
320impl_pin!(PIO0_29, Bank::Bank0, 29);
321impl_pin!(PIO0_30, Bank::Bank0, 30);
322impl_pin!(PIO0_31, Bank::Bank0, 31);
323impl_pin!(PIO1_0, Bank::Bank1, 0);
324impl_pin!(PIO1_1, Bank::Bank1, 1);
325impl_pin!(PIO1_2, Bank::Bank1, 2);
326impl_pin!(PIO1_3, Bank::Bank1, 3);
327impl_pin!(PIO1_4, Bank::Bank1, 4);
328impl_pin!(PIO1_5, Bank::Bank1, 5);
329impl_pin!(PIO1_6, Bank::Bank1, 6);
330impl_pin!(PIO1_7, Bank::Bank1, 7);
331impl_pin!(PIO1_8, Bank::Bank1, 8);
332impl_pin!(PIO1_9, Bank::Bank1, 9);
333impl_pin!(PIO1_10, Bank::Bank1, 10);
334impl_pin!(PIO1_11, Bank::Bank1, 11);
335impl_pin!(PIO1_12, Bank::Bank1, 12);
336impl_pin!(PIO1_13, Bank::Bank1, 13);
337impl_pin!(PIO1_14, Bank::Bank1, 14);
338impl_pin!(PIO1_15, Bank::Bank1, 15);
339impl_pin!(PIO1_16, Bank::Bank1, 16);
340impl_pin!(PIO1_17, Bank::Bank1, 17);
341impl_pin!(PIO1_18, Bank::Bank1, 18);
342impl_pin!(PIO1_19, Bank::Bank1, 19);
343impl_pin!(PIO1_20, Bank::Bank1, 20);
344impl_pin!(PIO1_21, Bank::Bank1, 21);
345impl_pin!(PIO1_22, Bank::Bank1, 22);
346impl_pin!(PIO1_23, Bank::Bank1, 23);
347impl_pin!(PIO1_24, Bank::Bank1, 24);
348impl_pin!(PIO1_25, Bank::Bank1, 25);
349impl_pin!(PIO1_26, Bank::Bank1, 26);
350impl_pin!(PIO1_27, Bank::Bank1, 27);
351impl_pin!(PIO1_28, Bank::Bank1, 28);
352impl_pin!(PIO1_29, Bank::Bank1, 29);
353impl_pin!(PIO1_30, Bank::Bank1, 30);
354impl_pin!(PIO1_31, Bank::Bank1, 31);
diff --git a/embassy-nxp/src/pac_utils.rs b/embassy-nxp/src/gpio/lpc55.rs
index 86a807f6c..94cd8b7f8 100644
--- a/embassy-nxp/src/pac_utils.rs
+++ b/embassy-nxp/src/gpio/lpc55.rs
@@ -1,3 +1,266 @@
1use embassy_hal_internal::{impl_peripheral, PeripheralType};
2
3use crate::{peripherals, Peri};
4
5pub(crate) fn init() {
6 // Enable clocks for GPIO, PINT, and IOCON
7 syscon_reg()
8 .ahbclkctrl0
9 .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable());
10}
11
12/// The GPIO pin level for pins set on "Digital" mode.
13#[derive(Debug, Eq, PartialEq, Clone, Copy)]
14pub enum Level {
15 /// Logical low. Corresponds to 0V.
16 Low,
17 /// Logical high. Corresponds to VDD.
18 High,
19}
20
21/// Pull setting for a GPIO input set on "Digital" mode.
22#[derive(Debug, Clone, Copy, Eq, PartialEq)]
23pub enum Pull {
24 /// No pull.
25 None,
26 /// Internal pull-up resistor.
27 Up,
28 /// Internal pull-down resistor.
29 Down,
30}
31
32/// The LPC55 boards have two GPIO banks, each with 32 pins. This enum represents the two banks.
33#[derive(Debug, Eq, PartialEq, Clone, Copy)]
34pub enum Bank {
35 Bank0 = 0,
36 Bank1 = 1,
37}
38
39/// GPIO output driver. Internally, this is a specialized [Flex] pin.
40pub struct Output<'d> {
41 pub(crate) pin: Flex<'d>,
42}
43
44impl<'d> Output<'d> {
45 /// Create GPIO output driver for a [Pin] with the provided [initial output](Level).
46 #[inline]
47 pub fn new(pin: Peri<'d, impl Pin>, initial_output: Level) -> Self {
48 let mut pin = Flex::new(pin);
49 pin.set_as_output();
50 let mut result = Self { pin };
51
52 match initial_output {
53 Level::High => result.set_high(),
54 Level::Low => result.set_low(),
55 };
56
57 result
58 }
59
60 pub fn set_high(&mut self) {
61 gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
62 }
63
64 pub fn set_low(&mut self) {
65 gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
66 }
67
68 pub fn toggle(&mut self) {
69 gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) })
70 }
71
72 /// Get the current output level of the pin. Note that the value returned by this function is
73 /// the voltage level reported by the pin, not the value set by the output driver.
74 pub fn level(&self) -> Level {
75 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits();
76 if bits & self.pin.bit() != 0 {
77 Level::High
78 } else {
79 Level::Low
80 }
81 }
82}
83
84/// GPIO input driver. Internally, this is a specialized [Flex] pin.
85pub struct Input<'d> {
86 pub(crate) pin: Flex<'d>,
87}
88
89impl<'d> Input<'d> {
90 /// Create GPIO output driver for a [Pin] with the provided [Pull].
91 #[inline]
92 pub fn new(pin: Peri<'d, impl Pin>, pull: Pull) -> Self {
93 let mut pin = Flex::new(pin);
94 pin.set_as_input();
95 let mut result = Self { pin };
96 result.set_pull(pull);
97
98 result
99 }
100
101 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None].
102 pub fn set_pull(&mut self, pull: Pull) {
103 match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), {
104 register.modify(|_, w| match pull {
105 Pull::None => w.mode().inactive(),
106 Pull::Up => w.mode().pull_up(),
107 Pull::Down => w.mode().pull_down(),
108 });
109 });
110 }
111
112 /// Get the current input level of the pin.
113 pub fn read(&self) -> Level {
114 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits();
115 if bits & self.pin.bit() != 0 {
116 Level::High
117 } else {
118 Level::Low
119 }
120 }
121}
122
123/// A flexible GPIO (digital mode) pin whose mode is not yet determined. Under the hood, this is a
124/// reference to a type-erased pin called ["AnyPin"](AnyPin).
125pub struct Flex<'d> {
126 pub(crate) pin: Peri<'d, AnyPin>,
127}
128
129impl<'d> Flex<'d> {
130 /// Wrap the pin in a `Flex`.
131 ///
132 /// Note: you cannot assume that the pin will be in Digital mode after this call.
133 #[inline]
134 pub fn new(pin: Peri<'d, impl Pin>) -> Self {
135 Self { pin: pin.into() }
136 }
137
138 /// Get the bank of this pin. See also [Bank].
139 ///
140 /// # Example
141 ///
142 /// ```
143 /// use embassy_nxp::gpio::{Bank, Flex};
144 ///
145 /// let p = embassy_nxp::init(Default::default());
146 /// let pin = Flex::new(p.PIO1_15);
147 ///
148 /// assert_eq!(pin.pin_bank(), Bank::Bank1);
149 /// ```
150 pub fn pin_bank(&self) -> Bank {
151 self.pin.pin_bank()
152 }
153
154 /// Get the number of this pin within its bank. See also [Bank].
155 ///
156 /// # Example
157 ///
158 /// ```
159 /// use embassy_nxp::gpio::Flex;
160 ///
161 /// let p = embassy_nxp::init(Default::default());
162 /// let pin = Flex::new(p.PIO1_15);
163 ///
164 /// assert_eq!(pin.pin_number(), 15 as u8);
165 /// ```
166 pub fn pin_number(&self) -> u8 {
167 self.pin.pin_number()
168 }
169
170 /// Get the bit mask for this pin. Useful for setting or clearing bits in a register. Note:
171 /// PIOx_0 is bit 0, PIOx_1 is bit 1, etc.
172 ///
173 /// # Example
174 ///
175 /// ```
176 /// use embassy_nxp::gpio::Flex;
177 ///
178 /// let p = embassy_nxp::init(Default::default());
179 /// let pin = Flex::new(p.PIO1_3);
180 ///
181 /// assert_eq!(pin.bit(), 0b0000_1000);
182 /// ```
183 pub fn bit(&self) -> u32 {
184 1 << self.pin.pin_number()
185 }
186
187 /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default
188 /// setting for pins is (usually) non-digital.
189 fn set_as_digital(&mut self) {
190 match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), {
191 register.modify(|_, w| w.digimode().digital());
192 });
193 }
194
195 /// Set the pin in output mode. This implies setting the pin to digital mode, which this
196 /// function handles itself.
197 pub fn set_as_output(&mut self) {
198 self.set_as_digital();
199 gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) })
200 }
201
202 pub fn set_as_input(&mut self) {
203 self.set_as_digital();
204 gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) })
205 }
206}
207
208/// Sealed trait for pins. This trait is sealed and cannot be implemented outside of this crate.
209pub(crate) trait SealedPin: Sized {
210 fn pin_bank(&self) -> Bank;
211 fn pin_number(&self) -> u8;
212}
213
214/// Interface for a Pin that can be configured by an [Input] or [Output] driver, or converted to an
215/// [AnyPin]. By default, this trait is sealed and cannot be implemented outside of the
216/// `embassy-nxp` crate due to the [SealedPin] trait.
217#[allow(private_bounds)]
218pub trait Pin: PeripheralType + Into<AnyPin> + SealedPin + Sized + 'static {
219 /// Returns the pin number within a bank
220 #[inline]
221 fn pin(&self) -> u8 {
222 self.pin_number()
223 }
224
225 /// Returns the bank of this pin
226 #[inline]
227 fn bank(&self) -> Bank {
228 self.pin_bank()
229 }
230}
231
232/// Type-erased GPIO pin.
233pub struct AnyPin {
234 pin_bank: Bank,
235 pin_number: u8,
236}
237
238impl AnyPin {
239 /// Unsafely create a new type-erased pin.
240 ///
241 /// # Safety
242 ///
243 /// You must ensure that you’re only using one instance of this type at a time.
244 pub unsafe fn steal(pin_bank: Bank, pin_number: u8) -> Peri<'static, Self> {
245 Peri::new_unchecked(Self { pin_bank, pin_number })
246 }
247}
248
249impl_peripheral!(AnyPin);
250
251impl Pin for AnyPin {}
252impl SealedPin for AnyPin {
253 #[inline]
254 fn pin_bank(&self) -> Bank {
255 self.pin_bank
256 }
257
258 #[inline]
259 fn pin_number(&self) -> u8 {
260 self.pin_number
261 }
262}
263
1/// Get the GPIO register block. This is used to configure all GPIO pins. 264/// Get the GPIO register block. This is used to configure all GPIO pins.
2/// 265///
3/// # Safety 266/// # Safety
@@ -321,3 +584,94 @@ macro_rules! match_iocon {
321} 584}
322 585
323pub(crate) use match_iocon; 586pub(crate) use match_iocon;
587
588macro_rules! impl_pin {
589 ($name:ident, $bank:expr, $pin_num:expr) => {
590 impl Pin for peripherals::$name {}
591 impl SealedPin for peripherals::$name {
592 #[inline]
593 fn pin_bank(&self) -> Bank {
594 $bank
595 }
596
597 #[inline]
598 fn pin_number(&self) -> u8 {
599 $pin_num
600 }
601 }
602
603 impl From<peripherals::$name> for crate::gpio::AnyPin {
604 fn from(val: peripherals::$name) -> Self {
605 Self {
606 pin_bank: val.pin_bank(),
607 pin_number: val.pin_number(),
608 }
609 }
610 }
611 };
612}
613
614impl_pin!(PIO0_0, Bank::Bank0, 0);
615impl_pin!(PIO0_1, Bank::Bank0, 1);
616impl_pin!(PIO0_2, Bank::Bank0, 2);
617impl_pin!(PIO0_3, Bank::Bank0, 3);
618impl_pin!(PIO0_4, Bank::Bank0, 4);
619impl_pin!(PIO0_5, Bank::Bank0, 5);
620impl_pin!(PIO0_6, Bank::Bank0, 6);
621impl_pin!(PIO0_7, Bank::Bank0, 7);
622impl_pin!(PIO0_8, Bank::Bank0, 8);
623impl_pin!(PIO0_9, Bank::Bank0, 9);
624impl_pin!(PIO0_10, Bank::Bank0, 10);
625impl_pin!(PIO0_11, Bank::Bank0, 11);
626impl_pin!(PIO0_12, Bank::Bank0, 12);
627impl_pin!(PIO0_13, Bank::Bank0, 13);
628impl_pin!(PIO0_14, Bank::Bank0, 14);
629impl_pin!(PIO0_15, Bank::Bank0, 15);
630impl_pin!(PIO0_16, Bank::Bank0, 16);
631impl_pin!(PIO0_17, Bank::Bank0, 17);
632impl_pin!(PIO0_18, Bank::Bank0, 18);
633impl_pin!(PIO0_19, Bank::Bank0, 19);
634impl_pin!(PIO0_20, Bank::Bank0, 20);
635impl_pin!(PIO0_21, Bank::Bank0, 21);
636impl_pin!(PIO0_22, Bank::Bank0, 22);
637impl_pin!(PIO0_23, Bank::Bank0, 23);
638impl_pin!(PIO0_24, Bank::Bank0, 24);
639impl_pin!(PIO0_25, Bank::Bank0, 25);
640impl_pin!(PIO0_26, Bank::Bank0, 26);
641impl_pin!(PIO0_27, Bank::Bank0, 27);
642impl_pin!(PIO0_28, Bank::Bank0, 28);
643impl_pin!(PIO0_29, Bank::Bank0, 29);
644impl_pin!(PIO0_30, Bank::Bank0, 30);
645impl_pin!(PIO0_31, Bank::Bank0, 31);
646impl_pin!(PIO1_0, Bank::Bank1, 0);
647impl_pin!(PIO1_1, Bank::Bank1, 1);
648impl_pin!(PIO1_2, Bank::Bank1, 2);
649impl_pin!(PIO1_3, Bank::Bank1, 3);
650impl_pin!(PIO1_4, Bank::Bank1, 4);
651impl_pin!(PIO1_5, Bank::Bank1, 5);
652impl_pin!(PIO1_6, Bank::Bank1, 6);
653impl_pin!(PIO1_7, Bank::Bank1, 7);
654impl_pin!(PIO1_8, Bank::Bank1, 8);
655impl_pin!(PIO1_9, Bank::Bank1, 9);
656impl_pin!(PIO1_10, Bank::Bank1, 10);
657impl_pin!(PIO1_11, Bank::Bank1, 11);
658impl_pin!(PIO1_12, Bank::Bank1, 12);
659impl_pin!(PIO1_13, Bank::Bank1, 13);
660impl_pin!(PIO1_14, Bank::Bank1, 14);
661impl_pin!(PIO1_15, Bank::Bank1, 15);
662impl_pin!(PIO1_16, Bank::Bank1, 16);
663impl_pin!(PIO1_17, Bank::Bank1, 17);
664impl_pin!(PIO1_18, Bank::Bank1, 18);
665impl_pin!(PIO1_19, Bank::Bank1, 19);
666impl_pin!(PIO1_20, Bank::Bank1, 20);
667impl_pin!(PIO1_21, Bank::Bank1, 21);
668impl_pin!(PIO1_22, Bank::Bank1, 22);
669impl_pin!(PIO1_23, Bank::Bank1, 23);
670impl_pin!(PIO1_24, Bank::Bank1, 24);
671impl_pin!(PIO1_25, Bank::Bank1, 25);
672impl_pin!(PIO1_26, Bank::Bank1, 26);
673impl_pin!(PIO1_27, Bank::Bank1, 27);
674impl_pin!(PIO1_28, Bank::Bank1, 28);
675impl_pin!(PIO1_29, Bank::Bank1, 29);
676impl_pin!(PIO1_30, Bank::Bank1, 30);
677impl_pin!(PIO1_31, Bank::Bank1, 31);
diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs
index ad2056c06..433aca9e0 100644
--- a/embassy-nxp/src/lib.rs
+++ b/embassy-nxp/src/lib.rs
@@ -1,11 +1,19 @@
1#![no_std] 1#![no_std]
2 2
3pub mod gpio; 3pub mod gpio;
4mod pac_utils; 4#[cfg(feature = "lpc55")]
5pub mod pint; 5pub mod pint;
6 6
7pub use embassy_hal_internal::Peri; 7// This mod MUST go last, so that it sees all the `impl_foo!` macros
8pub use lpc55_pac as pac; 8#[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")]
9mod chip;
10
11#[cfg(feature = "unstable-pac")]
12pub use chip::pac;
13#[cfg(not(feature = "unstable-pac"))]
14pub(crate) use chip::pac;
15pub use chip::{peripherals, Peripherals};
16pub use embassy_hal_internal::{Peri, PeripheralType};
9 17
10/// Initialize the `embassy-nxp` HAL with the provided configuration. 18/// Initialize the `embassy-nxp` HAL with the provided configuration.
11/// 19///
@@ -13,81 +21,15 @@ pub use lpc55_pac as pac;
13/// 21///
14/// This should only be called once and at startup, otherwise it panics. 22/// This should only be called once and at startup, otherwise it panics.
15pub fn init(_config: config::Config) -> Peripherals { 23pub fn init(_config: config::Config) -> Peripherals {
16 gpio::init(); 24 #[cfg(feature = "lpc55")]
17 pint::init(); 25 {
26 gpio::init();
27 pint::init();
28 }
18 29
19 crate::Peripherals::take() 30 crate::Peripherals::take()
20} 31}
21 32
22embassy_hal_internal::peripherals! {
23 // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other
24 // peripheral types (e.g. I2C).
25 PIO0_0,
26 PIO0_1,
27 PIO0_2,
28 PIO0_3,
29 PIO0_4,
30 PIO0_5,
31 PIO0_6,
32 PIO0_7,
33 PIO0_8,
34 PIO0_9,
35 PIO0_10,
36 PIO0_11,
37 PIO0_12,
38 PIO0_13,
39 PIO0_14,
40 PIO0_15,
41 PIO0_16,
42 PIO0_17,
43 PIO0_18,
44 PIO0_19,
45 PIO0_20,
46 PIO0_21,
47 PIO0_22,
48 PIO0_23,
49 PIO0_24,
50 PIO0_25,
51 PIO0_26,
52 PIO0_27,
53 PIO0_28,
54 PIO0_29,
55 PIO0_30,
56 PIO0_31,
57 PIO1_0,
58 PIO1_1,
59 PIO1_2,
60 PIO1_3,
61 PIO1_4,
62 PIO1_5,
63 PIO1_6,
64 PIO1_7,
65 PIO1_8,
66 PIO1_9,
67 PIO1_10,
68 PIO1_11,
69 PIO1_12,
70 PIO1_13,
71 PIO1_14,
72 PIO1_15,
73 PIO1_16,
74 PIO1_17,
75 PIO1_18,
76 PIO1_19,
77 PIO1_20,
78 PIO1_21,
79 PIO1_22,
80 PIO1_23,
81 PIO1_24,
82 PIO1_25,
83 PIO1_26,
84 PIO1_27,
85 PIO1_28,
86 PIO1_29,
87 PIO1_30,
88 PIO1_31,
89}
90
91/// HAL configuration for the NXP board. 33/// HAL configuration for the NXP board.
92pub mod config { 34pub mod config {
93 #[derive(Default)] 35 #[derive(Default)]
diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs
index 8d6dc1277..dc117e7e3 100644
--- a/embassy-nxp/src/pint.rs
+++ b/embassy-nxp/src/pint.rs
@@ -7,9 +7,8 @@ use core::task::{Context, Poll};
7use critical_section::Mutex; 7use critical_section::Mutex;
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9 9
10use crate::gpio::{self, AnyPin, Level, SealedPin}; 10use crate::gpio::{self, inputmux_reg, pint_reg, syscon_reg, AnyPin, Level, SealedPin};
11use crate::pac::interrupt; 11use crate::pac::interrupt;
12use crate::pac_utils::*;
13use crate::Peri; 12use crate::Peri;
14 13
15struct PinInterrupt { 14struct PinInterrupt {