aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-11-25 18:08:13 +0100
committerGitHub <[email protected]>2025-11-25 18:08:13 +0100
commit05bf2d0438fe8c41d0fe26b85106ff73a6e273e9 (patch)
tree8a2969ac89735154f8090d629d9c37814a25190a
parent7ee5cb570f0c0daeb2e6a9d5120fd96ee885025f (diff)
Wire up Lpuart pins (#43)
Allow the HAL lpuart driver to correctly configure pins as requested on init.
-rw-r--r--Cargo.lock2
-rw-r--r--examples/Cargo.lock2
-rw-r--r--examples/src/bin/adc_interrupt.rs26
-rw-r--r--examples/src/bin/adc_polling.rs31
-rw-r--r--examples/src/bin/hello.rs3
-rw-r--r--examples/src/bin/lpuart_buffered.rs29
-rw-r--r--examples/src/bin/lpuart_polling.rs12
-rw-r--r--examples/src/bin/rtc_alarm.rs33
-rw-r--r--examples/src/lib.rs9
-rw-r--r--src/clocks/config.rs5
-rw-r--r--src/clocks/mod.rs5
-rw-r--r--src/interrupt.rs2
-rw-r--r--src/lib.rs1
-rw-r--r--src/lpuart/buffered.rs20
-rw-r--r--src/lpuart/mod.rs231
-rw-r--r--src/pins.rs34
16 files changed, 205 insertions, 240 deletions
diff --git a/Cargo.lock b/Cargo.lock
index eb6c142ef..314120a47 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -324,7 +324,7 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
324[[package]] 324[[package]]
325name = "mcxa-pac" 325name = "mcxa-pac"
326version = "0.1.0" 326version = "0.1.0"
327source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#9a857ec9780527679978b42cc60288aeef03baa2" 327source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca"
328dependencies = [ 328dependencies = [
329 "cortex-m", 329 "cortex-m",
330 "cortex-m-rt", 330 "cortex-m-rt",
diff --git a/examples/Cargo.lock b/examples/Cargo.lock
index 56ae41d48..263807120 100644
--- a/examples/Cargo.lock
+++ b/examples/Cargo.lock
@@ -442,7 +442,7 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
442[[package]] 442[[package]]
443name = "mcxa-pac" 443name = "mcxa-pac"
444version = "0.1.0" 444version = "0.1.0"
445source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#9a857ec9780527679978b42cc60288aeef03baa2" 445source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca"
446dependencies = [ 446dependencies = [
447 "cortex-m", 447 "cortex-m",
448 "cortex-m-rt", 448 "cortex-m-rt",
diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs
index 0d3a75a28..83d8046b3 100644
--- a/examples/src/bin/adc_interrupt.rs
+++ b/examples/src/bin/adc_interrupt.rs
@@ -6,7 +6,6 @@ use embassy_mcxa_examples::init_adc_pins;
6use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; 6use hal::adc::{LpadcConfig, TriggerPriorityPolicy};
7use hal::clocks::periph_helpers::{AdcClockSel, Div4}; 7use hal::clocks::periph_helpers::{AdcClockSel, Div4};
8use hal::clocks::PoweredClock; 8use hal::clocks::PoweredClock;
9use hal::lpuart::{Config, Lpuart};
10use hal::pac::adc1::cfg::{Pwrsel, Refsel}; 9use hal::pac::adc1::cfg::{Pwrsel, Refsel};
11use hal::pac::adc1::cmdl1::{Adch, Mode}; 10use hal::pac::adc1::cmdl1::{Adch, Mode};
12use hal::pac::adc1::ctrl::CalAvgs; 11use hal::pac::adc1::ctrl::CalAvgs;
@@ -26,26 +25,7 @@ static KEEP_ADC: unsafe extern "C" fn() = ADC1;
26async fn main(_spawner: Spawner) { 25async fn main(_spawner: Spawner) {
27 let p = hal::init(hal::config::Config::default()); 26 let p = hal::init(hal::config::Config::default());
28 27
29 // Create UART configuration 28 defmt::info!("ADC interrupt Example");
30 let config = Config {
31 baudrate_bps: 115_200,
32 enable_tx: true,
33 enable_rx: true,
34 ..Default::default()
35 };
36
37 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
38 unsafe {
39 embassy_mcxa_examples::init_uart2_pins();
40 }
41 let mut uart = Lpuart::new_blocking(
42 p.LPUART2, // Peripheral
43 p.P2_2, // TX pin
44 p.P2_3, // RX pin
45 config,
46 )
47 .unwrap();
48 uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n");
49 29
50 unsafe { 30 unsafe {
51 init_adc_pins(); 31 init_adc_pins();
@@ -81,7 +61,7 @@ async fn main(_spawner: Spawner) {
81 conv_trigger_config.enable_hardware_trigger = false; 61 conv_trigger_config.enable_hardware_trigger = false;
82 adc.set_conv_trigger_config(0, &conv_trigger_config); 62 adc.set_conv_trigger_config(0, &conv_trigger_config);
83 63
84 uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); 64 defmt::info!("ADC configuration done...");
85 65
86 adc.enable_interrupt(0x1); 66 adc.enable_interrupt(0x1);
87 67
@@ -98,7 +78,7 @@ async fn main(_spawner: Spawner) {
98 while !adc.is_interrupt_triggered() { 78 while !adc.is_interrupt_triggered() {
99 // Wait until the interrupt is triggered 79 // Wait until the interrupt is triggered
100 } 80 }
101 uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); 81 defmt::info!("*** ADC interrupt TRIGGERED! ***");
102 //TBD need to print the value 82 //TBD need to print the value
103 } 83 }
104} 84}
diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs
index 02ac321b5..ddf3f586b 100644
--- a/examples/src/bin/adc_polling.rs
+++ b/examples/src/bin/adc_polling.rs
@@ -1,19 +1,15 @@
1#![no_std] 1#![no_std]
2#![no_main] 2#![no_main]
3 3
4use core::fmt::Write;
5
6use embassy_executor::Spawner; 4use embassy_executor::Spawner;
7use embassy_mcxa_examples::{init_adc_pins, init_uart2_pins}; 5use embassy_mcxa_examples::init_adc_pins;
8use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; 6use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy};
9use hal::clocks::periph_helpers::{AdcClockSel, Div4}; 7use hal::clocks::periph_helpers::{AdcClockSel, Div4};
10use hal::clocks::PoweredClock; 8use hal::clocks::PoweredClock;
11use hal::lpuart::{Config, Lpuart};
12use hal::pac::adc1::cfg::{Pwrsel, Refsel}; 9use hal::pac::adc1::cfg::{Pwrsel, Refsel};
13use hal::pac::adc1::cmdl1::{Adch, Mode}; 10use hal::pac::adc1::cmdl1::{Adch, Mode};
14use hal::pac::adc1::ctrl::CalAvgs; 11use hal::pac::adc1::ctrl::CalAvgs;
15use hal::pac::adc1::tctrl::Tcmd; 12use hal::pac::adc1::tctrl::Tcmd;
16use heapless::String;
17use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; 13use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
18 14
19const G_LPADC_RESULT_SHIFT: u32 = 0; 15const G_LPADC_RESULT_SHIFT: u32 = 0;
@@ -22,28 +18,11 @@ const G_LPADC_RESULT_SHIFT: u32 = 0;
22async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
23 let p = hal::init(hal::config::Config::default()); 19 let p = hal::init(hal::config::Config::default());
24 20
25 // Create UART configuration
26 let config = Config {
27 baudrate_bps: 115_200,
28 enable_tx: true,
29 enable_rx: true,
30 ..Default::default()
31 };
32
33 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
34 unsafe { 21 unsafe {
35 init_uart2_pins();
36 init_adc_pins(); 22 init_adc_pins();
37 } 23 }
38 let mut uart = Lpuart::new_blocking(
39 p.LPUART2, // Peripheral
40 p.P2_2, // TX pin
41 p.P2_3, // RX pin
42 config,
43 )
44 .unwrap();
45 24
46 uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); 25 defmt::info!("=== ADC polling Example ===");
47 26
48 let adc_config = LpadcConfig { 27 let adc_config = LpadcConfig {
49 enable_in_doze_mode: true, 28 enable_in_doze_mode: true,
@@ -75,7 +54,7 @@ async fn main(_spawner: Spawner) {
75 conv_trigger_config.enable_hardware_trigger = false; 54 conv_trigger_config.enable_hardware_trigger = false;
76 adc.set_conv_trigger_config(0, &conv_trigger_config); 55 adc.set_conv_trigger_config(0, &conv_trigger_config);
77 56
78 uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); 57 defmt::info!("=== ADC configuration done... ===");
79 58
80 loop { 59 loop {
81 adc.do_software_trigger(1); 60 adc.do_software_trigger(1);
@@ -84,8 +63,6 @@ async fn main(_spawner: Spawner) {
84 result = hal::adc::get_conv_result(); 63 result = hal::adc::get_conv_result();
85 } 64 }
86 let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; 65 let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT;
87 let mut buf: String<16> = String::new(); // adjust size as needed 66 defmt::info!("value: {=u16}", value);
88 write!(buf, "\r\nvalue: {}\r\n", value).unwrap();
89 uart.write_str_blocking(&buf);
90 } 67 }
91} 68}
diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs
index 0362480c1..f426d1898 100644
--- a/examples/src/bin/hello.rs
+++ b/examples/src/bin/hello.rs
@@ -27,9 +27,6 @@ async fn main(_spawner: Spawner) {
27 }; 27 };
28 28
29 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX 29 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
30 unsafe {
31 embassy_mcxa_examples::init_uart2_pins();
32 }
33 let mut uart = Lpuart::new_blocking( 30 let mut uart = Lpuart::new_blocking(
34 p.LPUART2, // Peripheral 31 p.LPUART2, // Peripheral
35 p.P2_2, // TX pin 32 p.P2_2, // TX pin
diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs
index 4c9294f57..7f77d557d 100644
--- a/examples/src/bin/lpuart_buffered.rs
+++ b/examples/src/bin/lpuart_buffered.rs
@@ -2,39 +2,28 @@
2#![no_main] 2#![no_main]
3 3
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_mcxa as hal; 5use embassy_mcxa::clocks::config::Div8;
6use embassy_mcxa::interrupt::typelevel::Handler;
7use embassy_mcxa::lpuart::buffered::BufferedLpuart; 6use embassy_mcxa::lpuart::buffered::BufferedLpuart;
8use embassy_mcxa::lpuart::Config; 7use embassy_mcxa::lpuart::Config;
9use embassy_mcxa::{bind_interrupts, lpuart}; 8use embassy_mcxa::{bind_interrupts, lpuart};
10use embassy_mcxa_examples::init_uart2_pins; 9use embedded_io_async::Write;
11use embedded_io_async::{Read, Write}; 10use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
12 11
13// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver 12// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver
14bind_interrupts!(struct Irqs { 13bind_interrupts!(struct Irqs {
15 LPUART2 => lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>; 14 LPUART2 => lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>;
16}); 15});
17 16
18// Wrapper function for the interrupt handler
19unsafe extern "C" fn lpuart2_handler() {
20 lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>::on_interrupt();
21}
22
23#[embassy_executor::main] 17#[embassy_executor::main]
24async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
25 let p = hal::init(hal::config::Config::default()); 19 let mut cfg = hal::config::Config::default();
26 20 cfg.clock_cfg.sirc.fro_12m_enabled = true;
27 unsafe { 21 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
28 hal::interrupt::install_irq_handler(hal::pac::Interrupt::LPUART2, lpuart2_handler); 22 let p = hal::init(cfg);
29 }
30 23
31 // Configure NVIC for LPUART2 24 // Configure NVIC for LPUART2
32 hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); 25 hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3);
33 26
34 unsafe {
35 init_uart2_pins();
36 }
37
38 // UART configuration (enable both TX and RX) 27 // UART configuration (enable both TX and RX)
39 let config = Config { 28 let config = Config {
40 baudrate_bps: 115_200, 29 baudrate_bps: 115_200,
@@ -69,7 +58,7 @@ async fn main(_spawner: Spawner) {
69 // Echo loop 58 // Echo loop
70 let mut buf = [0u8; 4]; 59 let mut buf = [0u8; 4];
71 loop { 60 loop {
72 rx.read_exact(&mut buf[..]).await.unwrap(); 61 let used = rx.read(&mut buf).await.unwrap();
73 tx.write_all(&buf[..]).await.unwrap(); 62 tx.write_all(&buf[..used]).await.unwrap();
74 } 63 }
75} 64}
diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs
index c8666e64a..9cea418cc 100644
--- a/examples/src/bin/lpuart_polling.rs
+++ b/examples/src/bin/lpuart_polling.rs
@@ -2,22 +2,20 @@
2#![no_main] 2#![no_main]
3 3
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_mcxa_examples::init_uart2_pins; 5use embassy_mcxa::clocks::config::Div8;
6use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; 6use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
7 7
8use crate::hal::lpuart::{Config, Lpuart}; 8use crate::hal::lpuart::{Config, Lpuart};
9 9
10#[embassy_executor::main] 10#[embassy_executor::main]
11async fn main(_spawner: Spawner) { 11async fn main(_spawner: Spawner) {
12 let p = hal::init(hal::config::Config::default()); 12 let mut cfg = hal::config::Config::default();
13 cfg.clock_cfg.sirc.fro_12m_enabled = true;
14 cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div());
15 let p = hal::init(cfg);
13 16
14 defmt::info!("boot"); 17 defmt::info!("boot");
15 18
16 // Board-level init for UART2 clocks and pins.
17 unsafe {
18 init_uart2_pins();
19 }
20
21 // Create UART configuration 19 // Create UART configuration
22 let config = Config { 20 let config = Config {
23 baudrate_bps: 115_200, 21 baudrate_bps: 115_200,
diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs
index 6f8a77101..a7800a2d1 100644
--- a/examples/src/bin/rtc_alarm.rs
+++ b/examples/src/bin/rtc_alarm.rs
@@ -3,7 +3,6 @@
3 3
4use embassy_executor::Spawner; 4use embassy_executor::Spawner;
5use embassy_mcxa as hal; 5use embassy_mcxa as hal;
6use hal::lpuart::{Config, Lpuart};
7use hal::rtc::{RtcDateTime, RtcInterruptEnable}; 6use hal::rtc::{RtcDateTime, RtcInterruptEnable};
8use hal::InterruptExt; 7use hal::InterruptExt;
9 8
@@ -24,27 +23,7 @@ static KEEP_RTC: unsafe extern "C" fn() = RTC;
24async fn main(_spawner: Spawner) { 23async fn main(_spawner: Spawner) {
25 let p = hal::init(hal::config::Config::default()); 24 let p = hal::init(hal::config::Config::default());
26 25
27 // Create UART configuration 26 defmt::info!("=== RTC Alarm Example ===");
28 let config = Config {
29 baudrate_bps: 115_200,
30 enable_tx: true,
31 enable_rx: true,
32 ..Default::default()
33 };
34
35 // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX
36 unsafe {
37 embassy_mcxa_examples::init_uart2_pins();
38 }
39 let mut uart = Lpuart::new_blocking(
40 p.LPUART2, // Peripheral
41 p.P2_2, // TX pin
42 p.P2_3, // RX pin
43 config,
44 )
45 .unwrap();
46
47 uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n");
48 27
49 let rtc_config = hal::rtc::get_default_config(); 28 let rtc_config = hal::rtc::get_default_config();
50 29
@@ -61,14 +40,14 @@ async fn main(_spawner: Spawner) {
61 40
62 rtc.stop(); 41 rtc.stop();
63 42
64 uart.write_str_blocking("Time set to: 2025-10-15 14:30:00\r\n"); 43 defmt::info!("Time set to: 2025-10-15 14:30:00");
65 rtc.set_datetime(now); 44 rtc.set_datetime(now);
66 45
67 let mut alarm = now; 46 let mut alarm = now;
68 alarm.second += 10; 47 alarm.second += 10;
69 48
70 rtc.set_alarm(alarm); 49 rtc.set_alarm(alarm);
71 uart.write_str_blocking("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)\r\n"); 50 defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)");
72 51
73 rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE); 52 rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE);
74 53
@@ -82,14 +61,14 @@ async fn main(_spawner: Spawner) {
82 61
83 rtc.start(); 62 rtc.start();
84 63
85 uart.write_str_blocking("RTC started, waiting for alarm...\r\n"); 64 defmt::info!("RTC started, waiting for alarm...");
86 65
87 loop { 66 loop {
88 if rtc.is_alarm_triggered() { 67 if rtc.is_alarm_triggered() {
89 uart.write_str_blocking("\r\n*** ALARM TRIGGERED! ***\r\n"); 68 defmt::info!("*** ALARM TRIGGERED! ***");
90 break; 69 break;
91 } 70 }
92 } 71 }
93 72
94 uart.write_str_blocking("Example complete - Test PASSED!\r\n"); 73 defmt::info!("Example complete - Test PASSED!");
95} 74}
diff --git a/examples/src/lib.rs b/examples/src/lib.rs
index f5f6124c0..2573a6adc 100644
--- a/examples/src/lib.rs
+++ b/examples/src/lib.rs
@@ -7,15 +7,6 @@
7use hal::{clocks, pins}; 7use hal::{clocks, pins};
8use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; 8use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _};
9 9
10/// Initialize clocks and pin muxing for UART2 debug console.
11/// Safe to call multiple times; writes are idempotent for our use.
12pub unsafe fn init_uart2_pins() {
13 // NOTE: Lpuart has been updated to properly enable + reset its own clocks.
14 // GPIO has not.
15 _ = clocks::enable_and_reset::<hal::peripherals::PORT2>(&clocks::periph_helpers::NoConfig);
16 pins::configure_uart2_pins_port2();
17}
18
19/// Initialize clocks and pin muxing for ADC. 10/// Initialize clocks and pin muxing for ADC.
20pub unsafe fn init_adc_pins() { 11pub unsafe fn init_adc_pins() {
21 // NOTE: Lpuart has been updated to properly enable + reset its own clocks. 12 // NOTE: Lpuart has been updated to properly enable + reset its own clocks.
diff --git a/src/clocks/config.rs b/src/clocks/config.rs
index a517afcca..0563b8917 100644
--- a/src/clocks/config.rs
+++ b/src/clocks/config.rs
@@ -21,6 +21,11 @@ impl Div8 {
21 Self(n) 21 Self(n)
22 } 22 }
23 23
24 /// Divide by one, or no division
25 pub const fn no_div() -> Self {
26 Self(0)
27 }
28
24 /// Store a specific divisor value that will divide the source 29 /// Store a specific divisor value that will divide the source
25 /// by `n`. e.g. `Div8::from_divisor(1)` will divide the source 30 /// by `n`. e.g. `Div8::from_divisor(1)` will divide the source
26 /// by 1, and `Div8::from_divisor(256)` will divide the source 31 /// by 1, and `Div8::from_divisor(256)` will divide the source
diff --git a/src/clocks/mod.rs b/src/clocks/mod.rs
index 948355079..cd6318c4b 100644
--- a/src/clocks/mod.rs
+++ b/src/clocks/mod.rs
@@ -928,6 +928,11 @@ pub(crate) mod gate {
928 #[cfg(not(feature = "time"))] 928 #[cfg(not(feature = "time"))]
929 impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig); 929 impl_cc_gate!(OSTIMER0, mrcc_glb_cc1, mrcc_glb_rst1, ostimer0, OsTimerConfig);
930 930
931 impl_cc_gate!(LPUART0, mrcc_glb_cc0, mrcc_glb_rst0, lpuart0, LpuartConfig);
932 impl_cc_gate!(LPUART1, mrcc_glb_cc0, mrcc_glb_rst0, lpuart1, LpuartConfig);
931 impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig); 933 impl_cc_gate!(LPUART2, mrcc_glb_cc0, mrcc_glb_rst0, lpuart2, LpuartConfig);
934 impl_cc_gate!(LPUART3, mrcc_glb_cc0, mrcc_glb_rst0, lpuart3, LpuartConfig);
935 impl_cc_gate!(LPUART4, mrcc_glb_cc0, mrcc_glb_rst0, lpuart4, LpuartConfig);
936 impl_cc_gate!(LPUART5, mrcc_glb_cc1, mrcc_glb_rst1, lpuart5, LpuartConfig);
932 impl_cc_gate!(ADC1, mrcc_glb_cc1, mrcc_glb_rst1, adc1, AdcConfig); 937 impl_cc_gate!(ADC1, mrcc_glb_cc1, mrcc_glb_rst1, adc1, AdcConfig);
933} 938}
diff --git a/src/interrupt.rs b/src/interrupt.rs
index 134ff03fd..4d409067a 100644
--- a/src/interrupt.rs
+++ b/src/interrupt.rs
@@ -7,7 +7,7 @@
7#![allow(clippy::missing_safety_doc)] 7#![allow(clippy::missing_safety_doc)]
8 8
9mod generated { 9mod generated {
10 embassy_hal_internal::interrupt_mod!(OS_EVENT, LPUART2, RTC, ADC1); 10 embassy_hal_internal::interrupt_mod!(OS_EVENT, LPUART0, LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, RTC, ADC1,);
11} 11}
12 12
13use core::sync::atomic::{AtomicU16, AtomicU32, Ordering}; 13use core::sync::atomic::{AtomicU16, AtomicU32, Ordering};
diff --git a/src/lib.rs b/src/lib.rs
index 95e6b3479..f9dda67d9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -88,6 +88,7 @@ embassy_hal_internal::peripherals!(
88 LPUART2, 88 LPUART2,
89 LPUART3, 89 LPUART3,
90 LPUART4, 90 LPUART4,
91 LPUART5,
91 92
92 MAU0, 93 MAU0,
93 MBC0, 94 MBC0,
diff --git a/src/lpuart/buffered.rs b/src/lpuart/buffered.rs
index 7b575c086..6f41c33c9 100644
--- a/src/lpuart/buffered.rs
+++ b/src/lpuart/buffered.rs
@@ -123,28 +123,24 @@ impl<'a> BufferedLpuart<'a> {
123 config: Config, 123 config: Config,
124 ) -> Result<Self> { 124 ) -> Result<Self> {
125 // Configure pins if provided 125 // Configure pins if provided
126 let tx_pin = tx_pin.map(|pin| { 126 let tx_pin: Option<Peri<'a, AnyPin>> = tx_pin.map(|pin| {
127 pin.as_tx(); 127 pin.as_tx();
128 let converted: Peri<'a, AnyPin> = pin.into(); 128 pin.into()
129 converted
130 }); 129 });
131 130
132 let rx_pin = rx_pin.map(|pin| { 131 let rx_pin: Option<Peri<'a, AnyPin>> = rx_pin.map(|pin| {
133 pin.as_rx(); 132 pin.as_rx();
134 let converted: Peri<'a, AnyPin> = pin.into(); 133 pin.into()
135 converted
136 }); 134 });
137 135
138 let rts_pin = rts_pin.map(|pin| { 136 let rts_pin: Option<Peri<'a, AnyPin>> = rts_pin.map(|pin| {
139 pin.as_rts(); 137 pin.as_rts();
140 let converted: Peri<'a, AnyPin> = pin.into(); 138 pin.into()
141 converted
142 }); 139 });
143 140
144 let cts_pin = cts_pin.map(|pin| { 141 let cts_pin: Option<Peri<'a, AnyPin>> = cts_pin.map(|pin| {
145 pin.as_cts(); 142 pin.as_cts();
146 let converted: Peri<'a, AnyPin> = pin.into(); 143 pin.into()
147 converted
148 }); 144 });
149 145
150 let state = T::buffered_state(); 146 let state = T::buffered_state();
diff --git a/src/lpuart/mod.rs b/src/lpuart/mod.rs
index f069f6567..911c2a8e9 100644
--- a/src/lpuart/mod.rs
+++ b/src/lpuart/mod.rs
@@ -5,11 +5,12 @@ use paste::paste;
5 5
6use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig}; 6use crate::clocks::periph_helpers::{Div4, LpuartClockSel, LpuartConfig};
7use crate::clocks::{enable_and_reset, ClockError, Gate, PoweredClock}; 7use crate::clocks::{enable_and_reset, ClockError, Gate, PoweredClock};
8use crate::gpio::SealedPin;
8use crate::pac::lpuart0::baud::Sbns as StopBits; 9use crate::pac::lpuart0::baud::Sbns as StopBits;
9use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, Pt as Parity, M as DataBits}; 10use crate::pac::lpuart0::ctrl::{Idlecfg as IdleConfig, Ilt as IdleType, Pt as Parity, M as DataBits};
10use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource}; 11use crate::pac::lpuart0::modir::{Txctsc as TxCtsConfig, Txctssrc as TxCtsSource};
11use crate::pac::lpuart0::stat::Msbf as MsbFirst; 12use crate::pac::lpuart0::stat::Msbf as MsbFirst;
12use crate::{interrupt, pac}; 13use crate::{interrupt, pac, AnyPin};
13 14
14pub mod buffered; 15pub mod buffered;
15 16
@@ -20,55 +21,6 @@ pub mod buffered;
20// Stub implementation for LIB (Peripherals), GPIO, DMA and CLOCK until stable API 21// Stub implementation for LIB (Peripherals), GPIO, DMA and CLOCK until stable API
21// Pin and Clock initialization is currently done at the examples level. 22// Pin and Clock initialization is currently done at the examples level.
22 23
23// --- START GPIO ---
24
25mod gpio {
26 use embassy_hal_internal::PeripheralType;
27 trait SealedPin {}
28
29 #[allow(private_bounds)]
30 pub trait GpioPin: SealedPin + Sized + PeripheralType + Into<AnyPin> + 'static {
31 /// Type-erase the pin.
32 fn degrade(self) -> AnyPin {
33 todo!()
34 }
35 }
36
37 // Add this macro to implement GpioPin for all pins
38 macro_rules! impl_gpio_pin {
39 ($($pin:ident),*) => {
40 $(
41 impl SealedPin for crate::peripherals::$pin {}
42
43 impl GpioPin for crate::peripherals::$pin {}
44
45 impl From<crate::peripherals::$pin> for AnyPin {
46 // TODO: AJM: any reason we aren't using $pin?
47 fn from(_val: crate::peripherals::$pin) -> Self {
48 AnyPin
49 }
50 }
51 )*
52 };
53 }
54
55 // Implement GpioPin for all pins from lib.rs
56 impl_gpio_pin!(P2_2, P2_3);
57
58 #[derive(Debug, Clone, Copy)]
59 pub struct AnyPin;
60
61 impl PeripheralType for AnyPin {}
62
63 pub enum Alt {
64 ALT3,
65 }
66}
67
68use gpio::{AnyPin, GpioPin as Pin};
69
70// --- END GPIO ---
71
72// --- START DMA --- 24// --- START DMA ---
73mod dma { 25mod dma {
74 pub struct Channel<'d> { 26 pub struct Channel<'d> {
@@ -144,8 +96,7 @@ macro_rules! impl_instance {
144 }; 96 };
145} 97}
146 98
147// impl_instance!(0, 1, 2, 3, 4); 99impl_instance!(0, 1, 2, 3, 4, 5);
148impl_instance!(2);
149 100
150// ============================================================================ 101// ============================================================================
151// INSTANCE HELPER FUNCTIONS 102// INSTANCE HELPER FUNCTIONS
@@ -391,54 +342,184 @@ pub fn has_data(regs: Regs) -> bool {
391// PIN TRAITS FOR LPUART FUNCTIONALITY 342// PIN TRAITS FOR LPUART FUNCTIONALITY
392// ============================================================================ 343// ============================================================================
393 344
394impl<T: Pin> sealed::Sealed for T {} 345impl<T: SealedPin> sealed::Sealed for T {}
395 346
396/// io configuration trait for Lpuart Tx configuration 347/// io configuration trait for Lpuart Tx configuration
397pub trait TxPin<T: Instance>: Pin + sealed::Sealed + PeripheralType { 348pub trait TxPin<T: Instance>: Into<AnyPin> + sealed::Sealed + PeripheralType {
398 /// convert the pin to appropriate function for Lpuart Tx usage 349 /// convert the pin to appropriate function for Lpuart Tx usage
399 fn as_tx(&self); 350 fn as_tx(&self);
400} 351}
401 352
402/// io configuration trait for Lpuart Rx configuration 353/// io configuration trait for Lpuart Rx configuration
403pub trait RxPin<T: Instance>: Pin + sealed::Sealed + PeripheralType { 354pub trait RxPin<T: Instance>: Into<AnyPin> + sealed::Sealed + PeripheralType {
404 /// convert the pin to appropriate function for Lpuart Rx usage 355 /// convert the pin to appropriate function for Lpuart Rx usage
405 fn as_rx(&self); 356 fn as_rx(&self);
406} 357}
407 358
408/// io configuration trait for Lpuart Cts 359/// io configuration trait for Lpuart Cts
409pub trait CtsPin<T: Instance>: Pin + sealed::Sealed + PeripheralType { 360pub trait CtsPin<T: Instance>: Into<AnyPin> + sealed::Sealed + PeripheralType {
410 /// convert the pin to appropriate function for Lpuart Cts usage 361 /// convert the pin to appropriate function for Lpuart Cts usage
411 fn as_cts(&self); 362 fn as_cts(&self);
412} 363}
413 364
414/// io configuration trait for Lpuart Rts 365/// io configuration trait for Lpuart Rts
415pub trait RtsPin<T: Instance>: Pin + sealed::Sealed + PeripheralType { 366pub trait RtsPin<T: Instance>: Into<AnyPin> + sealed::Sealed + PeripheralType {
416 /// convert the pin to appropriate function for Lpuart Rts usage 367 /// convert the pin to appropriate function for Lpuart Rts usage
417 fn as_rts(&self); 368 fn as_rts(&self);
418} 369}
419 370
420macro_rules! impl_pin_trait { 371macro_rules! impl_tx_pin {
421 ($fcn:ident, $mode:ident, $($pin:ident, $alt:ident),*) => { 372 ($inst:ident, $pin:ident, $alt:ident) => {
422 paste! { 373 impl TxPin<crate::peripherals::$inst> for crate::peripherals::$pin {
423 $( 374 fn as_tx(&self) {
424 impl [<$mode:camel Pin>]<crate::peripherals::$fcn> for crate::peripherals::$pin { 375 // TODO: Check these are right
425 fn [<as_ $mode>](&self) { 376 self.set_pull(crate::gpio::Pull::Up);
426 let _alt = gpio::Alt::$alt; 377 self.set_slew_rate(crate::gpio::SlewRate::Fast.into());
427 // todo!("Configure pin for LPUART function") 378 self.set_drive_strength(crate::gpio::DriveStrength::Double.into());
428 } 379 self.set_function(crate::pac::port0::pcr0::Mux::$alt);
429 } 380 self.set_enable_input_buffer();
430 )* 381 }
382 }
383 };
384}
385
386macro_rules! impl_rx_pin {
387 ($inst:ident, $pin:ident, $alt:ident) => {
388 impl RxPin<crate::peripherals::$inst> for crate::peripherals::$pin {
389 fn as_rx(&self) {
390 // TODO: Check these are right
391 self.set_pull(crate::gpio::Pull::Up);
392 self.set_slew_rate(crate::gpio::SlewRate::Fast.into());
393 self.set_drive_strength(crate::gpio::DriveStrength::Double.into());
394 self.set_function(crate::pac::port0::pcr0::Mux::$alt);
395 self.set_enable_input_buffer();
396 }
397 }
398 };
399}
400
401// TODO: Macro and impls for CTS/RTS pins
402macro_rules! impl_cts_pin {
403 ($inst:ident, $pin:ident, $alt:ident) => {
404 impl CtsPin<crate::peripherals::$inst> for crate::peripherals::$pin {
405 fn as_cts(&self) {
406 todo!()
407 }
408 }
409 };
410}
411
412macro_rules! impl_rts_pin {
413 ($inst:ident, $pin:ident, $alt:ident) => {
414 impl RtsPin<crate::peripherals::$inst> for crate::peripherals::$pin {
415 fn as_rts(&self) {
416 todo!()
417 }
431 } 418 }
432 }; 419 };
433} 420}
434 421
435// Document identifier: MCXA343/344 Rev. 1DraftB ReleaseCandidate, 2025-07-10 - 6.1 MCX A173, A174 Signal Multiplexing and Pin Assignments 422// LPUART 0
436// impl_pin_trait!(LPUART0, rx, P2_0, ALT2, P0_2, ALT2, P0_20, ALT3); 423impl_tx_pin!(LPUART0, P0_3, Mux2);
437// impl_pin_trait!(LPUART0, tx, P2_1, ALT2, P0_3, ALT2, P0_21, ALT3); 424impl_tx_pin!(LPUART0, P0_21, Mux3);
438// impl_pin_trait!(LPUART0, rts, P2_2, ALT2, P0_0, ALT2, P0_22, ALT3); 425impl_tx_pin!(LPUART0, P2_1, Mux2);
439// impl_pin_trait!(LPUART0, cts, P2_3, ALT2, P0_1, ALT2, P0_23, ALT3); 426
440impl_pin_trait!(LPUART2, rx, P2_3, ALT3); 427impl_rx_pin!(LPUART0, P0_2, Mux2);
441impl_pin_trait!(LPUART2, tx, P2_2, ALT3); 428impl_rx_pin!(LPUART0, P0_20, Mux3);
429impl_rx_pin!(LPUART0, P2_0, Mux2);
430
431impl_cts_pin!(LPUART0, P0_1, Mux2);
432impl_cts_pin!(LPUART0, P0_23, Mux3);
433impl_cts_pin!(LPUART0, P2_3, Mux2);
434
435impl_rts_pin!(LPUART0, P0_0, Mux2);
436impl_rts_pin!(LPUART0, P0_22, Mux3);
437impl_rts_pin!(LPUART0, P2_2, Mux2);
438
439// LPUART 1
440impl_tx_pin!(LPUART1, P1_9, Mux2);
441impl_tx_pin!(LPUART1, P2_13, Mux3);
442impl_tx_pin!(LPUART1, P3_9, Mux3);
443impl_tx_pin!(LPUART1, P3_21, Mux3);
444
445impl_rx_pin!(LPUART1, P1_8, Mux2);
446impl_rx_pin!(LPUART1, P2_12, Mux3);
447impl_rx_pin!(LPUART1, P3_8, Mux3);
448impl_rx_pin!(LPUART1, P3_20, Mux3);
449
450impl_cts_pin!(LPUART1, P1_11, Mux2);
451impl_cts_pin!(LPUART1, P2_17, Mux3);
452impl_cts_pin!(LPUART1, P3_11, Mux3);
453impl_cts_pin!(LPUART1, P3_23, Mux3);
454
455impl_rts_pin!(LPUART1, P1_10, Mux2);
456impl_rts_pin!(LPUART1, P2_15, Mux3);
457impl_rts_pin!(LPUART1, P2_16, Mux3);
458impl_rts_pin!(LPUART1, P3_10, Mux3);
459
460// LPUART 2
461impl_tx_pin!(LPUART2, P1_5, Mux3);
462impl_tx_pin!(LPUART2, P1_13, Mux3);
463impl_tx_pin!(LPUART2, P2_2, Mux3);
464impl_tx_pin!(LPUART2, P2_10, Mux3);
465impl_tx_pin!(LPUART2, P3_15, Mux2);
466
467impl_rx_pin!(LPUART2, P1_4, Mux3);
468impl_rx_pin!(LPUART2, P1_12, Mux3);
469impl_rx_pin!(LPUART2, P2_3, Mux3);
470impl_rx_pin!(LPUART2, P2_11, Mux3);
471impl_rx_pin!(LPUART2, P3_14, Mux2);
472
473impl_cts_pin!(LPUART2, P1_7, Mux3);
474impl_cts_pin!(LPUART2, P1_15, Mux3);
475impl_cts_pin!(LPUART2, P2_4, Mux3);
476impl_cts_pin!(LPUART2, P3_13, Mux2);
477
478impl_rts_pin!(LPUART2, P1_6, Mux3);
479impl_rts_pin!(LPUART2, P1_14, Mux3);
480impl_rts_pin!(LPUART2, P2_5, Mux3);
481impl_rts_pin!(LPUART2, P3_12, Mux2);
482
483// LPUART 3
484impl_tx_pin!(LPUART3, P3_1, Mux3);
485impl_tx_pin!(LPUART3, P3_12, Mux3);
486impl_tx_pin!(LPUART3, P4_5, Mux3);
487
488impl_rx_pin!(LPUART3, P3_0, Mux3);
489impl_rx_pin!(LPUART3, P3_13, Mux3);
490impl_rx_pin!(LPUART3, P4_2, Mux3);
491
492impl_cts_pin!(LPUART3, P3_7, Mux3);
493impl_cts_pin!(LPUART3, P3_14, Mux3);
494impl_cts_pin!(LPUART3, P4_6, Mux3);
495
496impl_rts_pin!(LPUART3, P3_6, Mux3);
497impl_rts_pin!(LPUART3, P3_15, Mux3);
498impl_rts_pin!(LPUART3, P4_7, Mux3);
499
500// LPUART 4
501impl_tx_pin!(LPUART4, P2_7, Mux3);
502impl_tx_pin!(LPUART4, P3_19, Mux2);
503impl_tx_pin!(LPUART4, P3_27, Mux3);
504impl_tx_pin!(LPUART4, P4_3, Mux3);
505
506impl_rx_pin!(LPUART4, P2_6, Mux3);
507impl_rx_pin!(LPUART4, P3_18, Mux2);
508impl_rx_pin!(LPUART4, P3_28, Mux3);
509impl_rx_pin!(LPUART4, P4_4, Mux3);
510
511impl_cts_pin!(LPUART4, P2_0, Mux3);
512impl_cts_pin!(LPUART4, P3_17, Mux2);
513impl_cts_pin!(LPUART4, P3_31, Mux3);
514
515impl_rts_pin!(LPUART4, P2_1, Mux3);
516impl_rts_pin!(LPUART4, P3_16, Mux2);
517impl_rts_pin!(LPUART4, P3_30, Mux3);
518
519// LPUART 5
520//
521// TODO: The datasheet doesn't list tx/rx/cts/rts pins for LPUART5
522// See https://github.com/OpenDevicePartnership/embassy-mcxa/issues/48
442 523
443// ============================================================================ 524// ============================================================================
444// ERROR TYPES AND RESULTS 525// ERROR TYPES AND RESULTS
diff --git a/src/pins.rs b/src/pins.rs
index 0a83a41f0..fdf1b0a86 100644
--- a/src/pins.rs
+++ b/src/pins.rs
@@ -1,40 +1,6 @@
1//! Pin configuration helpers (separate from peripheral drivers). 1//! Pin configuration helpers (separate from peripheral drivers).
2use crate::pac; 2use crate::pac;
3 3
4pub unsafe fn configure_uart2_pins_port2() {
5 // P2_2 = LPUART2_TX ALT3, P2_3 = LPUART2_RX ALT3 with pull-up, input enable, high drive, slow slew.
6 let port2 = &*pac::Port2::ptr();
7 port2.pcr2().write(|w| {
8 w.ps()
9 .ps1()
10 .pe()
11 .pe1()
12 .sre()
13 .sre1()
14 .dse()
15 .dse1()
16 .mux()
17 .mux3()
18 .ibe()
19 .ibe1()
20 });
21 port2.pcr3().write(|w| {
22 w.ps()
23 .ps1()
24 .pe()
25 .pe1()
26 .sre()
27 .sre1()
28 .dse()
29 .dse1()
30 .mux()
31 .mux3()
32 .ibe()
33 .ibe1()
34 });
35 core::arch::asm!("dsb sy; isb sy");
36}
37
38pub unsafe fn configure_adc_pins() { 4pub unsafe fn configure_adc_pins() {
39 // P1_10 = ADC1_A8 5 // P1_10 = ADC1_A8
40 let port1 = &*pac::Port1::ptr(); 6 let port1 = &*pac::Port1::ptr();