aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Balbi <[email protected]>2025-11-18 12:16:14 -0800
committerGitHub <[email protected]>2025-11-18 12:16:14 -0800
commitffe3e5acae6c0038db4176dc7d031b57f865e07f (patch)
treef69475bd7f177ad2ceb69d77ea02a408e5bf6ef7
parente07497690faf1c8a14229183f4054f96832b1d5d (diff)
Correct gpio driver (#9)
* Correct gpio driver Signed-off-by: Felipe Balbi <[email protected]> * Simplify blinky example Make it look like every other HAL for consistency. While at that, also rename the example to match the name used by other HALs. Signed-off-by: Felipe Balbi <[email protected]> * Add some documentation to GPIO driver Signed-off-by: Felipe Balbi <[email protected]> * Enable GPIO clocks during HAL initialization Provide the user with working GPIO clocks. Signed-off-by: Felipe Balbi <[email protected]> --------- Signed-off-by: Felipe Balbi <[email protected]> Co-authored-by: Felipe Balbi <[email protected]>
-rw-r--r--Cargo.toml2
-rw-r--r--examples/src/bin/adc_interrupt.rs6
-rw-r--r--examples/src/bin/adc_polling.rs6
-rw-r--r--examples/src/bin/blink.rs81
-rw-r--r--examples/src/bin/blinky.rs49
-rw-r--r--examples/src/bin/hello.rs6
-rw-r--r--examples/src/bin/lpuart_buffered.rs4
-rw-r--r--examples/src/bin/lpuart_polling.rs6
-rw-r--r--examples/src/bin/ostimer_alarm.rs6
-rw-r--r--examples/src/bin/ostimer_async.rs6
-rw-r--r--examples/src/bin/ostimer_counter.rs6
-rw-r--r--examples/src/bin/ostimer_race_test.rs6
-rw-r--r--examples/src/bin/rtc_alarm.rs6
-rw-r--r--examples/src/lib.rs6
-rw-r--r--src/clocks/mod.rs7
-rw-r--r--src/gpio.rs480
-rw-r--r--src/lib.rs315
-rw-r--r--src/lpuart/mod.rs14
18 files changed, 827 insertions, 185 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 841ce1903..60f836ac3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -17,7 +17,7 @@ embassy-hal-internal = { version = "0.3.0", features = ["cortex-m", "prio-bits-3
17embassy-sync = "0.7.2" 17embassy-sync = "0.7.2"
18embassy-time = "0.5.0" 18embassy-time = "0.5.0"
19embassy-time-driver = "0.2.1" 19embassy-time-driver = "0.2.1"
20embedded-hal = { package = "embedded-hal", version = "1.0" } 20embedded-hal-1 = { package = "embedded-hal", version = "1.0" }
21embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } 21embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] }
22embedded-hal-async = { version = "1.0" } 22embedded-hal-async = { version = "1.0" }
23embedded-hal-nb = { version = "1.0" } 23embedded-hal-nb = { version = "1.0" }
diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs
index 6812ba5d3..9fed052fd 100644
--- a/examples/src/bin/adc_interrupt.rs
+++ b/examples/src/bin/adc_interrupt.rs
@@ -34,14 +34,14 @@ async fn main(_spawner: Spawner) {
34 ..Default::default() 34 ..Default::default()
35 }; 35 };
36 36
37 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 37 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
38 unsafe { 38 unsafe {
39 embassy_mcxa_examples::init_uart2_pins(hal::pac()); 39 embassy_mcxa_examples::init_uart2_pins(hal::pac());
40 } 40 }
41 let mut uart = Lpuart::new_blocking( 41 let mut uart = Lpuart::new_blocking(
42 p.LPUART2, // Peripheral 42 p.LPUART2, // Peripheral
43 p.PIO2_2, // TX pin 43 p.P2_2, // TX pin
44 p.PIO2_3, // RX pin 44 p.P2_3, // RX pin
45 config, 45 config,
46 ) 46 )
47 .unwrap(); 47 .unwrap();
diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs
index 421306e9b..545f8f77a 100644
--- a/examples/src/bin/adc_polling.rs
+++ b/examples/src/bin/adc_polling.rs
@@ -34,14 +34,14 @@ async fn main(_spawner: Spawner) {
34 ..Default::default() 34 ..Default::default()
35 }; 35 };
36 36
37 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 37 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
38 unsafe { 38 unsafe {
39 init_uart2_pins(hal::pac()); 39 init_uart2_pins(hal::pac());
40 } 40 }
41 let mut uart = Lpuart::new_blocking( 41 let mut uart = Lpuart::new_blocking(
42 p.LPUART2, // Peripheral 42 p.LPUART2, // Peripheral
43 p.PIO2_2, // TX pin 43 p.P2_2, // TX pin
44 p.PIO2_3, // RX pin 44 p.P2_3, // RX pin
45 config, 45 config,
46 ) 46 )
47 .unwrap(); 47 .unwrap();
diff --git a/examples/src/bin/blink.rs b/examples/src/bin/blink.rs
deleted file mode 100644
index d8b158d50..000000000
--- a/examples/src/bin/blink.rs
+++ /dev/null
@@ -1,81 +0,0 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa as hal;
6use embassy_mcxa::bind_interrupts;
7use embassy_mcxa_examples::init_led_gpio_clocks;
8use embassy_time::{Duration, Timer};
9use hal::gpio::pins::PIO3_18;
10use hal::gpio::{Level, Output};
11
12// Bind only OS_EVENT for timer interrupts
13bind_interrupts!(struct Irqs {
14 OS_EVENT => hal::ostimer::time_driver::OsEventHandler;
15});
16
17#[used]
18#[no_mangle]
19static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT;
20
21#[embassy_executor::main]
22async fn main(_spawner: Spawner) {
23 let _p = hal::init(hal::config::Config::default());
24
25 unsafe {
26 init_led_gpio_clocks(hal::pac());
27 }
28
29 defmt::info!("Blink example");
30
31 // Initialize embassy-time global driver backed by OSTIMER0
32 hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000);
33
34 // Configure LED pin for GPIO mode
35 PIO3_18::set_mux_gpio();
36
37 let mut led = Output::new(PIO3_18::degrade(), Level::High);
38
39 // Complex blinking pattern: SOS in Morse code
40 // S: ... (3 short)
41 // O: --- (3 long)
42 // S: ... (3 short)
43 // With pauses between letters and words
44
45 loop {
46 defmt::info!("SOS");
47
48 // S: three short blinks
49 for _ in 0..3 {
50 led.set_low();
51 Timer::after(Duration::from_millis(150)).await;
52 led.set_high();
53 Timer::after(Duration::from_millis(150)).await;
54 }
55
56 // Pause between letters
57 Timer::after(Duration::from_millis(300)).await;
58
59 // O: three long blinks
60 for _ in 0..3 {
61 led.set_low();
62 Timer::after(Duration::from_millis(450)).await;
63 led.set_high();
64 Timer::after(Duration::from_millis(150)).await;
65 }
66
67 // Pause between letters
68 Timer::after(Duration::from_millis(300)).await;
69
70 // S: three short blinks
71 for _ in 0..3 {
72 led.set_low();
73 Timer::after(Duration::from_millis(150)).await;
74 led.set_high();
75 Timer::after(Duration::from_millis(150)).await;
76 }
77
78 // Long pause between words (SOS repeats)
79 Timer::after(Duration::from_millis(1000)).await;
80 }
81}
diff --git a/examples/src/bin/blinky.rs b/examples/src/bin/blinky.rs
new file mode 100644
index 000000000..28d83a12e
--- /dev/null
+++ b/examples/src/bin/blinky.rs
@@ -0,0 +1,49 @@
1#![no_std]
2#![no_main]
3
4use embassy_executor::Spawner;
5use embassy_mcxa::bind_interrupts;
6use embassy_time::Timer;
7use hal::gpio::{Level, Output};
8use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
9
10// Bind only OS_EVENT for timer interrupts
11bind_interrupts!(struct Irqs {
12 OS_EVENT => hal::ostimer::time_driver::OsEventHandler;
13});
14
15#[used]
16#[no_mangle]
17static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT;
18
19#[embassy_executor::main]
20async fn main(_spawner: Spawner) {
21 let p = hal::init(hal::config::Config::default());
22
23 defmt::info!("Blink example");
24
25 // Initialize embassy-time global driver backed by OSTIMER0
26 hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000);
27
28 let mut red = Output::new(p.P3_18, Level::High);
29 let mut green = Output::new(p.P3_19, Level::High);
30 let mut blue = Output::new(p.P3_21, Level::High);
31
32 loop {
33 defmt::info!("Toggle LEDs");
34
35 red.toggle();
36 Timer::after_millis(250).await;
37
38 red.toggle();
39 green.toggle();
40 Timer::after_millis(250).await;
41
42 green.toggle();
43 blue.toggle();
44 Timer::after_millis(250).await;
45 blue.toggle();
46
47 Timer::after_millis(250).await;
48 }
49}
diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs
index 207c157c3..e2d0b413d 100644
--- a/examples/src/bin/hello.rs
+++ b/examples/src/bin/hello.rs
@@ -26,14 +26,14 @@ async fn main(_spawner: Spawner) {
26 ..Default::default() 26 ..Default::default()
27 }; 27 };
28 28
29 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 29 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
30 unsafe { 30 unsafe {
31 embassy_mcxa_examples::init_uart2_pins(hal::pac()); 31 embassy_mcxa_examples::init_uart2_pins(hal::pac());
32 } 32 }
33 let mut uart = Lpuart::new_blocking( 33 let mut uart = Lpuart::new_blocking(
34 p.LPUART2, // Peripheral 34 p.LPUART2, // Peripheral
35 p.PIO2_2, // TX pin 35 p.P2_2, // TX pin
36 p.PIO2_3, // RX pin 36 p.P2_3, // RX pin
37 config, 37 config,
38 ) 38 )
39 .unwrap(); 39 .unwrap();
diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs
index 642d4af65..b0d19ef16 100644
--- a/examples/src/bin/lpuart_buffered.rs
+++ b/examples/src/bin/lpuart_buffered.rs
@@ -51,8 +51,8 @@ async fn main(_spawner: Spawner) {
51 // Create a buffered LPUART2 instance with both TX and RX 51 // Create a buffered LPUART2 instance with both TX and RX
52 let mut uart = BufferedLpuart::new( 52 let mut uart = BufferedLpuart::new(
53 p.LPUART2, 53 p.LPUART2,
54 p.PIO2_2, // TX pin 54 p.P2_2, // TX pin
55 p.PIO2_3, // RX pin 55 p.P2_3, // RX pin
56 Irqs, 56 Irqs,
57 &mut tx_buf, 57 &mut tx_buf,
58 &mut rx_buf, 58 &mut rx_buf,
diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs
index bea82c33e..525d42e2c 100644
--- a/examples/src/bin/lpuart_polling.rs
+++ b/examples/src/bin/lpuart_polling.rs
@@ -26,11 +26,11 @@ async fn main(_spawner: Spawner) {
26 ..Default::default() 26 ..Default::default()
27 }; 27 };
28 28
29 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 29 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
30 let lpuart = Lpuart::new_blocking( 30 let lpuart = Lpuart::new_blocking(
31 p.LPUART2, // Peripheral 31 p.LPUART2, // Peripheral
32 p.PIO2_2, // TX pin 32 p.P2_2, // TX pin
33 p.PIO2_3, // RX pin 33 p.P2_3, // RX pin
34 config, 34 config,
35 ) 35 )
36 .unwrap(); 36 .unwrap();
diff --git a/examples/src/bin/ostimer_alarm.rs b/examples/src/bin/ostimer_alarm.rs
index 03fb93319..6d38741b7 100644
--- a/examples/src/bin/ostimer_alarm.rs
+++ b/examples/src/bin/ostimer_alarm.rs
@@ -40,14 +40,14 @@ async fn main(_spawner: Spawner) {
40 ..Default::default() 40 ..Default::default()
41 }; 41 };
42 42
43 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 43 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
44 unsafe { 44 unsafe {
45 init_uart2_pins(hal::pac()); 45 init_uart2_pins(hal::pac());
46 } 46 }
47 let mut uart = Lpuart::new_blocking( 47 let mut uart = Lpuart::new_blocking(
48 p.LPUART2, // Peripheral 48 p.LPUART2, // Peripheral
49 p.PIO2_2, // TX pin 49 p.P2_2, // TX pin
50 p.PIO2_3, // RX pin 50 p.P2_3, // RX pin
51 config, 51 config,
52 ) 52 )
53 .unwrap(); 53 .unwrap();
diff --git a/examples/src/bin/ostimer_async.rs b/examples/src/bin/ostimer_async.rs
index 881f09374..f043184e7 100644
--- a/examples/src/bin/ostimer_async.rs
+++ b/examples/src/bin/ostimer_async.rs
@@ -29,14 +29,14 @@ async fn main(_spawner: Spawner) {
29 ..Default::default() 29 ..Default::default()
30 }; 30 };
31 31
32 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 32 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
33 unsafe { 33 unsafe {
34 init_uart2_pins(hal::pac()); 34 init_uart2_pins(hal::pac());
35 } 35 }
36 let mut uart = Lpuart::new_blocking( 36 let mut uart = Lpuart::new_blocking(
37 p.LPUART2, // Peripheral 37 p.LPUART2, // Peripheral
38 p.PIO2_2, // TX pin 38 p.P2_2, // TX pin
39 p.PIO2_3, // RX pin 39 p.P2_3, // RX pin
40 config, 40 config,
41 ) 41 )
42 .unwrap(); 42 .unwrap();
diff --git a/examples/src/bin/ostimer_counter.rs b/examples/src/bin/ostimer_counter.rs
index 2fbc251b9..f36915ff2 100644
--- a/examples/src/bin/ostimer_counter.rs
+++ b/examples/src/bin/ostimer_counter.rs
@@ -30,14 +30,14 @@ async fn main(_spawner: Spawner) {
30 ..Default::default() 30 ..Default::default()
31 }; 31 };
32 32
33 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 33 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
34 unsafe { 34 unsafe {
35 embassy_mcxa_examples::init_uart2_pins(hal::pac()); 35 embassy_mcxa_examples::init_uart2_pins(hal::pac());
36 } 36 }
37 let mut uart = Lpuart::new_blocking( 37 let mut uart = Lpuart::new_blocking(
38 p.LPUART2, // Peripheral 38 p.LPUART2, // Peripheral
39 p.PIO2_2, // TX pin 39 p.P2_2, // TX pin
40 p.PIO2_3, // RX pin 40 p.P2_3, // RX pin
41 config, 41 config,
42 ) 42 )
43 .unwrap(); 43 .unwrap();
diff --git a/examples/src/bin/ostimer_race_test.rs b/examples/src/bin/ostimer_race_test.rs
index 168a952cd..0106b92a7 100644
--- a/examples/src/bin/ostimer_race_test.rs
+++ b/examples/src/bin/ostimer_race_test.rs
@@ -80,14 +80,14 @@ async fn main(_spawner: Spawner) {
80 ..Default::default() 80 ..Default::default()
81 }; 81 };
82 82
83 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 83 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
84 unsafe { 84 unsafe {
85 embassy_mcxa_examples::init_uart2_pins(hal::pac()); 85 embassy_mcxa_examples::init_uart2_pins(hal::pac());
86 } 86 }
87 let mut uart = Lpuart::new_blocking( 87 let mut uart = Lpuart::new_blocking(
88 p.LPUART2, // Peripheral 88 p.LPUART2, // Peripheral
89 p.PIO2_2, // TX pin 89 p.P2_2, // TX pin
90 p.PIO2_3, // RX pin 90 p.P2_3, // RX pin
91 config, 91 config,
92 ) 92 )
93 .unwrap(); 93 .unwrap();
diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs
index 40a1207df..a54b4a817 100644
--- a/examples/src/bin/rtc_alarm.rs
+++ b/examples/src/bin/rtc_alarm.rs
@@ -32,14 +32,14 @@ async fn main(_spawner: Spawner) {
32 ..Default::default() 32 ..Default::default()
33 }; 33 };
34 34
35 // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX 35 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
36 unsafe { 36 unsafe {
37 embassy_mcxa_examples::init_uart2_pins(hal::pac()); 37 embassy_mcxa_examples::init_uart2_pins(hal::pac());
38 } 38 }
39 let mut uart = Lpuart::new_blocking( 39 let mut uart = Lpuart::new_blocking(
40 p.LPUART2, // Peripheral 40 p.LPUART2, // Peripheral
41 p.PIO2_2, // TX pin 41 p.P2_2, // TX pin
42 p.PIO2_3, // RX pin 42 p.P2_3, // RX pin
43 config, 43 config,
44 ) 44 )
45 .unwrap(); 45 .unwrap();
diff --git a/examples/src/lib.rs b/examples/src/lib.rs
index 4bb334da5..66b93450a 100644
--- a/examples/src/lib.rs
+++ b/examples/src/lib.rs
@@ -16,12 +16,6 @@ pub unsafe fn init_uart2_pins(_p: &hal::pac::Peripherals) {
16 pins::configure_uart2_pins_port2(); 16 pins::configure_uart2_pins_port2();
17} 17}
18 18
19/// Initialize clocks for the LED GPIO/PORT used by the blink example.
20pub unsafe fn init_led_gpio_clocks(_p: &hal::pac::Peripherals) {
21 _ = clocks::enable_and_reset::<hal::peripherals::PORT3>(&clocks::periph_helpers::NoConfig);
22 _ = clocks::enable_and_reset::<hal::peripherals::GPIO3>(&clocks::periph_helpers::NoConfig);
23}
24
25/// Initialize clocks and pin muxing for ADC. 19/// Initialize clocks and pin muxing for ADC.
26pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) { 20pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) {
27 // NOTE: Lpuart has been updated to properly enable + reset its own clocks. 21 // NOTE: Lpuart has been updated to properly enable + reset its own clocks.
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs
index e02840592..558fb0278 100644
--- a/src/clocks/mod.rs
+++ b/src/clocks/mod.rs
@@ -874,10 +874,17 @@ pub(crate) mod gate {
874 // other than enabling through the MRCC gate. Currently, these peripherals will 874 // other than enabling through the MRCC gate. Currently, these peripherals will
875 // ALWAYS return `Ok(0)` when calling [`enable_and_reset()`] and/or 875 // ALWAYS return `Ok(0)` when calling [`enable_and_reset()`] and/or
876 // [`SPConfHelper::post_enable_config()`]. 876 // [`SPConfHelper::post_enable_config()`].
877 impl_cc_gate!(PORT0, mrcc_glb_cc1, mrcc_glb_rst1, port0, NoConfig);
877 impl_cc_gate!(PORT1, mrcc_glb_cc1, mrcc_glb_rst1, port1, NoConfig); 878 impl_cc_gate!(PORT1, mrcc_glb_cc1, mrcc_glb_rst1, port1, NoConfig);
878 impl_cc_gate!(PORT2, mrcc_glb_cc1, mrcc_glb_rst1, port2, NoConfig); 879 impl_cc_gate!(PORT2, mrcc_glb_cc1, mrcc_glb_rst1, port2, NoConfig);
879 impl_cc_gate!(PORT3, mrcc_glb_cc1, mrcc_glb_rst1, port3, NoConfig); 880 impl_cc_gate!(PORT3, mrcc_glb_cc1, mrcc_glb_rst1, port3, NoConfig);
881 impl_cc_gate!(PORT4, mrcc_glb_cc1, mrcc_glb_rst1, port4, NoConfig);
882
883 impl_cc_gate!(GPIO0, mrcc_glb_cc2, mrcc_glb_rst2, gpio0, NoConfig);
884 impl_cc_gate!(GPIO1, mrcc_glb_cc2, mrcc_glb_rst2, gpio1, NoConfig);
885 impl_cc_gate!(GPIO2, mrcc_glb_cc2, mrcc_glb_rst2, gpio2, NoConfig);
880 impl_cc_gate!(GPIO3, mrcc_glb_cc2, mrcc_glb_rst2, gpio3, NoConfig); 886 impl_cc_gate!(GPIO3, mrcc_glb_cc2, mrcc_glb_rst2, gpio3, NoConfig);
887 impl_cc_gate!(GPIO4, mrcc_glb_cc2, mrcc_glb_rst2, gpio4, NoConfig);
881 888
882 // These peripherals DO have meaningful configuration, and could fail if the system 889 // These peripherals DO have meaningful configuration, and could fail if the system
883 // clocks do not match their needs. 890 // clocks do not match their needs.
diff --git a/src/gpio.rs b/src/gpio.rs
index 1e7214b28..09a414d3b 100644
--- a/src/gpio.rs
+++ b/src/gpio.rs
@@ -2,9 +2,11 @@
2//! The exported `Output`/`Input` drivers own a `Flex` so they no longer depend on the 2//! The exported `Output`/`Input` drivers own a `Flex` so they no longer depend on the
3//! concrete pin type. 3//! concrete pin type.
4 4
5use core::convert::Infallible;
5use core::marker::PhantomData; 6use core::marker::PhantomData;
6 7
7use crate::{pac, pins as pin_config}; 8use embassy_hal_internal::{Peri, PeripheralType};
9use paste::paste;
8 10
9/// Logical level for GPIO pins. 11/// Logical level for GPIO pins.
10#[derive(Copy, Clone, Eq, PartialEq, Debug)] 12#[derive(Copy, Clone, Eq, PartialEq, Debug)]
@@ -13,140 +15,350 @@ pub enum Level {
13 High, 15 High,
14} 16}
15 17
16pub type Gpio = crate::peripherals::GPIO; 18pub type Gpio = crate::peripherals::GPIO0;
17 19
18/// Type-erased representation of a GPIO pin. 20/// Type-erased representation of a GPIO pin.
19#[derive(Copy, Clone)]
20pub struct AnyPin { 21pub struct AnyPin {
21 port: u8, 22 port: usize,
22 pin: u8, 23 pin: usize,
23 gpio: *const pac::gpio0::RegisterBlock, 24 gpio: &'static crate::pac::gpio0::RegisterBlock,
24} 25}
25 26
26impl AnyPin { 27impl AnyPin {
27 /// Create an `AnyPin` from raw components. 28 /// Create an `AnyPin` from raw components.
28 pub fn new(port: u8, pin: u8, gpio: *const pac::gpio0::RegisterBlock) -> Self { 29 pub fn new(port: usize, pin: usize, gpio: &'static crate::pac::gpio0::RegisterBlock) -> Self {
29 Self { port, pin, gpio } 30 Self { port, pin, gpio }
30 } 31 }
31 32
32 #[inline(always)] 33 #[inline(always)]
33 fn mask(&self) -> u32 { 34 fn mask(&self) -> u32 {
34 1u32 << self.pin 35 1 << self.pin
35 } 36 }
36 37
37 #[inline(always)] 38 #[inline(always)]
38 fn gpio(&self) -> &'static pac::gpio0::RegisterBlock { 39 fn gpio(&self) -> &'static crate::pac::gpio0::RegisterBlock {
39 unsafe { &*self.gpio } 40 self.gpio
40 } 41 }
41 42
42 #[inline(always)] 43 #[inline(always)]
43 pub fn port_index(&self) -> u8 { 44 pub fn port_index(&self) -> usize {
44 self.port 45 self.port
45 } 46 }
46 47
47 #[inline(always)] 48 #[inline(always)]
48 pub fn pin_index(&self) -> u8 { 49 pub fn pin_index(&self) -> usize {
49 self.pin 50 self.pin
50 } 51 }
51} 52}
52 53
53/// Type-level trait implemented by concrete pin ZSTs. 54embassy_hal_internal::impl_peripheral!(AnyPin);
54pub trait PinId {
55 fn port_index() -> u8;
56 fn pin_index() -> u8;
57 fn gpio_ptr() -> *const pac::gpio0::RegisterBlock;
58 55
59 fn set_mux_gpio() { 56trait SealedPin {
60 unsafe { pin_config::set_pin_mux_gpio(Self::port_index(), Self::pin_index()) } 57 fn pin_port(&self) -> usize;
58
59 fn port(&self) -> usize {
60 self.pin_port() / 32
61 } 61 }
62 62
63 fn degrade() -> AnyPin { 63 fn pin(&self) -> usize {
64 AnyPin::new(Self::port_index(), Self::pin_index(), Self::gpio_ptr()) 64 self.pin_port() % 32
65 } 65 }
66
67 fn gpio(&self) -> &'static crate::pac::gpio0::RegisterBlock;
66} 68}
67 69
68pub mod pins { 70/// GPIO pin trait.
69 use super::{pac, AnyPin, PinId}; 71#[allow(private_bounds)]
72pub trait GpioPin: SealedPin + Sized + PeripheralType + Into<AnyPin> + 'static {
73 /// Type-erase the pin.
74 fn degrade(self) -> AnyPin {
75 // SAFETY: This is only called within the GpioPin trait, which is only
76 // implemented within this module on valid pin peripherals and thus
77 // has been verified to be correct.
78 AnyPin::new(self.port(), self.pin(), self.gpio())
79 }
80}
70 81
71 macro_rules! define_pin { 82impl SealedPin for AnyPin {
72 ($Name:ident, $port:literal, $pin:literal, $GpioBlk:ident) => { 83 #[inline]
73 pub struct $Name; 84 fn pin_port(&self) -> usize {
74 impl super::PinId for $Name { 85 self.port * 32 + self.pin
75 #[inline(always)] 86 }
76 fn port_index() -> u8 { 87
77 $port 88 #[inline]
78 } 89 fn gpio(&self) -> &'static crate::pac::gpio0::RegisterBlock {
79 #[inline(always)] 90 self.gpio()
80 fn pin_index() -> u8 { 91 }
81 $pin 92}
82 } 93
83 #[inline(always)] 94impl GpioPin for AnyPin {}
84 fn gpio_ptr() -> *const pac::gpio0::RegisterBlock { 95
85 pac::$GpioBlk::ptr() 96macro_rules! impl_pin {
86 } 97 ($peri:ident, $port:expr, $pin:expr, $block:ident) => {
98 impl SealedPin for crate::peripherals::$peri {
99 #[inline]
100 fn pin_port(&self) -> usize {
101 $port * 32 + $pin
87 } 102 }
88 103
89 impl $Name { 104 #[inline]
90 /// Convenience helper to obtain a type-erased handle to this pin. 105 fn gpio(&self) -> &'static crate::pac::gpio0::RegisterBlock {
91 pub fn degrade() -> AnyPin { 106 unsafe { &*crate::pac::$block::ptr() }
92 <Self as PinId>::degrade() 107 }
93 } 108 }
94 109
95 pub fn set_mux_gpio() { 110 impl GpioPin for crate::peripherals::$peri {}
96 <Self as PinId>::set_mux_gpio() 111
97 } 112 impl From<crate::peripherals::$peri> for AnyPin {
113 fn from(value: crate::peripherals::$peri) -> Self {
114 value.degrade()
98 } 115 }
99 }; 116 }
100 }
101 117
102 // Extend this list as more pins are needed. 118 impl crate::peripherals::$peri {
103 define_pin!(PIO3_18, 3, 18, Gpio3); 119 /// Convenience helper to obtain a type-erased handle to this pin.
120 pub fn degrade(&self) -> AnyPin {
121 AnyPin::new(self.port(), self.pin(), self.gpio())
122 }
123
124 #[inline]
125 pub fn set_mux_gpio() {
126 paste! {
127 let port = unsafe { crate::pac::[<Port $port>]::steal()};
128 port.[<pcr $pin>]().write(|w| w.mux().mux00());
129 }
130 }
131 }
132 };
104} 133}
105 134
135impl_pin!(P0_0, 0, 0, Gpio0);
136impl_pin!(P0_1, 0, 1, Gpio0);
137impl_pin!(P0_2, 0, 2, Gpio0);
138impl_pin!(P0_3, 0, 3, Gpio0);
139impl_pin!(P0_4, 0, 4, Gpio0);
140impl_pin!(P0_5, 0, 5, Gpio0);
141impl_pin!(P0_6, 0, 6, Gpio0);
142impl_pin!(P0_7, 0, 7, Gpio0);
143impl_pin!(P0_8, 0, 8, Gpio0);
144impl_pin!(P0_9, 0, 9, Gpio0);
145impl_pin!(P0_10, 0, 10, Gpio0);
146impl_pin!(P0_11, 0, 11, Gpio0);
147impl_pin!(P0_12, 0, 12, Gpio0);
148impl_pin!(P0_13, 0, 13, Gpio0);
149impl_pin!(P0_14, 0, 14, Gpio0);
150impl_pin!(P0_15, 0, 15, Gpio0);
151impl_pin!(P0_16, 0, 16, Gpio0);
152impl_pin!(P0_17, 0, 17, Gpio0);
153impl_pin!(P0_18, 0, 18, Gpio0);
154impl_pin!(P0_19, 0, 19, Gpio0);
155impl_pin!(P0_20, 0, 20, Gpio0);
156impl_pin!(P0_21, 0, 21, Gpio0);
157impl_pin!(P0_22, 0, 22, Gpio0);
158impl_pin!(P0_23, 0, 23, Gpio0);
159impl_pin!(P0_24, 0, 24, Gpio0);
160impl_pin!(P0_25, 0, 25, Gpio0);
161impl_pin!(P0_26, 0, 26, Gpio0);
162impl_pin!(P0_27, 0, 27, Gpio0);
163impl_pin!(P0_28, 0, 28, Gpio0);
164impl_pin!(P0_29, 0, 29, Gpio0);
165impl_pin!(P0_30, 0, 30, Gpio0);
166impl_pin!(P0_31, 0, 31, Gpio0);
167
168impl_pin!(P1_0, 1, 0, Gpio1);
169impl_pin!(P1_1, 1, 1, Gpio1);
170impl_pin!(P1_2, 1, 2, Gpio1);
171impl_pin!(P1_3, 1, 3, Gpio1);
172impl_pin!(P1_4, 1, 4, Gpio1);
173impl_pin!(P1_5, 1, 5, Gpio1);
174impl_pin!(P1_6, 1, 6, Gpio1);
175impl_pin!(P1_7, 1, 7, Gpio1);
176impl_pin!(P1_8, 1, 8, Gpio1);
177impl_pin!(P1_9, 1, 9, Gpio1);
178impl_pin!(P1_10, 1, 10, Gpio1);
179impl_pin!(P1_11, 1, 11, Gpio1);
180impl_pin!(P1_12, 1, 12, Gpio1);
181impl_pin!(P1_13, 1, 13, Gpio1);
182impl_pin!(P1_14, 1, 14, Gpio1);
183impl_pin!(P1_15, 1, 15, Gpio1);
184impl_pin!(P1_16, 1, 16, Gpio1);
185impl_pin!(P1_17, 1, 17, Gpio1);
186impl_pin!(P1_18, 1, 18, Gpio1);
187impl_pin!(P1_19, 1, 19, Gpio1);
188impl_pin!(P1_20, 1, 20, Gpio1);
189impl_pin!(P1_21, 1, 21, Gpio1);
190impl_pin!(P1_22, 1, 22, Gpio1);
191impl_pin!(P1_23, 1, 23, Gpio1);
192impl_pin!(P1_24, 1, 24, Gpio1);
193impl_pin!(P1_25, 1, 25, Gpio1);
194impl_pin!(P1_26, 1, 26, Gpio1);
195impl_pin!(P1_27, 1, 27, Gpio1);
196impl_pin!(P1_28, 1, 28, Gpio1);
197impl_pin!(P1_29, 1, 29, Gpio1);
198impl_pin!(P1_30, 1, 30, Gpio1);
199impl_pin!(P1_31, 1, 31, Gpio1);
200
201impl_pin!(P2_0, 2, 0, Gpio2);
202impl_pin!(P2_1, 2, 1, Gpio2);
203impl_pin!(P2_2, 2, 2, Gpio2);
204impl_pin!(P2_3, 2, 3, Gpio2);
205impl_pin!(P2_4, 2, 4, Gpio2);
206impl_pin!(P2_5, 2, 5, Gpio2);
207impl_pin!(P2_6, 2, 6, Gpio2);
208impl_pin!(P2_7, 2, 7, Gpio2);
209impl_pin!(P2_8, 2, 8, Gpio2);
210impl_pin!(P2_9, 2, 9, Gpio2);
211impl_pin!(P2_10, 2, 10, Gpio2);
212impl_pin!(P2_11, 2, 11, Gpio2);
213impl_pin!(P2_12, 2, 12, Gpio2);
214impl_pin!(P2_13, 2, 13, Gpio2);
215impl_pin!(P2_14, 2, 14, Gpio2);
216impl_pin!(P2_15, 2, 15, Gpio2);
217impl_pin!(P2_16, 2, 16, Gpio2);
218impl_pin!(P2_17, 2, 17, Gpio2);
219impl_pin!(P2_18, 2, 18, Gpio2);
220impl_pin!(P2_19, 2, 19, Gpio2);
221impl_pin!(P2_20, 2, 20, Gpio2);
222impl_pin!(P2_21, 2, 21, Gpio2);
223impl_pin!(P2_22, 2, 22, Gpio2);
224impl_pin!(P2_23, 2, 23, Gpio2);
225impl_pin!(P2_24, 2, 24, Gpio2);
226impl_pin!(P2_25, 2, 25, Gpio2);
227impl_pin!(P2_26, 2, 26, Gpio2);
228impl_pin!(P2_27, 2, 27, Gpio2);
229impl_pin!(P2_28, 2, 28, Gpio2);
230impl_pin!(P2_29, 2, 29, Gpio2);
231impl_pin!(P2_30, 2, 30, Gpio2);
232impl_pin!(P2_31, 2, 31, Gpio2);
233
234impl_pin!(P3_0, 3, 0, Gpio3);
235impl_pin!(P3_1, 3, 1, Gpio3);
236impl_pin!(P3_2, 3, 2, Gpio3);
237impl_pin!(P3_3, 3, 3, Gpio3);
238impl_pin!(P3_4, 3, 4, Gpio3);
239impl_pin!(P3_5, 3, 5, Gpio3);
240impl_pin!(P3_6, 3, 6, Gpio3);
241impl_pin!(P3_7, 3, 7, Gpio3);
242impl_pin!(P3_8, 3, 8, Gpio3);
243impl_pin!(P3_9, 3, 9, Gpio3);
244impl_pin!(P3_10, 3, 10, Gpio3);
245impl_pin!(P3_11, 3, 11, Gpio3);
246impl_pin!(P3_12, 3, 12, Gpio3);
247impl_pin!(P3_13, 3, 13, Gpio3);
248impl_pin!(P3_14, 3, 14, Gpio3);
249impl_pin!(P3_15, 3, 15, Gpio3);
250impl_pin!(P3_16, 3, 16, Gpio3);
251impl_pin!(P3_17, 3, 17, Gpio3);
252impl_pin!(P3_18, 3, 18, Gpio3);
253impl_pin!(P3_19, 3, 19, Gpio3);
254impl_pin!(P3_20, 3, 20, Gpio3);
255impl_pin!(P3_21, 3, 21, Gpio3);
256impl_pin!(P3_22, 3, 22, Gpio3);
257impl_pin!(P3_23, 3, 23, Gpio3);
258impl_pin!(P3_24, 3, 24, Gpio3);
259impl_pin!(P3_25, 3, 25, Gpio3);
260impl_pin!(P3_26, 3, 26, Gpio3);
261impl_pin!(P3_27, 3, 27, Gpio3);
262impl_pin!(P3_28, 3, 28, Gpio3);
263impl_pin!(P3_29, 3, 29, Gpio3);
264impl_pin!(P3_30, 3, 30, Gpio3);
265impl_pin!(P3_31, 3, 31, Gpio3);
266
267impl_pin!(P4_0, 4, 0, Gpio4);
268impl_pin!(P4_1, 4, 1, Gpio4);
269impl_pin!(P4_2, 4, 2, Gpio4);
270impl_pin!(P4_3, 4, 3, Gpio4);
271impl_pin!(P4_4, 4, 4, Gpio4);
272impl_pin!(P4_5, 4, 5, Gpio4);
273impl_pin!(P4_6, 4, 6, Gpio4);
274impl_pin!(P4_7, 4, 7, Gpio4);
275impl_pin!(P4_8, 4, 8, Gpio4);
276impl_pin!(P4_9, 4, 9, Gpio4);
277impl_pin!(P4_10, 4, 10, Gpio4);
278impl_pin!(P4_11, 4, 11, Gpio4);
279impl_pin!(P4_12, 4, 12, Gpio4);
280impl_pin!(P4_13, 4, 13, Gpio4);
281impl_pin!(P4_14, 4, 14, Gpio4);
282impl_pin!(P4_15, 4, 15, Gpio4);
283impl_pin!(P4_16, 4, 16, Gpio4);
284impl_pin!(P4_17, 4, 17, Gpio4);
285impl_pin!(P4_18, 4, 18, Gpio4);
286impl_pin!(P4_19, 4, 19, Gpio4);
287impl_pin!(P4_20, 4, 20, Gpio4);
288impl_pin!(P4_21, 4, 21, Gpio4);
289impl_pin!(P4_22, 4, 22, Gpio4);
290impl_pin!(P4_23, 4, 23, Gpio4);
291impl_pin!(P4_24, 4, 24, Gpio4);
292impl_pin!(P4_25, 4, 25, Gpio4);
293impl_pin!(P4_26, 4, 26, Gpio4);
294impl_pin!(P4_27, 4, 27, Gpio4);
295impl_pin!(P4_28, 4, 28, Gpio4);
296impl_pin!(P4_29, 4, 29, Gpio4);
297impl_pin!(P4_30, 4, 30, Gpio4);
298impl_pin!(P4_31, 4, 31, Gpio4);
299
106/// A flexible pin that can be configured as input or output. 300/// A flexible pin that can be configured as input or output.
107pub struct Flex<'d> { 301pub struct Flex<'d> {
108 pin: AnyPin, 302 pin: Peri<'d, AnyPin>,
109 _marker: PhantomData<&'d mut ()>, 303 _marker: PhantomData<&'d mut ()>,
110} 304}
111 305
112impl<'d> Flex<'d> { 306impl<'d> Flex<'d> {
113 pub fn new(pin: AnyPin) -> Self { 307 /// Wrap the pin in a `Flex`.
308 ///
309 /// The pin remains unmodified. The initial output level is unspecified, but
310 /// can be changed before the pin is put into output mode.
311 pub fn new(pin: Peri<'d, impl GpioPin>) -> Self {
114 Self { 312 Self {
115 pin, 313 pin: pin.into(),
116 _marker: PhantomData, 314 _marker: PhantomData,
117 } 315 }
118 } 316 }
119 317
120 #[inline(always)] 318 #[inline]
121 fn gpio(&self) -> &'static pac::gpio0::RegisterBlock { 319 fn gpio(&self) -> &'static crate::pac::gpio0::RegisterBlock {
122 self.pin.gpio() 320 self.pin.gpio()
123 } 321 }
124 322
125 #[inline(always)] 323 #[inline]
126 fn mask(&self) -> u32 { 324 fn mask(&self) -> u32 {
127 self.pin.mask() 325 self.pin.mask()
128 } 326 }
129 327
328 /// Put the pin into input mode.
329 ///
330 /// The pull setting is left unchanged.
331 #[inline]
130 pub fn set_as_input(&mut self) { 332 pub fn set_as_input(&mut self) {
131 let mask = self.mask(); 333 let mask = self.mask();
132 let gpio = self.gpio(); 334 let gpio = self.gpio();
133 gpio.pddr().modify(|r, w| unsafe { w.bits(r.bits() & !mask) }); 335 gpio.pddr().modify(|r, w| unsafe { w.bits(r.bits() & !mask) });
134 } 336 }
135 337
338 /// Put the pin into output mode.
339 ///
340 /// The initial output level is left unchanged.
341 #[inline]
136 pub fn set_as_output(&mut self) { 342 pub fn set_as_output(&mut self) {
137 let mask = self.mask(); 343 let mask = self.mask();
138 let gpio = self.gpio(); 344 let gpio = self.gpio();
139 gpio.pddr().modify(|r, w| unsafe { w.bits(r.bits() | mask) }); 345 gpio.pddr().modify(|r, w| unsafe { w.bits(r.bits() | mask) });
140 } 346 }
141 347
348 /// Set output level to High.
349 #[inline]
142 pub fn set_high(&mut self) { 350 pub fn set_high(&mut self) {
143 self.gpio().psor().write(|w| unsafe { w.bits(self.mask()) }); 351 self.gpio().psor().write(|w| unsafe { w.bits(self.mask()) });
144 } 352 }
145 353
354 /// Set output level to Low.
355 #[inline]
146 pub fn set_low(&mut self) { 356 pub fn set_low(&mut self) {
147 self.gpio().pcor().write(|w| unsafe { w.bits(self.mask()) }); 357 self.gpio().pcor().write(|w| unsafe { w.bits(self.mask()) });
148 } 358 }
149 359
360 /// Set output level to the given `Level`.
361 #[inline]
150 pub fn set_level(&mut self, level: Level) { 362 pub fn set_level(&mut self, level: Level) {
151 match level { 363 match level {
152 Level::High => self.set_high(), 364 Level::High => self.set_high(),
@@ -154,17 +366,35 @@ impl<'d> Flex<'d> {
154 } 366 }
155 } 367 }
156 368
369 /// Toggle output level.
370 #[inline]
157 pub fn toggle(&mut self) { 371 pub fn toggle(&mut self) {
158 self.gpio().ptor().write(|w| unsafe { w.bits(self.mask()) }); 372 self.gpio().ptor().write(|w| unsafe { w.bits(self.mask()) });
159 } 373 }
160 374
375 /// Get whether the pin input level is high.
376 #[inline]
161 pub fn is_high(&self) -> bool { 377 pub fn is_high(&self) -> bool {
162 (self.gpio().pdir().read().bits() & self.mask()) != 0 378 (self.gpio().pdir().read().bits() & self.mask()) != 0
163 } 379 }
164 380
381 /// Get whether the pin input level is low.
382 #[inline]
165 pub fn is_low(&self) -> bool { 383 pub fn is_low(&self) -> bool {
166 !self.is_high() 384 !self.is_high()
167 } 385 }
386
387 /// Is the output pin set as high?
388 #[inline]
389 pub fn is_set_high(&self) -> bool {
390 self.is_high()
391 }
392
393 /// Is the output pin set as low?
394 #[inline]
395 pub fn is_set_low(&self) -> bool {
396 !self.is_set_high()
397 }
168} 398}
169 399
170/// GPIO output driver that owns a `Flex` pin. 400/// GPIO output driver that owns a `Flex` pin.
@@ -173,44 +403,52 @@ pub struct Output<'d> {
173} 403}
174 404
175impl<'d> Output<'d> { 405impl<'d> Output<'d> {
176 pub fn new(pin: AnyPin, initial: Level) -> Self { 406 /// Create a GPIO output driver for a [GpioPin] with the provided [Level].
407 pub fn new(pin: Peri<'d, impl GpioPin>, initial: Level) -> Self {
177 let mut flex = Flex::new(pin); 408 let mut flex = Flex::new(pin);
178 flex.set_level(initial); 409 flex.set_level(initial);
179 flex.set_as_output(); 410 flex.set_as_output();
180 Self { flex } 411 Self { flex }
181 } 412 }
182 413
414 /// Set the output as high.
183 #[inline] 415 #[inline]
184 pub fn set_high(&mut self) { 416 pub fn set_high(&mut self) {
185 self.flex.set_high(); 417 self.flex.set_high();
186 } 418 }
187 419
420 /// Set the output as low.
188 #[inline] 421 #[inline]
189 pub fn set_low(&mut self) { 422 pub fn set_low(&mut self) {
190 self.flex.set_low(); 423 self.flex.set_low();
191 } 424 }
192 425
426 /// Set the output level.
193 #[inline] 427 #[inline]
194 pub fn set_level(&mut self, level: Level) { 428 pub fn set_level(&mut self, level: Level) {
195 self.flex.set_level(level); 429 self.flex.set_level(level);
196 } 430 }
197 431
432 /// Toggle the output level.
198 #[inline] 433 #[inline]
199 pub fn toggle(&mut self) { 434 pub fn toggle(&mut self) {
200 self.flex.toggle(); 435 self.flex.toggle();
201 } 436 }
202 437
438 /// Is the output pin set as high?
203 #[inline] 439 #[inline]
204 pub fn is_set_high(&self) -> bool { 440 pub fn is_set_high(&self) -> bool {
205 self.flex.is_high() 441 self.flex.is_high()
206 } 442 }
207 443
444 /// Is the output pin set as low?
208 #[inline] 445 #[inline]
209 pub fn is_set_low(&self) -> bool { 446 pub fn is_set_low(&self) -> bool {
210 !self.is_set_high() 447 !self.is_set_high()
211 } 448 }
212 449
213 /// Expose the inner `Flex` if callers need to reconfigure the pin. 450 /// Expose the inner `Flex` if callers need to reconfigure the pin.
451 #[inline]
214 pub fn into_flex(self) -> Flex<'d> { 452 pub fn into_flex(self) -> Flex<'d> {
215 self.flex 453 self.flex
216 } 454 }
@@ -222,23 +460,147 @@ pub struct Input<'d> {
222} 460}
223 461
224impl<'d> Input<'d> { 462impl<'d> Input<'d> {
225 pub fn new(pin: AnyPin) -> Self { 463 /// Create a GPIO input driver for a [GpioPin].
464 pub fn new(pin: Peri<'d, impl GpioPin>) -> Self {
226 let mut flex = Flex::new(pin); 465 let mut flex = Flex::new(pin);
227 flex.set_as_input(); 466 flex.set_as_input();
228 Self { flex } 467 Self { flex }
229 } 468 }
230 469
470 /// Get whether the pin input level is high.
231 #[inline] 471 #[inline]
232 pub fn is_high(&self) -> bool { 472 pub fn is_high(&self) -> bool {
233 self.flex.is_high() 473 self.flex.is_high()
234 } 474 }
235 475
476 /// Get whether the pin input level is low.
236 #[inline] 477 #[inline]
237 pub fn is_low(&self) -> bool { 478 pub fn is_low(&self) -> bool {
238 self.flex.is_low() 479 self.flex.is_low()
239 } 480 }
240 481
482 /// Expose the inner `Flex` if callers need to reconfigure the pin.
483 #[inline]
241 pub fn into_flex(self) -> Flex<'d> { 484 pub fn into_flex(self) -> Flex<'d> {
242 self.flex 485 self.flex
243 } 486 }
244} 487}
488
489// Both embedded_hal 0.2 and 1.0 must be supported by embassy HALs.
490impl embedded_hal_02::digital::v2::InputPin for Flex<'_> {
491 // GPIO operations on this block cannot fail, therefor we set the error type
492 // to Infallible to guarantee that we can only produce Ok variants.
493 type Error = Infallible;
494
495 #[inline]
496 fn is_high(&self) -> Result<bool, Self::Error> {
497 Ok(self.is_high())
498 }
499
500 #[inline]
501 fn is_low(&self) -> Result<bool, Self::Error> {
502 Ok(self.is_low())
503 }
504}
505
506impl embedded_hal_02::digital::v2::InputPin for Input<'_> {
507 type Error = Infallible;
508
509 #[inline]
510 fn is_high(&self) -> Result<bool, Self::Error> {
511 Ok(self.is_high())
512 }
513
514 #[inline]
515 fn is_low(&self) -> Result<bool, Self::Error> {
516 Ok(self.is_low())
517 }
518}
519
520impl embedded_hal_02::digital::v2::OutputPin for Flex<'_> {
521 type Error = Infallible;
522
523 #[inline]
524 fn set_high(&mut self) -> Result<(), Self::Error> {
525 self.set_high();
526 Ok(())
527 }
528
529 #[inline]
530 fn set_low(&mut self) -> Result<(), Self::Error> {
531 self.set_low();
532 Ok(())
533 }
534}
535
536impl embedded_hal_02::digital::v2::StatefulOutputPin for Flex<'_> {
537 #[inline]
538 fn is_set_high(&self) -> Result<bool, Self::Error> {
539 Ok(self.is_set_high())
540 }
541
542 #[inline]
543 fn is_set_low(&self) -> Result<bool, Self::Error> {
544 Ok(self.is_set_low())
545 }
546}
547
548impl embedded_hal_02::digital::v2::ToggleableOutputPin for Flex<'_> {
549 type Error = Infallible;
550
551 #[inline]
552 fn toggle(&mut self) -> Result<(), Self::Error> {
553 self.toggle();
554 Ok(())
555 }
556}
557
558impl embedded_hal_1::digital::ErrorType for Flex<'_> {
559 type Error = Infallible;
560}
561
562impl embedded_hal_1::digital::ErrorType for Input<'_> {
563 type Error = Infallible;
564}
565
566impl embedded_hal_1::digital::ErrorType for Output<'_> {
567 type Error = Infallible;
568}
569
570impl embedded_hal_1::digital::InputPin for Input<'_> {
571 #[inline]
572 fn is_high(&mut self) -> Result<bool, Self::Error> {
573 Ok((*self).is_high())
574 }
575
576 #[inline]
577 fn is_low(&mut self) -> Result<bool, Self::Error> {
578 Ok((*self).is_low())
579 }
580}
581
582impl embedded_hal_1::digital::OutputPin for Flex<'_> {
583 #[inline]
584 fn set_high(&mut self) -> Result<(), Self::Error> {
585 self.set_high();
586 Ok(())
587 }
588
589 #[inline]
590 fn set_low(&mut self) -> Result<(), Self::Error> {
591 self.set_low();
592 Ok(())
593 }
594}
595
596impl embedded_hal_1::digital::StatefulOutputPin for Flex<'_> {
597 #[inline]
598 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
599 Ok((*self).is_set_high())
600 }
601
602 #[inline]
603 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
604 Ok((*self).is_set_low())
605 }
606}
diff --git a/src/lib.rs b/src/lib.rs
index 86c0dc45b..c885ecc50 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -14,7 +14,301 @@ pub mod lpuart;
14pub mod ostimer; 14pub mod ostimer;
15pub mod rtc; 15pub mod rtc;
16 16
17embassy_hal_internal::peripherals!(PORT1, PORT2, PORT3, LPUART2, OSTIMER0, GPIO, PIO2_2, PIO2_3, GPIO3, RTC0, ADC1,); 17#[rustfmt::skip]
18embassy_hal_internal::peripherals!(
19 ADC0,
20 ADC1,
21
22 AOI0,
23 AOI1,
24
25 CAN0,
26 CAN1,
27
28 CDOG0,
29 CDOG1,
30
31 CMC,
32 CMP0,
33 CMP1,
34 CRC0,
35
36 CTIMER0,
37 CTIMER1,
38 CTIMER2,
39 CTIMER3,
40 CTIMER4,
41
42 DBGMAILBOX,
43 DMA0,
44 EDMA0_TCD0,
45 EIM0,
46 EQDC0,
47 EQDC1,
48 ERM0,
49 FLEXIO0,
50 FLEXPWM0,
51 FLEXPWM1,
52 FMC0,
53 FMU0,
54 FREQME0,
55 GLIKEY0,
56
57 GPIO0,
58 GPIO1,
59 GPIO2,
60 GPIO3,
61 GPIO4,
62
63 I3C0,
64 INPUTMUX0,
65
66 LPI2C0,
67 LPI2C1,
68 LPI2C2,
69 LPI2C3,
70
71 LPSPI0,
72 LPSPI1,
73
74 LPTMR0,
75
76 LPUART0,
77 LPUART1,
78 LPUART2,
79 LPUART3,
80 LPUART4,
81
82 MAU0,
83 MBC0,
84 MRCC0,
85 OPAMP0,
86 OSTIMER0,
87
88 P0_0,
89 P0_1,
90 P0_2,
91 P0_3,
92 P0_4,
93 P0_5,
94 P0_6,
95 P0_7,
96 P0_8,
97 P0_9,
98 P0_10,
99 P0_11,
100 P0_12,
101 P0_13,
102 P0_14,
103 P0_15,
104 P0_16,
105 P0_17,
106 P0_18,
107 P0_19,
108 P0_20,
109 P0_21,
110 P0_22,
111 P0_23,
112 P0_24,
113 P0_25,
114 P0_26,
115 P0_27,
116 P0_28,
117 P0_29,
118 P0_30,
119 P0_31,
120
121 P1_0,
122 P1_1,
123 P1_2,
124 P1_3,
125 P1_4,
126 P1_5,
127 P1_6,
128 P1_7,
129 P1_8,
130 P1_9,
131 P1_10,
132 P1_11,
133 P1_12,
134 P1_13,
135 P1_14,
136 P1_15,
137 P1_16,
138 P1_17,
139 P1_18,
140 P1_19,
141 P1_20,
142 P1_21,
143 P1_22,
144 P1_23,
145 P1_24,
146 P1_25,
147 P1_26,
148 P1_27,
149 P1_28,
150 P1_29,
151 P1_30,
152 P1_31,
153
154 P2_0,
155 P2_1,
156 P2_2,
157 P2_3,
158 P2_4,
159 P2_5,
160 P2_6,
161 P2_7,
162 P2_8,
163 P2_9,
164 P2_10,
165 P2_11,
166 P2_12,
167 P2_13,
168 P2_14,
169 P2_15,
170 P2_16,
171 P2_17,
172 P2_18,
173 P2_19,
174 P2_20,
175 P2_21,
176 P2_22,
177 P2_23,
178 P2_24,
179 P2_25,
180 P2_26,
181 P2_27,
182 P2_28,
183 P2_29,
184 P2_30,
185 P2_31,
186
187 P3_0,
188 P3_1,
189 P3_2,
190 P3_3,
191 P3_4,
192 P3_5,
193 P3_6,
194 P3_7,
195 P3_8,
196 P3_9,
197 P3_10,
198 P3_11,
199 P3_12,
200 P3_13,
201 P3_14,
202 P3_15,
203 P3_16,
204 P3_17,
205 P3_18,
206 P3_19,
207 P3_20,
208 P3_21,
209 P3_22,
210 P3_23,
211 P3_24,
212 P3_25,
213 P3_26,
214 P3_27,
215 P3_28,
216 P3_29,
217 P3_30,
218 P3_31,
219
220 P4_0,
221 P4_1,
222 P4_2,
223 P4_3,
224 P4_4,
225 P4_5,
226 P4_6,
227 P4_7,
228 P4_8,
229 P4_9,
230 P4_10,
231 P4_11,
232 P4_12,
233 P4_13,
234 P4_14,
235 P4_15,
236 P4_16,
237 P4_17,
238 P4_18,
239 P4_19,
240 P4_20,
241 P4_21,
242 P4_22,
243 P4_23,
244 P4_24,
245 P4_25,
246 P4_26,
247 P4_27,
248 P4_28,
249 P4_29,
250 P4_30,
251 P4_31,
252
253 P5_0,
254 P5_1,
255 P5_2,
256 P5_3,
257 P5_4,
258 P5_5,
259 P5_6,
260 P5_7,
261 P5_8,
262 P5_9,
263 P5_10,
264 P5_11,
265 P5_12,
266 P5_13,
267 P5_14,
268 P5_15,
269 P5_16,
270 P5_17,
271 P5_18,
272 P5_19,
273 P5_20,
274 P5_21,
275 P5_22,
276 P5_23,
277 P5_24,
278 P5_25,
279 P5_26,
280 P5_27,
281 P5_28,
282 P5_29,
283 P5_30,
284 P5_31,
285
286 PKC0,
287
288 PORT0,
289 PORT1,
290 PORT2,
291 PORT3,
292 PORT4,
293
294 RTC0,
295 SAU,
296 SCG0,
297 SCN_SCB,
298 SGI0,
299 SMARTDMA0,
300 SPC0,
301 SYSCON,
302 TDET0,
303 TRNG0,
304 UDF0,
305 USB0,
306 UTICK0,
307 VBAT0,
308 WAKETIMER0,
309 WUU0,
310 WWDT0,
311);
18 312
19/// Get access to the PAC Peripherals for low-level register access. 313/// Get access to the PAC Peripherals for low-level register access.
20/// This is a lazy-initialized singleton that can be called after init(). 314/// This is a lazy-initialized singleton that can be called after init().
@@ -35,7 +329,6 @@ pub fn pac() -> &'static pac::Peripherals {
35 329
36// Re-export interrupt traits and types 330// Re-export interrupt traits and types
37pub use adc::Adc1 as Adc1Token; 331pub use adc::Adc1 as Adc1Token;
38pub use gpio::pins::*;
39pub use gpio::{AnyPin, Flex, Gpio as GpioToken, Input, Level, Output}; 332pub use gpio::{AnyPin, Flex, Gpio as GpioToken, Input, Level, Output};
40pub use interrupt::InterruptExt; 333pub use interrupt::InterruptExt;
41#[cfg(feature = "unstable-pac")] 334#[cfg(feature = "unstable-pac")]
@@ -59,6 +352,24 @@ pub fn init(cfg: crate::config::Config) -> Peripherals {
59 // Configure clocks 352 // Configure clocks
60 crate::clocks::init(cfg.clock_cfg).unwrap(); 353 crate::clocks::init(cfg.clock_cfg).unwrap();
61 354
355 // Enable GPIO clocks
356 unsafe {
357 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT0>(&crate::clocks::periph_helpers::NoConfig);
358 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO0>(&crate::clocks::periph_helpers::NoConfig);
359
360 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT1>(&crate::clocks::periph_helpers::NoConfig);
361 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO1>(&crate::clocks::periph_helpers::NoConfig);
362
363 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT2>(&crate::clocks::periph_helpers::NoConfig);
364 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO2>(&crate::clocks::periph_helpers::NoConfig);
365
366 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT3>(&crate::clocks::periph_helpers::NoConfig);
367 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO3>(&crate::clocks::periph_helpers::NoConfig);
368
369 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT4>(&crate::clocks::periph_helpers::NoConfig);
370 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO4>(&crate::clocks::periph_helpers::NoConfig);
371 }
372
62 peripherals 373 peripherals
63} 374}
64 375
diff --git a/src/lpuart/mod.rs b/src/lpuart/mod.rs
index b3d7c4885..f069f6567 100644
--- a/src/lpuart/mod.rs
+++ b/src/lpuart/mod.rs
@@ -53,7 +53,7 @@ mod gpio {
53 } 53 }
54 54
55 // Implement GpioPin for all pins from lib.rs 55 // Implement GpioPin for all pins from lib.rs
56 impl_gpio_pin!(PIO2_2, PIO2_3); 56 impl_gpio_pin!(P2_2, P2_3);
57 57
58 #[derive(Debug, Clone, Copy)] 58 #[derive(Debug, Clone, Copy)]
59 pub struct AnyPin; 59 pub struct AnyPin;
@@ -433,12 +433,12 @@ macro_rules! impl_pin_trait {
433} 433}
434 434
435// Document identifier: MCXA343/344 Rev. 1DraftB ReleaseCandidate, 2025-07-10 - 6.1 MCX A173, A174 Signal Multiplexing and Pin Assignments 435// Document identifier: MCXA343/344 Rev. 1DraftB ReleaseCandidate, 2025-07-10 - 6.1 MCX A173, A174 Signal Multiplexing and Pin Assignments
436// impl_pin_trait!(LPUART0, rx, PIO2_0, ALT2, PIO0_2, ALT2, PIO0_20, ALT3); 436// impl_pin_trait!(LPUART0, rx, P2_0, ALT2, P0_2, ALT2, P0_20, ALT3);
437// impl_pin_trait!(LPUART0, tx, PIO2_1, ALT2, PIO0_3, ALT2, PIO0_21, ALT3); 437// impl_pin_trait!(LPUART0, tx, P2_1, ALT2, P0_3, ALT2, P0_21, ALT3);
438// impl_pin_trait!(LPUART0, rts, PIO2_2, ALT2, PIO0_0, ALT2, PIO0_22, ALT3); 438// impl_pin_trait!(LPUART0, rts, P2_2, ALT2, P0_0, ALT2, P0_22, ALT3);
439// impl_pin_trait!(LPUART0, cts, PIO2_3, ALT2, PIO0_1, ALT2, PIO0_23, ALT3); 439// impl_pin_trait!(LPUART0, cts, P2_3, ALT2, P0_1, ALT2, P0_23, ALT3);
440impl_pin_trait!(LPUART2, rx, PIO2_3, ALT3); 440impl_pin_trait!(LPUART2, rx, P2_3, ALT3);
441impl_pin_trait!(LPUART2, tx, PIO2_2, ALT3); 441impl_pin_trait!(LPUART2, tx, P2_2, ALT3);
442 442
443// ============================================================================ 443// ============================================================================
444// ERROR TYPES AND RESULTS 444// ERROR TYPES AND RESULTS