diff options
| author | James Munns <[email protected]> | 2025-11-18 14:19:09 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-11-18 14:19:09 +0100 |
| commit | 5b1149a52dbec9e3bdd10dc341dc0751ab4798a6 (patch) | |
| tree | 3ff7098471cf660a54a707464a0e2feb2080b09e /examples | |
| parent | 62e297c130ac26afe4d7d5752bb79709bd370e39 (diff) | |
| parent | c8942aec2478ff077b55da0e86801f8a6a88a7de (diff) | |
Merge pull request #11 from jamesmunns/james/impl-clocks
Implement initial `clock` driver.
This PR introduces an initial two-phase clock driver system:
1. The first stage is responsible for initializing the core/system clocks at the time of `embassy_mcxa::init()`
2. The second stage is done on creation of peripherals
This work is limited to currently used clocks and peripherals, but has room for expansion for later peripherals. This model is based on the preliminary refactoring performed for the `embassy-imxrt` crate.
Diffstat (limited to 'examples')
| -rw-r--r-- | examples/src/bin/adc_interrupt.rs | 34 | ||||
| -rw-r--r-- | examples/src/bin/adc_polling.rs | 34 | ||||
| -rw-r--r-- | examples/src/bin/blink.rs | 5 | ||||
| -rw-r--r-- | examples/src/bin/hello.rs | 31 | ||||
| -rw-r--r-- | examples/src/bin/lpuart_buffered.rs | 21 | ||||
| -rw-r--r-- | examples/src/bin/lpuart_polling.rs | 16 | ||||
| -rw-r--r-- | examples/src/bin/ostimer_alarm.rs | 34 | ||||
| -rw-r--r-- | examples/src/bin/ostimer_async.rs | 30 | ||||
| -rw-r--r-- | examples/src/bin/ostimer_counter.rs | 32 | ||||
| -rw-r--r-- | examples/src/bin/ostimer_race_test.rs | 74 | ||||
| -rw-r--r-- | examples/src/bin/rtc_alarm.rs | 29 | ||||
| -rw-r--r-- | examples/src/bin/uart_interrupt.rs | 66 | ||||
| -rw-r--r-- | examples/src/common/mod.rs | 45 | ||||
| -rw-r--r-- | examples/src/lib.rs | 58 |
14 files changed, 239 insertions, 270 deletions
diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs index e174a5272..6812ba5d3 100644 --- a/examples/src/bin/adc_interrupt.rs +++ b/examples/src/bin/adc_interrupt.rs | |||
| @@ -2,13 +2,16 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa_examples::{init_adc, init_uart2}; | 5 | use embassy_mcxa_examples::init_adc_pins; |
| 6 | use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; | 6 | use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; |
| 7 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; | ||
| 8 | use hal::clocks::PoweredClock; | ||
| 9 | use hal::lpuart::{Config, Lpuart}; | ||
| 7 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; | 10 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; |
| 8 | use hal::pac::adc1::cmdl1::{Adch, Mode}; | 11 | use hal::pac::adc1::cmdl1::{Adch, Mode}; |
| 9 | use hal::pac::adc1::ctrl::CalAvgs; | 12 | use hal::pac::adc1::ctrl::CalAvgs; |
| 10 | use hal::pac::adc1::tctrl::Tcmd; | 13 | use hal::pac::adc1::tctrl::Tcmd; |
| 11 | use hal::{bind_interrupts, uart, InterruptExt}; | 14 | use hal::{bind_interrupts, InterruptExt}; |
| 12 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 15 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 13 | 16 | ||
| 14 | bind_interrupts!(struct Irqs { | 17 | bind_interrupts!(struct Irqs { |
| @@ -23,17 +26,29 @@ static KEEP_ADC: unsafe extern "C" fn() = ADC1; | |||
| 23 | async fn main(_spawner: Spawner) { | 26 | async fn main(_spawner: Spawner) { |
| 24 | let p = hal::init(hal::config::Config::default()); | 27 | let p = hal::init(hal::config::Config::default()); |
| 25 | 28 | ||
| 29 | // Create UART configuration | ||
| 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 PIO2_2 as TX and PIO2_3 as RX | ||
| 26 | unsafe { | 38 | unsafe { |
| 27 | init_uart2(hal::pac()); | 39 | embassy_mcxa_examples::init_uart2_pins(hal::pac()); |
| 28 | } | 40 | } |
| 29 | 41 | let mut uart = Lpuart::new_blocking( | |
| 30 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 42 | p.LPUART2, // Peripheral |
| 31 | let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); | 43 | p.PIO2_2, // TX pin |
| 32 | 44 | p.PIO2_3, // RX pin | |
| 45 | config, | ||
| 46 | ) | ||
| 47 | .unwrap(); | ||
| 33 | uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); | 48 | uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); |
| 34 | 49 | ||
| 35 | unsafe { | 50 | unsafe { |
| 36 | init_adc(hal::pac()); | 51 | init_adc_pins(hal::pac()); |
| 37 | } | 52 | } |
| 38 | 53 | ||
| 39 | let adc_config = LpadcConfig { | 54 | let adc_config = LpadcConfig { |
| @@ -47,6 +62,9 @@ async fn main(_spawner: Spawner) { | |||
| 47 | enable_conv_pause: false, | 62 | enable_conv_pause: false, |
| 48 | conv_pause_delay: 0, | 63 | conv_pause_delay: 0, |
| 49 | fifo_watermark: 0, | 64 | fifo_watermark: 0, |
| 65 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 66 | source: AdcClockSel::FroLfDiv, | ||
| 67 | div: Div4::no_div(), | ||
| 50 | }; | 68 | }; |
| 51 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); | 69 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); |
| 52 | 70 | ||
diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs index 741551d49..421306e9b 100644 --- a/examples/src/bin/adc_polling.rs +++ b/examples/src/bin/adc_polling.rs | |||
| @@ -4,13 +4,15 @@ | |||
| 4 | use core::fmt::Write; | 4 | use core::fmt::Write; |
| 5 | 5 | ||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_mcxa_examples::{init_adc, init_uart2}; | 7 | use embassy_mcxa_examples::{init_adc_pins, init_uart2_pins}; |
| 8 | use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; | 8 | use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; |
| 9 | use hal::clocks::periph_helpers::{AdcClockSel, Div4}; | ||
| 10 | use hal::clocks::PoweredClock; | ||
| 11 | use hal::lpuart::{Config, Lpuart}; | ||
| 9 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; | 12 | use hal::pac::adc1::cfg::{Pwrsel, Refsel}; |
| 10 | use hal::pac::adc1::cmdl1::{Adch, Mode}; | 13 | use hal::pac::adc1::cmdl1::{Adch, Mode}; |
| 11 | use hal::pac::adc1::ctrl::CalAvgs; | 14 | use hal::pac::adc1::ctrl::CalAvgs; |
| 12 | use hal::pac::adc1::tctrl::Tcmd; | 15 | use hal::pac::adc1::tctrl::Tcmd; |
| 13 | use hal::uart; | ||
| 14 | use heapless::String; | 16 | use heapless::String; |
| 15 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 17 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 16 | 18 | ||
| @@ -21,16 +23,33 @@ async fn main(_spawner: Spawner) { | |||
| 21 | let p = hal::init(hal::config::Config::default()); | 23 | let p = hal::init(hal::config::Config::default()); |
| 22 | 24 | ||
| 23 | unsafe { | 25 | unsafe { |
| 24 | init_uart2(hal::pac()); | 26 | init_uart2_pins(hal::pac()); |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 27 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 29 | // Create UART configuration |
| 28 | let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); | 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 PIO2_2 as TX and PIO2_3 as RX | ||
| 38 | unsafe { | ||
| 39 | init_uart2_pins(hal::pac()); | ||
| 40 | } | ||
| 41 | let mut uart = Lpuart::new_blocking( | ||
| 42 | p.LPUART2, // Peripheral | ||
| 43 | p.PIO2_2, // TX pin | ||
| 44 | p.PIO2_3, // RX pin | ||
| 45 | config, | ||
| 46 | ) | ||
| 47 | .unwrap(); | ||
| 29 | 48 | ||
| 30 | uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); | 49 | uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); |
| 31 | 50 | ||
| 32 | unsafe { | 51 | unsafe { |
| 33 | init_adc(hal::pac()); | 52 | init_adc_pins(hal::pac()); |
| 34 | } | 53 | } |
| 35 | 54 | ||
| 36 | let adc_config = LpadcConfig { | 55 | let adc_config = LpadcConfig { |
| @@ -44,6 +63,9 @@ async fn main(_spawner: Spawner) { | |||
| 44 | enable_conv_pause: false, | 63 | enable_conv_pause: false, |
| 45 | conv_pause_delay: 0, | 64 | conv_pause_delay: 0, |
| 46 | fifo_watermark: 0, | 65 | fifo_watermark: 0, |
| 66 | power: PoweredClock::NormalEnabledDeepSleepDisabled, | ||
| 67 | source: AdcClockSel::FroLfDiv, | ||
| 68 | div: Div4::no_div(), | ||
| 47 | }; | 69 | }; |
| 48 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); | 70 | let adc = hal::adc::Adc::<hal::adc::Adc1>::new(p.ADC1, adc_config); |
| 49 | 71 | ||
diff --git a/examples/src/bin/blink.rs b/examples/src/bin/blink.rs index c36fc9421..d8b158d50 100644 --- a/examples/src/bin/blink.rs +++ b/examples/src/bin/blink.rs | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa as hal; | 5 | use embassy_mcxa as hal; |
| 6 | use embassy_mcxa::bind_interrupts; | 6 | use embassy_mcxa::bind_interrupts; |
| 7 | use embassy_mcxa_examples::{init_led, init_ostimer0}; | 7 | use embassy_mcxa_examples::init_led_gpio_clocks; |
| 8 | use embassy_time::{Duration, Timer}; | 8 | use embassy_time::{Duration, Timer}; |
| 9 | use hal::gpio::pins::PIO3_18; | 9 | use hal::gpio::pins::PIO3_18; |
| 10 | use hal::gpio::{Level, Output}; | 10 | use hal::gpio::{Level, Output}; |
| @@ -23,8 +23,7 @@ async fn main(_spawner: Spawner) { | |||
| 23 | let _p = hal::init(hal::config::Config::default()); | 23 | let _p = hal::init(hal::config::Config::default()); |
| 24 | 24 | ||
| 25 | unsafe { | 25 | unsafe { |
| 26 | init_led(hal::pac()); | 26 | init_led_gpio_clocks(hal::pac()); |
| 27 | init_ostimer0(hal::pac()); | ||
| 28 | } | 27 | } |
| 29 | 28 | ||
| 30 | defmt::info!("Blink example"); | 29 | defmt::info!("Blink example"); |
diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs index 5c4336d50..207c157c3 100644 --- a/examples/src/bin/hello.rs +++ b/examples/src/bin/hello.rs | |||
| @@ -2,12 +2,11 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa_examples::init_uart2; | 5 | use hal::lpuart::{Blocking, Config, Lpuart}; |
| 6 | use hal::uart; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 6 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 8 | 7 | ||
| 9 | /// Simple helper to write a byte as hex to UART | 8 | /// Simple helper to write a byte as hex to UART |
| 10 | fn write_hex_byte(uart: &hal::uart::Uart<hal::uart::Lpuart2>, byte: u8) { | 9 | fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { |
| 11 | const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; | 10 | const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; |
| 12 | uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); | 11 | uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); |
| 13 | uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); | 12 | uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); |
| @@ -19,15 +18,25 @@ async fn main(_spawner: Spawner) { | |||
| 19 | 18 | ||
| 20 | defmt::info!("boot"); | 19 | defmt::info!("boot"); |
| 21 | 20 | ||
| 22 | // Board-level init for UART2 clocks and pins. | 21 | // Create UART configuration |
| 22 | let config = Config { | ||
| 23 | baudrate_bps: 115_200, | ||
| 24 | enable_tx: true, | ||
| 25 | enable_rx: true, | ||
| 26 | ..Default::default() | ||
| 27 | }; | ||
| 28 | |||
| 29 | // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX | ||
| 23 | unsafe { | 30 | unsafe { |
| 24 | init_uart2(hal::pac()); | 31 | embassy_mcxa_examples::init_uart2_pins(hal::pac()); |
| 25 | } | 32 | } |
| 26 | 33 | let mut uart = Lpuart::new_blocking( | |
| 27 | // Get UART source frequency from clock configuration | 34 | p.LPUART2, // Peripheral |
| 28 | // Using hardcoded frequency for now - dynamic detection may have issues | 35 | p.PIO2_2, // TX pin |
| 29 | let src = 12_000_000; // FRO_LF_DIV at 12MHz with DIV=0 | 36 | p.PIO2_3, // RX pin |
| 30 | let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); | 37 | config, |
| 38 | ) | ||
| 39 | .unwrap(); | ||
| 31 | 40 | ||
| 32 | // Print welcome message before any async delays to guarantee early console output | 41 | // Print welcome message before any async delays to guarantee early console output |
| 33 | uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); | 42 | uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); |
| @@ -66,7 +75,7 @@ async fn main(_spawner: Spawner) { | |||
| 66 | let num_str = &command[4..]; | 75 | let num_str = &command[4..]; |
| 67 | if let Ok(num) = parse_u8(num_str) { | 76 | if let Ok(num) = parse_u8(num_str) { |
| 68 | uart.write_str_blocking("Hex: 0x"); | 77 | uart.write_str_blocking("Hex: 0x"); |
| 69 | write_hex_byte(&uart, num); | 78 | write_hex_byte(&mut uart, num); |
| 70 | uart.write_str_blocking("\r\n"); | 79 | uart.write_str_blocking("\r\n"); |
| 71 | } else { | 80 | } else { |
| 72 | uart.write_str_blocking("Invalid number for hex command\r\n"); | 81 | uart.write_str_blocking("Invalid number for hex command\r\n"); |
diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs index 480d8e1f7..642d4af65 100644 --- a/examples/src/bin/lpuart_buffered.rs +++ b/examples/src/bin/lpuart_buffered.rs | |||
| @@ -5,24 +5,24 @@ use embassy_executor::Spawner; | |||
| 5 | use embassy_mcxa as hal; | 5 | use embassy_mcxa as hal; |
| 6 | use embassy_mcxa::interrupt::typelevel::Handler; | 6 | use embassy_mcxa::interrupt::typelevel::Handler; |
| 7 | use embassy_mcxa::lpuart::buffered::BufferedLpuart; | 7 | use embassy_mcxa::lpuart::buffered::BufferedLpuart; |
| 8 | use embassy_mcxa::lpuart::Config; | ||
| 8 | use embassy_mcxa::{bind_interrupts, lpuart}; | 9 | use embassy_mcxa::{bind_interrupts, lpuart}; |
| 9 | use embassy_mcxa_examples::{init_ostimer0, init_uart2}; | 10 | use embassy_mcxa_examples::init_uart2_pins; |
| 10 | use embedded_io_async::{Read, Write}; | 11 | use embedded_io_async::{Read, Write}; |
| 11 | 12 | ||
| 12 | // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver | 13 | // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver |
| 13 | bind_interrupts!(struct Irqs { | 14 | bind_interrupts!(struct Irqs { |
| 14 | LPUART2 => lpuart::buffered::BufferedInterruptHandler::<lpuart::lib::peripherals::LPUART2>; | 15 | LPUART2 => lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>; |
| 15 | }); | 16 | }); |
| 16 | 17 | ||
| 17 | // Wrapper function for the interrupt handler | 18 | // Wrapper function for the interrupt handler |
| 18 | unsafe extern "C" fn lpuart2_handler() { | 19 | unsafe extern "C" fn lpuart2_handler() { |
| 19 | lpuart::buffered::BufferedInterruptHandler::<lpuart::lib::peripherals::LPUART2>::on_interrupt(); | 20 | lpuart::buffered::BufferedInterruptHandler::<hal::peripherals::LPUART2>::on_interrupt(); |
| 20 | } | 21 | } |
| 21 | 22 | ||
| 22 | #[embassy_executor::main] | 23 | #[embassy_executor::main] |
| 23 | async fn main(_spawner: Spawner) { | 24 | async fn main(_spawner: Spawner) { |
| 24 | let _p = hal::init(hal::config::Config::default()); | 25 | let p = hal::init(hal::config::Config::default()); |
| 25 | let p2 = lpuart::lib::init(); | ||
| 26 | 26 | ||
| 27 | unsafe { | 27 | unsafe { |
| 28 | hal::interrupt::install_irq_handler(hal::pac::Interrupt::LPUART2, lpuart2_handler); | 28 | hal::interrupt::install_irq_handler(hal::pac::Interrupt::LPUART2, lpuart2_handler); |
| @@ -32,12 +32,11 @@ async fn main(_spawner: Spawner) { | |||
| 32 | hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); | 32 | hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); |
| 33 | 33 | ||
| 34 | unsafe { | 34 | unsafe { |
| 35 | init_uart2(hal::pac()); | 35 | init_uart2_pins(hal::pac()); |
| 36 | init_ostimer0(hal::pac()); | ||
| 37 | } | 36 | } |
| 38 | 37 | ||
| 39 | // UART configuration (enable both TX and RX) | 38 | // UART configuration (enable both TX and RX) |
| 40 | let config = lpuart::Config { | 39 | let config = Config { |
| 41 | baudrate_bps: 115_200, | 40 | baudrate_bps: 115_200, |
| 42 | enable_tx: true, | 41 | enable_tx: true, |
| 43 | enable_rx: true, | 42 | enable_rx: true, |
| @@ -51,9 +50,9 @@ async fn main(_spawner: Spawner) { | |||
| 51 | 50 | ||
| 52 | // Create a buffered LPUART2 instance with both TX and RX | 51 | // Create a buffered LPUART2 instance with both TX and RX |
| 53 | let mut uart = BufferedLpuart::new( | 52 | let mut uart = BufferedLpuart::new( |
| 54 | p2.LPUART2, | 53 | p.LPUART2, |
| 55 | p2.PIO2_2, // TX pin | 54 | p.PIO2_2, // TX pin |
| 56 | p2.PIO2_3, // RX pin | 55 | p.PIO2_3, // RX pin |
| 57 | Irqs, | 56 | Irqs, |
| 58 | &mut tx_buf, | 57 | &mut tx_buf, |
| 59 | &mut rx_buf, | 58 | &mut rx_buf, |
diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs index 215714569..bea82c33e 100644 --- a/examples/src/bin/lpuart_polling.rs +++ b/examples/src/bin/lpuart_polling.rs | |||
| @@ -2,20 +2,20 @@ | |||
| 2 | #![no_main] | 2 | #![no_main] |
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa_examples::init_uart2; | 5 | use embassy_mcxa_examples::init_uart2_pins; |
| 6 | use hal::lpuart::{lib, Config, Lpuart}; | ||
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 6 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 8 | 7 | ||
| 8 | use crate::hal::lpuart::{Config, Lpuart}; | ||
| 9 | |||
| 9 | #[embassy_executor::main] | 10 | #[embassy_executor::main] |
| 10 | async fn main(_spawner: Spawner) { | 11 | async fn main(_spawner: Spawner) { |
| 11 | let _p = hal::init(hal::config::Config::default()); | 12 | let p = hal::init(hal::config::Config::default()); |
| 12 | let p2 = lib::init(); | ||
| 13 | 13 | ||
| 14 | defmt::info!("boot"); | 14 | defmt::info!("boot"); |
| 15 | 15 | ||
| 16 | // Board-level init for UART2 clocks and pins. | 16 | // Board-level init for UART2 clocks and pins. |
| 17 | unsafe { | 17 | unsafe { |
| 18 | init_uart2(hal::pac()); | 18 | init_uart2_pins(hal::pac()); |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | // Create UART configuration | 21 | // Create UART configuration |
| @@ -28,9 +28,9 @@ async fn main(_spawner: Spawner) { | |||
| 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 PIO2_2 as TX and PIO2_3 as RX |
| 30 | let lpuart = Lpuart::new_blocking( | 30 | let lpuart = Lpuart::new_blocking( |
| 31 | p2.LPUART2, // Peripheral | 31 | p.LPUART2, // Peripheral |
| 32 | p2.PIO2_2, // TX pin | 32 | p.PIO2_2, // TX pin |
| 33 | p2.PIO2_3, // RX pin | 33 | p.PIO2_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 953f98c01..03fb93319 100644 --- a/examples/src/bin/ostimer_alarm.rs +++ b/examples/src/bin/ostimer_alarm.rs | |||
| @@ -5,8 +5,10 @@ use core::sync::atomic::{AtomicBool, Ordering}; | |||
| 5 | 5 | ||
| 6 | use embassy_executor::Spawner; | 6 | use embassy_executor::Spawner; |
| 7 | use embassy_mcxa::bind_interrupts; | 7 | use embassy_mcxa::bind_interrupts; |
| 8 | use embassy_mcxa_examples::{init_ostimer0, init_uart2}; | 8 | use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; |
| 9 | use hal::uart; | 9 | use embassy_mcxa::clocks::PoweredClock; |
| 10 | use embassy_mcxa::lpuart::{Config, Lpuart}; | ||
| 11 | use embassy_mcxa_examples::init_uart2_pins; | ||
| 10 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 12 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 11 | 13 | ||
| 12 | // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. | 14 | // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. |
| @@ -30,13 +32,26 @@ fn alarm_callback() { | |||
| 30 | async fn main(_spawner: Spawner) { | 32 | async fn main(_spawner: Spawner) { |
| 31 | let p = hal::init(hal::config::Config::default()); | 33 | let p = hal::init(hal::config::Config::default()); |
| 32 | 34 | ||
| 33 | // Enable/clock OSTIMER0 and UART2 before touching their registers | 35 | // Create UART configuration |
| 36 | let config = Config { | ||
| 37 | baudrate_bps: 115_200, | ||
| 38 | enable_tx: true, | ||
| 39 | enable_rx: true, | ||
| 40 | ..Default::default() | ||
| 41 | }; | ||
| 42 | |||
| 43 | // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX | ||
| 34 | unsafe { | 44 | unsafe { |
| 35 | init_ostimer0(hal::pac()); | 45 | init_uart2_pins(hal::pac()); |
| 36 | init_uart2(hal::pac()); | ||
| 37 | } | 46 | } |
| 38 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 47 | let mut uart = Lpuart::new_blocking( |
| 39 | let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); | 48 | p.LPUART2, // Peripheral |
| 49 | p.PIO2_2, // TX pin | ||
| 50 | p.PIO2_3, // RX pin | ||
| 51 | config, | ||
| 52 | ) | ||
| 53 | .unwrap(); | ||
| 54 | |||
| 40 | uart.write_str_blocking("OSTIMER Alarm Example\n"); | 55 | uart.write_str_blocking("OSTIMER Alarm Example\n"); |
| 41 | 56 | ||
| 42 | // Initialize embassy-time global driver backed by OSTIMER0 | 57 | // Initialize embassy-time global driver backed by OSTIMER0 |
| @@ -45,9 +60,10 @@ async fn main(_spawner: Spawner) { | |||
| 45 | // Create OSTIMER instance | 60 | // Create OSTIMER instance |
| 46 | let config = hal::ostimer::Config { | 61 | let config = hal::ostimer::Config { |
| 47 | init_match_max: true, | 62 | init_match_max: true, |
| 48 | clock_frequency_hz: 1_000_000, // 1MHz | 63 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 64 | source: OstimerClockSel::Clk1M, | ||
| 49 | }; | 65 | }; |
| 50 | let ostimer = hal::ostimer::Ostimer::<hal::ostimer::Ostimer0>::new(p.OSTIMER0, config, hal::pac()); | 66 | let ostimer = hal::ostimer::Ostimer::<hal::ostimer::Ostimer0>::new(p.OSTIMER0, config); |
| 51 | 67 | ||
| 52 | // Create alarm with callback | 68 | // Create alarm with callback |
| 53 | let alarm = hal::ostimer::Alarm::new() | 69 | let alarm = hal::ostimer::Alarm::new() |
diff --git a/examples/src/bin/ostimer_async.rs b/examples/src/bin/ostimer_async.rs index 34862b61f..881f09374 100644 --- a/examples/src/bin/ostimer_async.rs +++ b/examples/src/bin/ostimer_async.rs | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa::bind_interrupts; | 5 | use embassy_mcxa::bind_interrupts; |
| 6 | use embassy_mcxa_examples::{init_ostimer0, init_uart2}; | 6 | use embassy_mcxa_examples::init_uart2_pins; |
| 7 | use embassy_time::{Duration, Timer}; | 7 | use embassy_time::{Duration, Timer}; |
| 8 | use hal::uart; | 8 | use hal::lpuart::{Config, Lpuart}; |
| 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 10 | 10 | ||
| 11 | // Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. | 11 | // Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. |
| @@ -19,16 +19,28 @@ static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; | |||
| 19 | 19 | ||
| 20 | #[embassy_executor::main] | 20 | #[embassy_executor::main] |
| 21 | async fn main(_spawner: Spawner) { | 21 | async fn main(_spawner: Spawner) { |
| 22 | let _p = hal::init(hal::config::Config::default()); | 22 | let p = hal::init(hal::config::Config::default()); |
| 23 | 23 | ||
| 24 | // Enable/clock OSTIMER0 and UART2 before touching their registers | 24 | // Create UART configuration |
| 25 | let config = Config { | ||
| 26 | baudrate_bps: 115_200, | ||
| 27 | enable_tx: true, | ||
| 28 | enable_rx: true, | ||
| 29 | ..Default::default() | ||
| 30 | }; | ||
| 31 | |||
| 32 | // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX | ||
| 25 | unsafe { | 33 | unsafe { |
| 26 | init_ostimer0(hal::pac()); | 34 | init_uart2_pins(hal::pac()); |
| 27 | init_uart2(hal::pac()); | ||
| 28 | } | 35 | } |
| 29 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 36 | let mut uart = Lpuart::new_blocking( |
| 30 | let uart = uart::Uart::<uart::Lpuart2>::new(_p.LPUART2, uart::Config::new(src)); | 37 | p.LPUART2, // Peripheral |
| 31 | uart.write_str_blocking("boot\n"); | 38 | p.PIO2_2, // TX pin |
| 39 | p.PIO2_3, // RX pin | ||
| 40 | config, | ||
| 41 | ) | ||
| 42 | .unwrap(); | ||
| 43 | uart.blocking_write(b"boot\n").unwrap(); | ||
| 32 | 44 | ||
| 33 | // Avoid mass NVIC writes here; DefaultHandler now safely returns. | 45 | // Avoid mass NVIC writes here; DefaultHandler now safely returns. |
| 34 | 46 | ||
diff --git a/examples/src/bin/ostimer_counter.rs b/examples/src/bin/ostimer_counter.rs index 20044760a..2fbc251b9 100644 --- a/examples/src/bin/ostimer_counter.rs +++ b/examples/src/bin/ostimer_counter.rs | |||
| @@ -7,7 +7,9 @@ | |||
| 7 | #![no_main] | 7 | #![no_main] |
| 8 | 8 | ||
| 9 | use embassy_executor::Spawner; | 9 | use embassy_executor::Spawner; |
| 10 | use embassy_mcxa_examples::{init_ostimer0, init_uart2}; | 10 | use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; |
| 11 | use embassy_mcxa::clocks::PoweredClock; | ||
| 12 | use embassy_mcxa::lpuart::{Blocking, Config, Lpuart}; | ||
| 11 | use embassy_time::{Duration, Timer}; | 13 | use embassy_time::{Duration, Timer}; |
| 12 | use hal::bind_interrupts; | 14 | use hal::bind_interrupts; |
| 13 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 15 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| @@ -20,13 +22,25 @@ bind_interrupts!(struct Irqs { | |||
| 20 | async fn main(_spawner: Spawner) { | 22 | async fn main(_spawner: Spawner) { |
| 21 | let p = hal::init(Default::default()); | 23 | let p = hal::init(Default::default()); |
| 22 | 24 | ||
| 23 | // Enable/clock OSTIMER0 and UART2 before touching their registers | 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 PIO2_2 as TX and PIO2_3 as RX | ||
| 24 | unsafe { | 34 | unsafe { |
| 25 | init_ostimer0(hal::pac()); | 35 | embassy_mcxa_examples::init_uart2_pins(hal::pac()); |
| 26 | init_uart2(hal::pac()); | ||
| 27 | } | 36 | } |
| 28 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 37 | let mut uart = Lpuart::new_blocking( |
| 29 | let mut uart = hal::uart::Uart::<hal::uart::Lpuart2>::new(p.LPUART2, hal::uart::Config::new(src)); | 38 | p.LPUART2, // Peripheral |
| 39 | p.PIO2_2, // TX pin | ||
| 40 | p.PIO2_3, // RX pin | ||
| 41 | config, | ||
| 42 | ) | ||
| 43 | .unwrap(); | ||
| 30 | 44 | ||
| 31 | uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); | 45 | uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); |
| 32 | 46 | ||
| @@ -41,9 +55,9 @@ async fn main(_spawner: Spawner) { | |||
| 41 | p.OSTIMER0, | 55 | p.OSTIMER0, |
| 42 | hal::ostimer::Config { | 56 | hal::ostimer::Config { |
| 43 | init_match_max: true, | 57 | init_match_max: true, |
| 44 | clock_frequency_hz: 1_000_000, | 58 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 59 | source: OstimerClockSel::Clk1M, | ||
| 45 | }, | 60 | }, |
| 46 | hal::pac(), | ||
| 47 | ); | 61 | ); |
| 48 | 62 | ||
| 49 | // Read initial counter value | 63 | // Read initial counter value |
| @@ -89,7 +103,7 @@ async fn main(_spawner: Spawner) { | |||
| 89 | } | 103 | } |
| 90 | 104 | ||
| 91 | // Helper function to write a u64 value as decimal string | 105 | // Helper function to write a u64 value as decimal string |
| 92 | fn write_u64(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u64) { | 106 | fn write_u64(uart: &mut Lpuart<'_, Blocking>, value: u64) { |
| 93 | if value == 0 { | 107 | if value == 0 { |
| 94 | uart.write_str_blocking("0"); | 108 | uart.write_str_blocking("0"); |
| 95 | return; | 109 | return; |
diff --git a/examples/src/bin/ostimer_race_test.rs b/examples/src/bin/ostimer_race_test.rs index 720a058d5..168a952cd 100644 --- a/examples/src/bin/ostimer_race_test.rs +++ b/examples/src/bin/ostimer_race_test.rs | |||
| @@ -12,7 +12,9 @@ | |||
| 12 | use core::sync::atomic::{AtomicU32, Ordering}; | 12 | use core::sync::atomic::{AtomicU32, Ordering}; |
| 13 | 13 | ||
| 14 | use embassy_executor::Spawner; | 14 | use embassy_executor::Spawner; |
| 15 | use embassy_mcxa_examples::{init_ostimer0, init_uart2}; | 15 | use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; |
| 16 | use embassy_mcxa::clocks::PoweredClock; | ||
| 17 | use embassy_mcxa::lpuart::{Blocking, Config, Lpuart}; | ||
| 16 | use embassy_time::{Duration, Timer}; | 18 | use embassy_time::{Duration, Timer}; |
| 17 | use hal::bind_interrupts; | 19 | use hal::bind_interrupts; |
| 18 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 20 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| @@ -41,7 +43,7 @@ fn alarm_callback() { | |||
| 41 | } | 43 | } |
| 42 | } | 44 | } |
| 43 | 45 | ||
| 44 | fn report_default_handler(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>) { | 46 | fn report_default_handler(uart: &mut Lpuart<'_, Blocking>) { |
| 45 | let snapshot = hal::interrupt::default_handler_snapshot(); | 47 | let snapshot = hal::interrupt::default_handler_snapshot(); |
| 46 | if snapshot.count == 0 { | 48 | if snapshot.count == 0 { |
| 47 | return; | 49 | return; |
| @@ -70,13 +72,25 @@ fn report_default_handler(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>) { | |||
| 70 | async fn main(_spawner: Spawner) { | 72 | async fn main(_spawner: Spawner) { |
| 71 | let p = hal::init(Default::default()); | 73 | let p = hal::init(Default::default()); |
| 72 | 74 | ||
| 73 | // Enable/clock OSTIMER0 and UART2 before touching their registers | 75 | // Create UART configuration |
| 76 | let config = Config { | ||
| 77 | baudrate_bps: 115_200, | ||
| 78 | enable_tx: true, | ||
| 79 | enable_rx: true, | ||
| 80 | ..Default::default() | ||
| 81 | }; | ||
| 82 | |||
| 83 | // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX | ||
| 74 | unsafe { | 84 | unsafe { |
| 75 | init_ostimer0(hal::pac()); | 85 | embassy_mcxa_examples::init_uart2_pins(hal::pac()); |
| 76 | init_uart2(hal::pac()); | ||
| 77 | } | 86 | } |
| 78 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 87 | let mut uart = Lpuart::new_blocking( |
| 79 | let mut uart = hal::uart::Uart::<hal::uart::Lpuart2>::new(p.LPUART2, hal::uart::Config::new(src)); | 88 | p.LPUART2, // Peripheral |
| 89 | p.PIO2_2, // TX pin | ||
| 90 | p.PIO2_3, // RX pin | ||
| 91 | config, | ||
| 92 | ) | ||
| 93 | .unwrap(); | ||
| 80 | 94 | ||
| 81 | uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); | 95 | uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); |
| 82 | 96 | ||
| @@ -95,9 +109,9 @@ async fn main(_spawner: Spawner) { | |||
| 95 | p.OSTIMER0, | 109 | p.OSTIMER0, |
| 96 | hal::ostimer::Config { | 110 | hal::ostimer::Config { |
| 97 | init_match_max: true, | 111 | init_match_max: true, |
| 98 | clock_frequency_hz: 1_000_000, | 112 | power: PoweredClock::NormalEnabledDeepSleepDisabled, |
| 113 | source: OstimerClockSel::Clk1M, | ||
| 99 | }, | 114 | }, |
| 100 | hal::pac(), | ||
| 101 | ); | 115 | ); |
| 102 | 116 | ||
| 103 | uart.write_str_blocking("OSTIMER instance created\n"); | 117 | uart.write_str_blocking("OSTIMER instance created\n"); |
| @@ -136,7 +150,7 @@ async fn main(_spawner: Spawner) { | |||
| 136 | // Test rapid alarm scheduling to stress interrupt handling | 150 | // Test rapid alarm scheduling to stress interrupt handling |
| 137 | async fn test_rapid_alarms( | 151 | async fn test_rapid_alarms( |
| 138 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, | 152 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, |
| 139 | uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, | 153 | uart: &mut Lpuart<'_, Blocking>, |
| 140 | ) { | 154 | ) { |
| 141 | let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); | 155 | let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); |
| 142 | 156 | ||
| @@ -173,7 +187,7 @@ async fn test_rapid_alarms( | |||
| 173 | // Test reading counter while interrupts are firing | 187 | // Test reading counter while interrupts are firing |
| 174 | async fn test_counter_reading_during_interrupts( | 188 | async fn test_counter_reading_during_interrupts( |
| 175 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, | 189 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, |
| 176 | uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, | 190 | uart: &mut Lpuart<'_, Blocking>, |
| 177 | ) { | 191 | ) { |
| 178 | let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); | 192 | let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); |
| 179 | 193 | ||
| @@ -234,7 +248,7 @@ async fn test_counter_reading_during_interrupts( | |||
| 234 | // Test concurrent timer operations (embassy-time + alarms) | 248 | // Test concurrent timer operations (embassy-time + alarms) |
| 235 | async fn test_concurrent_operations( | 249 | async fn test_concurrent_operations( |
| 236 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, | 250 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, |
| 237 | uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, | 251 | uart: &mut Lpuart<'_, Blocking>, |
| 238 | ) { | 252 | ) { |
| 239 | let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); | 253 | let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); |
| 240 | 254 | ||
| @@ -263,7 +277,7 @@ async fn test_concurrent_operations( | |||
| 263 | // Test timer reset during active operations | 277 | // Test timer reset during active operations |
| 264 | async fn test_reset_during_operation( | 278 | async fn test_reset_during_operation( |
| 265 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, | 279 | ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, |
| 266 | uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, | 280 | uart: &mut Lpuart<'_, Blocking>, |
| 267 | peripherals: &hal::pac::Peripherals, | 281 | peripherals: &hal::pac::Peripherals, |
| 268 | ) { | 282 | ) { |
| 269 | let initial_counter = ostimer.now(); | 283 | let initial_counter = ostimer.now(); |
| @@ -304,7 +318,7 @@ async fn test_reset_during_operation( | |||
| 304 | } | 318 | } |
| 305 | 319 | ||
| 306 | // Helper function to write a u32 value as decimal string | 320 | // Helper function to write a u32 value as decimal string |
| 307 | fn write_u32(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u32) { | 321 | fn write_u32(uart: &mut Lpuart<'_, Blocking>, value: u32) { |
| 308 | if value == 0 { | 322 | if value == 0 { |
| 309 | uart.write_str_blocking("0"); | 323 | uart.write_str_blocking("0"); |
| 310 | return; | 324 | return; |
| @@ -339,7 +353,7 @@ fn write_u32(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u32) { | |||
| 339 | } | 353 | } |
| 340 | } | 354 | } |
| 341 | 355 | ||
| 342 | fn write_hex32(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u32) { | 356 | fn write_hex32(uart: &mut Lpuart<'_, Blocking>, value: u32) { |
| 343 | let mut buf = [b'0'; 8]; | 357 | let mut buf = [b'0'; 8]; |
| 344 | let mut tmp = value; | 358 | let mut tmp = value; |
| 345 | for i in (0..8).rev() { | 359 | for i in (0..8).rev() { |
| @@ -351,15 +365,13 @@ fn write_hex32(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u32) { | |||
| 351 | }; | 365 | }; |
| 352 | tmp >>= 4; | 366 | tmp >>= 4; |
| 353 | } | 367 | } |
| 354 | for b in &buf { | 368 | uart.blocking_write(&buf).unwrap(); |
| 355 | uart.write_byte(*b); | ||
| 356 | } | ||
| 357 | } | 369 | } |
| 358 | 370 | ||
| 359 | // Helper function to write a u64 value as decimal string | 371 | // Helper function to write a u64 value as decimal string |
| 360 | fn write_u64(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u64) { | 372 | fn write_u64(uart: &mut Lpuart<'_, Blocking>, value: u64) { |
| 361 | if value == 0 { | 373 | if value == 0 { |
| 362 | uart.write_str_blocking("0"); | 374 | uart.blocking_write(b"0").unwrap(); |
| 363 | return; | 375 | return; |
| 364 | } | 376 | } |
| 365 | 377 | ||
| @@ -377,17 +389,17 @@ fn write_u64(uart: &mut hal::uart::Uart<hal::uart::Lpuart2>, value: u64) { | |||
| 377 | while i > 0 { | 389 | while i > 0 { |
| 378 | i -= 1; | 390 | i -= 1; |
| 379 | match buffer[i] { | 391 | match buffer[i] { |
| 380 | b'0' => uart.write_str_blocking("0"), | 392 | b'0' => uart.blocking_write(b"0").unwrap(), |
| 381 | b'1' => uart.write_str_blocking("1"), | 393 | b'1' => uart.blocking_write(b"1").unwrap(), |
| 382 | b'2' => uart.write_str_blocking("2"), | 394 | b'2' => uart.blocking_write(b"2").unwrap(), |
| 383 | b'3' => uart.write_str_blocking("3"), | 395 | b'3' => uart.blocking_write(b"3").unwrap(), |
| 384 | b'4' => uart.write_str_blocking("4"), | 396 | b'4' => uart.blocking_write(b"4").unwrap(), |
| 385 | b'5' => uart.write_str_blocking("5"), | 397 | b'5' => uart.blocking_write(b"5").unwrap(), |
| 386 | b'6' => uart.write_str_blocking("6"), | 398 | b'6' => uart.blocking_write(b"6").unwrap(), |
| 387 | b'7' => uart.write_str_blocking("7"), | 399 | b'7' => uart.blocking_write(b"7").unwrap(), |
| 388 | b'8' => uart.write_str_blocking("8"), | 400 | b'8' => uart.blocking_write(b"8").unwrap(), |
| 389 | b'9' => uart.write_str_blocking("9"), | 401 | b'9' => uart.blocking_write(b"9").unwrap(), |
| 390 | _ => uart.write_str_blocking("?"), | 402 | _ => uart.blocking_write(b"?").unwrap(), |
| 391 | } | 403 | } |
| 392 | } | 404 | } |
| 393 | } | 405 | } |
diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs index dc07b5757..40a1207df 100644 --- a/examples/src/bin/rtc_alarm.rs +++ b/examples/src/bin/rtc_alarm.rs | |||
| @@ -3,11 +3,11 @@ | |||
| 3 | 3 | ||
| 4 | use embassy_executor::Spawner; | 4 | use embassy_executor::Spawner; |
| 5 | use embassy_mcxa as hal; | 5 | use embassy_mcxa as hal; |
| 6 | use embassy_mcxa_examples::init_uart2; | 6 | use hal::lpuart::{Config, Lpuart}; |
| 7 | use hal::rtc::{RtcDateTime, RtcInterruptEnable}; | 7 | use hal::rtc::{RtcDateTime, RtcInterruptEnable}; |
| 8 | use hal::{uart, InterruptExt}; | 8 | use hal::InterruptExt; |
| 9 | 9 | ||
| 10 | type MyRtc = hal::rtc::Rtc<hal::rtc::Rtc0>; | 10 | type MyRtc = hal::rtc::Rtc<'static, hal::rtc::Rtc0>; |
| 11 | 11 | ||
| 12 | use embassy_mcxa::bind_interrupts; | 12 | use embassy_mcxa::bind_interrupts; |
| 13 | use {defmt_rtt as _, panic_probe as _}; | 13 | use {defmt_rtt as _, panic_probe as _}; |
| @@ -24,17 +24,28 @@ static KEEP_RTC: unsafe extern "C" fn() = RTC; | |||
| 24 | async fn main(_spawner: Spawner) { | 24 | async fn main(_spawner: Spawner) { |
| 25 | let p = hal::init(hal::config::Config::default()); | 25 | let p = hal::init(hal::config::Config::default()); |
| 26 | 26 | ||
| 27 | // Create UART configuration | ||
| 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 PIO2_2 as TX and PIO2_3 as RX | ||
| 27 | unsafe { | 36 | unsafe { |
| 28 | init_uart2(hal::pac()); | 37 | embassy_mcxa_examples::init_uart2_pins(hal::pac()); |
| 29 | } | 38 | } |
| 30 | 39 | let mut uart = Lpuart::new_blocking( | |
| 31 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | 40 | p.LPUART2, // Peripheral |
| 32 | let uart = uart::Uart::<uart::Lpuart2>::new(p.LPUART2, uart::Config::new(src)); | 41 | p.PIO2_2, // TX pin |
| 42 | p.PIO2_3, // RX pin | ||
| 43 | config, | ||
| 44 | ) | ||
| 45 | .unwrap(); | ||
| 33 | 46 | ||
| 34 | uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); | 47 | uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); |
| 35 | 48 | ||
| 36 | unsafe { hal::clocks::init_fro16k(hal::pac()) }; | ||
| 37 | |||
| 38 | let rtc_config = hal::rtc::get_default_config(); | 49 | let rtc_config = hal::rtc::get_default_config(); |
| 39 | 50 | ||
| 40 | let rtc = MyRtc::new(p.RTC0, rtc_config); | 51 | let rtc = MyRtc::new(p.RTC0, rtc_config); |
diff --git a/examples/src/bin/uart_interrupt.rs b/examples/src/bin/uart_interrupt.rs deleted file mode 100644 index 100588727..000000000 --- a/examples/src/bin/uart_interrupt.rs +++ /dev/null | |||
| @@ -1,66 +0,0 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | |||
| 4 | use embassy_executor::Spawner; | ||
| 5 | use embassy_mcxa::bind_interrupts; | ||
| 6 | use embassy_mcxa_examples::init_uart2; | ||
| 7 | use hal::interrupt::typelevel::Handler; | ||
| 8 | use hal::uart; | ||
| 9 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | ||
| 10 | |||
| 11 | // Bind LPUART2 interrupt to our handler | ||
| 12 | bind_interrupts!(struct Irqs { | ||
| 13 | LPUART2 => hal::uart::UartInterruptHandler; | ||
| 14 | }); | ||
| 15 | |||
| 16 | #[used] | ||
| 17 | #[no_mangle] | ||
| 18 | static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; | ||
| 19 | |||
| 20 | // Wrapper function for the interrupt handler | ||
| 21 | unsafe extern "C" fn lpuart2_handler() { | ||
| 22 | hal::uart::UartInterruptHandler::on_interrupt(); | ||
| 23 | } | ||
| 24 | |||
| 25 | #[embassy_executor::main] | ||
| 26 | async fn main(_spawner: Spawner) { | ||
| 27 | let _p = hal::init(hal::config::Config::default()); | ||
| 28 | |||
| 29 | // Enable/clock UART2 before touching its registers | ||
| 30 | unsafe { | ||
| 31 | init_uart2(hal::pac()); | ||
| 32 | } | ||
| 33 | let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; | ||
| 34 | let uart = uart::Uart::<uart::Lpuart2>::new(_p.LPUART2, uart::Config::new(src)); | ||
| 35 | |||
| 36 | // Configure LPUART2 interrupt for UART operation BEFORE any UART usage | ||
| 37 | hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); | ||
| 38 | |||
| 39 | // Manually install the interrupt handler and enable RX IRQs in the peripheral | ||
| 40 | unsafe { | ||
| 41 | hal::interrupt::LPUART2.install_handler(lpuart2_handler); | ||
| 42 | // Enable RX interrupts so the handler actually fires on incoming bytes | ||
| 43 | uart.enable_rx_interrupts(); | ||
| 44 | } | ||
| 45 | |||
| 46 | // Print welcome message | ||
| 47 | uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); | ||
| 48 | uart.write_str_blocking("Type characters to echo them back.\r\n"); | ||
| 49 | |||
| 50 | // Log using defmt if enabled | ||
| 51 | defmt::info!("UART interrupt echo demo starting..."); | ||
| 52 | |||
| 53 | loop { | ||
| 54 | // Check if we have received any data | ||
| 55 | if uart.rx_data_available() { | ||
| 56 | if let Some(byte) = uart.try_read_byte() { | ||
| 57 | // Echo it back | ||
| 58 | uart.write_byte(byte); | ||
| 59 | uart.write_str_blocking(" (received)\r\n"); | ||
| 60 | } | ||
| 61 | } else { | ||
| 62 | // No data available, wait a bit before checking again | ||
| 63 | cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz | ||
| 64 | } | ||
| 65 | } | ||
| 66 | } | ||
diff --git a/examples/src/common/mod.rs b/examples/src/common/mod.rs deleted file mode 100644 index 8cb4590f8..000000000 --- a/examples/src/common/mod.rs +++ /dev/null | |||
| @@ -1,45 +0,0 @@ | |||
| 1 | //! Shared board-specific helpers for the FRDM-MCXA276 examples. | ||
| 2 | //! These live with the examples so the HAL stays generic. | ||
| 3 | |||
| 4 | use hal::{clocks, pins, reset}; | ||
| 5 | use {embassy_mcxa as hal, panic_probe as _}; | ||
| 6 | |||
| 7 | /// Initialize clocks and pin muxing for UART2 debug console. | ||
| 8 | /// Safe to call multiple times; writes are idempotent for our use. | ||
| 9 | #[allow(dead_code)] | ||
| 10 | pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { | ||
| 11 | clocks::ensure_frolf_running(p); | ||
| 12 | clocks::enable_uart2_port2(p); | ||
| 13 | reset::release_reset_port2(p); | ||
| 14 | reset::release_reset_lpuart2(p); | ||
| 15 | pins::configure_uart2_pins_port2(); | ||
| 16 | clocks::select_uart2_clock(p); | ||
| 17 | } | ||
| 18 | |||
| 19 | /// Initialize clocks for the LED GPIO/PORT used by the blink example. | ||
| 20 | #[allow(dead_code)] | ||
| 21 | pub unsafe fn init_led(p: &hal::pac::Peripherals) { | ||
| 22 | clocks::enable_led_port(p); | ||
| 23 | reset::release_reset_gpio3(p); | ||
| 24 | reset::release_reset_port3(p); | ||
| 25 | } | ||
| 26 | |||
| 27 | /// Initialize clocks for OSTIMER0 (1 MHz source). | ||
| 28 | #[allow(dead_code)] | ||
| 29 | pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { | ||
| 30 | clocks::ensure_frolf_running(p); | ||
| 31 | clocks::enable_ostimer0(p); | ||
| 32 | reset::release_reset_ostimer0(p); | ||
| 33 | clocks::select_ostimer0_clock_1m(p); | ||
| 34 | } | ||
| 35 | |||
| 36 | /// Initialize clocks and pin muxing for ADC. | ||
| 37 | #[allow(dead_code)] | ||
| 38 | pub unsafe fn init_adc(p: &hal::pac::Peripherals) { | ||
| 39 | clocks::ensure_frolf_running(p); | ||
| 40 | clocks::enable_adc(p); | ||
| 41 | reset::release_reset_port1(p); | ||
| 42 | reset::release_reset_adc1(p); | ||
| 43 | pins::configure_adc_pins(); | ||
| 44 | clocks::select_adc_clock(p); | ||
| 45 | } | ||
diff --git a/examples/src/lib.rs b/examples/src/lib.rs index cf4194559..4bb334da5 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs | |||
| @@ -1,63 +1,31 @@ | |||
| 1 | #![no_std] | 1 | #![no_std] |
| 2 | #![allow(clippy::missing_safety_doc)] | ||
| 2 | 3 | ||
| 3 | //! Shared board-specific helpers for the FRDM-MCXA276 examples. | 4 | //! Shared board-specific helpers for the FRDM-MCXA276 examples. |
| 4 | //! These live with the examples so the HAL stays generic. | 5 | //! These live with the examples so the HAL stays generic. |
| 5 | 6 | ||
| 6 | use hal::{clocks, pins, reset}; | 7 | use hal::{clocks, pins}; |
| 7 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; | 8 | use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; |
| 8 | 9 | ||
| 9 | /// Initialize clocks and pin muxing for UART2 debug console. | 10 | /// Initialize clocks and pin muxing for UART2 debug console. |
| 10 | /// Safe to call multiple times; writes are idempotent for our use. | 11 | /// Safe to call multiple times; writes are idempotent for our use. |
| 11 | /// | 12 | pub unsafe fn init_uart2_pins(_p: &hal::pac::Peripherals) { |
| 12 | /// # Safety | 13 | // NOTE: Lpuart has been updated to properly enable + reset its own clocks. |
| 13 | /// | 14 | // GPIO has not. |
| 14 | /// Called only once to initialize the peripheral | 15 | _ = clocks::enable_and_reset::<hal::peripherals::PORT2>(&clocks::periph_helpers::NoConfig); |
| 15 | #[allow(dead_code)] | ||
| 16 | pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { | ||
| 17 | clocks::ensure_frolf_running(p); | ||
| 18 | clocks::enable_uart2_port2(p); | ||
| 19 | reset::release_reset_port2(p); | ||
| 20 | reset::release_reset_lpuart2(p); | ||
| 21 | pins::configure_uart2_pins_port2(); | 16 | pins::configure_uart2_pins_port2(); |
| 22 | clocks::select_uart2_clock(p); | ||
| 23 | } | 17 | } |
| 24 | 18 | ||
| 25 | /// Initialize clocks for the LED GPIO/PORT used by the blink example. | 19 | /// Initialize clocks for the LED GPIO/PORT used by the blink example. |
| 26 | /// | 20 | pub unsafe fn init_led_gpio_clocks(_p: &hal::pac::Peripherals) { |
| 27 | /// # Safety | 21 | _ = clocks::enable_and_reset::<hal::peripherals::PORT3>(&clocks::periph_helpers::NoConfig); |
| 28 | /// | 22 | _ = clocks::enable_and_reset::<hal::peripherals::GPIO3>(&clocks::periph_helpers::NoConfig); |
| 29 | /// Called only once to initialize the peripheral | ||
| 30 | #[allow(dead_code)] | ||
| 31 | pub unsafe fn init_led(p: &hal::pac::Peripherals) { | ||
| 32 | clocks::enable_led_port(p); | ||
| 33 | reset::release_reset_gpio3(p); | ||
| 34 | reset::release_reset_port3(p); | ||
| 35 | } | ||
| 36 | |||
| 37 | /// Initialize clocks for OSTIMER0 (1 MHz source). | ||
| 38 | /// | ||
| 39 | /// # Safety | ||
| 40 | /// | ||
| 41 | /// Called only once to initialize the peripheral | ||
| 42 | #[allow(dead_code)] | ||
| 43 | pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { | ||
| 44 | clocks::ensure_frolf_running(p); | ||
| 45 | clocks::enable_ostimer0(p); | ||
| 46 | reset::release_reset_ostimer0(p); | ||
| 47 | clocks::select_ostimer0_clock_1m(p); | ||
| 48 | } | 23 | } |
| 49 | 24 | ||
| 50 | /// Initialize clocks and pin muxing for ADC. | 25 | /// Initialize clocks and pin muxing for ADC. |
| 51 | /// | 26 | pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) { |
| 52 | /// # Safety | 27 | // NOTE: Lpuart has been updated to properly enable + reset its own clocks. |
| 53 | /// | 28 | // GPIO has not. |
| 54 | /// Called only once to initialize the peripheral | 29 | _ = clocks::enable_and_reset::<hal::peripherals::PORT1>(&clocks::periph_helpers::NoConfig); |
| 55 | #[allow(dead_code)] | ||
| 56 | pub unsafe fn init_adc(p: &hal::pac::Peripherals) { | ||
| 57 | clocks::ensure_frolf_running(p); | ||
| 58 | clocks::enable_adc(p); | ||
| 59 | reset::release_reset_port1(p); | ||
| 60 | reset::release_reset_adc1(p); | ||
| 61 | pins::configure_adc_pins(); | 30 | pins::configure_adc_pins(); |
| 62 | clocks::select_adc_clock(p); | ||
| 63 | } | 31 | } |
