aboutsummaryrefslogtreecommitdiff
path: root/embassy-nxp/src
diff options
context:
space:
mode:
authorRoi Bachynskyi <[email protected]>2025-08-30 14:25:25 +0300
committerRoi Bachynskyi <[email protected]>2025-09-12 11:07:02 +0300
commit19bb3668669710dbd1d17dc5fb0dee6d915f012e (patch)
tree73e04c1468a4d85e69d9d3623b33c79c44dff015 /embassy-nxp/src
parent59461ba75ab674073b11f7612627c9e2c6426b93 (diff)
lpc55: gpio rewritten
Diffstat (limited to 'embassy-nxp/src')
-rw-r--r--embassy-nxp/src/chips/lpc55.rs2
-rw-r--r--embassy-nxp/src/gpio/lpc55.rs360
2 files changed, 41 insertions, 321 deletions
diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs
index e168ced00..711bff3e7 100644
--- a/embassy-nxp/src/chips/lpc55.rs
+++ b/embassy-nxp/src/chips/lpc55.rs
@@ -1,4 +1,4 @@
1pub use lpc55_pac as pac; 1pub use nxp_pac as pac;
2 2
3embassy_hal_internal::peripherals! { 3embassy_hal_internal::peripherals! {
4 // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other 4 // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other
diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs
index 8f407bb3a..36ea99d21 100644
--- a/embassy-nxp/src/gpio/lpc55.rs
+++ b/embassy-nxp/src/gpio/lpc55.rs
@@ -1,12 +1,17 @@
1use embassy_hal_internal::{impl_peripheral, PeripheralType}; 1use embassy_hal_internal::{impl_peripheral, PeripheralType};
2 2
3use crate::pac::iocon::vals::{PioDigimode, PioMode};
4use crate::pac::{GPIO, IOCON, SYSCON};
3use crate::{peripherals, Peri}; 5use crate::{peripherals, Peri};
4 6
5pub(crate) fn init() { 7pub(crate) fn init() {
6 // Enable clocks for GPIO, PINT, and IOCON 8 // Enable clocks for GPIO, PINT, and IOCON
7 syscon_reg() 9 SYSCON.ahbclkctrl0().modify(|w| {
8 .ahbclkctrl0 10 w.set_gpio0(true);
9 .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); 11 w.set_gpio1(true);
12 w.set_mux(true);
13 w.set_iocon(true);
14 });
10 info!("GPIO initialized"); 15 info!("GPIO initialized");
11} 16}
12 17
@@ -59,21 +64,24 @@ impl<'d> Output<'d> {
59 } 64 }
60 65
61 pub fn set_high(&mut self) { 66 pub fn set_high(&mut self) {
62 gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) 67 GPIO.set(self.pin.pin_bank() as usize)
68 .write(|w| w.set_setp(self.pin.bit()));
63 } 69 }
64 70
65 pub fn set_low(&mut self) { 71 pub fn set_low(&mut self) {
66 gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) 72 GPIO.clr(self.pin.pin_bank() as usize)
73 .write(|w| w.set_clrp(self.pin.bit()));
67 } 74 }
68 75
69 pub fn toggle(&mut self) { 76 pub fn toggle(&mut self) {
70 gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) 77 GPIO.not(self.pin.pin_bank() as usize)
78 .write(|w| w.set_notp(self.pin.bit()));
71 } 79 }
72 80
73 /// Get the current output level of the pin. Note that the value returned by this function is 81 /// 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. 82 /// the voltage level reported by the pin, not the value set by the output driver.
75 pub fn level(&self) -> Level { 83 pub fn level(&self) -> Level {
76 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); 84 let bits = GPIO.pin(self.pin.pin_bank() as usize).read().port();
77 if bits & self.pin.bit() != 0 { 85 if bits & self.pin.bit() != 0 {
78 Level::High 86 Level::High
79 } else { 87 } else {
@@ -101,18 +109,18 @@ impl<'d> Input<'d> {
101 109
102 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. 110 /// Set the pull configuration for the pin. To disable the pull, use [Pull::None].
103 pub fn set_pull(&mut self, pull: Pull) { 111 pub fn set_pull(&mut self, pull: Pull) {
104 match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { 112 match_iocon!(register, self.pin.pin_bank(), self.pin.pin_number(), {
105 register.modify(|_, w| match pull { 113 register.modify(|w| match pull {
106 Pull::None => w.mode().inactive(), 114 Pull::None => w.set_mode(PioMode::INACTIVE),
107 Pull::Up => w.mode().pull_up(), 115 Pull::Up => w.set_mode(PioMode::PULL_UP),
108 Pull::Down => w.mode().pull_down(), 116 Pull::Down => w.set_mode(PioMode::PULL_DOWN),
109 }); 117 });
110 }); 118 });
111 } 119 }
112 120
113 /// Get the current input level of the pin. 121 /// Get the current input level of the pin.
114 pub fn read(&self) -> Level { 122 pub fn read(&self) -> Level {
115 let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); 123 let bits = GPIO.pin(self.pin.pin_bank() as usize).read().port();
116 if bits & self.pin.bit() != 0 { 124 if bits & self.pin.bit() != 0 {
117 Level::High 125 Level::High
118 } else { 126 } else {
@@ -188,8 +196,8 @@ impl<'d> Flex<'d> {
188 /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default 196 /// 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. 197 /// setting for pins is (usually) non-digital.
190 fn set_as_digital(&mut self) { 198 fn set_as_digital(&mut self) {
191 match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { 199 match_iocon!(register, self.pin_bank(), self.pin_number(), {
192 register.modify(|_, w| w.digimode().digital()); 200 register.modify(|w| w.set_digimode(PioDigimode::DIGITAL));
193 }); 201 });
194 } 202 }
195 203
@@ -197,12 +205,14 @@ impl<'d> Flex<'d> {
197 /// function handles itself. 205 /// function handles itself.
198 pub fn set_as_output(&mut self) { 206 pub fn set_as_output(&mut self) {
199 self.set_as_digital(); 207 self.set_as_digital();
200 gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) 208 GPIO.dirset(self.pin.pin_bank() as usize)
209 .write(|w| w.set_dirsetp(self.bit()))
201 } 210 }
202 211
203 pub fn set_as_input(&mut self) { 212 pub fn set_as_input(&mut self) {
204 self.set_as_digital(); 213 self.set_as_digital();
205 gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) 214 GPIO.dirclr(self.pin.pin_bank() as usize)
215 .write(|w| w.set_dirclrp(self.bit()))
206 } 216 }
207} 217}
208 218
@@ -262,52 +272,6 @@ impl SealedPin for AnyPin {
262 } 272 }
263} 273}
264 274
265/// Get the GPIO register block. This is used to configure all GPIO pins.
266///
267/// # Safety
268/// Due to the type system of peripherals, access to the settings of a single pin is possible only
269/// by a single thread at a time. Read/Write operations on a single registers are NOT atomic. You
270/// must ensure that the GPIO registers are not accessed concurrently by multiple threads.
271pub(crate) fn gpio_reg() -> &'static lpc55_pac::gpio::RegisterBlock {
272 unsafe { &*lpc55_pac::GPIO::ptr() }
273}
274
275/// Get the IOCON register block.
276///
277/// # Safety
278/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
279/// registers are not accessed concurrently by multiple threads.
280pub(crate) fn iocon_reg() -> &'static lpc55_pac::iocon::RegisterBlock {
281 unsafe { &*lpc55_pac::IOCON::ptr() }
282}
283
284/// Get the INPUTMUX register block.
285///
286/// # Safety
287/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
288/// registers are not accessed concurrently by multiple threads.
289pub(crate) fn inputmux_reg() -> &'static lpc55_pac::inputmux::RegisterBlock {
290 unsafe { &*lpc55_pac::INPUTMUX::ptr() }
291}
292
293/// Get the SYSCON register block.
294///
295/// # Safety
296/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
297/// registers are not accessed concurrently by multiple threads.
298pub(crate) fn syscon_reg() -> &'static lpc55_pac::syscon::RegisterBlock {
299 unsafe { &*lpc55_pac::SYSCON::ptr() }
300}
301
302/// Get the PINT register block.
303///
304/// # Safety
305/// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO
306/// registers are not accessed concurrently by multiple threads.
307pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock {
308 unsafe { &*lpc55_pac::PINT::ptr() }
309}
310
311/// Match the pin bank and number of a pin to the corresponding IOCON register. 275/// Match the pin bank and number of a pin to the corresponding IOCON register.
312/// 276///
313/// # Example 277/// # Example
@@ -316,270 +280,26 @@ pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock {
316/// use embassy_nxp::pac_utils::{iocon_reg, match_iocon}; 280/// use embassy_nxp::pac_utils::{iocon_reg, match_iocon};
317/// 281///
318/// // Make pin PIO1_6 digital and set it to pull-down mode. 282/// // Make pin PIO1_6 digital and set it to pull-down mode.
319/// match_iocon!(register, iocon_reg(), Bank::Bank1, 6, { 283/// match_iocon!(register, Bank::Bank1, 6, {
320/// register.modify(|_, w| w.mode().pull_down().digimode().digital()); 284/// register.modify(|w|{
285/// w.set_mode(PioMode::PULL_DOWN);
286/// w.set_digimode(PioDigimode::DIGITAL);
287///
288/// }
321/// }); 289/// });
322/// ``` 290/// ```
323macro_rules! match_iocon { 291macro_rules! match_iocon {
324 ($register:ident, $iocon_register:expr, $pin_bank:expr, $pin_number:expr, $action:expr) => { 292 ($register:ident, $pin_bank:expr, $pin_number:expr, $action:expr) => {
325 match ($pin_bank, $pin_number) { 293 match $pin_bank {
326 (Bank::Bank0, 0) => { 294 Bank::Bank0 => {
327 let $register = &($iocon_register).pio0_0; 295 let $register = IOCON.pio0($pin_number as usize);
328 $action;
329 }
330 (Bank::Bank0, 1) => {
331 let $register = &($iocon_register).pio0_1;
332 $action;
333 }
334 (Bank::Bank0, 2) => {
335 let $register = &($iocon_register).pio0_2;
336 $action;
337 }
338 (Bank::Bank0, 3) => {
339 let $register = &($iocon_register).pio0_3;
340 $action;
341 }
342 (Bank::Bank0, 4) => {
343 let $register = &($iocon_register).pio0_4;
344 $action;
345 }
346 (Bank::Bank0, 5) => {
347 let $register = &($iocon_register).pio0_5;
348 $action;
349 }
350 (Bank::Bank0, 6) => {
351 let $register = &($iocon_register).pio0_6;
352 $action;
353 }
354 (Bank::Bank0, 7) => {
355 let $register = &($iocon_register).pio0_7;
356 $action;
357 }
358 (Bank::Bank0, 8) => {
359 let $register = &($iocon_register).pio0_8;
360 $action;
361 }
362 (Bank::Bank0, 9) => {
363 let $register = &($iocon_register).pio0_9;
364 $action;
365 }
366 (Bank::Bank0, 10) => {
367 let $register = &($iocon_register).pio0_10;
368 $action; 296 $action;
369 } 297 }
370 (Bank::Bank0, 11) => { 298
371 let $register = &($iocon_register).pio0_11; 299 Bank::Bank1 => {
372 $action; 300 let $register = IOCON.pio1($pin_number as usize);
373 }
374 (Bank::Bank0, 12) => {
375 let $register = &($iocon_register).pio0_12;
376 $action;
377 }
378 (Bank::Bank0, 13) => {
379 let $register = &($iocon_register).pio0_13;
380 $action;
381 }
382 (Bank::Bank0, 14) => {
383 let $register = &($iocon_register).pio0_14;
384 $action;
385 }
386 (Bank::Bank0, 15) => {
387 let $register = &($iocon_register).pio0_15;
388 $action;
389 }
390 (Bank::Bank0, 16) => {
391 let $register = &($iocon_register).pio0_16;
392 $action;
393 }
394 (Bank::Bank0, 17) => {
395 let $register = &($iocon_register).pio0_17;
396 $action;
397 }
398 (Bank::Bank0, 18) => {
399 let $register = &($iocon_register).pio0_18;
400 $action;
401 }
402 (Bank::Bank0, 19) => {
403 let $register = &($iocon_register).pio0_19;
404 $action;
405 }
406 (Bank::Bank0, 20) => {
407 let $register = &($iocon_register).pio0_20;
408 $action;
409 }
410 (Bank::Bank0, 21) => {
411 let $register = &($iocon_register).pio0_21;
412 $action;
413 }
414 (Bank::Bank0, 22) => {
415 let $register = &($iocon_register).pio0_22;
416 $action;
417 }
418 (Bank::Bank0, 23) => {
419 let $register = &($iocon_register).pio0_23;
420 $action;
421 }
422 (Bank::Bank0, 24) => {
423 let $register = &($iocon_register).pio0_24;
424 $action;
425 }
426 (Bank::Bank0, 25) => {
427 let $register = &($iocon_register).pio0_25;
428 $action;
429 }
430 (Bank::Bank0, 26) => {
431 let $register = &($iocon_register).pio0_26;
432 $action;
433 }
434 (Bank::Bank0, 27) => {
435 let $register = &($iocon_register).pio0_27;
436 $action;
437 }
438 (Bank::Bank0, 28) => {
439 let $register = &($iocon_register).pio0_28;
440 $action;
441 }
442 (Bank::Bank0, 29) => {
443 let $register = &($iocon_register).pio0_29;
444 $action;
445 }
446 (Bank::Bank0, 30) => {
447 let $register = &($iocon_register).pio0_30;
448 $action;
449 }
450 (Bank::Bank0, 31) => {
451 let $register = &($iocon_register).pio0_31;
452 $action;
453 }
454 (Bank::Bank1, 0) => {
455 let $register = &($iocon_register).pio1_0;
456 $action;
457 }
458 (Bank::Bank1, 1) => {
459 let $register = &($iocon_register).pio1_1;
460 $action;
461 }
462 (Bank::Bank1, 2) => {
463 let $register = &($iocon_register).pio1_2;
464 $action;
465 }
466 (Bank::Bank1, 3) => {
467 let $register = &($iocon_register).pio1_3;
468 $action;
469 }
470 (Bank::Bank1, 4) => {
471 let $register = &($iocon_register).pio1_4;
472 $action;
473 }
474 (Bank::Bank1, 5) => {
475 let $register = &($iocon_register).pio1_5;
476 $action;
477 }
478 (Bank::Bank1, 6) => {
479 let $register = &($iocon_register).pio1_6;
480 $action;
481 }
482 (Bank::Bank1, 7) => {
483 let $register = &($iocon_register).pio1_7;
484 $action;
485 }
486 (Bank::Bank1, 8) => {
487 let $register = &($iocon_register).pio1_8;
488 $action;
489 }
490 (Bank::Bank1, 9) => {
491 let $register = &($iocon_register).pio1_9;
492 $action;
493 }
494 (Bank::Bank1, 10) => {
495 let $register = &($iocon_register).pio1_10;
496 $action;
497 }
498 (Bank::Bank1, 11) => {
499 let $register = &($iocon_register).pio1_11;
500 $action;
501 }
502 (Bank::Bank1, 12) => {
503 let $register = &($iocon_register).pio1_12;
504 $action;
505 }
506 (Bank::Bank1, 13) => {
507 let $register = &($iocon_register).pio1_13;
508 $action;
509 }
510 (Bank::Bank1, 14) => {
511 let $register = &($iocon_register).pio1_14;
512 $action;
513 }
514 (Bank::Bank1, 15) => {
515 let $register = &($iocon_register).pio1_15;
516 $action;
517 }
518 (Bank::Bank1, 16) => {
519 let $register = &($iocon_register).pio1_16;
520 $action;
521 }
522 (Bank::Bank1, 17) => {
523 let $register = &($iocon_register).pio1_17;
524 $action;
525 }
526 (Bank::Bank1, 18) => {
527 let $register = &($iocon_register).pio1_18;
528 $action;
529 }
530 (Bank::Bank1, 19) => {
531 let $register = &($iocon_register).pio1_19;
532 $action;
533 }
534 (Bank::Bank1, 20) => {
535 let $register = &($iocon_register).pio1_20;
536 $action;
537 }
538 (Bank::Bank1, 21) => {
539 let $register = &($iocon_register).pio1_21;
540 $action;
541 }
542 (Bank::Bank1, 22) => {
543 let $register = &($iocon_register).pio1_22;
544 $action;
545 }
546 (Bank::Bank1, 23) => {
547 let $register = &($iocon_register).pio1_23;
548 $action;
549 }
550 (Bank::Bank1, 24) => {
551 let $register = &($iocon_register).pio1_24;
552 $action;
553 }
554 (Bank::Bank1, 25) => {
555 let $register = &($iocon_register).pio1_25;
556 $action;
557 }
558 (Bank::Bank1, 26) => {
559 let $register = &($iocon_register).pio1_26;
560 $action;
561 }
562 (Bank::Bank1, 27) => {
563 let $register = &($iocon_register).pio1_27;
564 $action;
565 }
566 (Bank::Bank1, 28) => {
567 let $register = &($iocon_register).pio1_28;
568 $action;
569 }
570 (Bank::Bank1, 29) => {
571 let $register = &($iocon_register).pio1_29;
572 $action;
573 }
574 (Bank::Bank1, 30) => {
575 let $register = &($iocon_register).pio1_30;
576 $action;
577 }
578 (Bank::Bank1, 31) => {
579 let $register = &($iocon_register).pio1_31;
580 $action; 301 $action;
581 } 302 }
582 _ => unreachable!(),
583 } 303 }
584 }; 304 };
585} 305}