From 0443134bc47918d2f8f0ede1b292b372629f8894 Mon Sep 17 00:00:00 2001 From: Bogdan Petru Chircu Mare Date: Fri, 31 Oct 2025 21:44:48 -0700 Subject: feat(mcxa276): initial HAL import --- examples/adc_interrupt.rs | 106 +++++++++++ examples/adc_polling.rs | 95 ++++++++++ examples/blink.rs | 93 ++++++++++ examples/common/mod.rs | 45 +++++ examples/hello.rs | 126 +++++++++++++ examples/lpuart_buffered.rs | 88 +++++++++ examples/lpuart_polling.rs | 67 +++++++ examples/ostimer_alarm.rs | 126 +++++++++++++ examples/ostimer_async.rs | 76 ++++++++ examples/ostimer_counter.rs | 142 +++++++++++++++ examples/ostimer_race_test.rs | 411 ++++++++++++++++++++++++++++++++++++++++++ examples/rtc_alarm.rs | 105 +++++++++++ examples/uart_interrupt.rs | 86 +++++++++ 13 files changed, 1566 insertions(+) create mode 100644 examples/adc_interrupt.rs create mode 100644 examples/adc_polling.rs create mode 100644 examples/blink.rs create mode 100644 examples/common/mod.rs create mode 100644 examples/hello.rs create mode 100644 examples/lpuart_buffered.rs create mode 100644 examples/lpuart_polling.rs create mode 100644 examples/ostimer_alarm.rs create mode 100644 examples/ostimer_async.rs create mode 100644 examples/ostimer_counter.rs create mode 100644 examples/ostimer_race_test.rs create mode 100644 examples/rtc_alarm.rs create mode 100644 examples/uart_interrupt.rs (limited to 'examples') diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs new file mode 100644 index 000000000..452eaae01 --- /dev/null +++ b/examples/adc_interrupt.rs @@ -0,0 +1,106 @@ +#![no_std] +#![no_main] + +use embassy_mcxa276 as hal; +use cortex_m; +use embassy_executor::Spawner; + +use hal::adc::{TriggerPriorityPolicy, LpadcConfig}; +use hal::pac::adc1::cfg::{Refsel, Pwrsel}; +use hal::pac::adc1::tctrl::{Tcmd}; +use hal::pac::adc1::cmdl1::{Adch, Mode}; +use hal::pac::adc1::ctrl::{CalAvgs}; + +use hal::uart; +mod common; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use hal::bind_interrupts; +use hal::InterruptExt; + +bind_interrupts!(struct Irqs { + ADC1 => hal::adc::AdcHandler; +}); + +#[used] +#[no_mangle] +static KEEP_ADC: unsafe extern "C" fn() = ADC1; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + unsafe { + common::init_uart2(hal::pac()); + } + + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); + + unsafe { + common::init_adc(hal::pac()); + } + + + let adc_config = LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + }; + let adc = hal::adc::Adc::::new(p.ADC1, adc_config); + + adc.do_offset_calibration(); + adc.do_auto_calibration(); + + let mut conv_command_config = adc.get_default_conv_command_config(); + conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; + conv_command_config.conversion_resolution_mode = Mode::Data16Bits; + adc.set_conv_command_config(1, &conv_command_config); + + let mut conv_trigger_config = adc.get_default_conv_trigger_config(); + conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; + conv_trigger_config.enable_hardware_trigger = false; + adc.set_conv_trigger_config(0, &conv_trigger_config); + + uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + + adc.enable_interrupt(0x1); + + unsafe { + hal::interrupt::ADC1.enable(); + } + + unsafe { + cortex_m::interrupt::enable(); + } + + loop { + adc.do_software_trigger(1); + while !adc.is_interrupt_triggered() { + // Wait until the interrupt is triggered + } + uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); + //TBD need to print the value + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} \ No newline at end of file diff --git a/examples/adc_polling.rs b/examples/adc_polling.rs new file mode 100644 index 000000000..7cb728e91 --- /dev/null +++ b/examples/adc_polling.rs @@ -0,0 +1,95 @@ +#![no_std] +#![no_main] + +use embassy_mcxa276 as hal; + +use embassy_executor::Spawner; + +use hal::adc::{TriggerPriorityPolicy, LpadcConfig, ConvResult}; +use hal::pac::adc1::cfg::{Refsel, Pwrsel}; +use hal::pac::adc1::tctrl::{Tcmd}; +use hal::pac::adc1::cmdl1::{Adch, Mode}; +use hal::pac::adc1::ctrl::{CalAvgs}; + +use hal::uart; + +mod common; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use core::fmt::Write; +use heapless::String; + + +const G_LPADC_RESULT_SHIFT: u32 = 0; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + unsafe { + common::init_uart2(hal::pac()); + } + + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); + + unsafe { + common::init_adc(hal::pac()); + } + + + let adc_config = LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + }; + let adc = hal::adc::Adc::::new(p.ADC1, adc_config); + + adc.do_offset_calibration(); + adc.do_auto_calibration(); + + let mut conv_command_config = adc.get_default_conv_command_config(); + conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; + conv_command_config.conversion_resolution_mode = Mode::Data16Bits; + adc.set_conv_command_config(1, &conv_command_config); + + let mut conv_trigger_config = adc.get_default_conv_trigger_config(); + conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; + conv_trigger_config.enable_hardware_trigger = false; + adc.set_conv_trigger_config(0, &conv_trigger_config); + + uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + + loop { + adc.do_software_trigger(1); + let mut result: Option = None; + while result.is_none() { + result = hal::adc::get_conv_result(); + } + let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; + let mut buf: String<16> = String::new(); // adjust size as needed + write!(buf, "\r\nvalue: {}\r\n", value).unwrap(); + uart.write_str_blocking(&buf); + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} \ No newline at end of file diff --git a/examples/blink.rs b/examples/blink.rs new file mode 100644 index 000000000..6289ac14e --- /dev/null +++ b/examples/blink.rs @@ -0,0 +1,93 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use embassy_time::{Duration, Timer}; +use hal::gpio::pins::PIO3_18; +use hal::gpio::{Level, Output}; + +mod common; + +use embassy_mcxa276::bind_interrupts; + +// Bind only OS_EVENT for timer interrupts +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + + // Board-style init: enable LED GPIO/PORT clocks used by blink + unsafe { + common::init_led(hal::pac()); + } + // Initialize OSTIMER for async timing + unsafe { + common::init_ostimer0(hal::pac()); + } + + // Initialize embassy-time global driver backed by OSTIMER0 + hal::ostimer::time_driver::init( + hal::config::Config::default().time_interrupt_priority, + 1_000_000, + ); + + // Configure LED pin for GPIO mode + PIO3_18::set_mux_gpio(); + + let mut led = Output::new(PIO3_18::degrade(), Level::High); + + // Complex blinking pattern: SOS in Morse code + // S: ... (3 short) + // O: --- (3 long) + // S: ... (3 short) + // With pauses between letters and words + + loop { + // S: three short blinks + for _ in 0..3 { + led.set_low(); + Timer::after(Duration::from_millis(150)).await; + led.set_high(); + Timer::after(Duration::from_millis(150)).await; + } + + // Pause between letters + Timer::after(Duration::from_millis(300)).await; + + // O: three long blinks + for _ in 0..3 { + led.set_low(); + Timer::after(Duration::from_millis(450)).await; + led.set_high(); + Timer::after(Duration::from_millis(150)).await; + } + + // Pause between letters + Timer::after(Duration::from_millis(300)).await; + + // S: three short blinks + for _ in 0..3 { + led.set_low(); + Timer::after(Duration::from_millis(150)).await; + led.set_high(); + Timer::after(Duration::from_millis(150)).await; + } + + // Long pause between words (SOS repeats) + Timer::after(Duration::from_millis(1000)).await; + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/common/mod.rs b/examples/common/mod.rs new file mode 100644 index 000000000..7ada4c456 --- /dev/null +++ b/examples/common/mod.rs @@ -0,0 +1,45 @@ +//! Shared board-specific helpers for the FRDM-MCXA276 examples. +//! These live with the examples so the HAL stays generic. + +use embassy_mcxa276 as hal; +use hal::{clocks, pins, reset}; + +/// Initialize clocks and pin muxing for UART2 debug console. +/// Safe to call multiple times; writes are idempotent for our use. +#[allow(dead_code)] +pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_uart2_port2(p); + reset::release_reset_port2(p); + reset::release_reset_lpuart2(p); + pins::configure_uart2_pins_port2(); + clocks::select_uart2_clock(p); +} + +/// Initialize clocks for the LED GPIO/PORT used by the blink example. +#[allow(dead_code)] +pub unsafe fn init_led(p: &hal::pac::Peripherals) { + clocks::enable_led_port(p); + reset::release_reset_gpio3(p); + reset::release_reset_port3(p); +} + +/// Initialize clocks for OSTIMER0 (1 MHz source). +#[allow(dead_code)] +pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_ostimer0(p); + reset::release_reset_ostimer0(p); + clocks::select_ostimer0_clock_1m(p); +} + +/// Initialize clocks and pin muxing for ADC. +#[allow(dead_code)] +pub unsafe fn init_adc(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_adc(p); + reset::release_reset_port1(p); + reset::release_reset_adc1(p); + pins::configure_adc_pins(); + clocks::select_adc_clock(p); +} diff --git a/examples/hello.rs b/examples/hello.rs new file mode 100644 index 000000000..591bf2460 --- /dev/null +++ b/examples/hello.rs @@ -0,0 +1,126 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use hal::uart; + +mod common; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +/// Simple helper to write a byte as hex to UART +fn write_hex_byte(uart: &hal::uart::Uart, byte: u8) { + const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; + uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); + uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + #[cfg(feature = "defmt")] + defmt::info!("boot"); + + // Board-level init for UART2 clocks and pins. + unsafe { + common::init_uart2(hal::pac()); + } + + // Get UART source frequency from clock configuration + // Using hardcoded frequency for now - dynamic detection may have issues + let src = 12_000_000; // FRO_LF_DIV at 12MHz with DIV=0 + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + // Print welcome message before any async delays to guarantee early console output + uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); + uart.write_str_blocking("Available commands:\r\n"); + uart.write_str_blocking(" help - Show this help\r\n"); + uart.write_str_blocking(" echo - Echo back the text\r\n"); + uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); + uart.write_str_blocking("Type a command: "); + + let mut buffer = [0u8; 64]; + let mut buf_idx = 0; + + loop { + // Read a byte from UART + let byte = uart.read_byte_blocking(); + + // Echo the character back + if byte == b'\r' || byte == b'\n' { + // Enter pressed - process command + uart.write_str_blocking("\r\n"); + + if buf_idx > 0 { + let command = &buffer[0..buf_idx]; + + if command == b"help" { + uart.write_str_blocking("Available commands:\r\n"); + uart.write_str_blocking(" help - Show this help\r\n"); + uart.write_str_blocking(" echo - Echo back the text\r\n"); + uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); + } else if command.starts_with(b"echo ") && command.len() > 5 { + uart.write_str_blocking("Echo: "); + uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or("")); + uart.write_str_blocking("\r\n"); + } else if command.starts_with(b"hex ") && command.len() > 4 { + // Parse the byte value + let num_str = &command[4..]; + if let Ok(num) = parse_u8(num_str) { + uart.write_str_blocking("Hex: 0x"); + write_hex_byte(&uart, num); + uart.write_str_blocking("\r\n"); + } else { + uart.write_str_blocking("Invalid number for hex command\r\n"); + } + } else if command.len() > 0 { + uart.write_str_blocking("Unknown command: "); + uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); + uart.write_str_blocking("\r\n"); + } + } + + // Reset buffer and prompt + buf_idx = 0; + uart.write_str_blocking("Type a command: "); + } else if byte == 8 || byte == 127 { + // Backspace + if buf_idx > 0 { + buf_idx -= 1; + uart.write_str_blocking("\x08 \x08"); // Erase character + } + } else if buf_idx < buffer.len() - 1 { + // Regular character + buffer[buf_idx] = byte; + buf_idx += 1; + uart.write_byte(byte); + } + } +} + +/// Simple parser for u8 from ASCII bytes +fn parse_u8(bytes: &[u8]) -> Result { + let mut result = 0u8; + for &b in bytes { + if b >= b'0' && b <= b'9' { + result = result.checked_mul(10).ok_or(())?; + result = result.checked_add(b - b'0').ok_or(())?; + } else { + return Err(()); + } + } + Ok(result) +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs new file mode 100644 index 000000000..88f256096 --- /dev/null +++ b/examples/lpuart_buffered.rs @@ -0,0 +1,88 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use embassy_mcxa276::interrupt::typelevel::Handler; +use embassy_mcxa276::lpuart; +use embassy_mcxa276::lpuart::buffered::BufferedLpuart; + +use embedded_io_async::{Read, Write}; + +use embassy_mcxa276::bind_interrupts; + +mod common; + +// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver +bind_interrupts!(struct Irqs { + LPUART2 => lpuart::buffered::BufferedInterruptHandler::; +}); + +// Wrapper function for the interrupt handler +unsafe extern "C" fn lpuart2_handler() { + lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + let p2 = lpuart::lib::init(); + + unsafe { + hal::interrupt::install_irq_handler(mcxa276_pac::Interrupt::LPUART2, lpuart2_handler); + } + + // Configure NVIC for LPUART2 + hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); + + unsafe { + common::init_uart2(hal::pac()); + common::init_ostimer0(hal::pac()); + } + + // UART configuration (enable both TX and RX) + let config = lpuart::Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + rx_fifo_watermark: 0, + tx_fifo_watermark: 0, + ..Default::default() + }; + + let mut tx_buf = [0u8; 256]; + let mut rx_buf = [0u8; 256]; + + // Create a buffered LPUART2 instance with both TX and RX + let mut uart = BufferedLpuart::new( + p2.LPUART2, + p2.PIO2_2, // TX pin + p2.PIO2_3, // RX pin + Irqs, + &mut tx_buf, + &mut rx_buf, + config, + ) + .unwrap(); + + // Split into TX and RX parts + let (tx, rx) = uart.split_ref(); + + tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); + tx.write(b"Type characters to echo them back.\r\n") + .await + .unwrap(); + + // Echo loop + let mut buf = [0u8; 4]; + loop { + rx.read_exact(&mut buf[..]).await.unwrap(); + tx.write_all(&buf[..]).await.unwrap(); + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/lpuart_polling.rs b/examples/lpuart_polling.rs new file mode 100644 index 000000000..c83c959e8 --- /dev/null +++ b/examples/lpuart_polling.rs @@ -0,0 +1,67 @@ +#![no_std] +#![no_main] + +use crate::hal::lpuart::{lib, Config, Lpuart}; +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +mod common; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + let p2 = lib::init(); + + #[cfg(feature = "defmt")] + defmt::info!("boot"); + + // Board-level init for UART2 clocks and pins. + unsafe { + common::init_uart2(hal::pac()); + } + + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + let lpuart = Lpuart::new_blocking( + p2.LPUART2, // Peripheral + p2.PIO2_2, // TX pin + p2.PIO2_3, // RX pin + config, + ) + .unwrap(); + + // Split into separate TX and RX parts + let (mut tx, mut rx) = lpuart.split(); + + // Write hello messages + tx.blocking_write(b"Hello world.\r\n").unwrap(); + tx.blocking_write(b"Echoing. Type characters...\r\n") + .unwrap(); + + // Echo loop + loop { + let mut buf = [0u8; 1]; + rx.blocking_read(&mut buf).unwrap(); + tx.blocking_write(&buf).unwrap(); + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs new file mode 100644 index 000000000..823e37c15 --- /dev/null +++ b/examples/ostimer_alarm.rs @@ -0,0 +1,126 @@ +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicBool, Ordering}; +use cortex_m; +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use hal::uart; + +mod common; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use embassy_mcxa276::bind_interrupts; + +// Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +// Global flag for alarm callback +static ALARM_FLAG: AtomicBool = AtomicBool::new(false); + +// Alarm callback function +fn alarm_callback() { + ALARM_FLAG.store(true, Ordering::Release); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + common::init_ostimer0(hal::pac()); + } + unsafe { + common::init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + uart.write_str_blocking("OSTIMER Alarm Example\n"); + + // Initialize embassy-time global driver backed by OSTIMER0 + hal::ostimer::time_driver::init( + hal::config::Config::default().time_interrupt_priority, + 1_000_000, + ); + + // Create OSTIMER instance + let config = hal::ostimer::Config { + init_match_max: true, + clock_frequency_hz: 1_000_000, // 1MHz + }; + let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); + + // Create alarm with callback + let alarm = hal::ostimer::Alarm::new() + .with_callback(alarm_callback) + .with_flag(&ALARM_FLAG); + + uart.write_str_blocking("Scheduling alarm for 2 seconds...\n"); + + // Schedule alarm to expire in 2 seconds (2,000,000 microseconds) + let scheduled = ostimer.schedule_alarm_delay(&alarm, 2_000_000); + if scheduled { + uart.write_str_blocking("Alarm scheduled successfully\n"); + } else { + uart.write_str_blocking("Failed to schedule alarm (would exceed timer capacity)\n"); + return; + } + + // Wait for alarm to expire + loop { + // Check if alarm has expired + if ALARM_FLAG.load(Ordering::Acquire) { + uart.write_str_blocking("Alarm expired! Callback executed.\n"); + break; + } + + // Busy wait - don't use Timer::after_millis as it interferes with alarm MATCH + for _ in 0..100000 { + cortex_m::asm::nop(); + } + } + + // Demonstrate canceling an alarm + uart.write_str_blocking("Scheduling another alarm for 3 seconds...\n"); + ALARM_FLAG.store(false, Ordering::Release); // Reset flag + + let scheduled = ostimer.schedule_alarm_delay(&alarm, 3_000_000); + if scheduled { + uart.write_str_blocking("Alarm scheduled. Waiting 1 second then canceling...\n"); + + // Wait 1 second + embassy_time::Timer::after_millis(1000).await; + + // Cancel the alarm + ostimer.cancel_alarm(&alarm); + uart.write_str_blocking("Alarm canceled\n"); + + // Check immediately if alarm flag is set + if !ALARM_FLAG.load(Ordering::Acquire) { + uart.write_str_blocking("Alarm was successfully canceled\n"); + } else { + uart.write_str_blocking("Alarm fired despite cancellation\n"); + } + } + + uart.write_str_blocking("Example complete\n"); +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/ostimer_async.rs b/examples/ostimer_async.rs new file mode 100644 index 000000000..181ce58ef --- /dev/null +++ b/examples/ostimer_async.rs @@ -0,0 +1,76 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use hal::uart; + +mod common; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use embassy_time::{Duration, Timer}; + +use embassy_mcxa276::bind_interrupts; + +// Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + common::init_ostimer0(hal::pac()); + } + unsafe { + common::init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); + uart.write_str_blocking("boot\n"); + + // Avoid mass NVIC writes here; DefaultHandler now safely returns. + + // Initialize embassy-time global driver backed by OSTIMER0 (re-enables OS_EVENT with priority) + // The bind_interrupts! macro handles handler binding automatically + + // Initialize OSTIMER with default 1MHz frequency + // Adjust this value to match your actual OSTIMER clock frequency + hal::ostimer::time_driver::init( + hal::config::Config::default().time_interrupt_priority, + 1_000_000, + ); + + // Removed force-pend; rely on real hardware match to trigger OS_EVENT. + + // Log using defmt if enabled + #[cfg(feature = "defmt")] + defmt::info!("OSTIMER async example starting..."); + + loop { + #[cfg(feature = "defmt")] + defmt::info!("tick"); + #[cfg(not(feature = "defmt"))] + uart.write_str_blocking("tick\n"); + Timer::after(Duration::from_millis(1000)).await; + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs new file mode 100644 index 000000000..3af0f03f2 --- /dev/null +++ b/examples/ostimer_counter.rs @@ -0,0 +1,142 @@ +//! # OSTIMER Counter Reading and Reset Example +//! +//! This example demonstrates the new timer counter reading and reset functionality +//! of the OSTIMER driver. + +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::{Duration, Timer}; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use embassy_mcxa276 as hal; +use hal::bind_interrupts; + +mod common; + +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(Default::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + common::init_ostimer0(hal::pac()); + } + unsafe { + common::init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + + uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); + + // Initialize the OSTIMER time driver + hal::ostimer::time_driver::init( + hal::interrupt::Priority::from(3), + 1_000_000, // 1MHz clock + ); + + // Create OSTIMER instance + let ostimer = hal::ostimer::Ostimer::::new( + p.OSTIMER0, + hal::ostimer::Config { + init_match_max: true, + clock_frequency_hz: 1_000_000, + }, + hal::pac(), + ); + + // Read initial counter value + let initial_counter = ostimer.now(); + uart.write_str_blocking("Initial counter value: "); + write_u64(&mut uart, initial_counter); + uart.write_str_blocking("\n"); + + // Wait a bit to let counter increment + Timer::after(Duration::from_millis(100)).await; + + // Read counter again + let counter_after_wait = ostimer.now(); + uart.write_str_blocking("Counter after 100ms wait: "); + write_u64(&mut uart, counter_after_wait); + uart.write_str_blocking("\n"); + uart.write_str_blocking("Difference: "); + write_u64(&mut uart, counter_after_wait - initial_counter); + uart.write_str_blocking(" ticks\n"); + + // Reset the timer + uart.write_str_blocking("Resetting timer...\n"); + ostimer.reset(hal::pac()); + + // Read counter after reset + let counter_after_reset = ostimer.now(); + uart.write_str_blocking("Counter after reset: "); + write_u64(&mut uart, counter_after_reset); + uart.write_str_blocking("\n"); + + // Wait again to verify timer is working + Timer::after(Duration::from_millis(50)).await; + + let final_counter = ostimer.now(); + uart.write_str_blocking("Counter after another 50ms: "); + write_u64(&mut uart, final_counter); + uart.write_str_blocking("\n"); + uart.write_str_blocking("Difference after reset: "); + write_u64(&mut uart, final_counter - counter_after_reset); + uart.write_str_blocking(" ticks\n"); + + uart.write_str_blocking("Example complete\n"); +} + +// Helper function to write a u64 value as decimal string +fn write_u64(uart: &mut hal::uart::Uart, value: u64) { + if value == 0 { + uart.write_str_blocking("0"); + return; + } + + let mut buffer = [0u8; 20]; // Enough for max u64 + let mut i = 0; + let mut v = value; + + while v > 0 { + buffer[i] = b'0' + (v % 10) as u8; + v /= 10; + i += 1; + } + + // Write digits in reverse order + while i > 0 { + i -= 1; + match buffer[i] { + b'0' => uart.write_str_blocking("0"), + b'1' => uart.write_str_blocking("1"), + b'2' => uart.write_str_blocking("2"), + b'3' => uart.write_str_blocking("3"), + b'4' => uart.write_str_blocking("4"), + b'5' => uart.write_str_blocking("5"), + b'6' => uart.write_str_blocking("6"), + b'7' => uart.write_str_blocking("7"), + b'8' => uart.write_str_blocking("8"), + b'9' => uart.write_str_blocking("9"), + _ => uart.write_str_blocking("?"), + } + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs new file mode 100644 index 000000000..4470b65fd --- /dev/null +++ b/examples/ostimer_race_test.rs @@ -0,0 +1,411 @@ +//! # OSTIMER Race Condition Test +//! +//! This example tests for race conditions in the OSTIMER driver by: +//! - Scheduling alarms sequentially (hardware limitation: only one at a time) +//! - Reading the counter during interrupt-heavy periods +//! - Testing concurrent timer operations +//! - Stress testing interrupt handling + +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::{Duration, Timer}; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use core::sync::atomic::{AtomicU32, Ordering}; +use embassy_mcxa276 as hal; +use hal::bind_interrupts; + +mod common; + +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +// Global counters for race condition detection +static ALARM_CALLBACK_COUNT: AtomicU32 = AtomicU32::new(0); +static INTERRUPT_COUNT: AtomicU32 = AtomicU32::new(0); +static RACE_DETECTED: AtomicU32 = AtomicU32::new(0); + +// Alarm callback function +fn alarm_callback() { + let _count = ALARM_CALLBACK_COUNT.fetch_add(1, Ordering::SeqCst); + INTERRUPT_COUNT.fetch_add(1, Ordering::SeqCst); + + // Simulate some work in the callback to increase chance of races + for _ in 0..10 { + cortex_m::asm::nop(); + } +} + +fn report_default_handler(uart: &mut hal::uart::Uart) { + let snapshot = hal::interrupt::default_handler_snapshot(); + if snapshot.count == 0 { + return; + } + + uart.write_str_blocking("WARNING: DefaultHandler executed "); + write_u32(uart, snapshot.count); + uart.write_str_blocking(" time(s). Vector="); + write_u32(uart, snapshot.vector as u32); + uart.write_str_blocking(" CFSR=0x"); + write_hex32(uart, snapshot.cfsr); + uart.write_str_blocking(" HFSR=0x"); + write_hex32(uart, snapshot.hfsr); + uart.write_str_blocking(" PC=0x"); + write_hex32(uart, snapshot.stacked_pc); + uart.write_str_blocking(" LR=0x"); + write_hex32(uart, snapshot.stacked_lr); + uart.write_str_blocking(" SP=0x"); + write_hex32(uart, snapshot.stacked_sp); + uart.write_str_blocking("\n"); + + hal::interrupt::clear_default_handler_snapshot(); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(Default::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + common::init_ostimer0(hal::pac()); + } + unsafe { + common::init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + + uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); + + // The bind_interrupts! macro handles handler binding automatically + + // Initialize the OSTIMER time driver FIRST + hal::ostimer::time_driver::init( + hal::interrupt::Priority::from(3), + 1_000_000, // 1MHz clock + ); + + uart.write_str_blocking("Time driver initialized\n"); + + // Create OSTIMER instance + let ostimer = hal::ostimer::Ostimer::::new( + p.OSTIMER0, + hal::ostimer::Config { + init_match_max: true, + clock_frequency_hz: 1_000_000, + }, + hal::pac(), + ); + + uart.write_str_blocking("OSTIMER instance created\n"); + + // Test 1: Sequential alarm scheduling (OSTIMER only supports one alarm at a time) + uart.write_str_blocking("Test 1: Sequential alarm scheduling...\n"); + test_rapid_alarms(&ostimer, &mut uart).await; + report_default_handler(&mut uart); + + // Test 2: Counter reading during interrupts + uart.write_str_blocking("Test 2: Counter reading during interrupts...\n"); + test_counter_reading_during_interrupts(&ostimer, &mut uart).await; + report_default_handler(&mut uart); + + // Test 3: Concurrent timer operations + uart.write_str_blocking("Test 3: Concurrent timer operations...\n"); + test_concurrent_operations(&ostimer, &mut uart).await; + report_default_handler(&mut uart); + + // Test 4: Timer reset during operation + uart.write_str_blocking("Test 4: Timer reset during operation...\n"); + test_reset_during_operation(&ostimer, &mut uart, hal::pac()).await; + report_default_handler(&mut uart); + + // Report results + uart.write_str_blocking("Race condition test complete\n"); + uart.write_str_blocking("Callback count: "); + write_u32(&mut uart, ALARM_CALLBACK_COUNT.load(Ordering::SeqCst)); + uart.write_str_blocking("\nInterrupt count: "); + write_u32(&mut uart, INTERRUPT_COUNT.load(Ordering::SeqCst)); + uart.write_str_blocking("\nRaces detected: "); + write_u32(&mut uart, RACE_DETECTED.load(Ordering::SeqCst)); + uart.write_str_blocking("\n"); +} + +// Test rapid alarm scheduling to stress interrupt handling +async fn test_rapid_alarms( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, +) { + let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); + + // Schedule 10 alarms sequentially (OSTIMER only supports one alarm at a time) + for _i in 0..10 { + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + let delay_us = 1000; // 1ms delay for each alarm + if ostimer.schedule_alarm_delay(&alarm, delay_us) { + // Wait for this alarm to complete before scheduling the next + Timer::after(Duration::from_micros(delay_us + 100)).await; + report_default_handler(uart); + } else { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm (match not ready)\n"); + } + } + + // All alarms should have completed by now + let final_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); + let expected_count = initial_count + 10; + + if final_count != expected_count { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Expected "); + write_u32(uart, expected_count); + uart.write_str_blocking(" callbacks, got "); + write_u32(uart, final_count); + uart.write_str_blocking("\n"); + } else { + uart.write_str_blocking("PASS: All rapid alarms executed\n"); + } +} + +// Test reading counter while interrupts are firing +async fn test_counter_reading_during_interrupts( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, +) { + let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + // Schedule an alarm that will fire soon + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + if !ostimer.schedule_alarm_delay(&alarm, 500) { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before counter stress\n"); + } + + // While alarm is pending, read the counter many times rapidly + // This tests if counter reading is atomic and doesn't get corrupted by interrupts + let mut last_counter = ostimer.now(); + let mut consistent_reads = 0; + let mut total_reads = 0; + + for _ in 0..1000 { + let current_counter = ostimer.now(); + total_reads += 1; + + // Check if counter is monotonically increasing (basic sanity check) + if current_counter >= last_counter { + consistent_reads += 1; + } + last_counter = current_counter; + + // Small delay between reads + for _ in 0..10 { + cortex_m::asm::nop(); + } + + report_default_handler(uart); + } + + // Wait for alarm to complete + Timer::after(Duration::from_millis(1)).await; + + let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + if consistent_reads == total_reads { + uart.write_str_blocking("PASS: Counter reading consistent during interrupts\n"); + } else { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Counter reading inconsistent: "); + write_u32(uart, consistent_reads); + uart.write_str_blocking("/"); + write_u32(uart, total_reads); + uart.write_str_blocking(" consistent\n"); + } + + if final_interrupt_count > initial_interrupt_count { + uart.write_str_blocking("PASS: Interrupt fired during counter reading test\n"); + } else { + uart.write_str_blocking("WARNING: No interrupt fired during counter reading test\n"); + } +} + +// Test concurrent timer operations (embassy-time + alarms) +async fn test_concurrent_operations( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, +) { + let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + // Start an embassy-time timer + let timer_future = Timer::after(Duration::from_millis(2)); + + // Schedule an alarm that should fire before the timer + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + if !ostimer.schedule_alarm_delay(&alarm, 1000) { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking( + "ERROR: Failed to program OSTIMER alarm before concurrent operations\n", + ); + } + + // Wait for both to complete + timer_future.await; + + let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + if final_interrupt_count > initial_interrupt_count { + uart.write_str_blocking("PASS: Concurrent operations completed\n"); + } else { + uart.write_str_blocking("WARNING: No interrupts during concurrent operations\n"); + } +} + +// Test timer reset during active operations +async fn test_reset_during_operation( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, + peripherals: &hal::pac::Peripherals, +) { + let initial_counter = ostimer.now(); + + // Schedule an alarm + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + if !ostimer.schedule_alarm_delay(&alarm, 2000) { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before reset test\n"); + } + + // Wait a bit then reset the timer + Timer::after(Duration::from_millis(1)).await; + ostimer.reset(peripherals); + + // Check counter after reset + let counter_after_reset = ostimer.now(); + + // Wait to see if the alarm still fires (it shouldn't after reset) + Timer::after(Duration::from_millis(2)).await; + + let final_counter = ostimer.now(); + + if counter_after_reset < initial_counter { + uart.write_str_blocking("PASS: Timer reset successful\n"); + } else { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Timer reset may have failed\n"); + } + + uart.write_str_blocking("Counter progression after reset: "); + write_u64(uart, initial_counter); + uart.write_str_blocking(" -> "); + write_u64(uart, counter_after_reset); + uart.write_str_blocking(" -> "); + write_u64(uart, final_counter); + uart.write_str_blocking("\n"); +} + +// Helper function to write a u32 value as decimal string +fn write_u32(uart: &mut hal::uart::Uart, value: u32) { + if value == 0 { + uart.write_str_blocking("0"); + return; + } + + let mut buffer = [0u8; 10]; // Enough for max u32 + let mut i = 0; + let mut v = value; + + while v > 0 { + buffer[i] = b'0' + (v % 10) as u8; + v /= 10; + i += 1; + } + + // Write digits in reverse order + while i > 0 { + i -= 1; + match buffer[i] { + b'0' => uart.write_str_blocking("0"), + b'1' => uart.write_str_blocking("1"), + b'2' => uart.write_str_blocking("2"), + b'3' => uart.write_str_blocking("3"), + b'4' => uart.write_str_blocking("4"), + b'5' => uart.write_str_blocking("5"), + b'6' => uart.write_str_blocking("6"), + b'7' => uart.write_str_blocking("7"), + b'8' => uart.write_str_blocking("8"), + b'9' => uart.write_str_blocking("9"), + _ => uart.write_str_blocking("?"), + } + } +} + +fn write_hex32(uart: &mut hal::uart::Uart, value: u32) { + let mut buf = [b'0'; 8]; + let mut tmp = value; + for i in (0..8).rev() { + let digit = (tmp & 0xF) as u8; + buf[i] = match digit { + 0..=9 => b'0' + digit, + 10..=15 => b'A' + (digit - 10), + _ => b'?', + }; + tmp >>= 4; + } + for b in &buf { + uart.write_byte(*b); + } +} + +// Helper function to write a u64 value as decimal string +fn write_u64(uart: &mut hal::uart::Uart, value: u64) { + if value == 0 { + uart.write_str_blocking("0"); + return; + } + + let mut buffer = [0u8; 20]; // Enough for max u64 + let mut i = 0; + let mut v = value; + + while v > 0 { + buffer[i] = b'0' + (v % 10) as u8; + v /= 10; + i += 1; + } + + // Write digits in reverse order + while i > 0 { + i -= 1; + match buffer[i] { + b'0' => uart.write_str_blocking("0"), + b'1' => uart.write_str_blocking("1"), + b'2' => uart.write_str_blocking("2"), + b'3' => uart.write_str_blocking("3"), + b'4' => uart.write_str_blocking("4"), + b'5' => uart.write_str_blocking("5"), + b'6' => uart.write_str_blocking("6"), + b'7' => uart.write_str_blocking("7"), + b'8' => uart.write_str_blocking("8"), + b'9' => uart.write_str_blocking("9"), + _ => uart.write_str_blocking("?"), + } + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/rtc_alarm.rs b/examples/rtc_alarm.rs new file mode 100644 index 000000000..8f4ff1623 --- /dev/null +++ b/examples/rtc_alarm.rs @@ -0,0 +1,105 @@ +#![no_std] +#![no_main] + + +use embassy_mcxa276 as hal; +use cortex_m; +use embassy_executor::Spawner; +use hal::rtc::{RtcDateTime, RtcInterruptEnable}; +use hal::uart; +use hal::InterruptExt; + +mod common; + +type MyRtc = hal::rtc::Rtc; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use embassy_mcxa276::bind_interrupts; +bind_interrupts!(struct Irqs { + RTC => hal::rtc::RtcHandler; +}); + +#[used] +#[no_mangle] +static KEEP_RTC: unsafe extern "C" fn() = RTC; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + + let p = hal::init(hal::config::Config::default()); + + unsafe { + common::init_uart2(hal::pac()); + } + + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); + + unsafe { hal::clocks::init_fro16k(hal::pac()) }; + + let rtc_config = hal::rtc::get_default_config(); + + let rtc = MyRtc::new(p.RTC0, rtc_config); + + let now = RtcDateTime { + year: 2025, + month: 10, + day: 15, + hour: 14, + minute: 30, + second: 0, + }; + + + rtc.stop(); + + uart.write_str_blocking("Time set to: 2025-10-15 14:30:00\r\n"); + rtc.set_datetime(now); + + let mut alarm = now; + alarm.second += 10; + + rtc.set_alarm(alarm); + uart.write_str_blocking("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)\r\n"); + + rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE); + + unsafe { + hal::interrupt::RTC.enable(); + } + + unsafe { + cortex_m::interrupt::enable(); + } + + rtc.start(); + + uart.write_str_blocking("RTC started, waiting for alarm...\r\n"); + + loop { + if rtc.is_alarm_triggered() { + uart.write_str_blocking("\r\n*** ALARM TRIGGERED! ***\r\n"); + break; + } + } + + uart.write_str_blocking("Example complete - Test PASSED!\r\n"); + + loop { + + } +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs new file mode 100644 index 000000000..b309ce973 --- /dev/null +++ b/examples/uart_interrupt.rs @@ -0,0 +1,86 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use hal::interrupt::typelevel::Handler; +use hal::uart; + +mod common; + +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use defmt_rtt as _; +#[cfg(feature = "defmt")] +use panic_probe as _; +#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] +use rtt_target as _; + +use embassy_mcxa276::bind_interrupts; + +// Bind LPUART2 interrupt to our handler +bind_interrupts!(struct Irqs { + LPUART2 => hal::uart::UartInterruptHandler; +}); + +#[used] +#[no_mangle] +static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; + +// Wrapper function for the interrupt handler +unsafe extern "C" fn lpuart2_handler() { + hal::uart::UartInterruptHandler::on_interrupt(); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + + // Enable/clock UART2 before touching its registers + unsafe { + common::init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); + + // Configure LPUART2 interrupt for UART operation BEFORE any UART usage + hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); + + // Manually install the interrupt handler + unsafe { + hal::interrupt::LPUART2.install_handler(lpuart2_handler); + } + + // Print welcome message + uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); + uart.write_str_blocking("Type characters to echo them back.\r\n"); + + // Log using defmt if enabled + #[cfg(feature = "defmt")] + defmt::info!("UART interrupt echo demo starting..."); + + loop { + // Check if we have received any data + if uart.rx_data_available() { + if let Some(byte) = uart.try_read_byte() { + // Echo it back + uart.write_byte(byte); + uart.write_str_blocking(" (received)\r\n"); + } + } else { + // No data available, wait a bit before checking again + cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz + } + } +} + +#[cfg(feature = "defmt")] +#[export_name = "_defmt_timestamp"] +fn defmt_timestamp(_fmt: defmt::Formatter<'_>) { + // Return empty timestamp for now +} + +#[cfg(not(feature = "defmt"))] +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} -- cgit From a71eff2e1cea55b393e793c023b8e51e5cc369a1 Mon Sep 17 00:00:00 2001 From: Bogdan Petru Chircu Mare Date: Thu, 6 Nov 2025 21:51:56 -0800 Subject: Fix uart_interrupt example: enable RX interrupts in peripheral The uart_interrupt example was not echoing received characters because the RX interrupt enable bit (RIE) was not being set in the LPUART control register. The NVIC interrupt was configured and the handler was installed, but the peripheral itself was not generating interrupts. Added uart.enable_rx_interrupts() call to enable RX data interrupts in the LPUART2 peripheral before entering the main loop. --- examples/uart_interrupt.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs index b309ce973..85743bb64 100644 --- a/examples/uart_interrupt.rs +++ b/examples/uart_interrupt.rs @@ -45,9 +45,11 @@ async fn main(_spawner: Spawner) { // Configure LPUART2 interrupt for UART operation BEFORE any UART usage hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); - // Manually install the interrupt handler + // Manually install the interrupt handler and enable RX IRQs in the peripheral unsafe { hal::interrupt::LPUART2.install_handler(lpuart2_handler); + // Enable RX interrupts so the handler actually fires on incoming bytes + uart.enable_rx_interrupts(); } // Print welcome message -- cgit From cb2ac2790f4b037056f9571abeb4d62360199426 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Nov 2025 10:06:55 -0800 Subject: Reduce number of features We don't need features for drivers that always exist. Signed-off-by: Felipe Balbi --- examples/adc_interrupt.rs | 54 +++++++++++++++++-------------------------- examples/adc_polling.rs | 47 ++++++++++++++----------------------- examples/blink.rs | 6 ----- examples/hello.rs | 14 +---------- examples/lpuart_buffered.rs | 6 ----- examples/lpuart_polling.rs | 16 ++----------- examples/ostimer_alarm.rs | 16 +++---------- examples/ostimer_async.rs | 20 ++-------------- examples/ostimer_counter.rs | 16 +++---------- examples/ostimer_race_test.rs | 17 +++----------- examples/rtc_alarm.rs | 25 ++++---------------- examples/uart_interrupt.rs | 21 +---------------- 12 files changed, 58 insertions(+), 200 deletions(-) (limited to 'examples') diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs index 452eaae01..26afd70b4 100644 --- a/examples/adc_interrupt.rs +++ b/examples/adc_interrupt.rs @@ -1,28 +1,23 @@ #![no_std] #![no_main] -use embassy_mcxa276 as hal; use cortex_m; use embassy_executor::Spawner; +use embassy_mcxa276 as hal; -use hal::adc::{TriggerPriorityPolicy, LpadcConfig}; -use hal::pac::adc1::cfg::{Refsel, Pwrsel}; -use hal::pac::adc1::tctrl::{Tcmd}; +use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; +use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; -use hal::pac::adc1::ctrl::{CalAvgs}; +use hal::pac::adc1::ctrl::CalAvgs; +use hal::pac::adc1::tctrl::Tcmd; use hal::uart; mod common; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; -use hal::bind_interrupts; use hal::InterruptExt; +use hal::bind_interrupts; bind_interrupts!(struct Irqs { ADC1 => hal::adc::AdcHandler; @@ -40,7 +35,7 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); @@ -48,19 +43,18 @@ async fn main(_spawner: Spawner) { unsafe { common::init_adc(hal::pac()); } - - + let adc_config = LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::Average128, - enable_analog_preliminary: true, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option3, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, }; let adc = hal::adc::Adc::::new(p.ADC1, adc_config); @@ -78,7 +72,7 @@ async fn main(_spawner: Spawner) { adc.set_conv_trigger_config(0, &conv_trigger_config); uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); - + adc.enable_interrupt(0x1); unsafe { @@ -92,15 +86,9 @@ async fn main(_spawner: Spawner) { loop { adc.do_software_trigger(1); while !adc.is_interrupt_triggered() { - // Wait until the interrupt is triggered + // Wait until the interrupt is triggered } uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); //TBD need to print the value } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} \ No newline at end of file diff --git a/examples/adc_polling.rs b/examples/adc_polling.rs index 7cb728e91..90be87c3f 100644 --- a/examples/adc_polling.rs +++ b/examples/adc_polling.rs @@ -5,27 +5,21 @@ use embassy_mcxa276 as hal; use embassy_executor::Spawner; -use hal::adc::{TriggerPriorityPolicy, LpadcConfig, ConvResult}; -use hal::pac::adc1::cfg::{Refsel, Pwrsel}; -use hal::pac::adc1::tctrl::{Tcmd}; +use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; +use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; -use hal::pac::adc1::ctrl::{CalAvgs}; +use hal::pac::adc1::ctrl::CalAvgs; +use hal::pac::adc1::tctrl::Tcmd; use hal::uart; mod common; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; use core::fmt::Write; use heapless::String; - const G_LPADC_RESULT_SHIFT: u32 = 0; #[embassy_executor::main] @@ -44,19 +38,18 @@ async fn main(_spawner: Spawner) { unsafe { common::init_adc(hal::pac()); } - - + let adc_config = LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::Average128, - enable_analog_preliminary: true, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option3, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, }; let adc = hal::adc::Adc::::new(p.ADC1, adc_config); @@ -74,7 +67,7 @@ async fn main(_spawner: Spawner) { adc.set_conv_trigger_config(0, &conv_trigger_config); uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); - + loop { adc.do_software_trigger(1); let mut result: Option = None; @@ -87,9 +80,3 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking(&buf); } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} \ No newline at end of file diff --git a/examples/blink.rs b/examples/blink.rs index 6289ac14e..a9b6e7093 100644 --- a/examples/blink.rs +++ b/examples/blink.rs @@ -85,9 +85,3 @@ async fn main(_spawner: Spawner) { Timer::after(Duration::from_millis(1000)).await; } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/hello.rs b/examples/hello.rs index 591bf2460..e39adaced 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -7,12 +7,7 @@ use hal::uart; mod common; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; /// Simple helper to write a byte as hex to UART fn write_hex_byte(uart: &hal::uart::Uart, byte: u8) { @@ -25,7 +20,6 @@ fn write_hex_byte(uart: &hal::uart::Uart, byte: u8) { async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); - #[cfg(feature = "defmt")] defmt::info!("boot"); // Board-level init for UART2 clocks and pins. @@ -118,9 +112,3 @@ fn parse_u8(bytes: &[u8]) -> Result { } Ok(result) } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs index 88f256096..d0d4d2ee0 100644 --- a/examples/lpuart_buffered.rs +++ b/examples/lpuart_buffered.rs @@ -80,9 +80,3 @@ async fn main(_spawner: Spawner) { tx.write_all(&buf[..]).await.unwrap(); } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/lpuart_polling.rs b/examples/lpuart_polling.rs index c83c959e8..f9172de40 100644 --- a/examples/lpuart_polling.rs +++ b/examples/lpuart_polling.rs @@ -1,16 +1,11 @@ #![no_std] #![no_main] -use crate::hal::lpuart::{lib, Config, Lpuart}; +use crate::hal::lpuart::{Config, Lpuart, lib}; use embassy_executor::Spawner; use embassy_mcxa276 as hal; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; mod common; @@ -19,7 +14,6 @@ async fn main(_spawner: Spawner) { let _p = hal::init(hal::config::Config::default()); let p2 = lib::init(); - #[cfg(feature = "defmt")] defmt::info!("boot"); // Board-level init for UART2 clocks and pins. @@ -59,9 +53,3 @@ async fn main(_spawner: Spawner) { tx.blocking_write(&buf).unwrap(); } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs index 823e37c15..eca669509 100644 --- a/examples/ostimer_alarm.rs +++ b/examples/ostimer_alarm.rs @@ -9,12 +9,7 @@ use hal::uart; mod common; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; use embassy_mcxa276::bind_interrupts; @@ -61,7 +56,8 @@ async fn main(_spawner: Spawner) { init_match_max: true, clock_frequency_hz: 1_000_000, // 1MHz }; - let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); + let ostimer = + hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); // Create alarm with callback let alarm = hal::ostimer::Alarm::new() @@ -118,9 +114,3 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("Example complete\n"); } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/ostimer_async.rs b/examples/ostimer_async.rs index 181ce58ef..37fb3b3d1 100644 --- a/examples/ostimer_async.rs +++ b/examples/ostimer_async.rs @@ -7,16 +7,9 @@ use hal::uart; mod common; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; - -use embassy_time::{Duration, Timer}; - use embassy_mcxa276::bind_interrupts; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. bind_interrupts!(struct Irqs { @@ -57,20 +50,11 @@ async fn main(_spawner: Spawner) { // Removed force-pend; rely on real hardware match to trigger OS_EVENT. // Log using defmt if enabled - #[cfg(feature = "defmt")] defmt::info!("OSTIMER async example starting..."); loop { - #[cfg(feature = "defmt")] defmt::info!("tick"); - #[cfg(not(feature = "defmt"))] uart.write_str_blocking("tick\n"); Timer::after(Duration::from_millis(1000)).await; } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs index 3af0f03f2..1f5bdf434 100644 --- a/examples/ostimer_counter.rs +++ b/examples/ostimer_counter.rs @@ -9,12 +9,7 @@ use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; use embassy_mcxa276 as hal; use hal::bind_interrupts; @@ -37,7 +32,8 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + let mut uart = + hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); @@ -134,9 +130,3 @@ fn write_u64(uart: &mut hal::uart::Uart, value: u64) { } } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs index 4470b65fd..072310309 100644 --- a/examples/ostimer_race_test.rs +++ b/examples/ostimer_race_test.rs @@ -12,16 +12,10 @@ use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; - use core::sync::atomic::{AtomicU32, Ordering}; use embassy_mcxa276 as hal; use hal::bind_interrupts; +use {defmt_rtt as _, panic_probe as _}; mod common; @@ -86,7 +80,8 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + let mut uart = + hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); @@ -403,9 +398,3 @@ fn write_u64(uart: &mut hal::uart::Uart, value: u64) { } } } - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} diff --git a/examples/rtc_alarm.rs b/examples/rtc_alarm.rs index 8f4ff1623..a190b8ba5 100644 --- a/examples/rtc_alarm.rs +++ b/examples/rtc_alarm.rs @@ -1,26 +1,21 @@ #![no_std] #![no_main] - -use embassy_mcxa276 as hal; use cortex_m; use embassy_executor::Spawner; +use embassy_mcxa276 as hal; +use hal::InterruptExt; use hal::rtc::{RtcDateTime, RtcInterruptEnable}; use hal::uart; -use hal::InterruptExt; mod common; type MyRtc = hal::rtc::Rtc; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; +use {defmt_rtt as _, panic_probe as _}; use embassy_mcxa276::bind_interrupts; + bind_interrupts!(struct Irqs { RTC => hal::rtc::RtcHandler; }); @@ -31,7 +26,6 @@ static KEEP_RTC: unsafe extern "C" fn() = RTC; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); unsafe { @@ -58,12 +52,11 @@ async fn main(_spawner: Spawner) { second: 0, }; - rtc.stop(); uart.write_str_blocking("Time set to: 2025-10-15 14:30:00\r\n"); rtc.set_datetime(now); - + let mut alarm = now; alarm.second += 10; @@ -92,14 +85,6 @@ async fn main(_spawner: Spawner) { } uart.write_str_blocking("Example complete - Test PASSED!\r\n"); - - loop { - - } -} -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { loop {} } diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs index 85743bb64..bd734f859 100644 --- a/examples/uart_interrupt.rs +++ b/examples/uart_interrupt.rs @@ -8,14 +8,8 @@ use hal::uart; mod common; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use defmt_rtt as _; -#[cfg(feature = "defmt")] -use panic_probe as _; -#[cfg(all(feature = "defmt", feature = "defmt-rtt"))] -use rtt_target as _; - use embassy_mcxa276::bind_interrupts; +use {defmt_rtt as _, panic_probe as _}; // Bind LPUART2 interrupt to our handler bind_interrupts!(struct Irqs { @@ -57,7 +51,6 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("Type characters to echo them back.\r\n"); // Log using defmt if enabled - #[cfg(feature = "defmt")] defmt::info!("UART interrupt echo demo starting..."); loop { @@ -74,15 +67,3 @@ async fn main(_spawner: Spawner) { } } } - -#[cfg(feature = "defmt")] -#[export_name = "_defmt_timestamp"] -fn defmt_timestamp(_fmt: defmt::Formatter<'_>) { - // Return empty timestamp for now -} - -#[cfg(not(feature = "defmt"))] -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} -- cgit From e75066820ad320495ca70570641c90d75247b19b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 7 Nov 2025 10:07:33 -0800 Subject: cargo +nightly fmt Signed-off-by: Felipe Balbi --- examples/adc_interrupt.rs | 9 ++------- examples/adc_polling.rs | 9 +++------ examples/blink.rs | 5 +---- examples/lpuart_buffered.rs | 9 ++------- examples/lpuart_polling.rs | 8 +++----- examples/ostimer_alarm.rs | 15 +++++---------- examples/ostimer_async.rs | 5 +---- examples/ostimer_counter.rs | 8 ++------ examples/ostimer_race_test.rs | 14 +++++--------- examples/rtc_alarm.rs | 9 +++------ 10 files changed, 27 insertions(+), 64 deletions(-) (limited to 'examples') diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs index 26afd70b4..f0df3196c 100644 --- a/examples/adc_interrupt.rs +++ b/examples/adc_interrupt.rs @@ -1,24 +1,19 @@ #![no_std] #![no_main] -use cortex_m; use embassy_executor::Spawner; -use embassy_mcxa276 as hal; - use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; use hal::pac::adc1::ctrl::CalAvgs; use hal::pac::adc1::tctrl::Tcmd; - use hal::uart; +use {cortex_m, embassy_mcxa276 as hal}; mod common; +use hal::{bind_interrupts, InterruptExt}; use {defmt_rtt as _, panic_probe as _}; -use hal::InterruptExt; -use hal::bind_interrupts; - bind_interrupts!(struct Irqs { ADC1 => hal::adc::AdcHandler; }); diff --git a/examples/adc_polling.rs b/examples/adc_polling.rs index 90be87c3f..561500d2d 100644 --- a/examples/adc_polling.rs +++ b/examples/adc_polling.rs @@ -1,24 +1,21 @@ #![no_std] #![no_main] -use embassy_mcxa276 as hal; - use embassy_executor::Spawner; - +use embassy_mcxa276 as hal; use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; use hal::pac::adc1::ctrl::CalAvgs; use hal::pac::adc1::tctrl::Tcmd; - use hal::uart; mod common; -use {defmt_rtt as _, panic_probe as _}; - use core::fmt::Write; + use heapless::String; +use {defmt_rtt as _, panic_probe as _}; const G_LPADC_RESULT_SHIFT: u32 = 0; diff --git a/examples/blink.rs b/examples/blink.rs index a9b6e7093..564353d5c 100644 --- a/examples/blink.rs +++ b/examples/blink.rs @@ -34,10 +34,7 @@ async fn main(_spawner: Spawner) { } // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init( - hal::config::Config::default().time_interrupt_priority, - 1_000_000, - ); + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); // Configure LED pin for GPIO mode PIO3_18::set_mux_gpio(); diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs index d0d4d2ee0..30ba3f333 100644 --- a/examples/lpuart_buffered.rs +++ b/examples/lpuart_buffered.rs @@ -4,13 +4,10 @@ use embassy_executor::Spawner; use embassy_mcxa276 as hal; use embassy_mcxa276::interrupt::typelevel::Handler; -use embassy_mcxa276::lpuart; use embassy_mcxa276::lpuart::buffered::BufferedLpuart; - +use embassy_mcxa276::{bind_interrupts, lpuart}; use embedded_io_async::{Read, Write}; -use embassy_mcxa276::bind_interrupts; - mod common; // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver @@ -69,9 +66,7 @@ async fn main(_spawner: Spawner) { let (tx, rx) = uart.split_ref(); tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); - tx.write(b"Type characters to echo them back.\r\n") - .await - .unwrap(); + tx.write(b"Type characters to echo them back.\r\n").await.unwrap(); // Echo loop let mut buf = [0u8; 4]; diff --git a/examples/lpuart_polling.rs b/examples/lpuart_polling.rs index f9172de40..067c7eb53 100644 --- a/examples/lpuart_polling.rs +++ b/examples/lpuart_polling.rs @@ -1,11 +1,10 @@ #![no_std] #![no_main] -use crate::hal::lpuart::{Config, Lpuart, lib}; use embassy_executor::Spawner; -use embassy_mcxa276 as hal; +use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; -use {defmt_rtt as _, panic_probe as _}; +use crate::hal::lpuart::{lib, Config, Lpuart}; mod common; @@ -43,8 +42,7 @@ async fn main(_spawner: Spawner) { // Write hello messages tx.blocking_write(b"Hello world.\r\n").unwrap(); - tx.blocking_write(b"Echoing. Type characters...\r\n") - .unwrap(); + tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap(); // Echo loop loop { diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs index eca669509..78ca4bbc5 100644 --- a/examples/ostimer_alarm.rs +++ b/examples/ostimer_alarm.rs @@ -2,16 +2,15 @@ #![no_main] use core::sync::atomic::{AtomicBool, Ordering}; -use cortex_m; + use embassy_executor::Spawner; -use embassy_mcxa276 as hal; use hal::uart; +use {cortex_m, embassy_mcxa276 as hal}; mod common; -use {defmt_rtt as _, panic_probe as _}; - use embassy_mcxa276::bind_interrupts; +use {defmt_rtt as _, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. bind_interrupts!(struct Irqs { @@ -46,18 +45,14 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("OSTIMER Alarm Example\n"); // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init( - hal::config::Config::default().time_interrupt_priority, - 1_000_000, - ); + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); // Create OSTIMER instance let config = hal::ostimer::Config { init_match_max: true, clock_frequency_hz: 1_000_000, // 1MHz }; - let ostimer = - hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); + let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); // Create alarm with callback let alarm = hal::ostimer::Alarm::new() diff --git a/examples/ostimer_async.rs b/examples/ostimer_async.rs index 37fb3b3d1..27e14e022 100644 --- a/examples/ostimer_async.rs +++ b/examples/ostimer_async.rs @@ -42,10 +42,7 @@ async fn main(_spawner: Spawner) { // Initialize OSTIMER with default 1MHz frequency // Adjust this value to match your actual OSTIMER clock frequency - hal::ostimer::time_driver::init( - hal::config::Config::default().time_interrupt_priority, - 1_000_000, - ); + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); // Removed force-pend; rely on real hardware match to trigger OS_EVENT. diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs index 1f5bdf434..e95140a88 100644 --- a/examples/ostimer_counter.rs +++ b/examples/ostimer_counter.rs @@ -8,11 +8,8 @@ use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; - -use {defmt_rtt as _, panic_probe as _}; - -use embassy_mcxa276 as hal; use hal::bind_interrupts; +use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; mod common; @@ -32,8 +29,7 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = - hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs index 072310309..a637b6353 100644 --- a/examples/ostimer_race_test.rs +++ b/examples/ostimer_race_test.rs @@ -9,13 +9,12 @@ #![no_std] #![no_main] +use core::sync::atomic::{AtomicU32, Ordering}; + use embassy_executor::Spawner; use embassy_time::{Duration, Timer}; - -use core::sync::atomic::{AtomicU32, Ordering}; -use embassy_mcxa276 as hal; use hal::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; +use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; mod common; @@ -80,8 +79,7 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = - hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); @@ -250,9 +248,7 @@ async fn test_concurrent_operations( let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); if !ostimer.schedule_alarm_delay(&alarm, 1000) { RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking( - "ERROR: Failed to program OSTIMER alarm before concurrent operations\n", - ); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before concurrent operations\n"); } // Wait for both to complete diff --git a/examples/rtc_alarm.rs b/examples/rtc_alarm.rs index a190b8ba5..c27fd4c55 100644 --- a/examples/rtc_alarm.rs +++ b/examples/rtc_alarm.rs @@ -1,20 +1,17 @@ #![no_std] #![no_main] -use cortex_m; use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::InterruptExt; use hal::rtc::{RtcDateTime, RtcInterruptEnable}; -use hal::uart; +use hal::{uart, InterruptExt}; +use {cortex_m, embassy_mcxa276 as hal}; mod common; type MyRtc = hal::rtc::Rtc; -use {defmt_rtt as _, panic_probe as _}; - use embassy_mcxa276::bind_interrupts; +use {defmt_rtt as _, panic_probe as _}; bind_interrupts!(struct Irqs { RTC => hal::rtc::RtcHandler; -- cgit From 110a5eb4e58ecee5bc45bd47c3366ea241587e1b Mon Sep 17 00:00:00 2001 From: James Munns Date: Wed, 12 Nov 2025 17:16:19 +0100 Subject: Remove example feats, get examples building No CI, but this can be checked with `cargo check --all --examples`, which now succeeds. --- examples/adc_interrupt.rs | 8 ++++---- examples/adc_polling.rs | 8 ++++---- examples/common/mod.rs | 10 +++++----- examples/lpuart_buffered.rs | 2 +- examples/ostimer_race_test.rs | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'examples') diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs index f0df3196c..dc82cfd30 100644 --- a/examples/adc_interrupt.rs +++ b/examples/adc_interrupt.rs @@ -3,11 +3,11 @@ use embassy_executor::Spawner; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; -use hal::pac::adc1::cfg::{Pwrsel, Refsel}; -use hal::pac::adc1::cmdl1::{Adch, Mode}; -use hal::pac::adc1::ctrl::CalAvgs; -use hal::pac::adc1::tctrl::Tcmd; use hal::uart; +use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; +use mcxa_pac::adc1::cmdl1::{Adch, Mode}; +use mcxa_pac::adc1::ctrl::CalAvgs; +use mcxa_pac::adc1::tctrl::Tcmd; use {cortex_m, embassy_mcxa276 as hal}; mod common; diff --git a/examples/adc_polling.rs b/examples/adc_polling.rs index 561500d2d..4b5f9422d 100644 --- a/examples/adc_polling.rs +++ b/examples/adc_polling.rs @@ -4,11 +4,11 @@ use embassy_executor::Spawner; use embassy_mcxa276 as hal; use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; -use hal::pac::adc1::cfg::{Pwrsel, Refsel}; -use hal::pac::adc1::cmdl1::{Adch, Mode}; -use hal::pac::adc1::ctrl::CalAvgs; -use hal::pac::adc1::tctrl::Tcmd; use hal::uart; +use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; +use mcxa_pac::adc1::cmdl1::{Adch, Mode}; +use mcxa_pac::adc1::ctrl::CalAvgs; +use mcxa_pac::adc1::tctrl::Tcmd; mod common; diff --git a/examples/common/mod.rs b/examples/common/mod.rs index 7ada4c456..8c52c8e86 100644 --- a/examples/common/mod.rs +++ b/examples/common/mod.rs @@ -1,13 +1,13 @@ //! Shared board-specific helpers for the FRDM-MCXA276 examples. //! These live with the examples so the HAL stays generic. -use embassy_mcxa276 as hal; use hal::{clocks, pins, reset}; +use {embassy_mcxa276 as hal, panic_probe as _}; /// Initialize clocks and pin muxing for UART2 debug console. /// Safe to call multiple times; writes are idempotent for our use. #[allow(dead_code)] -pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { +pub unsafe fn init_uart2(p: &mcxa_pac::Peripherals) { clocks::ensure_frolf_running(p); clocks::enable_uart2_port2(p); reset::release_reset_port2(p); @@ -18,7 +18,7 @@ pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { /// Initialize clocks for the LED GPIO/PORT used by the blink example. #[allow(dead_code)] -pub unsafe fn init_led(p: &hal::pac::Peripherals) { +pub unsafe fn init_led(p: &mcxa_pac::Peripherals) { clocks::enable_led_port(p); reset::release_reset_gpio3(p); reset::release_reset_port3(p); @@ -26,7 +26,7 @@ pub unsafe fn init_led(p: &hal::pac::Peripherals) { /// Initialize clocks for OSTIMER0 (1 MHz source). #[allow(dead_code)] -pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { +pub unsafe fn init_ostimer0(p: &mcxa_pac::Peripherals) { clocks::ensure_frolf_running(p); clocks::enable_ostimer0(p); reset::release_reset_ostimer0(p); @@ -35,7 +35,7 @@ pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { /// Initialize clocks and pin muxing for ADC. #[allow(dead_code)] -pub unsafe fn init_adc(p: &hal::pac::Peripherals) { +pub unsafe fn init_adc(p: &mcxa_pac::Peripherals) { clocks::ensure_frolf_running(p); clocks::enable_adc(p); reset::release_reset_port1(p); diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs index 30ba3f333..35d311143 100644 --- a/examples/lpuart_buffered.rs +++ b/examples/lpuart_buffered.rs @@ -26,7 +26,7 @@ async fn main(_spawner: Spawner) { let p2 = lpuart::lib::init(); unsafe { - hal::interrupt::install_irq_handler(mcxa276_pac::Interrupt::LPUART2, lpuart2_handler); + hal::interrupt::install_irq_handler(mcxa_pac::Interrupt::LPUART2, lpuart2_handler); } // Configure NVIC for LPUART2 diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs index a637b6353..368a3e52f 100644 --- a/examples/ostimer_race_test.rs +++ b/examples/ostimer_race_test.rs @@ -267,7 +267,7 @@ async fn test_concurrent_operations( async fn test_reset_during_operation( ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, uart: &mut hal::uart::Uart, - peripherals: &hal::pac::Peripherals, + peripherals: &mcxa_pac::Peripherals, ) { let initial_counter = ostimer.now(); -- cgit From 77b2c602a60e41c7c977003a6d40367ac285930e Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 13 Nov 2025 13:17:44 -0800 Subject: Move examples to a package of their own (#16) * Move examples to a package of their own * cargo +nightly fmt * Add missing safety doc * cargo clippy examples * fmt again --------- Co-authored-by: Felipe Balbi --- examples/.cargo/config.toml | 17 + examples/.gitignore | 1 + examples/Cargo.lock | 625 ++++++++++++++++++++++++++++++++++ examples/Cargo.toml | 21 ++ examples/adc_interrupt.rs | 89 ----- examples/adc_polling.rs | 79 ----- examples/blink.rs | 84 ----- examples/build.rs | 20 ++ examples/common/mod.rs | 45 --- examples/hello.rs | 114 ------- examples/lpuart_buffered.rs | 77 ----- examples/lpuart_polling.rs | 53 --- examples/memory.x | 5 + examples/ostimer_alarm.rs | 111 ------ examples/ostimer_async.rs | 57 ---- examples/ostimer_counter.rs | 128 ------- examples/ostimer_race_test.rs | 396 --------------------- examples/rtc_alarm.rs | 87 ----- examples/src/bin/adc_interrupt.rs | 86 +++++ examples/src/bin/adc_polling.rs | 76 +++++ examples/src/bin/blink.rs | 78 +++++ examples/src/bin/hello.rs | 111 ++++++ examples/src/bin/lpuart_buffered.rs | 76 +++++ examples/src/bin/lpuart_polling.rs | 51 +++ examples/src/bin/ostimer_alarm.rs | 106 ++++++ examples/src/bin/ostimer_async.rs | 52 +++ examples/src/bin/ostimer_counter.rs | 125 +++++++ examples/src/bin/ostimer_race_test.rs | 393 +++++++++++++++++++++ examples/src/bin/rtc_alarm.rs | 84 +++++ examples/src/bin/uart_interrupt.rs | 66 ++++ examples/src/common/mod.rs | 45 +++ examples/src/lib.rs | 63 ++++ examples/uart_interrupt.rs | 69 ---- 33 files changed, 2101 insertions(+), 1389 deletions(-) create mode 100644 examples/.cargo/config.toml create mode 100644 examples/.gitignore create mode 100644 examples/Cargo.lock create mode 100644 examples/Cargo.toml delete mode 100644 examples/adc_interrupt.rs delete mode 100644 examples/adc_polling.rs delete mode 100644 examples/blink.rs create mode 100644 examples/build.rs delete mode 100644 examples/common/mod.rs delete mode 100644 examples/hello.rs delete mode 100644 examples/lpuart_buffered.rs delete mode 100644 examples/lpuart_polling.rs create mode 100644 examples/memory.x delete mode 100644 examples/ostimer_alarm.rs delete mode 100644 examples/ostimer_async.rs delete mode 100644 examples/ostimer_counter.rs delete mode 100644 examples/ostimer_race_test.rs delete mode 100644 examples/rtc_alarm.rs create mode 100644 examples/src/bin/adc_interrupt.rs create mode 100644 examples/src/bin/adc_polling.rs create mode 100644 examples/src/bin/blink.rs create mode 100644 examples/src/bin/hello.rs create mode 100644 examples/src/bin/lpuart_buffered.rs create mode 100644 examples/src/bin/lpuart_polling.rs create mode 100644 examples/src/bin/ostimer_alarm.rs create mode 100644 examples/src/bin/ostimer_async.rs create mode 100644 examples/src/bin/ostimer_counter.rs create mode 100644 examples/src/bin/ostimer_race_test.rs create mode 100644 examples/src/bin/rtc_alarm.rs create mode 100644 examples/src/bin/uart_interrupt.rs create mode 100644 examples/src/common/mod.rs create mode 100644 examples/src/lib.rs delete mode 100644 examples/uart_interrupt.rs (limited to 'examples') diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml new file mode 100644 index 000000000..ecb11be64 --- /dev/null +++ b/examples/.cargo/config.toml @@ -0,0 +1,17 @@ +[target.thumbv8m.main-none-eabihf] +runner = 'probe-rs run --chip MCXA276 --preverify --verify' + +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tdefmt.x", + # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x + # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + "-C", "link-arg=--nmagic", +] + +[build] +target = "thumbv8m.main-none-eabihf" # Cortex-M33 + +[env] +DEFMT_LOG = "trace" diff --git a/examples/.gitignore b/examples/.gitignore new file mode 100644 index 000000000..2f7896d1d --- /dev/null +++ b/examples/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/examples/Cargo.lock b/examples/Cargo.lock new file mode 100644 index 000000000..b774aff97 --- /dev/null +++ b/examples/Cargo.lock @@ -0,0 +1,625 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" +dependencies = [ + "bitflags", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d5a25c99d89c40f5676bec8cefe0614f17f0f40e916f98e345dae941807f9e" +dependencies = [ + "critical-section", + "defmt", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "embassy-embedded-hal" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" +dependencies = [ + "embassy-futures", + "embassy-hal-internal", + "embassy-sync", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" +dependencies = [ + "cortex-m", + "critical-section", + "document-features", + "embassy-executor-macros", + "embassy-executor-timer-queue", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "embassy-executor-timer-queue" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" + +[[package]] +name = "embassy-futures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" + +[[package]] +name = "embassy-hal-internal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" +dependencies = [ + "cortex-m", + "critical-section", + "num-traits", +] + +[[package]] +name = "embassy-mcxa" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-hal-internal", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "heapless 0.8.0", + "mcxa-pac", + "nb 1.1.0", + "paste", +] + +[[package]] +name = "embassy-mcxa-examples" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-mcxa", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embedded-io-async", + "heapless 0.9.2", + "panic-probe", +] + +[[package]] +name = "embassy-sync" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-core", + "futures-sink", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-core", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" +dependencies = [ + "document-features", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "mcxa-pac" +version = "0.1.0" +source = "git+https://github.com/OpenDevicePartnership/mcxa-pac?rev=3ab4c868f75a9240bb8fdce24982d34f2273aabf#3ab4c868f75a9240bb8fdce24982d34f2273aabf" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "vcell", +] + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "panic-probe" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a" +dependencies = [ + "cortex-m", + "defmt", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 000000000..6b100de42 --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "embassy-mcxa-examples" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[dependencies] +cortex-m = { version = "0.7", features = ["critical-section-single-core"] } +cortex-m-rt = { version = "0.7", features = ["device"] } +critical-section = "1.2.0" +defmt = "1.0" +defmt-rtt = "1.0" +embassy-embedded-hal = "0.5.0" +embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false } +embassy-mcxa = { path = "../", features = ["defmt", "rt", "unstable-pac"] } +embassy-sync = "0.7.2" +embassy-time = "0.5.0" +embassy-time-driver = "0.2.1" +embedded-io-async = "0.6.1" +heapless = "0.9.2" +panic-probe = { version = "1.0", features = ["print-defmt"] } diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs deleted file mode 100644 index dc82cfd30..000000000 --- a/examples/adc_interrupt.rs +++ /dev/null @@ -1,89 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; -use hal::uart; -use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; -use mcxa_pac::adc1::cmdl1::{Adch, Mode}; -use mcxa_pac::adc1::ctrl::CalAvgs; -use mcxa_pac::adc1::tctrl::Tcmd; -use {cortex_m, embassy_mcxa276 as hal}; -mod common; - -use hal::{bind_interrupts, InterruptExt}; -use {defmt_rtt as _, panic_probe as _}; - -bind_interrupts!(struct Irqs { - ADC1 => hal::adc::AdcHandler; -}); - -#[used] -#[no_mangle] -static KEEP_ADC: unsafe extern "C" fn() = ADC1; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - unsafe { - common::init_uart2(hal::pac()); - } - - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - - uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); - - unsafe { - common::init_adc(hal::pac()); - } - - let adc_config = LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::Average128, - enable_analog_preliminary: true, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option3, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, - }; - let adc = hal::adc::Adc::::new(p.ADC1, adc_config); - - adc.do_offset_calibration(); - adc.do_auto_calibration(); - - let mut conv_command_config = adc.get_default_conv_command_config(); - conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; - conv_command_config.conversion_resolution_mode = Mode::Data16Bits; - adc.set_conv_command_config(1, &conv_command_config); - - let mut conv_trigger_config = adc.get_default_conv_trigger_config(); - conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; - conv_trigger_config.enable_hardware_trigger = false; - adc.set_conv_trigger_config(0, &conv_trigger_config); - - uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); - - adc.enable_interrupt(0x1); - - unsafe { - hal::interrupt::ADC1.enable(); - } - - unsafe { - cortex_m::interrupt::enable(); - } - - loop { - adc.do_software_trigger(1); - while !adc.is_interrupt_triggered() { - // Wait until the interrupt is triggered - } - uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); - //TBD need to print the value - } -} diff --git a/examples/adc_polling.rs b/examples/adc_polling.rs deleted file mode 100644 index 4b5f9422d..000000000 --- a/examples/adc_polling.rs +++ /dev/null @@ -1,79 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; -use hal::uart; -use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; -use mcxa_pac::adc1::cmdl1::{Adch, Mode}; -use mcxa_pac::adc1::ctrl::CalAvgs; -use mcxa_pac::adc1::tctrl::Tcmd; - -mod common; - -use core::fmt::Write; - -use heapless::String; -use {defmt_rtt as _, panic_probe as _}; - -const G_LPADC_RESULT_SHIFT: u32 = 0; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - unsafe { - common::init_uart2(hal::pac()); - } - - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - - uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); - - unsafe { - common::init_adc(hal::pac()); - } - - let adc_config = LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::Average128, - enable_analog_preliminary: true, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option3, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, - }; - let adc = hal::adc::Adc::::new(p.ADC1, adc_config); - - adc.do_offset_calibration(); - adc.do_auto_calibration(); - - let mut conv_command_config = adc.get_default_conv_command_config(); - conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; - conv_command_config.conversion_resolution_mode = Mode::Data16Bits; - adc.set_conv_command_config(1, &conv_command_config); - - let mut conv_trigger_config = adc.get_default_conv_trigger_config(); - conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; - conv_trigger_config.enable_hardware_trigger = false; - adc.set_conv_trigger_config(0, &conv_trigger_config); - - uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); - - loop { - adc.do_software_trigger(1); - let mut result: Option = None; - while result.is_none() { - result = hal::adc::get_conv_result(); - } - let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; - let mut buf: String<16> = String::new(); // adjust size as needed - write!(buf, "\r\nvalue: {}\r\n", value).unwrap(); - uart.write_str_blocking(&buf); - } -} diff --git a/examples/blink.rs b/examples/blink.rs deleted file mode 100644 index 564353d5c..000000000 --- a/examples/blink.rs +++ /dev/null @@ -1,84 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use embassy_time::{Duration, Timer}; -use hal::gpio::pins::PIO3_18; -use hal::gpio::{Level, Output}; - -mod common; - -use embassy_mcxa276::bind_interrupts; - -// Bind only OS_EVENT for timer interrupts -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - - // Board-style init: enable LED GPIO/PORT clocks used by blink - unsafe { - common::init_led(hal::pac()); - } - // Initialize OSTIMER for async timing - unsafe { - common::init_ostimer0(hal::pac()); - } - - // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - - // Configure LED pin for GPIO mode - PIO3_18::set_mux_gpio(); - - let mut led = Output::new(PIO3_18::degrade(), Level::High); - - // Complex blinking pattern: SOS in Morse code - // S: ... (3 short) - // O: --- (3 long) - // S: ... (3 short) - // With pauses between letters and words - - loop { - // S: three short blinks - for _ in 0..3 { - led.set_low(); - Timer::after(Duration::from_millis(150)).await; - led.set_high(); - Timer::after(Duration::from_millis(150)).await; - } - - // Pause between letters - Timer::after(Duration::from_millis(300)).await; - - // O: three long blinks - for _ in 0..3 { - led.set_low(); - Timer::after(Duration::from_millis(450)).await; - led.set_high(); - Timer::after(Duration::from_millis(150)).await; - } - - // Pause between letters - Timer::after(Duration::from_millis(300)).await; - - // S: three short blinks - for _ in 0..3 { - led.set_low(); - Timer::after(Duration::from_millis(150)).await; - led.set_high(); - Timer::after(Duration::from_millis(150)).await; - } - - // Long pause between words (SOS repeats) - Timer::after(Duration::from_millis(1000)).await; - } -} diff --git a/examples/build.rs b/examples/build.rs new file mode 100644 index 000000000..f076bba9f --- /dev/null +++ b/examples/build.rs @@ -0,0 +1,20 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + // Generate memory.x - put "FLASH" at start of RAM, RAM after "FLASH" + // cortex-m-rt expects FLASH for code, RAM for data/bss/stack + // Both are in RAM, but separated to satisfy cortex-m-rt's expectations + // MCXA256 has 128KB RAM total + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rerun-if-changed=memory.x"); +} diff --git a/examples/common/mod.rs b/examples/common/mod.rs deleted file mode 100644 index 8c52c8e86..000000000 --- a/examples/common/mod.rs +++ /dev/null @@ -1,45 +0,0 @@ -//! Shared board-specific helpers for the FRDM-MCXA276 examples. -//! These live with the examples so the HAL stays generic. - -use hal::{clocks, pins, reset}; -use {embassy_mcxa276 as hal, panic_probe as _}; - -/// Initialize clocks and pin muxing for UART2 debug console. -/// Safe to call multiple times; writes are idempotent for our use. -#[allow(dead_code)] -pub unsafe fn init_uart2(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_uart2_port2(p); - reset::release_reset_port2(p); - reset::release_reset_lpuart2(p); - pins::configure_uart2_pins_port2(); - clocks::select_uart2_clock(p); -} - -/// Initialize clocks for the LED GPIO/PORT used by the blink example. -#[allow(dead_code)] -pub unsafe fn init_led(p: &mcxa_pac::Peripherals) { - clocks::enable_led_port(p); - reset::release_reset_gpio3(p); - reset::release_reset_port3(p); -} - -/// Initialize clocks for OSTIMER0 (1 MHz source). -#[allow(dead_code)] -pub unsafe fn init_ostimer0(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_ostimer0(p); - reset::release_reset_ostimer0(p); - clocks::select_ostimer0_clock_1m(p); -} - -/// Initialize clocks and pin muxing for ADC. -#[allow(dead_code)] -pub unsafe fn init_adc(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_adc(p); - reset::release_reset_port1(p); - reset::release_reset_adc1(p); - pins::configure_adc_pins(); - clocks::select_adc_clock(p); -} diff --git a/examples/hello.rs b/examples/hello.rs deleted file mode 100644 index e39adaced..000000000 --- a/examples/hello.rs +++ /dev/null @@ -1,114 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::uart; - -mod common; - -use {defmt_rtt as _, panic_probe as _}; - -/// Simple helper to write a byte as hex to UART -fn write_hex_byte(uart: &hal::uart::Uart, byte: u8) { - const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; - uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); - uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - defmt::info!("boot"); - - // Board-level init for UART2 clocks and pins. - unsafe { - common::init_uart2(hal::pac()); - } - - // Get UART source frequency from clock configuration - // Using hardcoded frequency for now - dynamic detection may have issues - let src = 12_000_000; // FRO_LF_DIV at 12MHz with DIV=0 - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - - // Print welcome message before any async delays to guarantee early console output - uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); - uart.write_str_blocking("Available commands:\r\n"); - uart.write_str_blocking(" help - Show this help\r\n"); - uart.write_str_blocking(" echo - Echo back the text\r\n"); - uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); - uart.write_str_blocking("Type a command: "); - - let mut buffer = [0u8; 64]; - let mut buf_idx = 0; - - loop { - // Read a byte from UART - let byte = uart.read_byte_blocking(); - - // Echo the character back - if byte == b'\r' || byte == b'\n' { - // Enter pressed - process command - uart.write_str_blocking("\r\n"); - - if buf_idx > 0 { - let command = &buffer[0..buf_idx]; - - if command == b"help" { - uart.write_str_blocking("Available commands:\r\n"); - uart.write_str_blocking(" help - Show this help\r\n"); - uart.write_str_blocking(" echo - Echo back the text\r\n"); - uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); - } else if command.starts_with(b"echo ") && command.len() > 5 { - uart.write_str_blocking("Echo: "); - uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or("")); - uart.write_str_blocking("\r\n"); - } else if command.starts_with(b"hex ") && command.len() > 4 { - // Parse the byte value - let num_str = &command[4..]; - if let Ok(num) = parse_u8(num_str) { - uart.write_str_blocking("Hex: 0x"); - write_hex_byte(&uart, num); - uart.write_str_blocking("\r\n"); - } else { - uart.write_str_blocking("Invalid number for hex command\r\n"); - } - } else if command.len() > 0 { - uart.write_str_blocking("Unknown command: "); - uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); - uart.write_str_blocking("\r\n"); - } - } - - // Reset buffer and prompt - buf_idx = 0; - uart.write_str_blocking("Type a command: "); - } else if byte == 8 || byte == 127 { - // Backspace - if buf_idx > 0 { - buf_idx -= 1; - uart.write_str_blocking("\x08 \x08"); // Erase character - } - } else if buf_idx < buffer.len() - 1 { - // Regular character - buffer[buf_idx] = byte; - buf_idx += 1; - uart.write_byte(byte); - } - } -} - -/// Simple parser for u8 from ASCII bytes -fn parse_u8(bytes: &[u8]) -> Result { - let mut result = 0u8; - for &b in bytes { - if b >= b'0' && b <= b'9' { - result = result.checked_mul(10).ok_or(())?; - result = result.checked_add(b - b'0').ok_or(())?; - } else { - return Err(()); - } - } - Ok(result) -} diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs deleted file mode 100644 index 35d311143..000000000 --- a/examples/lpuart_buffered.rs +++ /dev/null @@ -1,77 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use embassy_mcxa276::interrupt::typelevel::Handler; -use embassy_mcxa276::lpuart::buffered::BufferedLpuart; -use embassy_mcxa276::{bind_interrupts, lpuart}; -use embedded_io_async::{Read, Write}; - -mod common; - -// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver -bind_interrupts!(struct Irqs { - LPUART2 => lpuart::buffered::BufferedInterruptHandler::; -}); - -// Wrapper function for the interrupt handler -unsafe extern "C" fn lpuart2_handler() { - lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - let p2 = lpuart::lib::init(); - - unsafe { - hal::interrupt::install_irq_handler(mcxa_pac::Interrupt::LPUART2, lpuart2_handler); - } - - // Configure NVIC for LPUART2 - hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); - - unsafe { - common::init_uart2(hal::pac()); - common::init_ostimer0(hal::pac()); - } - - // UART configuration (enable both TX and RX) - let config = lpuart::Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - rx_fifo_watermark: 0, - tx_fifo_watermark: 0, - ..Default::default() - }; - - let mut tx_buf = [0u8; 256]; - let mut rx_buf = [0u8; 256]; - - // Create a buffered LPUART2 instance with both TX and RX - let mut uart = BufferedLpuart::new( - p2.LPUART2, - p2.PIO2_2, // TX pin - p2.PIO2_3, // RX pin - Irqs, - &mut tx_buf, - &mut rx_buf, - config, - ) - .unwrap(); - - // Split into TX and RX parts - let (tx, rx) = uart.split_ref(); - - tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); - tx.write(b"Type characters to echo them back.\r\n").await.unwrap(); - - // Echo loop - let mut buf = [0u8; 4]; - loop { - rx.read_exact(&mut buf[..]).await.unwrap(); - tx.write_all(&buf[..]).await.unwrap(); - } -} diff --git a/examples/lpuart_polling.rs b/examples/lpuart_polling.rs deleted file mode 100644 index 067c7eb53..000000000 --- a/examples/lpuart_polling.rs +++ /dev/null @@ -1,53 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; - -use crate::hal::lpuart::{lib, Config, Lpuart}; - -mod common; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - let p2 = lib::init(); - - defmt::info!("boot"); - - // Board-level init for UART2 clocks and pins. - unsafe { - common::init_uart2(hal::pac()); - } - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX - let lpuart = Lpuart::new_blocking( - p2.LPUART2, // Peripheral - p2.PIO2_2, // TX pin - p2.PIO2_3, // RX pin - config, - ) - .unwrap(); - - // Split into separate TX and RX parts - let (mut tx, mut rx) = lpuart.split(); - - // Write hello messages - tx.blocking_write(b"Hello world.\r\n").unwrap(); - tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap(); - - // Echo loop - loop { - let mut buf = [0u8; 1]; - rx.blocking_read(&mut buf).unwrap(); - tx.blocking_write(&buf).unwrap(); - } -} diff --git a/examples/memory.x b/examples/memory.x new file mode 100644 index 000000000..f4263a412 --- /dev/null +++ b/examples/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x20000000, LENGTH = 64K + RAM : ORIGIN = 0x20010000, LENGTH = 64K +} diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs deleted file mode 100644 index 78ca4bbc5..000000000 --- a/examples/ostimer_alarm.rs +++ /dev/null @@ -1,111 +0,0 @@ -#![no_std] -#![no_main] - -use core::sync::atomic::{AtomicBool, Ordering}; - -use embassy_executor::Spawner; -use hal::uart; -use {cortex_m, embassy_mcxa276 as hal}; - -mod common; - -use embassy_mcxa276::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; - -// Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -// Global flag for alarm callback -static ALARM_FLAG: AtomicBool = AtomicBool::new(false); - -// Alarm callback function -fn alarm_callback() { - ALARM_FLAG.store(true, Ordering::Release); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - uart.write_str_blocking("OSTIMER Alarm Example\n"); - - // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - - // Create OSTIMER instance - let config = hal::ostimer::Config { - init_match_max: true, - clock_frequency_hz: 1_000_000, // 1MHz - }; - let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); - - // Create alarm with callback - let alarm = hal::ostimer::Alarm::new() - .with_callback(alarm_callback) - .with_flag(&ALARM_FLAG); - - uart.write_str_blocking("Scheduling alarm for 2 seconds...\n"); - - // Schedule alarm to expire in 2 seconds (2,000,000 microseconds) - let scheduled = ostimer.schedule_alarm_delay(&alarm, 2_000_000); - if scheduled { - uart.write_str_blocking("Alarm scheduled successfully\n"); - } else { - uart.write_str_blocking("Failed to schedule alarm (would exceed timer capacity)\n"); - return; - } - - // Wait for alarm to expire - loop { - // Check if alarm has expired - if ALARM_FLAG.load(Ordering::Acquire) { - uart.write_str_blocking("Alarm expired! Callback executed.\n"); - break; - } - - // Busy wait - don't use Timer::after_millis as it interferes with alarm MATCH - for _ in 0..100000 { - cortex_m::asm::nop(); - } - } - - // Demonstrate canceling an alarm - uart.write_str_blocking("Scheduling another alarm for 3 seconds...\n"); - ALARM_FLAG.store(false, Ordering::Release); // Reset flag - - let scheduled = ostimer.schedule_alarm_delay(&alarm, 3_000_000); - if scheduled { - uart.write_str_blocking("Alarm scheduled. Waiting 1 second then canceling...\n"); - - // Wait 1 second - embassy_time::Timer::after_millis(1000).await; - - // Cancel the alarm - ostimer.cancel_alarm(&alarm); - uart.write_str_blocking("Alarm canceled\n"); - - // Check immediately if alarm flag is set - if !ALARM_FLAG.load(Ordering::Acquire) { - uart.write_str_blocking("Alarm was successfully canceled\n"); - } else { - uart.write_str_blocking("Alarm fired despite cancellation\n"); - } - } - - uart.write_str_blocking("Example complete\n"); -} diff --git a/examples/ostimer_async.rs b/examples/ostimer_async.rs deleted file mode 100644 index 27e14e022..000000000 --- a/examples/ostimer_async.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::uart; - -mod common; - -use embassy_mcxa276::bind_interrupts; -use embassy_time::{Duration, Timer}; -use {defmt_rtt as _, panic_probe as _}; - -// Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); - uart.write_str_blocking("boot\n"); - - // Avoid mass NVIC writes here; DefaultHandler now safely returns. - - // Initialize embassy-time global driver backed by OSTIMER0 (re-enables OS_EVENT with priority) - // The bind_interrupts! macro handles handler binding automatically - - // Initialize OSTIMER with default 1MHz frequency - // Adjust this value to match your actual OSTIMER clock frequency - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - - // Removed force-pend; rely on real hardware match to trigger OS_EVENT. - - // Log using defmt if enabled - defmt::info!("OSTIMER async example starting..."); - - loop { - defmt::info!("tick"); - uart.write_str_blocking("tick\n"); - Timer::after(Duration::from_millis(1000)).await; - } -} diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs deleted file mode 100644 index e95140a88..000000000 --- a/examples/ostimer_counter.rs +++ /dev/null @@ -1,128 +0,0 @@ -//! # OSTIMER Counter Reading and Reset Example -//! -//! This example demonstrates the new timer counter reading and reset functionality -//! of the OSTIMER driver. - -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::{Duration, Timer}; -use hal::bind_interrupts; -use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; - -mod common; - -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(Default::default()); - - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); - - uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); - - // Initialize the OSTIMER time driver - hal::ostimer::time_driver::init( - hal::interrupt::Priority::from(3), - 1_000_000, // 1MHz clock - ); - - // Create OSTIMER instance - let ostimer = hal::ostimer::Ostimer::::new( - p.OSTIMER0, - hal::ostimer::Config { - init_match_max: true, - clock_frequency_hz: 1_000_000, - }, - hal::pac(), - ); - - // Read initial counter value - let initial_counter = ostimer.now(); - uart.write_str_blocking("Initial counter value: "); - write_u64(&mut uart, initial_counter); - uart.write_str_blocking("\n"); - - // Wait a bit to let counter increment - Timer::after(Duration::from_millis(100)).await; - - // Read counter again - let counter_after_wait = ostimer.now(); - uart.write_str_blocking("Counter after 100ms wait: "); - write_u64(&mut uart, counter_after_wait); - uart.write_str_blocking("\n"); - uart.write_str_blocking("Difference: "); - write_u64(&mut uart, counter_after_wait - initial_counter); - uart.write_str_blocking(" ticks\n"); - - // Reset the timer - uart.write_str_blocking("Resetting timer...\n"); - ostimer.reset(hal::pac()); - - // Read counter after reset - let counter_after_reset = ostimer.now(); - uart.write_str_blocking("Counter after reset: "); - write_u64(&mut uart, counter_after_reset); - uart.write_str_blocking("\n"); - - // Wait again to verify timer is working - Timer::after(Duration::from_millis(50)).await; - - let final_counter = ostimer.now(); - uart.write_str_blocking("Counter after another 50ms: "); - write_u64(&mut uart, final_counter); - uart.write_str_blocking("\n"); - uart.write_str_blocking("Difference after reset: "); - write_u64(&mut uart, final_counter - counter_after_reset); - uart.write_str_blocking(" ticks\n"); - - uart.write_str_blocking("Example complete\n"); -} - -// Helper function to write a u64 value as decimal string -fn write_u64(uart: &mut hal::uart::Uart, value: u64) { - if value == 0 { - uart.write_str_blocking("0"); - return; - } - - let mut buffer = [0u8; 20]; // Enough for max u64 - let mut i = 0; - let mut v = value; - - while v > 0 { - buffer[i] = b'0' + (v % 10) as u8; - v /= 10; - i += 1; - } - - // Write digits in reverse order - while i > 0 { - i -= 1; - match buffer[i] { - b'0' => uart.write_str_blocking("0"), - b'1' => uart.write_str_blocking("1"), - b'2' => uart.write_str_blocking("2"), - b'3' => uart.write_str_blocking("3"), - b'4' => uart.write_str_blocking("4"), - b'5' => uart.write_str_blocking("5"), - b'6' => uart.write_str_blocking("6"), - b'7' => uart.write_str_blocking("7"), - b'8' => uart.write_str_blocking("8"), - b'9' => uart.write_str_blocking("9"), - _ => uart.write_str_blocking("?"), - } - } -} diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs deleted file mode 100644 index 368a3e52f..000000000 --- a/examples/ostimer_race_test.rs +++ /dev/null @@ -1,396 +0,0 @@ -//! # OSTIMER Race Condition Test -//! -//! This example tests for race conditions in the OSTIMER driver by: -//! - Scheduling alarms sequentially (hardware limitation: only one at a time) -//! - Reading the counter during interrupt-heavy periods -//! - Testing concurrent timer operations -//! - Stress testing interrupt handling - -#![no_std] -#![no_main] - -use core::sync::atomic::{AtomicU32, Ordering}; - -use embassy_executor::Spawner; -use embassy_time::{Duration, Timer}; -use hal::bind_interrupts; -use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; - -mod common; - -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -// Global counters for race condition detection -static ALARM_CALLBACK_COUNT: AtomicU32 = AtomicU32::new(0); -static INTERRUPT_COUNT: AtomicU32 = AtomicU32::new(0); -static RACE_DETECTED: AtomicU32 = AtomicU32::new(0); - -// Alarm callback function -fn alarm_callback() { - let _count = ALARM_CALLBACK_COUNT.fetch_add(1, Ordering::SeqCst); - INTERRUPT_COUNT.fetch_add(1, Ordering::SeqCst); - - // Simulate some work in the callback to increase chance of races - for _ in 0..10 { - cortex_m::asm::nop(); - } -} - -fn report_default_handler(uart: &mut hal::uart::Uart) { - let snapshot = hal::interrupt::default_handler_snapshot(); - if snapshot.count == 0 { - return; - } - - uart.write_str_blocking("WARNING: DefaultHandler executed "); - write_u32(uart, snapshot.count); - uart.write_str_blocking(" time(s). Vector="); - write_u32(uart, snapshot.vector as u32); - uart.write_str_blocking(" CFSR=0x"); - write_hex32(uart, snapshot.cfsr); - uart.write_str_blocking(" HFSR=0x"); - write_hex32(uart, snapshot.hfsr); - uart.write_str_blocking(" PC=0x"); - write_hex32(uart, snapshot.stacked_pc); - uart.write_str_blocking(" LR=0x"); - write_hex32(uart, snapshot.stacked_lr); - uart.write_str_blocking(" SP=0x"); - write_hex32(uart, snapshot.stacked_sp); - uart.write_str_blocking("\n"); - - hal::interrupt::clear_default_handler_snapshot(); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(Default::default()); - - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); - - uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); - - // The bind_interrupts! macro handles handler binding automatically - - // Initialize the OSTIMER time driver FIRST - hal::ostimer::time_driver::init( - hal::interrupt::Priority::from(3), - 1_000_000, // 1MHz clock - ); - - uart.write_str_blocking("Time driver initialized\n"); - - // Create OSTIMER instance - let ostimer = hal::ostimer::Ostimer::::new( - p.OSTIMER0, - hal::ostimer::Config { - init_match_max: true, - clock_frequency_hz: 1_000_000, - }, - hal::pac(), - ); - - uart.write_str_blocking("OSTIMER instance created\n"); - - // Test 1: Sequential alarm scheduling (OSTIMER only supports one alarm at a time) - uart.write_str_blocking("Test 1: Sequential alarm scheduling...\n"); - test_rapid_alarms(&ostimer, &mut uart).await; - report_default_handler(&mut uart); - - // Test 2: Counter reading during interrupts - uart.write_str_blocking("Test 2: Counter reading during interrupts...\n"); - test_counter_reading_during_interrupts(&ostimer, &mut uart).await; - report_default_handler(&mut uart); - - // Test 3: Concurrent timer operations - uart.write_str_blocking("Test 3: Concurrent timer operations...\n"); - test_concurrent_operations(&ostimer, &mut uart).await; - report_default_handler(&mut uart); - - // Test 4: Timer reset during operation - uart.write_str_blocking("Test 4: Timer reset during operation...\n"); - test_reset_during_operation(&ostimer, &mut uart, hal::pac()).await; - report_default_handler(&mut uart); - - // Report results - uart.write_str_blocking("Race condition test complete\n"); - uart.write_str_blocking("Callback count: "); - write_u32(&mut uart, ALARM_CALLBACK_COUNT.load(Ordering::SeqCst)); - uart.write_str_blocking("\nInterrupt count: "); - write_u32(&mut uart, INTERRUPT_COUNT.load(Ordering::SeqCst)); - uart.write_str_blocking("\nRaces detected: "); - write_u32(&mut uart, RACE_DETECTED.load(Ordering::SeqCst)); - uart.write_str_blocking("\n"); -} - -// Test rapid alarm scheduling to stress interrupt handling -async fn test_rapid_alarms( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, -) { - let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); - - // Schedule 10 alarms sequentially (OSTIMER only supports one alarm at a time) - for _i in 0..10 { - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - let delay_us = 1000; // 1ms delay for each alarm - if ostimer.schedule_alarm_delay(&alarm, delay_us) { - // Wait for this alarm to complete before scheduling the next - Timer::after(Duration::from_micros(delay_us + 100)).await; - report_default_handler(uart); - } else { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm (match not ready)\n"); - } - } - - // All alarms should have completed by now - let final_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); - let expected_count = initial_count + 10; - - if final_count != expected_count { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Expected "); - write_u32(uart, expected_count); - uart.write_str_blocking(" callbacks, got "); - write_u32(uart, final_count); - uart.write_str_blocking("\n"); - } else { - uart.write_str_blocking("PASS: All rapid alarms executed\n"); - } -} - -// Test reading counter while interrupts are firing -async fn test_counter_reading_during_interrupts( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, -) { - let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - // Schedule an alarm that will fire soon - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - if !ostimer.schedule_alarm_delay(&alarm, 500) { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before counter stress\n"); - } - - // While alarm is pending, read the counter many times rapidly - // This tests if counter reading is atomic and doesn't get corrupted by interrupts - let mut last_counter = ostimer.now(); - let mut consistent_reads = 0; - let mut total_reads = 0; - - for _ in 0..1000 { - let current_counter = ostimer.now(); - total_reads += 1; - - // Check if counter is monotonically increasing (basic sanity check) - if current_counter >= last_counter { - consistent_reads += 1; - } - last_counter = current_counter; - - // Small delay between reads - for _ in 0..10 { - cortex_m::asm::nop(); - } - - report_default_handler(uart); - } - - // Wait for alarm to complete - Timer::after(Duration::from_millis(1)).await; - - let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - if consistent_reads == total_reads { - uart.write_str_blocking("PASS: Counter reading consistent during interrupts\n"); - } else { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Counter reading inconsistent: "); - write_u32(uart, consistent_reads); - uart.write_str_blocking("/"); - write_u32(uart, total_reads); - uart.write_str_blocking(" consistent\n"); - } - - if final_interrupt_count > initial_interrupt_count { - uart.write_str_blocking("PASS: Interrupt fired during counter reading test\n"); - } else { - uart.write_str_blocking("WARNING: No interrupt fired during counter reading test\n"); - } -} - -// Test concurrent timer operations (embassy-time + alarms) -async fn test_concurrent_operations( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, -) { - let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - // Start an embassy-time timer - let timer_future = Timer::after(Duration::from_millis(2)); - - // Schedule an alarm that should fire before the timer - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - if !ostimer.schedule_alarm_delay(&alarm, 1000) { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before concurrent operations\n"); - } - - // Wait for both to complete - timer_future.await; - - let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - if final_interrupt_count > initial_interrupt_count { - uart.write_str_blocking("PASS: Concurrent operations completed\n"); - } else { - uart.write_str_blocking("WARNING: No interrupts during concurrent operations\n"); - } -} - -// Test timer reset during active operations -async fn test_reset_during_operation( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, - peripherals: &mcxa_pac::Peripherals, -) { - let initial_counter = ostimer.now(); - - // Schedule an alarm - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - if !ostimer.schedule_alarm_delay(&alarm, 2000) { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before reset test\n"); - } - - // Wait a bit then reset the timer - Timer::after(Duration::from_millis(1)).await; - ostimer.reset(peripherals); - - // Check counter after reset - let counter_after_reset = ostimer.now(); - - // Wait to see if the alarm still fires (it shouldn't after reset) - Timer::after(Duration::from_millis(2)).await; - - let final_counter = ostimer.now(); - - if counter_after_reset < initial_counter { - uart.write_str_blocking("PASS: Timer reset successful\n"); - } else { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Timer reset may have failed\n"); - } - - uart.write_str_blocking("Counter progression after reset: "); - write_u64(uart, initial_counter); - uart.write_str_blocking(" -> "); - write_u64(uart, counter_after_reset); - uart.write_str_blocking(" -> "); - write_u64(uart, final_counter); - uart.write_str_blocking("\n"); -} - -// Helper function to write a u32 value as decimal string -fn write_u32(uart: &mut hal::uart::Uart, value: u32) { - if value == 0 { - uart.write_str_blocking("0"); - return; - } - - let mut buffer = [0u8; 10]; // Enough for max u32 - let mut i = 0; - let mut v = value; - - while v > 0 { - buffer[i] = b'0' + (v % 10) as u8; - v /= 10; - i += 1; - } - - // Write digits in reverse order - while i > 0 { - i -= 1; - match buffer[i] { - b'0' => uart.write_str_blocking("0"), - b'1' => uart.write_str_blocking("1"), - b'2' => uart.write_str_blocking("2"), - b'3' => uart.write_str_blocking("3"), - b'4' => uart.write_str_blocking("4"), - b'5' => uart.write_str_blocking("5"), - b'6' => uart.write_str_blocking("6"), - b'7' => uart.write_str_blocking("7"), - b'8' => uart.write_str_blocking("8"), - b'9' => uart.write_str_blocking("9"), - _ => uart.write_str_blocking("?"), - } - } -} - -fn write_hex32(uart: &mut hal::uart::Uart, value: u32) { - let mut buf = [b'0'; 8]; - let mut tmp = value; - for i in (0..8).rev() { - let digit = (tmp & 0xF) as u8; - buf[i] = match digit { - 0..=9 => b'0' + digit, - 10..=15 => b'A' + (digit - 10), - _ => b'?', - }; - tmp >>= 4; - } - for b in &buf { - uart.write_byte(*b); - } -} - -// Helper function to write a u64 value as decimal string -fn write_u64(uart: &mut hal::uart::Uart, value: u64) { - if value == 0 { - uart.write_str_blocking("0"); - return; - } - - let mut buffer = [0u8; 20]; // Enough for max u64 - let mut i = 0; - let mut v = value; - - while v > 0 { - buffer[i] = b'0' + (v % 10) as u8; - v /= 10; - i += 1; - } - - // Write digits in reverse order - while i > 0 { - i -= 1; - match buffer[i] { - b'0' => uart.write_str_blocking("0"), - b'1' => uart.write_str_blocking("1"), - b'2' => uart.write_str_blocking("2"), - b'3' => uart.write_str_blocking("3"), - b'4' => uart.write_str_blocking("4"), - b'5' => uart.write_str_blocking("5"), - b'6' => uart.write_str_blocking("6"), - b'7' => uart.write_str_blocking("7"), - b'8' => uart.write_str_blocking("8"), - b'9' => uart.write_str_blocking("9"), - _ => uart.write_str_blocking("?"), - } - } -} diff --git a/examples/rtc_alarm.rs b/examples/rtc_alarm.rs deleted file mode 100644 index c27fd4c55..000000000 --- a/examples/rtc_alarm.rs +++ /dev/null @@ -1,87 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use hal::rtc::{RtcDateTime, RtcInterruptEnable}; -use hal::{uart, InterruptExt}; -use {cortex_m, embassy_mcxa276 as hal}; - -mod common; - -type MyRtc = hal::rtc::Rtc; - -use embassy_mcxa276::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; - -bind_interrupts!(struct Irqs { - RTC => hal::rtc::RtcHandler; -}); - -#[used] -#[no_mangle] -static KEEP_RTC: unsafe extern "C" fn() = RTC; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - unsafe { - common::init_uart2(hal::pac()); - } - - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - - uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); - - unsafe { hal::clocks::init_fro16k(hal::pac()) }; - - let rtc_config = hal::rtc::get_default_config(); - - let rtc = MyRtc::new(p.RTC0, rtc_config); - - let now = RtcDateTime { - year: 2025, - month: 10, - day: 15, - hour: 14, - minute: 30, - second: 0, - }; - - rtc.stop(); - - uart.write_str_blocking("Time set to: 2025-10-15 14:30:00\r\n"); - rtc.set_datetime(now); - - let mut alarm = now; - alarm.second += 10; - - rtc.set_alarm(alarm); - uart.write_str_blocking("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)\r\n"); - - rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE); - - unsafe { - hal::interrupt::RTC.enable(); - } - - unsafe { - cortex_m::interrupt::enable(); - } - - rtc.start(); - - uart.write_str_blocking("RTC started, waiting for alarm...\r\n"); - - loop { - if rtc.is_alarm_triggered() { - uart.write_str_blocking("\r\n*** ALARM TRIGGERED! ***\r\n"); - break; - } - } - - uart.write_str_blocking("Example complete - Test PASSED!\r\n"); - - loop {} -} diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs new file mode 100644 index 000000000..e174a5272 --- /dev/null +++ b/examples/src/bin/adc_interrupt.rs @@ -0,0 +1,86 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa_examples::{init_adc, init_uart2}; +use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; +use hal::pac::adc1::cfg::{Pwrsel, Refsel}; +use hal::pac::adc1::cmdl1::{Adch, Mode}; +use hal::pac::adc1::ctrl::CalAvgs; +use hal::pac::adc1::tctrl::Tcmd; +use hal::{bind_interrupts, uart, InterruptExt}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!(struct Irqs { + ADC1 => hal::adc::AdcHandler; +}); + +#[used] +#[no_mangle] +static KEEP_ADC: unsafe extern "C" fn() = ADC1; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + unsafe { + init_uart2(hal::pac()); + } + + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); + + unsafe { + init_adc(hal::pac()); + } + + let adc_config = LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + }; + let adc = hal::adc::Adc::::new(p.ADC1, adc_config); + + adc.do_offset_calibration(); + adc.do_auto_calibration(); + + let mut conv_command_config = adc.get_default_conv_command_config(); + conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; + conv_command_config.conversion_resolution_mode = Mode::Data16Bits; + adc.set_conv_command_config(1, &conv_command_config); + + let mut conv_trigger_config = adc.get_default_conv_trigger_config(); + conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; + conv_trigger_config.enable_hardware_trigger = false; + adc.set_conv_trigger_config(0, &conv_trigger_config); + + uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + + adc.enable_interrupt(0x1); + + unsafe { + hal::interrupt::ADC1.enable(); + } + + unsafe { + cortex_m::interrupt::enable(); + } + + loop { + adc.do_software_trigger(1); + while !adc.is_interrupt_triggered() { + // Wait until the interrupt is triggered + } + uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); + //TBD need to print the value + } +} diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs new file mode 100644 index 000000000..741551d49 --- /dev/null +++ b/examples/src/bin/adc_polling.rs @@ -0,0 +1,76 @@ +#![no_std] +#![no_main] + +use core::fmt::Write; + +use embassy_executor::Spawner; +use embassy_mcxa_examples::{init_adc, init_uart2}; +use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; +use hal::pac::adc1::cfg::{Pwrsel, Refsel}; +use hal::pac::adc1::cmdl1::{Adch, Mode}; +use hal::pac::adc1::ctrl::CalAvgs; +use hal::pac::adc1::tctrl::Tcmd; +use hal::uart; +use heapless::String; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +const G_LPADC_RESULT_SHIFT: u32 = 0; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + unsafe { + init_uart2(hal::pac()); + } + + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); + + unsafe { + init_adc(hal::pac()); + } + + let adc_config = LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + }; + let adc = hal::adc::Adc::::new(p.ADC1, adc_config); + + adc.do_offset_calibration(); + adc.do_auto_calibration(); + + let mut conv_command_config = adc.get_default_conv_command_config(); + conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; + conv_command_config.conversion_resolution_mode = Mode::Data16Bits; + adc.set_conv_command_config(1, &conv_command_config); + + let mut conv_trigger_config = adc.get_default_conv_trigger_config(); + conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; + conv_trigger_config.enable_hardware_trigger = false; + adc.set_conv_trigger_config(0, &conv_trigger_config); + + uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + + loop { + adc.do_software_trigger(1); + let mut result: Option = None; + while result.is_none() { + result = hal::adc::get_conv_result(); + } + let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; + let mut buf: String<16> = String::new(); // adjust size as needed + write!(buf, "\r\nvalue: {}\r\n", value).unwrap(); + uart.write_str_blocking(&buf); + } +} diff --git a/examples/src/bin/blink.rs b/examples/src/bin/blink.rs new file mode 100644 index 000000000..d8a57c546 --- /dev/null +++ b/examples/src/bin/blink.rs @@ -0,0 +1,78 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa as hal; +use embassy_mcxa::bind_interrupts; +use embassy_mcxa_examples::{init_led, init_ostimer0}; +use embassy_time::{Duration, Timer}; +use hal::gpio::pins::PIO3_18; +use hal::gpio::{Level, Output}; + +// Bind only OS_EVENT for timer interrupts +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + + unsafe { + init_led(hal::pac()); + init_ostimer0(hal::pac()); + } + + // Initialize embassy-time global driver backed by OSTIMER0 + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); + + // Configure LED pin for GPIO mode + PIO3_18::set_mux_gpio(); + + let mut led = Output::new(PIO3_18::degrade(), Level::High); + + // Complex blinking pattern: SOS in Morse code + // S: ... (3 short) + // O: --- (3 long) + // S: ... (3 short) + // With pauses between letters and words + + loop { + // S: three short blinks + for _ in 0..3 { + led.set_low(); + Timer::after(Duration::from_millis(150)).await; + led.set_high(); + Timer::after(Duration::from_millis(150)).await; + } + + // Pause between letters + Timer::after(Duration::from_millis(300)).await; + + // O: three long blinks + for _ in 0..3 { + led.set_low(); + Timer::after(Duration::from_millis(450)).await; + led.set_high(); + Timer::after(Duration::from_millis(150)).await; + } + + // Pause between letters + Timer::after(Duration::from_millis(300)).await; + + // S: three short blinks + for _ in 0..3 { + led.set_low(); + Timer::after(Duration::from_millis(150)).await; + led.set_high(); + Timer::after(Duration::from_millis(150)).await; + } + + // Long pause between words (SOS repeats) + Timer::after(Duration::from_millis(1000)).await; + } +} diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs new file mode 100644 index 000000000..5c4336d50 --- /dev/null +++ b/examples/src/bin/hello.rs @@ -0,0 +1,111 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa_examples::init_uart2; +use hal::uart; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +/// Simple helper to write a byte as hex to UART +fn write_hex_byte(uart: &hal::uart::Uart, byte: u8) { + const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; + uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); + uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("boot"); + + // Board-level init for UART2 clocks and pins. + unsafe { + init_uart2(hal::pac()); + } + + // Get UART source frequency from clock configuration + // Using hardcoded frequency for now - dynamic detection may have issues + let src = 12_000_000; // FRO_LF_DIV at 12MHz with DIV=0 + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + // Print welcome message before any async delays to guarantee early console output + uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); + uart.write_str_blocking("Available commands:\r\n"); + uart.write_str_blocking(" help - Show this help\r\n"); + uart.write_str_blocking(" echo - Echo back the text\r\n"); + uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); + uart.write_str_blocking("Type a command: "); + + let mut buffer = [0u8; 64]; + let mut buf_idx = 0; + + loop { + // Read a byte from UART + let byte = uart.read_byte_blocking(); + + // Echo the character back + if byte == b'\r' || byte == b'\n' { + // Enter pressed - process command + uart.write_str_blocking("\r\n"); + + if buf_idx > 0 { + let command = &buffer[0..buf_idx]; + + if command == b"help" { + uart.write_str_blocking("Available commands:\r\n"); + uart.write_str_blocking(" help - Show this help\r\n"); + uart.write_str_blocking(" echo - Echo back the text\r\n"); + uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); + } else if command.starts_with(b"echo ") && command.len() > 5 { + uart.write_str_blocking("Echo: "); + uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or("")); + uart.write_str_blocking("\r\n"); + } else if command.starts_with(b"hex ") && command.len() > 4 { + // Parse the byte value + let num_str = &command[4..]; + if let Ok(num) = parse_u8(num_str) { + uart.write_str_blocking("Hex: 0x"); + write_hex_byte(&uart, num); + uart.write_str_blocking("\r\n"); + } else { + uart.write_str_blocking("Invalid number for hex command\r\n"); + } + } else if !command.is_empty() { + uart.write_str_blocking("Unknown command: "); + uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); + uart.write_str_blocking("\r\n"); + } + } + + // Reset buffer and prompt + buf_idx = 0; + uart.write_str_blocking("Type a command: "); + } else if byte == 8 || byte == 127 { + // Backspace + if buf_idx > 0 { + buf_idx -= 1; + uart.write_str_blocking("\x08 \x08"); // Erase character + } + } else if buf_idx < buffer.len() - 1 { + // Regular character + buffer[buf_idx] = byte; + buf_idx += 1; + uart.write_byte(byte); + } + } +} + +/// Simple parser for u8 from ASCII bytes +fn parse_u8(bytes: &[u8]) -> Result { + let mut result = 0u8; + for &b in bytes { + if b.is_ascii_digit() { + result = result.checked_mul(10).ok_or(())?; + result = result.checked_add(b - b'0').ok_or(())?; + } else { + return Err(()); + } + } + Ok(result) +} diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs new file mode 100644 index 000000000..480d8e1f7 --- /dev/null +++ b/examples/src/bin/lpuart_buffered.rs @@ -0,0 +1,76 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa as hal; +use embassy_mcxa::interrupt::typelevel::Handler; +use embassy_mcxa::lpuart::buffered::BufferedLpuart; +use embassy_mcxa::{bind_interrupts, lpuart}; +use embassy_mcxa_examples::{init_ostimer0, init_uart2}; +use embedded_io_async::{Read, Write}; + +// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver +bind_interrupts!(struct Irqs { + LPUART2 => lpuart::buffered::BufferedInterruptHandler::; +}); + +// Wrapper function for the interrupt handler +unsafe extern "C" fn lpuart2_handler() { + lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + let p2 = lpuart::lib::init(); + + unsafe { + hal::interrupt::install_irq_handler(hal::pac::Interrupt::LPUART2, lpuart2_handler); + } + + // Configure NVIC for LPUART2 + hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); + + unsafe { + init_uart2(hal::pac()); + init_ostimer0(hal::pac()); + } + + // UART configuration (enable both TX and RX) + let config = lpuart::Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + rx_fifo_watermark: 0, + tx_fifo_watermark: 0, + ..Default::default() + }; + + let mut tx_buf = [0u8; 256]; + let mut rx_buf = [0u8; 256]; + + // Create a buffered LPUART2 instance with both TX and RX + let mut uart = BufferedLpuart::new( + p2.LPUART2, + p2.PIO2_2, // TX pin + p2.PIO2_3, // RX pin + Irqs, + &mut tx_buf, + &mut rx_buf, + config, + ) + .unwrap(); + + // Split into TX and RX parts + let (tx, rx) = uart.split_ref(); + + tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); + tx.write(b"Type characters to echo them back.\r\n").await.unwrap(); + + // Echo loop + let mut buf = [0u8; 4]; + loop { + rx.read_exact(&mut buf[..]).await.unwrap(); + tx.write_all(&buf[..]).await.unwrap(); + } +} diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs new file mode 100644 index 000000000..215714569 --- /dev/null +++ b/examples/src/bin/lpuart_polling.rs @@ -0,0 +1,51 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa_examples::init_uart2; +use hal::lpuart::{lib, Config, Lpuart}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + let p2 = lib::init(); + + defmt::info!("boot"); + + // Board-level init for UART2 clocks and pins. + unsafe { + init_uart2(hal::pac()); + } + + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + let lpuart = Lpuart::new_blocking( + p2.LPUART2, // Peripheral + p2.PIO2_2, // TX pin + p2.PIO2_3, // RX pin + config, + ) + .unwrap(); + + // Split into separate TX and RX parts + let (mut tx, mut rx) = lpuart.split(); + + // Write hello messages + tx.blocking_write(b"Hello world.\r\n").unwrap(); + tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap(); + + // Echo loop + loop { + let mut buf = [0u8; 1]; + rx.blocking_read(&mut buf).unwrap(); + tx.blocking_write(&buf).unwrap(); + } +} diff --git a/examples/src/bin/ostimer_alarm.rs b/examples/src/bin/ostimer_alarm.rs new file mode 100644 index 000000000..953f98c01 --- /dev/null +++ b/examples/src/bin/ostimer_alarm.rs @@ -0,0 +1,106 @@ +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicBool, Ordering}; + +use embassy_executor::Spawner; +use embassy_mcxa::bind_interrupts; +use embassy_mcxa_examples::{init_ostimer0, init_uart2}; +use hal::uart; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +// Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +// Global flag for alarm callback +static ALARM_FLAG: AtomicBool = AtomicBool::new(false); + +// Alarm callback function +fn alarm_callback() { + ALARM_FLAG.store(true, Ordering::Release); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + init_ostimer0(hal::pac()); + init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + uart.write_str_blocking("OSTIMER Alarm Example\n"); + + // Initialize embassy-time global driver backed by OSTIMER0 + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); + + // Create OSTIMER instance + let config = hal::ostimer::Config { + init_match_max: true, + clock_frequency_hz: 1_000_000, // 1MHz + }; + let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); + + // Create alarm with callback + let alarm = hal::ostimer::Alarm::new() + .with_callback(alarm_callback) + .with_flag(&ALARM_FLAG); + + uart.write_str_blocking("Scheduling alarm for 2 seconds...\n"); + + // Schedule alarm to expire in 2 seconds (2,000,000 microseconds) + let scheduled = ostimer.schedule_alarm_delay(&alarm, 2_000_000); + if scheduled { + uart.write_str_blocking("Alarm scheduled successfully\n"); + } else { + uart.write_str_blocking("Failed to schedule alarm (would exceed timer capacity)\n"); + return; + } + + // Wait for alarm to expire + loop { + // Check if alarm has expired + if ALARM_FLAG.load(Ordering::Acquire) { + uart.write_str_blocking("Alarm expired! Callback executed.\n"); + break; + } + + // Busy wait - don't use Timer::after_millis as it interferes with alarm MATCH + for _ in 0..100000 { + cortex_m::asm::nop(); + } + } + + // Demonstrate canceling an alarm + uart.write_str_blocking("Scheduling another alarm for 3 seconds...\n"); + ALARM_FLAG.store(false, Ordering::Release); // Reset flag + + let scheduled = ostimer.schedule_alarm_delay(&alarm, 3_000_000); + if scheduled { + uart.write_str_blocking("Alarm scheduled. Waiting 1 second then canceling...\n"); + + // Wait 1 second + embassy_time::Timer::after_millis(1000).await; + + // Cancel the alarm + ostimer.cancel_alarm(&alarm); + uart.write_str_blocking("Alarm canceled\n"); + + // Check immediately if alarm flag is set + if !ALARM_FLAG.load(Ordering::Acquire) { + uart.write_str_blocking("Alarm was successfully canceled\n"); + } else { + uart.write_str_blocking("Alarm fired despite cancellation\n"); + } + } + + uart.write_str_blocking("Example complete\n"); +} diff --git a/examples/src/bin/ostimer_async.rs b/examples/src/bin/ostimer_async.rs new file mode 100644 index 000000000..34862b61f --- /dev/null +++ b/examples/src/bin/ostimer_async.rs @@ -0,0 +1,52 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::bind_interrupts; +use embassy_mcxa_examples::{init_ostimer0, init_uart2}; +use embassy_time::{Duration, Timer}; +use hal::uart; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +// Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + init_ostimer0(hal::pac()); + init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); + uart.write_str_blocking("boot\n"); + + // Avoid mass NVIC writes here; DefaultHandler now safely returns. + + // Initialize embassy-time global driver backed by OSTIMER0 (re-enables OS_EVENT with priority) + // The bind_interrupts! macro handles handler binding automatically + + // Initialize OSTIMER with default 1MHz frequency + // Adjust this value to match your actual OSTIMER clock frequency + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); + + // Removed force-pend; rely on real hardware match to trigger OS_EVENT. + + // Log using defmt if enabled + defmt::info!("OSTIMER async example starting..."); + + loop { + defmt::info!("tick"); + uart.write_str_blocking("tick\n"); + Timer::after(Duration::from_millis(1000)).await; + } +} diff --git a/examples/src/bin/ostimer_counter.rs b/examples/src/bin/ostimer_counter.rs new file mode 100644 index 000000000..20044760a --- /dev/null +++ b/examples/src/bin/ostimer_counter.rs @@ -0,0 +1,125 @@ +//! # OSTIMER Counter Reading and Reset Example +//! +//! This example demonstrates the new timer counter reading and reset functionality +//! of the OSTIMER driver. + +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa_examples::{init_ostimer0, init_uart2}; +use embassy_time::{Duration, Timer}; +use hal::bind_interrupts; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(Default::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + init_ostimer0(hal::pac()); + init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + + uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); + + // Initialize the OSTIMER time driver + hal::ostimer::time_driver::init( + hal::interrupt::Priority::from(3), + 1_000_000, // 1MHz clock + ); + + // Create OSTIMER instance + let ostimer = hal::ostimer::Ostimer::::new( + p.OSTIMER0, + hal::ostimer::Config { + init_match_max: true, + clock_frequency_hz: 1_000_000, + }, + hal::pac(), + ); + + // Read initial counter value + let initial_counter = ostimer.now(); + uart.write_str_blocking("Initial counter value: "); + write_u64(&mut uart, initial_counter); + uart.write_str_blocking("\n"); + + // Wait a bit to let counter increment + Timer::after(Duration::from_millis(100)).await; + + // Read counter again + let counter_after_wait = ostimer.now(); + uart.write_str_blocking("Counter after 100ms wait: "); + write_u64(&mut uart, counter_after_wait); + uart.write_str_blocking("\n"); + uart.write_str_blocking("Difference: "); + write_u64(&mut uart, counter_after_wait - initial_counter); + uart.write_str_blocking(" ticks\n"); + + // Reset the timer + uart.write_str_blocking("Resetting timer...\n"); + ostimer.reset(hal::pac()); + + // Read counter after reset + let counter_after_reset = ostimer.now(); + uart.write_str_blocking("Counter after reset: "); + write_u64(&mut uart, counter_after_reset); + uart.write_str_blocking("\n"); + + // Wait again to verify timer is working + Timer::after(Duration::from_millis(50)).await; + + let final_counter = ostimer.now(); + uart.write_str_blocking("Counter after another 50ms: "); + write_u64(&mut uart, final_counter); + uart.write_str_blocking("\n"); + uart.write_str_blocking("Difference after reset: "); + write_u64(&mut uart, final_counter - counter_after_reset); + uart.write_str_blocking(" ticks\n"); + + uart.write_str_blocking("Example complete\n"); +} + +// Helper function to write a u64 value as decimal string +fn write_u64(uart: &mut hal::uart::Uart, value: u64) { + if value == 0 { + uart.write_str_blocking("0"); + return; + } + + let mut buffer = [0u8; 20]; // Enough for max u64 + let mut i = 0; + let mut v = value; + + while v > 0 { + buffer[i] = b'0' + (v % 10) as u8; + v /= 10; + i += 1; + } + + // Write digits in reverse order + while i > 0 { + i -= 1; + match buffer[i] { + b'0' => uart.write_str_blocking("0"), + b'1' => uart.write_str_blocking("1"), + b'2' => uart.write_str_blocking("2"), + b'3' => uart.write_str_blocking("3"), + b'4' => uart.write_str_blocking("4"), + b'5' => uart.write_str_blocking("5"), + b'6' => uart.write_str_blocking("6"), + b'7' => uart.write_str_blocking("7"), + b'8' => uart.write_str_blocking("8"), + b'9' => uart.write_str_blocking("9"), + _ => uart.write_str_blocking("?"), + } + } +} diff --git a/examples/src/bin/ostimer_race_test.rs b/examples/src/bin/ostimer_race_test.rs new file mode 100644 index 000000000..720a058d5 --- /dev/null +++ b/examples/src/bin/ostimer_race_test.rs @@ -0,0 +1,393 @@ +//! # OSTIMER Race Condition Test +//! +//! This example tests for race conditions in the OSTIMER driver by: +//! - Scheduling alarms sequentially (hardware limitation: only one at a time) +//! - Reading the counter during interrupt-heavy periods +//! - Testing concurrent timer operations +//! - Stress testing interrupt handling + +#![no_std] +#![no_main] + +use core::sync::atomic::{AtomicU32, Ordering}; + +use embassy_executor::Spawner; +use embassy_mcxa_examples::{init_ostimer0, init_uart2}; +use embassy_time::{Duration, Timer}; +use hal::bind_interrupts; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +// Global counters for race condition detection +static ALARM_CALLBACK_COUNT: AtomicU32 = AtomicU32::new(0); +static INTERRUPT_COUNT: AtomicU32 = AtomicU32::new(0); +static RACE_DETECTED: AtomicU32 = AtomicU32::new(0); + +// Alarm callback function +fn alarm_callback() { + let _count = ALARM_CALLBACK_COUNT.fetch_add(1, Ordering::SeqCst); + INTERRUPT_COUNT.fetch_add(1, Ordering::SeqCst); + + // Simulate some work in the callback to increase chance of races + for _ in 0..10 { + cortex_m::asm::nop(); + } +} + +fn report_default_handler(uart: &mut hal::uart::Uart) { + let snapshot = hal::interrupt::default_handler_snapshot(); + if snapshot.count == 0 { + return; + } + + uart.write_str_blocking("WARNING: DefaultHandler executed "); + write_u32(uart, snapshot.count); + uart.write_str_blocking(" time(s). Vector="); + write_u32(uart, snapshot.vector as u32); + uart.write_str_blocking(" CFSR=0x"); + write_hex32(uart, snapshot.cfsr); + uart.write_str_blocking(" HFSR=0x"); + write_hex32(uart, snapshot.hfsr); + uart.write_str_blocking(" PC=0x"); + write_hex32(uart, snapshot.stacked_pc); + uart.write_str_blocking(" LR=0x"); + write_hex32(uart, snapshot.stacked_lr); + uart.write_str_blocking(" SP=0x"); + write_hex32(uart, snapshot.stacked_sp); + uart.write_str_blocking("\n"); + + hal::interrupt::clear_default_handler_snapshot(); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(Default::default()); + + // Enable/clock OSTIMER0 and UART2 before touching their registers + unsafe { + init_ostimer0(hal::pac()); + init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + + uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); + + // The bind_interrupts! macro handles handler binding automatically + + // Initialize the OSTIMER time driver FIRST + hal::ostimer::time_driver::init( + hal::interrupt::Priority::from(3), + 1_000_000, // 1MHz clock + ); + + uart.write_str_blocking("Time driver initialized\n"); + + // Create OSTIMER instance + let ostimer = hal::ostimer::Ostimer::::new( + p.OSTIMER0, + hal::ostimer::Config { + init_match_max: true, + clock_frequency_hz: 1_000_000, + }, + hal::pac(), + ); + + uart.write_str_blocking("OSTIMER instance created\n"); + + // Test 1: Sequential alarm scheduling (OSTIMER only supports one alarm at a time) + uart.write_str_blocking("Test 1: Sequential alarm scheduling...\n"); + test_rapid_alarms(&ostimer, &mut uart).await; + report_default_handler(&mut uart); + + // Test 2: Counter reading during interrupts + uart.write_str_blocking("Test 2: Counter reading during interrupts...\n"); + test_counter_reading_during_interrupts(&ostimer, &mut uart).await; + report_default_handler(&mut uart); + + // Test 3: Concurrent timer operations + uart.write_str_blocking("Test 3: Concurrent timer operations...\n"); + test_concurrent_operations(&ostimer, &mut uart).await; + report_default_handler(&mut uart); + + // Test 4: Timer reset during operation + uart.write_str_blocking("Test 4: Timer reset during operation...\n"); + test_reset_during_operation(&ostimer, &mut uart, hal::pac()).await; + report_default_handler(&mut uart); + + // Report results + uart.write_str_blocking("Race condition test complete\n"); + uart.write_str_blocking("Callback count: "); + write_u32(&mut uart, ALARM_CALLBACK_COUNT.load(Ordering::SeqCst)); + uart.write_str_blocking("\nInterrupt count: "); + write_u32(&mut uart, INTERRUPT_COUNT.load(Ordering::SeqCst)); + uart.write_str_blocking("\nRaces detected: "); + write_u32(&mut uart, RACE_DETECTED.load(Ordering::SeqCst)); + uart.write_str_blocking("\n"); +} + +// Test rapid alarm scheduling to stress interrupt handling +async fn test_rapid_alarms( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, +) { + let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); + + // Schedule 10 alarms sequentially (OSTIMER only supports one alarm at a time) + for _i in 0..10 { + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + let delay_us = 1000; // 1ms delay for each alarm + if ostimer.schedule_alarm_delay(&alarm, delay_us) { + // Wait for this alarm to complete before scheduling the next + Timer::after(Duration::from_micros(delay_us + 100)).await; + report_default_handler(uart); + } else { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm (match not ready)\n"); + } + } + + // All alarms should have completed by now + let final_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); + let expected_count = initial_count + 10; + + if final_count != expected_count { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Expected "); + write_u32(uart, expected_count); + uart.write_str_blocking(" callbacks, got "); + write_u32(uart, final_count); + uart.write_str_blocking("\n"); + } else { + uart.write_str_blocking("PASS: All rapid alarms executed\n"); + } +} + +// Test reading counter while interrupts are firing +async fn test_counter_reading_during_interrupts( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, +) { + let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + // Schedule an alarm that will fire soon + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + if !ostimer.schedule_alarm_delay(&alarm, 500) { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before counter stress\n"); + } + + // While alarm is pending, read the counter many times rapidly + // This tests if counter reading is atomic and doesn't get corrupted by interrupts + let mut last_counter = ostimer.now(); + let mut consistent_reads = 0; + let mut total_reads = 0; + + for _ in 0..1000 { + let current_counter = ostimer.now(); + total_reads += 1; + + // Check if counter is monotonically increasing (basic sanity check) + if current_counter >= last_counter { + consistent_reads += 1; + } + last_counter = current_counter; + + // Small delay between reads + for _ in 0..10 { + cortex_m::asm::nop(); + } + + report_default_handler(uart); + } + + // Wait for alarm to complete + Timer::after(Duration::from_millis(1)).await; + + let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + if consistent_reads == total_reads { + uart.write_str_blocking("PASS: Counter reading consistent during interrupts\n"); + } else { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Counter reading inconsistent: "); + write_u32(uart, consistent_reads); + uart.write_str_blocking("/"); + write_u32(uart, total_reads); + uart.write_str_blocking(" consistent\n"); + } + + if final_interrupt_count > initial_interrupt_count { + uart.write_str_blocking("PASS: Interrupt fired during counter reading test\n"); + } else { + uart.write_str_blocking("WARNING: No interrupt fired during counter reading test\n"); + } +} + +// Test concurrent timer operations (embassy-time + alarms) +async fn test_concurrent_operations( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, +) { + let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + // Start an embassy-time timer + let timer_future = Timer::after(Duration::from_millis(2)); + + // Schedule an alarm that should fire before the timer + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + if !ostimer.schedule_alarm_delay(&alarm, 1000) { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before concurrent operations\n"); + } + + // Wait for both to complete + timer_future.await; + + let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); + + if final_interrupt_count > initial_interrupt_count { + uart.write_str_blocking("PASS: Concurrent operations completed\n"); + } else { + uart.write_str_blocking("WARNING: No interrupts during concurrent operations\n"); + } +} + +// Test timer reset during active operations +async fn test_reset_during_operation( + ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, + uart: &mut hal::uart::Uart, + peripherals: &hal::pac::Peripherals, +) { + let initial_counter = ostimer.now(); + + // Schedule an alarm + let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); + if !ostimer.schedule_alarm_delay(&alarm, 2000) { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before reset test\n"); + } + + // Wait a bit then reset the timer + Timer::after(Duration::from_millis(1)).await; + ostimer.reset(peripherals); + + // Check counter after reset + let counter_after_reset = ostimer.now(); + + // Wait to see if the alarm still fires (it shouldn't after reset) + Timer::after(Duration::from_millis(2)).await; + + let final_counter = ostimer.now(); + + if counter_after_reset < initial_counter { + uart.write_str_blocking("PASS: Timer reset successful\n"); + } else { + RACE_DETECTED.fetch_add(1, Ordering::SeqCst); + uart.write_str_blocking("ERROR: Timer reset may have failed\n"); + } + + uart.write_str_blocking("Counter progression after reset: "); + write_u64(uart, initial_counter); + uart.write_str_blocking(" -> "); + write_u64(uart, counter_after_reset); + uart.write_str_blocking(" -> "); + write_u64(uart, final_counter); + uart.write_str_blocking("\n"); +} + +// Helper function to write a u32 value as decimal string +fn write_u32(uart: &mut hal::uart::Uart, value: u32) { + if value == 0 { + uart.write_str_blocking("0"); + return; + } + + let mut buffer = [0u8; 10]; // Enough for max u32 + let mut i = 0; + let mut v = value; + + while v > 0 { + buffer[i] = b'0' + (v % 10) as u8; + v /= 10; + i += 1; + } + + // Write digits in reverse order + while i > 0 { + i -= 1; + match buffer[i] { + b'0' => uart.write_str_blocking("0"), + b'1' => uart.write_str_blocking("1"), + b'2' => uart.write_str_blocking("2"), + b'3' => uart.write_str_blocking("3"), + b'4' => uart.write_str_blocking("4"), + b'5' => uart.write_str_blocking("5"), + b'6' => uart.write_str_blocking("6"), + b'7' => uart.write_str_blocking("7"), + b'8' => uart.write_str_blocking("8"), + b'9' => uart.write_str_blocking("9"), + _ => uart.write_str_blocking("?"), + } + } +} + +fn write_hex32(uart: &mut hal::uart::Uart, value: u32) { + let mut buf = [b'0'; 8]; + let mut tmp = value; + for i in (0..8).rev() { + let digit = (tmp & 0xF) as u8; + buf[i] = match digit { + 0..=9 => b'0' + digit, + 10..=15 => b'A' + (digit - 10), + _ => b'?', + }; + tmp >>= 4; + } + for b in &buf { + uart.write_byte(*b); + } +} + +// Helper function to write a u64 value as decimal string +fn write_u64(uart: &mut hal::uart::Uart, value: u64) { + if value == 0 { + uart.write_str_blocking("0"); + return; + } + + let mut buffer = [0u8; 20]; // Enough for max u64 + let mut i = 0; + let mut v = value; + + while v > 0 { + buffer[i] = b'0' + (v % 10) as u8; + v /= 10; + i += 1; + } + + // Write digits in reverse order + while i > 0 { + i -= 1; + match buffer[i] { + b'0' => uart.write_str_blocking("0"), + b'1' => uart.write_str_blocking("1"), + b'2' => uart.write_str_blocking("2"), + b'3' => uart.write_str_blocking("3"), + b'4' => uart.write_str_blocking("4"), + b'5' => uart.write_str_blocking("5"), + b'6' => uart.write_str_blocking("6"), + b'7' => uart.write_str_blocking("7"), + b'8' => uart.write_str_blocking("8"), + b'9' => uart.write_str_blocking("9"), + _ => uart.write_str_blocking("?"), + } + } +} diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs new file mode 100644 index 000000000..dc07b5757 --- /dev/null +++ b/examples/src/bin/rtc_alarm.rs @@ -0,0 +1,84 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa as hal; +use embassy_mcxa_examples::init_uart2; +use hal::rtc::{RtcDateTime, RtcInterruptEnable}; +use hal::{uart, InterruptExt}; + +type MyRtc = hal::rtc::Rtc; + +use embassy_mcxa::bind_interrupts; +use {defmt_rtt as _, panic_probe as _}; + +bind_interrupts!(struct Irqs { + RTC => hal::rtc::RtcHandler; +}); + +#[used] +#[no_mangle] +static KEEP_RTC: unsafe extern "C" fn() = RTC; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + unsafe { + init_uart2(hal::pac()); + } + + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + + uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); + + unsafe { hal::clocks::init_fro16k(hal::pac()) }; + + let rtc_config = hal::rtc::get_default_config(); + + let rtc = MyRtc::new(p.RTC0, rtc_config); + + let now = RtcDateTime { + year: 2025, + month: 10, + day: 15, + hour: 14, + minute: 30, + second: 0, + }; + + rtc.stop(); + + uart.write_str_blocking("Time set to: 2025-10-15 14:30:00\r\n"); + rtc.set_datetime(now); + + let mut alarm = now; + alarm.second += 10; + + rtc.set_alarm(alarm); + uart.write_str_blocking("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)\r\n"); + + rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE); + + unsafe { + hal::interrupt::RTC.enable(); + } + + unsafe { + cortex_m::interrupt::enable(); + } + + rtc.start(); + + uart.write_str_blocking("RTC started, waiting for alarm...\r\n"); + + loop { + if rtc.is_alarm_triggered() { + uart.write_str_blocking("\r\n*** ALARM TRIGGERED! ***\r\n"); + break; + } + } + + uart.write_str_blocking("Example complete - Test PASSED!\r\n"); +} diff --git a/examples/src/bin/uart_interrupt.rs b/examples/src/bin/uart_interrupt.rs new file mode 100644 index 000000000..100588727 --- /dev/null +++ b/examples/src/bin/uart_interrupt.rs @@ -0,0 +1,66 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::bind_interrupts; +use embassy_mcxa_examples::init_uart2; +use hal::interrupt::typelevel::Handler; +use hal::uart; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +// Bind LPUART2 interrupt to our handler +bind_interrupts!(struct Irqs { + LPUART2 => hal::uart::UartInterruptHandler; +}); + +#[used] +#[no_mangle] +static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; + +// Wrapper function for the interrupt handler +unsafe extern "C" fn lpuart2_handler() { + hal::uart::UartInterruptHandler::on_interrupt(); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let _p = hal::init(hal::config::Config::default()); + + // Enable/clock UART2 before touching its registers + unsafe { + init_uart2(hal::pac()); + } + let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); + + // Configure LPUART2 interrupt for UART operation BEFORE any UART usage + hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); + + // Manually install the interrupt handler and enable RX IRQs in the peripheral + unsafe { + hal::interrupt::LPUART2.install_handler(lpuart2_handler); + // Enable RX interrupts so the handler actually fires on incoming bytes + uart.enable_rx_interrupts(); + } + + // Print welcome message + uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); + uart.write_str_blocking("Type characters to echo them back.\r\n"); + + // Log using defmt if enabled + defmt::info!("UART interrupt echo demo starting..."); + + loop { + // Check if we have received any data + if uart.rx_data_available() { + if let Some(byte) = uart.try_read_byte() { + // Echo it back + uart.write_byte(byte); + uart.write_str_blocking(" (received)\r\n"); + } + } else { + // No data available, wait a bit before checking again + cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz + } + } +} diff --git a/examples/src/common/mod.rs b/examples/src/common/mod.rs new file mode 100644 index 000000000..8cb4590f8 --- /dev/null +++ b/examples/src/common/mod.rs @@ -0,0 +1,45 @@ +//! Shared board-specific helpers for the FRDM-MCXA276 examples. +//! These live with the examples so the HAL stays generic. + +use hal::{clocks, pins, reset}; +use {embassy_mcxa as hal, panic_probe as _}; + +/// Initialize clocks and pin muxing for UART2 debug console. +/// Safe to call multiple times; writes are idempotent for our use. +#[allow(dead_code)] +pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_uart2_port2(p); + reset::release_reset_port2(p); + reset::release_reset_lpuart2(p); + pins::configure_uart2_pins_port2(); + clocks::select_uart2_clock(p); +} + +/// Initialize clocks for the LED GPIO/PORT used by the blink example. +#[allow(dead_code)] +pub unsafe fn init_led(p: &hal::pac::Peripherals) { + clocks::enable_led_port(p); + reset::release_reset_gpio3(p); + reset::release_reset_port3(p); +} + +/// Initialize clocks for OSTIMER0 (1 MHz source). +#[allow(dead_code)] +pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_ostimer0(p); + reset::release_reset_ostimer0(p); + clocks::select_ostimer0_clock_1m(p); +} + +/// Initialize clocks and pin muxing for ADC. +#[allow(dead_code)] +pub unsafe fn init_adc(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_adc(p); + reset::release_reset_port1(p); + reset::release_reset_adc1(p); + pins::configure_adc_pins(); + clocks::select_adc_clock(p); +} diff --git a/examples/src/lib.rs b/examples/src/lib.rs new file mode 100644 index 000000000..cf4194559 --- /dev/null +++ b/examples/src/lib.rs @@ -0,0 +1,63 @@ +#![no_std] + +//! Shared board-specific helpers for the FRDM-MCXA276 examples. +//! These live with the examples so the HAL stays generic. + +use hal::{clocks, pins, reset}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +/// Initialize clocks and pin muxing for UART2 debug console. +/// Safe to call multiple times; writes are idempotent for our use. +/// +/// # Safety +/// +/// Called only once to initialize the peripheral +#[allow(dead_code)] +pub unsafe fn init_uart2(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_uart2_port2(p); + reset::release_reset_port2(p); + reset::release_reset_lpuart2(p); + pins::configure_uart2_pins_port2(); + clocks::select_uart2_clock(p); +} + +/// Initialize clocks for the LED GPIO/PORT used by the blink example. +/// +/// # Safety +/// +/// Called only once to initialize the peripheral +#[allow(dead_code)] +pub unsafe fn init_led(p: &hal::pac::Peripherals) { + clocks::enable_led_port(p); + reset::release_reset_gpio3(p); + reset::release_reset_port3(p); +} + +/// Initialize clocks for OSTIMER0 (1 MHz source). +/// +/// # Safety +/// +/// Called only once to initialize the peripheral +#[allow(dead_code)] +pub unsafe fn init_ostimer0(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_ostimer0(p); + reset::release_reset_ostimer0(p); + clocks::select_ostimer0_clock_1m(p); +} + +/// Initialize clocks and pin muxing for ADC. +/// +/// # Safety +/// +/// Called only once to initialize the peripheral +#[allow(dead_code)] +pub unsafe fn init_adc(p: &hal::pac::Peripherals) { + clocks::ensure_frolf_running(p); + clocks::enable_adc(p); + reset::release_reset_port1(p); + reset::release_reset_adc1(p); + pins::configure_adc_pins(); + clocks::select_adc_clock(p); +} diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs deleted file mode 100644 index bd734f859..000000000 --- a/examples/uart_interrupt.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::interrupt::typelevel::Handler; -use hal::uart; - -mod common; - -use embassy_mcxa276::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; - -// Bind LPUART2 interrupt to our handler -bind_interrupts!(struct Irqs { - LPUART2 => hal::uart::UartInterruptHandler; -}); - -#[used] -#[no_mangle] -static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; - -// Wrapper function for the interrupt handler -unsafe extern "C" fn lpuart2_handler() { - hal::uart::UartInterruptHandler::on_interrupt(); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - - // Enable/clock UART2 before touching its registers - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); - - // Configure LPUART2 interrupt for UART operation BEFORE any UART usage - hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); - - // Manually install the interrupt handler and enable RX IRQs in the peripheral - unsafe { - hal::interrupt::LPUART2.install_handler(lpuart2_handler); - // Enable RX interrupts so the handler actually fires on incoming bytes - uart.enable_rx_interrupts(); - } - - // Print welcome message - uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); - uart.write_str_blocking("Type characters to echo them back.\r\n"); - - // Log using defmt if enabled - defmt::info!("UART interrupt echo demo starting..."); - - loop { - // Check if we have received any data - if uart.rx_data_available() { - if let Some(byte) = uart.try_read_byte() { - // Echo it back - uart.write_byte(byte); - uart.write_str_blocking(" (received)\r\n"); - } - } else { - // No data available, wait a bit before checking again - cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz - } - } -} -- cgit From e799d6c8956ed3ea5ced65d58c3065a22927ad10 Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 14 Nov 2025 17:29:31 +0100 Subject: More work on examples --- examples/adc_interrupt.rs | 15 ++++--- examples/common/mod.rs | 38 +++++----------- examples/lpuart_buffered.rs | 5 +-- examples/ostimer_alarm.rs | 7 +-- examples/ostimer_counter.rs | 8 ++-- examples/ostimer_race_test.rs | 5 ++- examples/uart_interrupt.rs | 100 +++++++++++++++++++++--------------------- 7 files changed, 84 insertions(+), 94 deletions(-) (limited to 'examples') diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs index dc82cfd30..3be85ac75 100644 --- a/examples/adc_interrupt.rs +++ b/examples/adc_interrupt.rs @@ -2,6 +2,8 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa276::clocks::periph_helpers::{AdcClockSel, Div4}; +use embassy_mcxa276::clocks::PoweredClock; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; use hal::uart; use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; @@ -30,10 +32,10 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + // let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; + // let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); + // uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); unsafe { common::init_adc(hal::pac()); @@ -50,6 +52,9 @@ async fn main(_spawner: Spawner) { enable_conv_pause: false, conv_pause_delay: 0, fifo_watermark: 0, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: AdcClockSel::FroLfDiv, + div: Div4::no_div(), }; let adc = hal::adc::Adc::::new(p.ADC1, adc_config); @@ -66,7 +71,7 @@ async fn main(_spawner: Spawner) { conv_trigger_config.enable_hardware_trigger = false; adc.set_conv_trigger_config(0, &conv_trigger_config); - uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + // uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); adc.enable_interrupt(0x1); @@ -83,7 +88,7 @@ async fn main(_spawner: Spawner) { while !adc.is_interrupt_triggered() { // Wait until the interrupt is triggered } - uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); + // uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); //TBD need to print the value } } diff --git a/examples/common/mod.rs b/examples/common/mod.rs index 8c52c8e86..7b197a590 100644 --- a/examples/common/mod.rs +++ b/examples/common/mod.rs @@ -1,45 +1,31 @@ //! Shared board-specific helpers for the FRDM-MCXA276 examples. //! These live with the examples so the HAL stays generic. -use hal::{clocks, pins, reset}; +use hal::{clocks, pins}; use {embassy_mcxa276 as hal, panic_probe as _}; /// Initialize clocks and pin muxing for UART2 debug console. /// Safe to call multiple times; writes are idempotent for our use. #[allow(dead_code)] -pub unsafe fn init_uart2(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_uart2_port2(p); - reset::release_reset_port2(p); - reset::release_reset_lpuart2(p); +pub unsafe fn init_uart2(_p: &mcxa_pac::Peripherals) { + // NOTE: Lpuart has been updated to properly enable + reset its own clocks. + // GPIO has not. + _ = clocks::enable_and_reset::(&clocks::NoConfig); pins::configure_uart2_pins_port2(); - clocks::select_uart2_clock(p); } /// Initialize clocks for the LED GPIO/PORT used by the blink example. #[allow(dead_code)] -pub unsafe fn init_led(p: &mcxa_pac::Peripherals) { - clocks::enable_led_port(p); - reset::release_reset_gpio3(p); - reset::release_reset_port3(p); -} - -/// Initialize clocks for OSTIMER0 (1 MHz source). -#[allow(dead_code)] -pub unsafe fn init_ostimer0(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_ostimer0(p); - reset::release_reset_ostimer0(p); - clocks::select_ostimer0_clock_1m(p); +pub unsafe fn init_led(_p: &mcxa_pac::Peripherals) { + _ = clocks::enable_and_reset::(&clocks::NoConfig); + _ = clocks::enable_and_reset::(&clocks::NoConfig); } /// Initialize clocks and pin muxing for ADC. #[allow(dead_code)] -pub unsafe fn init_adc(p: &mcxa_pac::Peripherals) { - clocks::ensure_frolf_running(p); - clocks::enable_adc(p); - reset::release_reset_port1(p); - reset::release_reset_adc1(p); +pub unsafe fn init_adc(_p: &mcxa_pac::Peripherals) { + // NOTE: Lpuart has been updated to properly enable + reset its own clocks. + // GPIO has not. + _ = clocks::enable_and_reset::(&clocks::NoConfig); pins::configure_adc_pins(); - clocks::select_adc_clock(p); } diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs index 35d311143..6ae690c56 100644 --- a/examples/lpuart_buffered.rs +++ b/examples/lpuart_buffered.rs @@ -12,18 +12,17 @@ mod common; // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver bind_interrupts!(struct Irqs { - LPUART2 => lpuart::buffered::BufferedInterruptHandler::; + LPUART2 => lpuart::buffered::BufferedInterruptHandler::; }); // Wrapper function for the interrupt handler unsafe extern "C" fn lpuart2_handler() { - lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); + lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); } #[embassy_executor::main] async fn main(_spawner: Spawner) { let _p = hal::init(hal::config::Config::default()); - let p2 = lpuart::lib::init(); unsafe { hal::interrupt::install_irq_handler(mcxa_pac::Interrupt::LPUART2, lpuart2_handler); diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs index 78ca4bbc5..4f29a2c7c 100644 --- a/examples/ostimer_alarm.rs +++ b/examples/ostimer_alarm.rs @@ -9,7 +9,7 @@ use {cortex_m, embassy_mcxa276 as hal}; mod common; -use embassy_mcxa276::bind_interrupts; +use embassy_mcxa276::{bind_interrupts, clocks::{periph_helpers::OstimerClockSel, PoweredClock}}; use {defmt_rtt as _, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. @@ -50,9 +50,10 @@ async fn main(_spawner: Spawner) { // Create OSTIMER instance let config = hal::ostimer::Config { init_match_max: true, - clock_frequency_hz: 1_000_000, // 1MHz + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, }; - let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config, hal::pac()); + let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config); // Create alarm with callback let alarm = hal::ostimer::Alarm::new() diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs index e95140a88..069e879d8 100644 --- a/examples/ostimer_counter.rs +++ b/examples/ostimer_counter.rs @@ -7,6 +7,7 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; @@ -22,9 +23,6 @@ async fn main(_spawner: Spawner) { let p = hal::init(Default::default()); // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } unsafe { common::init_uart2(hal::pac()); } @@ -44,9 +42,9 @@ async fn main(_spawner: Spawner) { p.OSTIMER0, hal::ostimer::Config { init_match_max: true, - clock_frequency_hz: 1_000_000, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, }, - hal::pac(), ); // Read initial counter value diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs index 368a3e52f..6e3d4ac21 100644 --- a/examples/ostimer_race_test.rs +++ b/examples/ostimer_race_test.rs @@ -12,6 +12,7 @@ use core::sync::atomic::{AtomicU32, Ordering}; use embassy_executor::Spawner; +use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; @@ -98,9 +99,9 @@ async fn main(_spawner: Spawner) { p.OSTIMER0, hal::ostimer::Config { init_match_max: true, - clock_frequency_hz: 1_000_000, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: OstimerClockSel::Clk1M, }, - hal::pac(), ); uart.write_str_blocking("OSTIMER instance created\n"); diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs index bd734f859..190a4d850 100644 --- a/examples/uart_interrupt.rs +++ b/examples/uart_interrupt.rs @@ -2,68 +2,68 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::interrupt::typelevel::Handler; -use hal::uart; +// use embassy_mcxa276 as hal; +// use hal::interrupt::typelevel::Handler; +// use hal::uart; -mod common; +// mod common; -use embassy_mcxa276::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; +// use embassy_mcxa276::bind_interrupts; +// use {defmt_rtt as _, panic_probe as _}; -// Bind LPUART2 interrupt to our handler -bind_interrupts!(struct Irqs { - LPUART2 => hal::uart::UartInterruptHandler; -}); +// // Bind LPUART2 interrupt to our handler +// bind_interrupts!(struct Irqs { +// LPUART2 => hal::uart::UartInterruptHandler; +// }); -#[used] -#[no_mangle] -static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; +// #[used] +// #[no_mangle] +// static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; -// Wrapper function for the interrupt handler -unsafe extern "C" fn lpuart2_handler() { - hal::uart::UartInterruptHandler::on_interrupt(); -} +// // Wrapper function for the interrupt handler +// unsafe extern "C" fn lpuart2_handler() { +// hal::uart::UartInterruptHandler::on_interrupt(); +// } #[embassy_executor::main] async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); +// let _p = hal::init(hal::config::Config::default()); - // Enable/clock UART2 before touching its registers - unsafe { - common::init_uart2(hal::pac()); - } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); +// // Enable/clock UART2 before touching its registers +// unsafe { +// common::init_uart2(hal::pac()); +// } +// let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; +// let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); - // Configure LPUART2 interrupt for UART operation BEFORE any UART usage - hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); +// // Configure LPUART2 interrupt for UART operation BEFORE any UART usage +// hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); - // Manually install the interrupt handler and enable RX IRQs in the peripheral - unsafe { - hal::interrupt::LPUART2.install_handler(lpuart2_handler); - // Enable RX interrupts so the handler actually fires on incoming bytes - uart.enable_rx_interrupts(); - } +// // Manually install the interrupt handler and enable RX IRQs in the peripheral +// unsafe { +// hal::interrupt::LPUART2.install_handler(lpuart2_handler); +// // Enable RX interrupts so the handler actually fires on incoming bytes +// uart.enable_rx_interrupts(); +// } - // Print welcome message - uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); - uart.write_str_blocking("Type characters to echo them back.\r\n"); +// // Print welcome message +// uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); +// uart.write_str_blocking("Type characters to echo them back.\r\n"); - // Log using defmt if enabled - defmt::info!("UART interrupt echo demo starting..."); +// // Log using defmt if enabled +// defmt::info!("UART interrupt echo demo starting..."); - loop { - // Check if we have received any data - if uart.rx_data_available() { - if let Some(byte) = uart.try_read_byte() { - // Echo it back - uart.write_byte(byte); - uart.write_str_blocking(" (received)\r\n"); - } - } else { - // No data available, wait a bit before checking again - cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz - } - } +// loop { +// // Check if we have received any data +// if uart.rx_data_available() { +// if let Some(byte) = uart.try_read_byte() { +// // Echo it back +// uart.write_byte(byte); +// uart.write_str_blocking(" (received)\r\n"); +// } +// } else { +// // No data available, wait a bit before checking again +// cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz +// } +// } } -- cgit From 8cdccae3c6c4a805cf5003b1a859734c105d76e8 Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 14 Nov 2025 18:43:27 +0100 Subject: Continue working on examples --- examples/adc_interrupt.rs | 29 ++++++++++++------ examples/adc_polling.rs | 30 +++++++++++++++--- examples/blink.rs | 4 --- examples/hello.rs | 33 ++++++++++++-------- examples/lpuart_buffered.rs | 9 +++--- examples/lpuart_polling.rs | 11 +++---- examples/ostimer_alarm.rs | 32 +++++++++++++------ examples/ostimer_async.rs | 29 ++++++++++++------ examples/ostimer_counter.rs | 26 +++++++++++++--- examples/ostimer_race_test.rs | 71 +++++++++++++++++++++++++------------------ examples/rtc_alarm.rs | 28 ++++++++++++----- examples/uart_interrupt.rs | 69 ----------------------------------------- 12 files changed, 200 insertions(+), 171 deletions(-) delete mode 100644 examples/uart_interrupt.rs (limited to 'examples') diff --git a/examples/adc_interrupt.rs b/examples/adc_interrupt.rs index 3be85ac75..536152539 100644 --- a/examples/adc_interrupt.rs +++ b/examples/adc_interrupt.rs @@ -4,13 +4,13 @@ use embassy_executor::Spawner; use embassy_mcxa276::clocks::periph_helpers::{AdcClockSel, Div4}; use embassy_mcxa276::clocks::PoweredClock; +use embassy_mcxa276::lpuart::{Config, Lpuart}; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; -use hal::uart; use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; use mcxa_pac::adc1::cmdl1::{Adch, Mode}; use mcxa_pac::adc1::ctrl::CalAvgs; use mcxa_pac::adc1::tctrl::Tcmd; -use {cortex_m, embassy_mcxa276 as hal}; +use {embassy_mcxa276 as hal}; mod common; use hal::{bind_interrupts, InterruptExt}; @@ -28,14 +28,25 @@ static KEEP_ADC: unsafe extern "C" fn() = ADC1; async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - - // let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - // let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); - - // uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); unsafe { common::init_adc(hal::pac()); @@ -71,7 +82,7 @@ async fn main(_spawner: Spawner) { conv_trigger_config.enable_hardware_trigger = false; adc.set_conv_trigger_config(0, &conv_trigger_config); - // uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); adc.enable_interrupt(0x1); @@ -88,7 +99,7 @@ async fn main(_spawner: Spawner) { while !adc.is_interrupt_triggered() { // Wait until the interrupt is triggered } - // uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); + uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); //TBD need to print the value } } diff --git a/examples/adc_polling.rs b/examples/adc_polling.rs index 4b5f9422d..2fe4153db 100644 --- a/examples/adc_polling.rs +++ b/examples/adc_polling.rs @@ -2,9 +2,11 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa276::clocks::periph_helpers::{AdcClockSel, Div4}; +use embassy_mcxa276::clocks::PoweredClock; +use embassy_mcxa276::lpuart::{Config, Lpuart}; use embassy_mcxa276 as hal; use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; -use hal::uart; use mcxa_pac::adc1::cfg::{Pwrsel, Refsel}; use mcxa_pac::adc1::cmdl1::{Adch, Mode}; use mcxa_pac::adc1::ctrl::CalAvgs; @@ -27,10 +29,27 @@ async fn main(_spawner: Spawner) { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + unsafe { + common::init_uart2(hal::pac()); + } + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); - uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); + uart.blocking_write(b"\r\n=== ADC polling Example ===\r\n").unwrap(); unsafe { common::init_adc(hal::pac()); @@ -47,6 +66,9 @@ async fn main(_spawner: Spawner) { enable_conv_pause: false, conv_pause_delay: 0, fifo_watermark: 0, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: AdcClockSel::FroLfDiv, + div: Div4::no_div(), }; let adc = hal::adc::Adc::::new(p.ADC1, adc_config); diff --git a/examples/blink.rs b/examples/blink.rs index 564353d5c..0f489abb9 100644 --- a/examples/blink.rs +++ b/examples/blink.rs @@ -28,10 +28,6 @@ async fn main(_spawner: Spawner) { unsafe { common::init_led(hal::pac()); } - // Initialize OSTIMER for async timing - unsafe { - common::init_ostimer0(hal::pac()); - } // Initialize embassy-time global driver backed by OSTIMER0 hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); diff --git a/examples/hello.rs b/examples/hello.rs index e39adaced..dbb53fdcf 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -2,15 +2,14 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::uart; +use embassy_mcxa276::{self as hal, lpuart::{Blocking, Config, Lpuart}}; mod common; use {defmt_rtt as _, panic_probe as _}; /// Simple helper to write a byte as hex to UART -fn write_hex_byte(uart: &hal::uart::Uart, byte: u8) { +fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); @@ -22,15 +21,25 @@ async fn main(_spawner: Spawner) { defmt::info!("boot"); - // Board-level init for UART2 clocks and pins. + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - - // Get UART source frequency from clock configuration - // Using hardcoded frequency for now - dynamic detection may have issues - let src = 12_000_000; // FRO_LF_DIV at 12MHz with DIV=0 - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); // Print welcome message before any async delays to guarantee early console output uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); @@ -69,12 +78,12 @@ async fn main(_spawner: Spawner) { let num_str = &command[4..]; if let Ok(num) = parse_u8(num_str) { uart.write_str_blocking("Hex: 0x"); - write_hex_byte(&uart, num); + write_hex_byte(&mut uart, num); uart.write_str_blocking("\r\n"); } else { uart.write_str_blocking("Invalid number for hex command\r\n"); } - } else if command.len() > 0 { + } else if !command.is_empty() { uart.write_str_blocking("Unknown command: "); uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); uart.write_str_blocking("\r\n"); @@ -103,7 +112,7 @@ async fn main(_spawner: Spawner) { fn parse_u8(bytes: &[u8]) -> Result { let mut result = 0u8; for &b in bytes { - if b >= b'0' && b <= b'9' { + if b.is_ascii_digit() { result = result.checked_mul(10).ok_or(())?; result = result.checked_add(b - b'0').ok_or(())?; } else { diff --git a/examples/lpuart_buffered.rs b/examples/lpuart_buffered.rs index 6ae690c56..9e297ca67 100644 --- a/examples/lpuart_buffered.rs +++ b/examples/lpuart_buffered.rs @@ -22,7 +22,7 @@ unsafe extern "C" fn lpuart2_handler() { #[embassy_executor::main] async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); + let p = hal::init(hal::config::Config::default()); unsafe { hal::interrupt::install_irq_handler(mcxa_pac::Interrupt::LPUART2, lpuart2_handler); @@ -33,7 +33,6 @@ async fn main(_spawner: Spawner) { unsafe { common::init_uart2(hal::pac()); - common::init_ostimer0(hal::pac()); } // UART configuration (enable both TX and RX) @@ -51,9 +50,9 @@ async fn main(_spawner: Spawner) { // Create a buffered LPUART2 instance with both TX and RX let mut uart = BufferedLpuart::new( - p2.LPUART2, - p2.PIO2_2, // TX pin - p2.PIO2_3, // RX pin + p.LPUART2, + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin Irqs, &mut tx_buf, &mut rx_buf, diff --git a/examples/lpuart_polling.rs b/examples/lpuart_polling.rs index 067c7eb53..c9630dca5 100644 --- a/examples/lpuart_polling.rs +++ b/examples/lpuart_polling.rs @@ -4,14 +4,13 @@ use embassy_executor::Spawner; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; -use crate::hal::lpuart::{lib, Config, Lpuart}; +use crate::hal::lpuart::{Config, Lpuart}; mod common; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - let p2 = lib::init(); + let p = hal::init(hal::config::Config::default()); defmt::info!("boot"); @@ -30,9 +29,9 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX let lpuart = Lpuart::new_blocking( - p2.LPUART2, // Peripheral - p2.PIO2_2, // TX pin - p2.PIO2_3, // RX pin + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin config, ) .unwrap(); diff --git a/examples/ostimer_alarm.rs b/examples/ostimer_alarm.rs index 4f29a2c7c..f3a84d312 100644 --- a/examples/ostimer_alarm.rs +++ b/examples/ostimer_alarm.rs @@ -4,12 +4,15 @@ use core::sync::atomic::{AtomicBool, Ordering}; use embassy_executor::Spawner; -use hal::uart; -use {cortex_m, embassy_mcxa276 as hal}; +use embassy_mcxa276 as hal; mod common; -use embassy_mcxa276::{bind_interrupts, clocks::{periph_helpers::OstimerClockSel, PoweredClock}}; +use embassy_mcxa276::{ + bind_interrupts, + clocks::{periph_helpers::OstimerClockSel, PoweredClock}, + lpuart::{Config, Lpuart}, +}; use {defmt_rtt as _, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. @@ -33,15 +36,26 @@ fn alarm_callback() { async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); + uart.write_str_blocking("OSTIMER Alarm Example\n"); // Initialize embassy-time global driver backed by OSTIMER0 diff --git a/examples/ostimer_async.rs b/examples/ostimer_async.rs index 27e14e022..2642a633d 100644 --- a/examples/ostimer_async.rs +++ b/examples/ostimer_async.rs @@ -2,8 +2,7 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa276 as hal; -use hal::uart; +use embassy_mcxa276::{self as hal, lpuart::{Config, Lpuart}}; mod common; @@ -22,18 +21,28 @@ static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); + let p = hal::init(hal::config::Config::default()); - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); - uart.write_str_blocking("boot\n"); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); + uart.blocking_write(b"boot\n").unwrap(); // Avoid mass NVIC writes here; DefaultHandler now safely returns. diff --git a/examples/ostimer_counter.rs b/examples/ostimer_counter.rs index 069e879d8..590c5a14b 100644 --- a/examples/ostimer_counter.rs +++ b/examples/ostimer_counter.rs @@ -7,7 +7,10 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; +use embassy_mcxa276::{ + clocks::{periph_helpers::OstimerClockSel, PoweredClock}, + lpuart::{Blocking, Config, Lpuart}, +}; use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; @@ -22,12 +25,25 @@ bind_interrupts!(struct Irqs { async fn main(_spawner: Spawner) { let p = hal::init(Default::default()); - // Enable/clock OSTIMER0 and UART2 before touching their registers + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); @@ -90,7 +106,7 @@ async fn main(_spawner: Spawner) { } // Helper function to write a u64 value as decimal string -fn write_u64(uart: &mut hal::uart::Uart, value: u64) { +fn write_u64(uart: &mut Lpuart<'_, Blocking>, value: u64) { if value == 0 { uart.write_str_blocking("0"); return; diff --git a/examples/ostimer_race_test.rs b/examples/ostimer_race_test.rs index 6e3d4ac21..131d10f64 100644 --- a/examples/ostimer_race_test.rs +++ b/examples/ostimer_race_test.rs @@ -12,7 +12,10 @@ use core::sync::atomic::{AtomicU32, Ordering}; use embassy_executor::Spawner; -use embassy_mcxa276::clocks::{periph_helpers::OstimerClockSel, PoweredClock}; +use embassy_mcxa276::{ + clocks::{periph_helpers::OstimerClockSel, PoweredClock}, + lpuart::{Blocking, Config, Lpuart}, +}; use embassy_time::{Duration, Timer}; use hal::bind_interrupts; use {defmt_rtt as _, embassy_mcxa276 as hal, panic_probe as _}; @@ -43,7 +46,7 @@ fn alarm_callback() { } } -fn report_default_handler(uart: &mut hal::uart::Uart) { +fn report_default_handler(uart: &mut Lpuart<'_, Blocking>) { let snapshot = hal::interrupt::default_handler_snapshot(); if snapshot.count == 0 { return; @@ -72,15 +75,25 @@ fn report_default_handler(uart: &mut hal::uart::Uart) { async fn main(_spawner: Spawner) { let p = hal::init(Default::default()); - // Enable/clock OSTIMER0 and UART2 before touching their registers - unsafe { - common::init_ostimer0(hal::pac()); - } + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let mut uart = hal::uart::Uart::::new(p.LPUART2, hal::uart::Config::new(src)); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); @@ -140,7 +153,7 @@ async fn main(_spawner: Spawner) { // Test rapid alarm scheduling to stress interrupt handling async fn test_rapid_alarms( ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, + uart: &mut Lpuart<'_, Blocking>, ) { let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); @@ -177,7 +190,7 @@ async fn test_rapid_alarms( // Test reading counter while interrupts are firing async fn test_counter_reading_during_interrupts( ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, + uart: &mut Lpuart<'_, Blocking>, ) { let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); @@ -238,7 +251,7 @@ async fn test_counter_reading_during_interrupts( // Test concurrent timer operations (embassy-time + alarms) async fn test_concurrent_operations( ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, + uart: &mut Lpuart<'_, Blocking>, ) { let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); @@ -267,7 +280,7 @@ async fn test_concurrent_operations( // Test timer reset during active operations async fn test_reset_during_operation( ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut hal::uart::Uart, + uart: &mut Lpuart<'_, Blocking>, peripherals: &mcxa_pac::Peripherals, ) { let initial_counter = ostimer.now(); @@ -308,7 +321,7 @@ async fn test_reset_during_operation( } // Helper function to write a u32 value as decimal string -fn write_u32(uart: &mut hal::uart::Uart, value: u32) { +fn write_u32(uart: &mut Lpuart<'_, Blocking>, value: u32) { if value == 0 { uart.write_str_blocking("0"); return; @@ -343,7 +356,7 @@ fn write_u32(uart: &mut hal::uart::Uart, value: u32) { } } -fn write_hex32(uart: &mut hal::uart::Uart, value: u32) { +fn write_hex32(uart: &mut Lpuart<'_, Blocking>, value: u32) { let mut buf = [b'0'; 8]; let mut tmp = value; for i in (0..8).rev() { @@ -355,15 +368,13 @@ fn write_hex32(uart: &mut hal::uart::Uart, value: u32) { }; tmp >>= 4; } - for b in &buf { - uart.write_byte(*b); - } + uart.blocking_write(&buf).unwrap(); } // Helper function to write a u64 value as decimal string -fn write_u64(uart: &mut hal::uart::Uart, value: u64) { +fn write_u64(uart: &mut Lpuart<'_, Blocking>, value: u64) { if value == 0 { - uart.write_str_blocking("0"); + uart.blocking_write(b"0").unwrap(); return; } @@ -381,17 +392,17 @@ fn write_u64(uart: &mut hal::uart::Uart, value: u64) { while i > 0 { i -= 1; match buffer[i] { - b'0' => uart.write_str_blocking("0"), - b'1' => uart.write_str_blocking("1"), - b'2' => uart.write_str_blocking("2"), - b'3' => uart.write_str_blocking("3"), - b'4' => uart.write_str_blocking("4"), - b'5' => uart.write_str_blocking("5"), - b'6' => uart.write_str_blocking("6"), - b'7' => uart.write_str_blocking("7"), - b'8' => uart.write_str_blocking("8"), - b'9' => uart.write_str_blocking("9"), - _ => uart.write_str_blocking("?"), + b'0' => uart.blocking_write(b"0").unwrap(), + b'1' => uart.blocking_write(b"1").unwrap(), + b'2' => uart.blocking_write(b"2").unwrap(), + b'3' => uart.blocking_write(b"3").unwrap(), + b'4' => uart.blocking_write(b"4").unwrap(), + b'5' => uart.blocking_write(b"5").unwrap(), + b'6' => uart.blocking_write(b"6").unwrap(), + b'7' => uart.blocking_write(b"7").unwrap(), + b'8' => uart.blocking_write(b"8").unwrap(), + b'9' => uart.blocking_write(b"9").unwrap(), + _ => uart.blocking_write(b"?").unwrap(), } } } diff --git a/examples/rtc_alarm.rs b/examples/rtc_alarm.rs index c27fd4c55..1cda37054 100644 --- a/examples/rtc_alarm.rs +++ b/examples/rtc_alarm.rs @@ -2,13 +2,14 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa276::lpuart::{Config, Lpuart}; use hal::rtc::{RtcDateTime, RtcInterruptEnable}; -use hal::{uart, InterruptExt}; -use {cortex_m, embassy_mcxa276 as hal}; +use hal::InterruptExt; +use {embassy_mcxa276 as hal}; mod common; -type MyRtc = hal::rtc::Rtc; +type MyRtc = hal::rtc::Rtc<'static, hal::rtc::Rtc0>; use embassy_mcxa276::bind_interrupts; use {defmt_rtt as _, panic_probe as _}; @@ -25,17 +26,28 @@ static KEEP_RTC: unsafe extern "C" fn() = RTC; async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + enable_tx: true, + enable_rx: true, + ..Default::default() + }; + + // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { common::init_uart2(hal::pac()); } - - let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; - let uart = uart::Uart::::new(p.LPUART2, uart::Config::new(src)); + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.PIO2_2, // TX pin + p.PIO2_3, // RX pin + config, + ) + .unwrap(); uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); - unsafe { hal::clocks::init_fro16k(hal::pac()) }; - let rtc_config = hal::rtc::get_default_config(); let rtc = MyRtc::new(p.RTC0, rtc_config); diff --git a/examples/uart_interrupt.rs b/examples/uart_interrupt.rs deleted file mode 100644 index 190a4d850..000000000 --- a/examples/uart_interrupt.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -// use embassy_mcxa276 as hal; -// use hal::interrupt::typelevel::Handler; -// use hal::uart; - -// mod common; - -// use embassy_mcxa276::bind_interrupts; -// use {defmt_rtt as _, panic_probe as _}; - -// // Bind LPUART2 interrupt to our handler -// bind_interrupts!(struct Irqs { -// LPUART2 => hal::uart::UartInterruptHandler; -// }); - -// #[used] -// #[no_mangle] -// static KEEP_LPUART2: unsafe extern "C" fn() = LPUART2; - -// // Wrapper function for the interrupt handler -// unsafe extern "C" fn lpuart2_handler() { -// hal::uart::UartInterruptHandler::on_interrupt(); -// } - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { -// let _p = hal::init(hal::config::Config::default()); - -// // Enable/clock UART2 before touching its registers -// unsafe { -// common::init_uart2(hal::pac()); -// } -// let src = unsafe { hal::clocks::uart2_src_hz(hal::pac()) }; -// let uart = uart::Uart::::new(_p.LPUART2, uart::Config::new(src)); - -// // Configure LPUART2 interrupt for UART operation BEFORE any UART usage -// hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::from(3)); - -// // Manually install the interrupt handler and enable RX IRQs in the peripheral -// unsafe { -// hal::interrupt::LPUART2.install_handler(lpuart2_handler); -// // Enable RX interrupts so the handler actually fires on incoming bytes -// uart.enable_rx_interrupts(); -// } - -// // Print welcome message -// uart.write_str_blocking("UART interrupt echo demo starting...\r\n"); -// uart.write_str_blocking("Type characters to echo them back.\r\n"); - -// // Log using defmt if enabled -// defmt::info!("UART interrupt echo demo starting..."); - -// loop { -// // Check if we have received any data -// if uart.rx_data_available() { -// if let Some(byte) = uart.try_read_byte() { -// // Echo it back -// uart.write_byte(byte); -// uart.write_str_blocking(" (received)\r\n"); -// } -// } else { -// // No data available, wait a bit before checking again -// cortex_m::asm::delay(12_000_000); // ~1 second at 12MHz -// } -// } -} -- cgit From 1f589e9428542cd94bc630b623accf04d9c36edf Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 14 Nov 2025 19:08:16 +0100 Subject: A little follow-up cleanup --- examples/src/bin/adc_interrupt.rs | 5 +++-- examples/src/bin/adc_polling.rs | 8 ++++---- examples/src/bin/blink.rs | 4 ++-- examples/src/bin/hello.rs | 2 +- examples/src/bin/lpuart_buffered.rs | 7 ++++--- examples/src/bin/lpuart_polling.rs | 4 ++-- examples/src/bin/ostimer_alarm.rs | 4 ++-- examples/src/bin/ostimer_async.rs | 9 +++++---- examples/src/bin/ostimer_counter.rs | 2 +- examples/src/bin/ostimer_race_test.rs | 2 +- examples/src/bin/rtc_alarm.rs | 9 +++++---- examples/src/lib.rs | 10 ++++------ 12 files changed, 34 insertions(+), 32 deletions(-) (limited to 'examples') diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs index be08ebf8c..6812ba5d3 100644 --- a/examples/src/bin/adc_interrupt.rs +++ b/examples/src/bin/adc_interrupt.rs @@ -2,6 +2,7 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa_examples::init_adc_pins; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; use hal::clocks::periph_helpers::{AdcClockSel, Div4}; use hal::clocks::PoweredClock; @@ -35,7 +36,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral @@ -47,7 +48,7 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); unsafe { - embassy_mcxa_examples::init_adc(hal::pac()); + init_adc_pins(hal::pac()); } let adc_config = LpadcConfig { diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs index 723f1e044..421306e9b 100644 --- a/examples/src/bin/adc_polling.rs +++ b/examples/src/bin/adc_polling.rs @@ -4,7 +4,7 @@ use core::fmt::Write; use embassy_executor::Spawner; -use embassy_mcxa_examples::{init_adc, init_uart2}; +use embassy_mcxa_examples::{init_adc_pins, init_uart2_pins}; use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; use hal::clocks::periph_helpers::{AdcClockSel, Div4}; use hal::clocks::PoweredClock; @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); unsafe { - init_uart2(hal::pac()); + init_uart2_pins(hal::pac()); } // Create UART configuration @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - init_uart2(hal::pac()); + init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral @@ -49,7 +49,7 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); unsafe { - init_adc(hal::pac()); + init_adc_pins(hal::pac()); } let adc_config = LpadcConfig { diff --git a/examples/src/bin/blink.rs b/examples/src/bin/blink.rs index ee59ac591..8c48e79f1 100644 --- a/examples/src/bin/blink.rs +++ b/examples/src/bin/blink.rs @@ -4,7 +4,7 @@ use embassy_executor::Spawner; use embassy_mcxa as hal; use embassy_mcxa::bind_interrupts; -use embassy_mcxa_examples::init_led; +use embassy_mcxa_examples::init_led_gpio_clocks; use embassy_time::{Duration, Timer}; use hal::gpio::pins::PIO3_18; use hal::gpio::{Level, Output}; @@ -23,7 +23,7 @@ async fn main(_spawner: Spawner) { let _p = hal::init(hal::config::Config::default()); unsafe { - init_led(hal::pac()); + init_led_gpio_clocks(hal::pac()); } // Initialize embassy-time global driver backed by OSTIMER0 diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs index ff7afa01d..207c157c3 100644 --- a/examples/src/bin/hello.rs +++ b/examples/src/bin/hello.rs @@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs index e96ab7b81..642d4af65 100644 --- a/examples/src/bin/lpuart_buffered.rs +++ b/examples/src/bin/lpuart_buffered.rs @@ -5,8 +5,9 @@ use embassy_executor::Spawner; use embassy_mcxa as hal; use embassy_mcxa::interrupt::typelevel::Handler; use embassy_mcxa::lpuart::buffered::BufferedLpuart; +use embassy_mcxa::lpuart::Config; use embassy_mcxa::{bind_interrupts, lpuart}; -use embassy_mcxa_examples::init_uart2; +use embassy_mcxa_examples::init_uart2_pins; use embedded_io_async::{Read, Write}; // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver @@ -31,11 +32,11 @@ async fn main(_spawner: Spawner) { hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); unsafe { - init_uart2(hal::pac()); + init_uart2_pins(hal::pac()); } // UART configuration (enable both TX and RX) - let config = lpuart::Config { + let config = Config { baudrate_bps: 115_200, enable_tx: true, enable_rx: true, diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs index bdcfa0776..bea82c33e 100644 --- a/examples/src/bin/lpuart_polling.rs +++ b/examples/src/bin/lpuart_polling.rs @@ -2,7 +2,7 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa_examples::init_uart2; +use embassy_mcxa_examples::init_uart2_pins; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; use crate::hal::lpuart::{Config, Lpuart}; @@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) { // Board-level init for UART2 clocks and pins. unsafe { - init_uart2(hal::pac()); + init_uart2_pins(hal::pac()); } // Create UART configuration diff --git a/examples/src/bin/ostimer_alarm.rs b/examples/src/bin/ostimer_alarm.rs index 9e858b60b..36b1f403a 100644 --- a/examples/src/bin/ostimer_alarm.rs +++ b/examples/src/bin/ostimer_alarm.rs @@ -8,7 +8,7 @@ use embassy_mcxa::bind_interrupts; use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; use embassy_mcxa::clocks::PoweredClock; use embassy_mcxa::lpuart::{Config, Lpuart}; -use embassy_mcxa_examples::init_uart2; +use embassy_mcxa_examples::init_uart2_pins; use {cortex_m, defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. @@ -42,7 +42,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - init_uart2(hal::pac()); + init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral diff --git a/examples/src/bin/ostimer_async.rs b/examples/src/bin/ostimer_async.rs index 4e692a744..881f09374 100644 --- a/examples/src/bin/ostimer_async.rs +++ b/examples/src/bin/ostimer_async.rs @@ -3,8 +3,9 @@ use embassy_executor::Spawner; use embassy_mcxa::bind_interrupts; -use embassy_mcxa_examples::init_uart2; +use embassy_mcxa_examples::init_uart2_pins; use embassy_time::{Duration, Timer}; +use hal::lpuart::{Config, Lpuart}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. @@ -21,7 +22,7 @@ async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); // Create UART configuration - let config = hal::lpuart::Config { + let config = Config { baudrate_bps: 115_200, enable_tx: true, enable_rx: true, @@ -30,9 +31,9 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - init_uart2(hal::pac()); + init_uart2_pins(hal::pac()); } - let mut uart = hal::lpuart::Lpuart::new_blocking( + let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral p.PIO2_2, // TX pin p.PIO2_3, // RX pin diff --git a/examples/src/bin/ostimer_counter.rs b/examples/src/bin/ostimer_counter.rs index 47543160b..2fbc251b9 100644 --- a/examples/src/bin/ostimer_counter.rs +++ b/examples/src/bin/ostimer_counter.rs @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral diff --git a/examples/src/bin/ostimer_race_test.rs b/examples/src/bin/ostimer_race_test.rs index c2ecff969..168a952cd 100644 --- a/examples/src/bin/ostimer_race_test.rs +++ b/examples/src/bin/ostimer_race_test.rs @@ -82,7 +82,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs index e2eaa6ae2..40a1207df 100644 --- a/examples/src/bin/rtc_alarm.rs +++ b/examples/src/bin/rtc_alarm.rs @@ -2,9 +2,10 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa as hal; +use hal::lpuart::{Config, Lpuart}; use hal::rtc::{RtcDateTime, RtcInterruptEnable}; use hal::InterruptExt; -use {cortex_m, embassy_mcxa as hal}; type MyRtc = hal::rtc::Rtc<'static, hal::rtc::Rtc0>; @@ -24,7 +25,7 @@ async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); // Create UART configuration - let config = hal::lpuart::Config { + let config = Config { baudrate_bps: 115_200, enable_tx: true, enable_rx: true, @@ -33,9 +34,9 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(hal::pac()); } - let mut uart = hal::lpuart::Lpuart::new_blocking( + let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral p.PIO2_2, // TX pin p.PIO2_3, // RX pin diff --git a/examples/src/lib.rs b/examples/src/lib.rs index a45ab708d..be4761c32 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -1,4 +1,5 @@ #![no_std] +#![allow(clippy::missing_safety_doc)] //! Shared board-specific helpers for the FRDM-MCXA276 examples. //! These live with the examples so the HAL stays generic. @@ -8,8 +9,7 @@ use {embassy_mcxa as hal, panic_probe as _}; /// Initialize clocks and pin muxing for UART2 debug console. /// Safe to call multiple times; writes are idempotent for our use. -#[allow(dead_code)] -pub unsafe fn init_uart2(_p: &hal::pac::Peripherals) { +pub unsafe fn init_uart2_pins(_p: &hal::pac::Peripherals) { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. // GPIO has not. _ = clocks::enable_and_reset::(&clocks::NoConfig); @@ -17,15 +17,13 @@ pub unsafe fn init_uart2(_p: &hal::pac::Peripherals) { } /// Initialize clocks for the LED GPIO/PORT used by the blink example. -#[allow(dead_code)] -pub unsafe fn init_led(_p: &hal::pac::Peripherals) { +pub unsafe fn init_led_gpio_clocks(_p: &hal::pac::Peripherals) { _ = clocks::enable_and_reset::(&clocks::NoConfig); _ = clocks::enable_and_reset::(&clocks::NoConfig); } /// Initialize clocks and pin muxing for ADC. -#[allow(dead_code)] -pub unsafe fn init_adc(_p: &hal::pac::Peripherals) { +pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. // GPIO has not. _ = clocks::enable_and_reset::(&clocks::NoConfig); -- cgit From 728340ba05e9a16ceb472b147737c38c144d292d Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 14 Nov 2025 19:11:06 +0100 Subject: Remove redundant import --- examples/src/bin/ostimer_alarm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/src/bin/ostimer_alarm.rs b/examples/src/bin/ostimer_alarm.rs index 36b1f403a..03fb93319 100644 --- a/examples/src/bin/ostimer_alarm.rs +++ b/examples/src/bin/ostimer_alarm.rs @@ -9,7 +9,7 @@ use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; use embassy_mcxa::clocks::PoweredClock; use embassy_mcxa::lpuart::{Config, Lpuart}; use embassy_mcxa_examples::init_uart2_pins; -use {cortex_m, defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; // Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. bind_interrupts!(struct Irqs { -- cgit From a0c8e2d0299f3ae8eb24cd264d2b8e87f2bce464 Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 17 Nov 2025 15:02:26 +0100 Subject: Restore examples --- examples/src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'examples') diff --git a/examples/src/lib.rs b/examples/src/lib.rs index be4761c32..2018a3c25 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -12,20 +12,20 @@ use {embassy_mcxa as hal, panic_probe as _}; pub unsafe fn init_uart2_pins(_p: &hal::pac::Peripherals) { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. // GPIO has not. - _ = clocks::enable_and_reset::(&clocks::NoConfig); + _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); pins::configure_uart2_pins_port2(); } /// Initialize clocks for the LED GPIO/PORT used by the blink example. pub unsafe fn init_led_gpio_clocks(_p: &hal::pac::Peripherals) { - _ = clocks::enable_and_reset::(&clocks::NoConfig); - _ = clocks::enable_and_reset::(&clocks::NoConfig); + _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); + _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); } /// Initialize clocks and pin muxing for ADC. pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. // GPIO has not. - _ = clocks::enable_and_reset::(&clocks::NoConfig); + _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); pins::configure_adc_pins(); } -- cgit From 02285c2153d22f2c0c93a4ce920cdebc03f18658 Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 17 Nov 2025 16:38:32 +0100 Subject: Correct clk/rst field logic --- examples/memory.x | 4 ++-- examples/src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/memory.x b/examples/memory.x index f4263a412..528545b64 100644 --- a/examples/memory.x +++ b/examples/memory.x @@ -1,5 +1,5 @@ MEMORY { - FLASH : ORIGIN = 0x20000000, LENGTH = 64K - RAM : ORIGIN = 0x20010000, LENGTH = 64K + FLASH : ORIGIN = 0x20000000, LENGTH = 80K + RAM : ORIGIN = 0x20014000, LENGTH = 48K } diff --git a/examples/src/lib.rs b/examples/src/lib.rs index 2018a3c25..4bb334da5 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -5,7 +5,7 @@ //! These live with the examples so the HAL stays generic. use hal::{clocks, pins}; -use {embassy_mcxa as hal, panic_probe as _}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; /// Initialize clocks and pin muxing for UART2 debug console. /// Safe to call multiple times; writes are idempotent for our use. -- cgit From bf3ae8e4d69ef2e2ecfdf0b48734d9c91637eb16 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 17 Nov 2025 16:27:39 -0800 Subject: Let HAL build in isolation (#21) * Revert "chore(deps): bump embedded-io-async from 0.6.1 to 0.7.0 (#17)" This reverts commit 011c3b2de9361496faa0eea75ae19a77f2698f88. * Let HAL build in isolation while at that, also remove bogus dependency on embassy-executor. Signed-off-by: Felipe Balbi * Certify syn 2.0.110 Signed-off-by: Felipe Balbi --------- Signed-off-by: Felipe Balbi --- examples/Cargo.lock | 1 - 1 file changed, 1 deletion(-) (limited to 'examples') diff --git a/examples/Cargo.lock b/examples/Cargo.lock index b774aff97..b2ac9a051 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -240,7 +240,6 @@ dependencies = [ "critical-section", "defmt", "embassy-embedded-hal", - "embassy-executor", "embassy-hal-internal", "embassy-sync", "embassy-time", -- cgit From 62e297c130ac26afe4d7d5752bb79709bd370e39 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 17 Nov 2025 16:34:11 -0800 Subject: Allow writing binary to flash (#20) Turns out probe-rs works out of the box. Signed-off-by: Felipe Balbi --- examples/.cargo/config.toml | 2 +- examples/Cargo.toml | 4 ++++ examples/memory.x | 4 ++-- examples/src/bin/blink.rs | 4 ++++ 4 files changed, 11 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml index ecb11be64..aedc55b06 100644 --- a/examples/.cargo/config.toml +++ b/examples/.cargo/config.toml @@ -1,5 +1,5 @@ [target.thumbv8m.main-none-eabihf] -runner = 'probe-rs run --chip MCXA276 --preverify --verify' +runner = 'probe-rs run --chip MCXA276 --preverify --verify --protocol swd --speed 12000' rustflags = [ "-C", "linker=flip-link", diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 6b100de42..d03d3d95c 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -19,3 +19,7 @@ embassy-time-driver = "0.2.1" embedded-io-async = "0.6.1" heapless = "0.9.2" panic-probe = { version = "1.0", features = ["print-defmt"] } + +[profile.release] +lto = true # better optimizations +debug = 2 # enough information for defmt/rtt locations diff --git a/examples/memory.x b/examples/memory.x index f4263a412..315ced58a 100644 --- a/examples/memory.x +++ b/examples/memory.x @@ -1,5 +1,5 @@ MEMORY { - FLASH : ORIGIN = 0x20000000, LENGTH = 64K - RAM : ORIGIN = 0x20010000, LENGTH = 64K + FLASH : ORIGIN = 0x00000000, LENGTH = 1M + RAM : ORIGIN = 0x20000000, LENGTH = 128K } diff --git a/examples/src/bin/blink.rs b/examples/src/bin/blink.rs index d8a57c546..c36fc9421 100644 --- a/examples/src/bin/blink.rs +++ b/examples/src/bin/blink.rs @@ -27,6 +27,8 @@ async fn main(_spawner: Spawner) { init_ostimer0(hal::pac()); } + defmt::info!("Blink example"); + // Initialize embassy-time global driver backed by OSTIMER0 hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); @@ -42,6 +44,8 @@ async fn main(_spawner: Spawner) { // With pauses between letters and words loop { + defmt::info!("SOS"); + // S: three short blinks for _ in 0..3 { led.set_low(); -- cgit From ffe3e5acae6c0038db4176dc7d031b57f865e07f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 18 Nov 2025 12:16:14 -0800 Subject: Correct gpio driver (#9) * Correct gpio driver Signed-off-by: Felipe Balbi * 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 * Add some documentation to GPIO driver Signed-off-by: Felipe Balbi * Enable GPIO clocks during HAL initialization Provide the user with working GPIO clocks. Signed-off-by: Felipe Balbi --------- Signed-off-by: Felipe Balbi Co-authored-by: Felipe Balbi --- examples/src/bin/adc_interrupt.rs | 6 +-- examples/src/bin/adc_polling.rs | 6 +-- examples/src/bin/blink.rs | 81 ----------------------------------- examples/src/bin/blinky.rs | 49 +++++++++++++++++++++ examples/src/bin/hello.rs | 6 +-- examples/src/bin/lpuart_buffered.rs | 4 +- examples/src/bin/lpuart_polling.rs | 6 +-- examples/src/bin/ostimer_alarm.rs | 6 +-- examples/src/bin/ostimer_async.rs | 6 +-- examples/src/bin/ostimer_counter.rs | 6 +-- examples/src/bin/ostimer_race_test.rs | 6 +-- examples/src/bin/rtc_alarm.rs | 6 +-- examples/src/lib.rs | 6 --- 13 files changed, 78 insertions(+), 116 deletions(-) delete mode 100644 examples/src/bin/blink.rs create mode 100644 examples/src/bin/blinky.rs (limited to 'examples') 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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa as hal; -use embassy_mcxa::bind_interrupts; -use embassy_mcxa_examples::init_led_gpio_clocks; -use embassy_time::{Duration, Timer}; -use hal::gpio::pins::PIO3_18; -use hal::gpio::{Level, Output}; - -// Bind only OS_EVENT for timer interrupts -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let _p = hal::init(hal::config::Config::default()); - - unsafe { - init_led_gpio_clocks(hal::pac()); - } - - defmt::info!("Blink example"); - - // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - - // Configure LED pin for GPIO mode - PIO3_18::set_mux_gpio(); - - let mut led = Output::new(PIO3_18::degrade(), Level::High); - - // Complex blinking pattern: SOS in Morse code - // S: ... (3 short) - // O: --- (3 long) - // S: ... (3 short) - // With pauses between letters and words - - loop { - defmt::info!("SOS"); - - // S: three short blinks - for _ in 0..3 { - led.set_low(); - Timer::after(Duration::from_millis(150)).await; - led.set_high(); - Timer::after(Duration::from_millis(150)).await; - } - - // Pause between letters - Timer::after(Duration::from_millis(300)).await; - - // O: three long blinks - for _ in 0..3 { - led.set_low(); - Timer::after(Duration::from_millis(450)).await; - led.set_high(); - Timer::after(Duration::from_millis(150)).await; - } - - // Pause between letters - Timer::after(Duration::from_millis(300)).await; - - // S: three short blinks - for _ in 0..3 { - led.set_low(); - Timer::after(Duration::from_millis(150)).await; - led.set_high(); - Timer::after(Duration::from_millis(150)).await; - } - - // Long pause between words (SOS repeats) - Timer::after(Duration::from_millis(1000)).await; - } -} 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 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::bind_interrupts; +use embassy_time::Timer; +use hal::gpio::{Level, Output}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +// Bind only OS_EVENT for timer interrupts +bind_interrupts!(struct Irqs { + OS_EVENT => hal::ostimer::time_driver::OsEventHandler; +}); + +#[used] +#[no_mangle] +static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("Blink example"); + + // Initialize embassy-time global driver backed by OSTIMER0 + hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); + + let mut red = Output::new(p.P3_18, Level::High); + let mut green = Output::new(p.P3_19, Level::High); + let mut blue = Output::new(p.P3_21, Level::High); + + loop { + defmt::info!("Toggle LEDs"); + + red.toggle(); + Timer::after_millis(250).await; + + red.toggle(); + green.toggle(); + Timer::after_millis(250).await; + + green.toggle(); + blue.toggle(); + Timer::after_millis(250).await; + blue.toggle(); + + Timer::after_millis(250).await; + } +} 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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { // Create a buffered LPUART2 instance with both TX and RX let mut uart = BufferedLpuart::new( p.LPUART2, - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin Irqs, &mut tx_buf, &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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX let lpuart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { ..Default::default() }; - // Create UART instance using LPUART2 with PIO2_2 as TX and PIO2_3 as RX + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { embassy_mcxa_examples::init_uart2_pins(hal::pac()); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral - p.PIO2_2, // TX pin - p.PIO2_3, // RX pin + p.P2_2, // TX pin + p.P2_3, // RX pin config, ) .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) { pins::configure_uart2_pins_port2(); } -/// Initialize clocks for the LED GPIO/PORT used by the blink example. -pub unsafe fn init_led_gpio_clocks(_p: &hal::pac::Peripherals) { - _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); - _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); -} - /// Initialize clocks and pin muxing for ADC. pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. -- cgit From a8eb124e47e633cd81e0863253d5f6bdd7545260 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 19 Nov 2025 09:11:54 -0800 Subject: OSTimer updates (#24) * Initialize OSTIMER0 during HAL initialization Provide the user with a working time driver. Signed-off-by: Felipe Balbi * Handle time_driver interrupt internally Signed-off-by: Felipe Balbi * Gate `time-driver` impl behind a `time` flag Also prevents creation of an `Ostimer` instance if the `time` feature is active. * Remove some dead code --------- Signed-off-by: Felipe Balbi Co-authored-by: James Munns --- examples/Cargo.lock | 1 + examples/Cargo.toml | 4 +- examples/src/bin/blinky.rs | 13 -- examples/src/bin/ostimer_alarm.rs | 122 ---------- examples/src/bin/ostimer_async.rs | 64 ------ examples/src/bin/ostimer_counter.rs | 139 ------------ examples/src/bin/ostimer_race_test.rs | 405 ---------------------------------- 7 files changed, 3 insertions(+), 745 deletions(-) delete mode 100644 examples/src/bin/ostimer_alarm.rs delete mode 100644 examples/src/bin/ostimer_async.rs delete mode 100644 examples/src/bin/ostimer_counter.rs delete mode 100644 examples/src/bin/ostimer_race_test.rs (limited to 'examples') diff --git a/examples/Cargo.lock b/examples/Cargo.lock index b2ac9a051..14f472cbf 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -446,6 +446,7 @@ source = "git+https://github.com/OpenDevicePartnership/mcxa-pac?rev=3ab4c868f75a dependencies = [ "cortex-m", "cortex-m-rt", + "critical-section", "vcell", ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d03d3d95c..d1c6a2071 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -6,13 +6,13 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } -cortex-m-rt = { version = "0.7", features = ["device"] } +cortex-m-rt = { version = "0.7" } critical-section = "1.2.0" defmt = "1.0" defmt-rtt = "1.0" embassy-embedded-hal = "0.5.0" embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false } -embassy-mcxa = { path = "../", features = ["defmt", "rt", "unstable-pac"] } +embassy-mcxa = { path = "../", features = ["defmt", "rt", "unstable-pac", "time"] } embassy-sync = "0.7.2" embassy-time = "0.5.0" embassy-time-driver = "0.2.1" diff --git a/examples/src/bin/blinky.rs b/examples/src/bin/blinky.rs index 28d83a12e..ab1e59bdb 100644 --- a/examples/src/bin/blinky.rs +++ b/examples/src/bin/blinky.rs @@ -2,29 +2,16 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa::bind_interrupts; use embassy_time::Timer; use hal::gpio::{Level, Output}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -// Bind only OS_EVENT for timer interrupts -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); defmt::info!("Blink example"); - // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - let mut red = Output::new(p.P3_18, Level::High); let mut green = Output::new(p.P3_19, Level::High); let mut blue = Output::new(p.P3_21, Level::High); diff --git a/examples/src/bin/ostimer_alarm.rs b/examples/src/bin/ostimer_alarm.rs deleted file mode 100644 index 6d38741b7..000000000 --- a/examples/src/bin/ostimer_alarm.rs +++ /dev/null @@ -1,122 +0,0 @@ -#![no_std] -#![no_main] - -use core::sync::atomic::{AtomicBool, Ordering}; - -use embassy_executor::Spawner; -use embassy_mcxa::bind_interrupts; -use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; -use embassy_mcxa::clocks::PoweredClock; -use embassy_mcxa::lpuart::{Config, Lpuart}; -use embassy_mcxa_examples::init_uart2_pins; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -// Bind only OS_EVENT, and retain the symbol explicitly so it can't be GC'ed. -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -// Global flag for alarm callback -static ALARM_FLAG: AtomicBool = AtomicBool::new(false); - -// Alarm callback function -fn alarm_callback() { - ALARM_FLAG.store(true, Ordering::Release); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - init_uart2_pins(hal::pac()); - } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - - uart.write_str_blocking("OSTIMER Alarm Example\n"); - - // Initialize embassy-time global driver backed by OSTIMER0 - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - - // Create OSTIMER instance - let config = hal::ostimer::Config { - init_match_max: true, - power: PoweredClock::NormalEnabledDeepSleepDisabled, - source: OstimerClockSel::Clk1M, - }; - let ostimer = hal::ostimer::Ostimer::::new(p.OSTIMER0, config); - - // Create alarm with callback - let alarm = hal::ostimer::Alarm::new() - .with_callback(alarm_callback) - .with_flag(&ALARM_FLAG); - - uart.write_str_blocking("Scheduling alarm for 2 seconds...\n"); - - // Schedule alarm to expire in 2 seconds (2,000,000 microseconds) - let scheduled = ostimer.schedule_alarm_delay(&alarm, 2_000_000); - if scheduled { - uart.write_str_blocking("Alarm scheduled successfully\n"); - } else { - uart.write_str_blocking("Failed to schedule alarm (would exceed timer capacity)\n"); - return; - } - - // Wait for alarm to expire - loop { - // Check if alarm has expired - if ALARM_FLAG.load(Ordering::Acquire) { - uart.write_str_blocking("Alarm expired! Callback executed.\n"); - break; - } - - // Busy wait - don't use Timer::after_millis as it interferes with alarm MATCH - for _ in 0..100000 { - cortex_m::asm::nop(); - } - } - - // Demonstrate canceling an alarm - uart.write_str_blocking("Scheduling another alarm for 3 seconds...\n"); - ALARM_FLAG.store(false, Ordering::Release); // Reset flag - - let scheduled = ostimer.schedule_alarm_delay(&alarm, 3_000_000); - if scheduled { - uart.write_str_blocking("Alarm scheduled. Waiting 1 second then canceling...\n"); - - // Wait 1 second - embassy_time::Timer::after_millis(1000).await; - - // Cancel the alarm - ostimer.cancel_alarm(&alarm); - uart.write_str_blocking("Alarm canceled\n"); - - // Check immediately if alarm flag is set - if !ALARM_FLAG.load(Ordering::Acquire) { - uart.write_str_blocking("Alarm was successfully canceled\n"); - } else { - uart.write_str_blocking("Alarm fired despite cancellation\n"); - } - } - - uart.write_str_blocking("Example complete\n"); -} diff --git a/examples/src/bin/ostimer_async.rs b/examples/src/bin/ostimer_async.rs deleted file mode 100644 index f043184e7..000000000 --- a/examples/src/bin/ostimer_async.rs +++ /dev/null @@ -1,64 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::bind_interrupts; -use embassy_mcxa_examples::init_uart2_pins; -use embassy_time::{Duration, Timer}; -use hal::lpuart::{Config, Lpuart}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -// Bind only OS_EVENT, and retain the symbol explicitly so it can’t be GC’ed. -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - init_uart2_pins(hal::pac()); - } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - uart.blocking_write(b"boot\n").unwrap(); - - // Avoid mass NVIC writes here; DefaultHandler now safely returns. - - // Initialize embassy-time global driver backed by OSTIMER0 (re-enables OS_EVENT with priority) - // The bind_interrupts! macro handles handler binding automatically - - // Initialize OSTIMER with default 1MHz frequency - // Adjust this value to match your actual OSTIMER clock frequency - hal::ostimer::time_driver::init(hal::config::Config::default().time_interrupt_priority, 1_000_000); - - // Removed force-pend; rely on real hardware match to trigger OS_EVENT. - - // Log using defmt if enabled - defmt::info!("OSTIMER async example starting..."); - - loop { - defmt::info!("tick"); - uart.write_str_blocking("tick\n"); - Timer::after(Duration::from_millis(1000)).await; - } -} diff --git a/examples/src/bin/ostimer_counter.rs b/examples/src/bin/ostimer_counter.rs deleted file mode 100644 index f36915ff2..000000000 --- a/examples/src/bin/ostimer_counter.rs +++ /dev/null @@ -1,139 +0,0 @@ -//! # OSTIMER Counter Reading and Reset Example -//! -//! This example demonstrates the new timer counter reading and reset functionality -//! of the OSTIMER driver. - -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; -use embassy_mcxa::clocks::PoweredClock; -use embassy_mcxa::lpuart::{Blocking, Config, Lpuart}; -use embassy_time::{Duration, Timer}; -use hal::bind_interrupts; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(Default::default()); - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - embassy_mcxa_examples::init_uart2_pins(hal::pac()); - } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - - uart.write_str_blocking("OSTIMER Counter Reading and Reset Example\n"); - - // Initialize the OSTIMER time driver - hal::ostimer::time_driver::init( - hal::interrupt::Priority::from(3), - 1_000_000, // 1MHz clock - ); - - // Create OSTIMER instance - let ostimer = hal::ostimer::Ostimer::::new( - p.OSTIMER0, - hal::ostimer::Config { - init_match_max: true, - power: PoweredClock::NormalEnabledDeepSleepDisabled, - source: OstimerClockSel::Clk1M, - }, - ); - - // Read initial counter value - let initial_counter = ostimer.now(); - uart.write_str_blocking("Initial counter value: "); - write_u64(&mut uart, initial_counter); - uart.write_str_blocking("\n"); - - // Wait a bit to let counter increment - Timer::after(Duration::from_millis(100)).await; - - // Read counter again - let counter_after_wait = ostimer.now(); - uart.write_str_blocking("Counter after 100ms wait: "); - write_u64(&mut uart, counter_after_wait); - uart.write_str_blocking("\n"); - uart.write_str_blocking("Difference: "); - write_u64(&mut uart, counter_after_wait - initial_counter); - uart.write_str_blocking(" ticks\n"); - - // Reset the timer - uart.write_str_blocking("Resetting timer...\n"); - ostimer.reset(hal::pac()); - - // Read counter after reset - let counter_after_reset = ostimer.now(); - uart.write_str_blocking("Counter after reset: "); - write_u64(&mut uart, counter_after_reset); - uart.write_str_blocking("\n"); - - // Wait again to verify timer is working - Timer::after(Duration::from_millis(50)).await; - - let final_counter = ostimer.now(); - uart.write_str_blocking("Counter after another 50ms: "); - write_u64(&mut uart, final_counter); - uart.write_str_blocking("\n"); - uart.write_str_blocking("Difference after reset: "); - write_u64(&mut uart, final_counter - counter_after_reset); - uart.write_str_blocking(" ticks\n"); - - uart.write_str_blocking("Example complete\n"); -} - -// Helper function to write a u64 value as decimal string -fn write_u64(uart: &mut Lpuart<'_, Blocking>, value: u64) { - if value == 0 { - uart.write_str_blocking("0"); - return; - } - - let mut buffer = [0u8; 20]; // Enough for max u64 - let mut i = 0; - let mut v = value; - - while v > 0 { - buffer[i] = b'0' + (v % 10) as u8; - v /= 10; - i += 1; - } - - // Write digits in reverse order - while i > 0 { - i -= 1; - match buffer[i] { - b'0' => uart.write_str_blocking("0"), - b'1' => uart.write_str_blocking("1"), - b'2' => uart.write_str_blocking("2"), - b'3' => uart.write_str_blocking("3"), - b'4' => uart.write_str_blocking("4"), - b'5' => uart.write_str_blocking("5"), - b'6' => uart.write_str_blocking("6"), - b'7' => uart.write_str_blocking("7"), - b'8' => uart.write_str_blocking("8"), - b'9' => uart.write_str_blocking("9"), - _ => uart.write_str_blocking("?"), - } - } -} diff --git a/examples/src/bin/ostimer_race_test.rs b/examples/src/bin/ostimer_race_test.rs deleted file mode 100644 index 0106b92a7..000000000 --- a/examples/src/bin/ostimer_race_test.rs +++ /dev/null @@ -1,405 +0,0 @@ -//! # OSTIMER Race Condition Test -//! -//! This example tests for race conditions in the OSTIMER driver by: -//! - Scheduling alarms sequentially (hardware limitation: only one at a time) -//! - Reading the counter during interrupt-heavy periods -//! - Testing concurrent timer operations -//! - Stress testing interrupt handling - -#![no_std] -#![no_main] - -use core::sync::atomic::{AtomicU32, Ordering}; - -use embassy_executor::Spawner; -use embassy_mcxa::clocks::periph_helpers::OstimerClockSel; -use embassy_mcxa::clocks::PoweredClock; -use embassy_mcxa::lpuart::{Blocking, Config, Lpuart}; -use embassy_time::{Duration, Timer}; -use hal::bind_interrupts; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -bind_interrupts!(struct Irqs { - OS_EVENT => hal::ostimer::time_driver::OsEventHandler; -}); - -#[used] -#[no_mangle] -static KEEP_OS_EVENT: unsafe extern "C" fn() = OS_EVENT; - -// Global counters for race condition detection -static ALARM_CALLBACK_COUNT: AtomicU32 = AtomicU32::new(0); -static INTERRUPT_COUNT: AtomicU32 = AtomicU32::new(0); -static RACE_DETECTED: AtomicU32 = AtomicU32::new(0); - -// Alarm callback function -fn alarm_callback() { - let _count = ALARM_CALLBACK_COUNT.fetch_add(1, Ordering::SeqCst); - INTERRUPT_COUNT.fetch_add(1, Ordering::SeqCst); - - // Simulate some work in the callback to increase chance of races - for _ in 0..10 { - cortex_m::asm::nop(); - } -} - -fn report_default_handler(uart: &mut Lpuart<'_, Blocking>) { - let snapshot = hal::interrupt::default_handler_snapshot(); - if snapshot.count == 0 { - return; - } - - uart.write_str_blocking("WARNING: DefaultHandler executed "); - write_u32(uart, snapshot.count); - uart.write_str_blocking(" time(s). Vector="); - write_u32(uart, snapshot.vector as u32); - uart.write_str_blocking(" CFSR=0x"); - write_hex32(uart, snapshot.cfsr); - uart.write_str_blocking(" HFSR=0x"); - write_hex32(uart, snapshot.hfsr); - uart.write_str_blocking(" PC=0x"); - write_hex32(uart, snapshot.stacked_pc); - uart.write_str_blocking(" LR=0x"); - write_hex32(uart, snapshot.stacked_lr); - uart.write_str_blocking(" SP=0x"); - write_hex32(uart, snapshot.stacked_sp); - uart.write_str_blocking("\n"); - - hal::interrupt::clear_default_handler_snapshot(); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(Default::default()); - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - embassy_mcxa_examples::init_uart2_pins(hal::pac()); - } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - - uart.write_str_blocking("OSTIMER Race Condition Test Starting...\n"); - - // The bind_interrupts! macro handles handler binding automatically - - // Initialize the OSTIMER time driver FIRST - hal::ostimer::time_driver::init( - hal::interrupt::Priority::from(3), - 1_000_000, // 1MHz clock - ); - - uart.write_str_blocking("Time driver initialized\n"); - - // Create OSTIMER instance - let ostimer = hal::ostimer::Ostimer::::new( - p.OSTIMER0, - hal::ostimer::Config { - init_match_max: true, - power: PoweredClock::NormalEnabledDeepSleepDisabled, - source: OstimerClockSel::Clk1M, - }, - ); - - uart.write_str_blocking("OSTIMER instance created\n"); - - // Test 1: Sequential alarm scheduling (OSTIMER only supports one alarm at a time) - uart.write_str_blocking("Test 1: Sequential alarm scheduling...\n"); - test_rapid_alarms(&ostimer, &mut uart).await; - report_default_handler(&mut uart); - - // Test 2: Counter reading during interrupts - uart.write_str_blocking("Test 2: Counter reading during interrupts...\n"); - test_counter_reading_during_interrupts(&ostimer, &mut uart).await; - report_default_handler(&mut uart); - - // Test 3: Concurrent timer operations - uart.write_str_blocking("Test 3: Concurrent timer operations...\n"); - test_concurrent_operations(&ostimer, &mut uart).await; - report_default_handler(&mut uart); - - // Test 4: Timer reset during operation - uart.write_str_blocking("Test 4: Timer reset during operation...\n"); - test_reset_during_operation(&ostimer, &mut uart, hal::pac()).await; - report_default_handler(&mut uart); - - // Report results - uart.write_str_blocking("Race condition test complete\n"); - uart.write_str_blocking("Callback count: "); - write_u32(&mut uart, ALARM_CALLBACK_COUNT.load(Ordering::SeqCst)); - uart.write_str_blocking("\nInterrupt count: "); - write_u32(&mut uart, INTERRUPT_COUNT.load(Ordering::SeqCst)); - uart.write_str_blocking("\nRaces detected: "); - write_u32(&mut uart, RACE_DETECTED.load(Ordering::SeqCst)); - uart.write_str_blocking("\n"); -} - -// Test rapid alarm scheduling to stress interrupt handling -async fn test_rapid_alarms( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut Lpuart<'_, Blocking>, -) { - let initial_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); - - // Schedule 10 alarms sequentially (OSTIMER only supports one alarm at a time) - for _i in 0..10 { - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - let delay_us = 1000; // 1ms delay for each alarm - if ostimer.schedule_alarm_delay(&alarm, delay_us) { - // Wait for this alarm to complete before scheduling the next - Timer::after(Duration::from_micros(delay_us + 100)).await; - report_default_handler(uart); - } else { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm (match not ready)\n"); - } - } - - // All alarms should have completed by now - let final_count = ALARM_CALLBACK_COUNT.load(Ordering::SeqCst); - let expected_count = initial_count + 10; - - if final_count != expected_count { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Expected "); - write_u32(uart, expected_count); - uart.write_str_blocking(" callbacks, got "); - write_u32(uart, final_count); - uart.write_str_blocking("\n"); - } else { - uart.write_str_blocking("PASS: All rapid alarms executed\n"); - } -} - -// Test reading counter while interrupts are firing -async fn test_counter_reading_during_interrupts( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut Lpuart<'_, Blocking>, -) { - let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - // Schedule an alarm that will fire soon - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - if !ostimer.schedule_alarm_delay(&alarm, 500) { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before counter stress\n"); - } - - // While alarm is pending, read the counter many times rapidly - // This tests if counter reading is atomic and doesn't get corrupted by interrupts - let mut last_counter = ostimer.now(); - let mut consistent_reads = 0; - let mut total_reads = 0; - - for _ in 0..1000 { - let current_counter = ostimer.now(); - total_reads += 1; - - // Check if counter is monotonically increasing (basic sanity check) - if current_counter >= last_counter { - consistent_reads += 1; - } - last_counter = current_counter; - - // Small delay between reads - for _ in 0..10 { - cortex_m::asm::nop(); - } - - report_default_handler(uart); - } - - // Wait for alarm to complete - Timer::after(Duration::from_millis(1)).await; - - let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - if consistent_reads == total_reads { - uart.write_str_blocking("PASS: Counter reading consistent during interrupts\n"); - } else { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Counter reading inconsistent: "); - write_u32(uart, consistent_reads); - uart.write_str_blocking("/"); - write_u32(uart, total_reads); - uart.write_str_blocking(" consistent\n"); - } - - if final_interrupt_count > initial_interrupt_count { - uart.write_str_blocking("PASS: Interrupt fired during counter reading test\n"); - } else { - uart.write_str_blocking("WARNING: No interrupt fired during counter reading test\n"); - } -} - -// Test concurrent timer operations (embassy-time + alarms) -async fn test_concurrent_operations( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut Lpuart<'_, Blocking>, -) { - let initial_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - // Start an embassy-time timer - let timer_future = Timer::after(Duration::from_millis(2)); - - // Schedule an alarm that should fire before the timer - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - if !ostimer.schedule_alarm_delay(&alarm, 1000) { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before concurrent operations\n"); - } - - // Wait for both to complete - timer_future.await; - - let final_interrupt_count = INTERRUPT_COUNT.load(Ordering::SeqCst); - - if final_interrupt_count > initial_interrupt_count { - uart.write_str_blocking("PASS: Concurrent operations completed\n"); - } else { - uart.write_str_blocking("WARNING: No interrupts during concurrent operations\n"); - } -} - -// Test timer reset during active operations -async fn test_reset_during_operation( - ostimer: &hal::ostimer::Ostimer<'_, hal::ostimer::Ostimer0>, - uart: &mut Lpuart<'_, Blocking>, - peripherals: &hal::pac::Peripherals, -) { - let initial_counter = ostimer.now(); - - // Schedule an alarm - let alarm = hal::ostimer::Alarm::new().with_callback(alarm_callback); - if !ostimer.schedule_alarm_delay(&alarm, 2000) { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Failed to program OSTIMER alarm before reset test\n"); - } - - // Wait a bit then reset the timer - Timer::after(Duration::from_millis(1)).await; - ostimer.reset(peripherals); - - // Check counter after reset - let counter_after_reset = ostimer.now(); - - // Wait to see if the alarm still fires (it shouldn't after reset) - Timer::after(Duration::from_millis(2)).await; - - let final_counter = ostimer.now(); - - if counter_after_reset < initial_counter { - uart.write_str_blocking("PASS: Timer reset successful\n"); - } else { - RACE_DETECTED.fetch_add(1, Ordering::SeqCst); - uart.write_str_blocking("ERROR: Timer reset may have failed\n"); - } - - uart.write_str_blocking("Counter progression after reset: "); - write_u64(uart, initial_counter); - uart.write_str_blocking(" -> "); - write_u64(uart, counter_after_reset); - uart.write_str_blocking(" -> "); - write_u64(uart, final_counter); - uart.write_str_blocking("\n"); -} - -// Helper function to write a u32 value as decimal string -fn write_u32(uart: &mut Lpuart<'_, Blocking>, value: u32) { - if value == 0 { - uart.write_str_blocking("0"); - return; - } - - let mut buffer = [0u8; 10]; // Enough for max u32 - let mut i = 0; - let mut v = value; - - while v > 0 { - buffer[i] = b'0' + (v % 10) as u8; - v /= 10; - i += 1; - } - - // Write digits in reverse order - while i > 0 { - i -= 1; - match buffer[i] { - b'0' => uart.write_str_blocking("0"), - b'1' => uart.write_str_blocking("1"), - b'2' => uart.write_str_blocking("2"), - b'3' => uart.write_str_blocking("3"), - b'4' => uart.write_str_blocking("4"), - b'5' => uart.write_str_blocking("5"), - b'6' => uart.write_str_blocking("6"), - b'7' => uart.write_str_blocking("7"), - b'8' => uart.write_str_blocking("8"), - b'9' => uart.write_str_blocking("9"), - _ => uart.write_str_blocking("?"), - } - } -} - -fn write_hex32(uart: &mut Lpuart<'_, Blocking>, value: u32) { - let mut buf = [b'0'; 8]; - let mut tmp = value; - for i in (0..8).rev() { - let digit = (tmp & 0xF) as u8; - buf[i] = match digit { - 0..=9 => b'0' + digit, - 10..=15 => b'A' + (digit - 10), - _ => b'?', - }; - tmp >>= 4; - } - uart.blocking_write(&buf).unwrap(); -} - -// Helper function to write a u64 value as decimal string -fn write_u64(uart: &mut Lpuart<'_, Blocking>, value: u64) { - if value == 0 { - uart.blocking_write(b"0").unwrap(); - return; - } - - let mut buffer = [0u8; 20]; // Enough for max u64 - let mut i = 0; - let mut v = value; - - while v > 0 { - buffer[i] = b'0' + (v % 10) as u8; - v /= 10; - i += 1; - } - - // Write digits in reverse order - while i > 0 { - i -= 1; - match buffer[i] { - b'0' => uart.blocking_write(b"0").unwrap(), - b'1' => uart.blocking_write(b"1").unwrap(), - b'2' => uart.blocking_write(b"2").unwrap(), - b'3' => uart.blocking_write(b"3").unwrap(), - b'4' => uart.blocking_write(b"4").unwrap(), - b'5' => uart.blocking_write(b"5").unwrap(), - b'6' => uart.blocking_write(b"6").unwrap(), - b'7' => uart.blocking_write(b"7").unwrap(), - b'8' => uart.blocking_write(b"8").unwrap(), - b'9' => uart.blocking_write(b"9").unwrap(), - _ => uart.blocking_write(b"?").unwrap(), - } - } -} -- cgit From eed314ebb58772476971af49b36b68301eb0d8cc Mon Sep 17 00:00:00 2001 From: MathisDerooNXP <52401665+MathisDeroo@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:00:01 -0800 Subject: Gpio support v2 (#26) * Improve GPIO driver and add button example - port and pcr registers are defined using paste! - added pin configuration for slew rate, drive strength, mux function, etc... - added button example to showcase input gpio feature Signed-off-by: Mathis Deroo * Add pull-up pull-down config support for input gpio Signed-off-by: Mathis Deroo * Replace GPIOs enum with existing ones in the PAC Signed-off-by: Mathis Deroo * Remove init_gpio_pin function as it is done in hal init config Signed-off-by: Mathis Deroo * Integrate feedback for the GPIO driver - Add again missing IO peripherals - Added function to configure separately slew rate, drive strength, pull. - Revert comment changes Signed-off-by: Mathis Deroo * Create user-readable field for the pin configuration Signed-off-by: Mathis Deroo * examples: button: remove left-over OSTIMER initialization While at that, also cargo fmt * Fix warnings * Add documentation for public functions Signed-off-by: Mathis Deroo * Expose port and pcr registers to AnyPin implementation Signed-off-by: Mathis Deroo * Remove unnecessary change Signed-off-by: Mathis Deroo * Run cargo fmt --------- Signed-off-by: Mathis Deroo Co-authored-by: Felipe Balbi --- examples/src/bin/blinky.rs | 8 ++++---- examples/src/bin/button.rs | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 examples/src/bin/button.rs (limited to 'examples') diff --git a/examples/src/bin/blinky.rs b/examples/src/bin/blinky.rs index ab1e59bdb..dd08ec0d9 100644 --- a/examples/src/bin/blinky.rs +++ b/examples/src/bin/blinky.rs @@ -3,7 +3,7 @@ use embassy_executor::Spawner; use embassy_time::Timer; -use hal::gpio::{Level, Output}; +use hal::gpio::{DriveStrength, Level, Output, SlewRate}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; #[embassy_executor::main] @@ -12,9 +12,9 @@ async fn main(_spawner: Spawner) { defmt::info!("Blink example"); - let mut red = Output::new(p.P3_18, Level::High); - let mut green = Output::new(p.P3_19, Level::High); - let mut blue = Output::new(p.P3_21, Level::High); + let mut red = Output::new(p.P3_18, Level::High, DriveStrength::Normal, SlewRate::Fast); + let mut green = Output::new(p.P3_19, Level::High, DriveStrength::Normal, SlewRate::Fast); + let mut blue = Output::new(p.P3_21, Level::High, DriveStrength::Normal, SlewRate::Fast); loop { defmt::info!("Toggle LEDs"); diff --git a/examples/src/bin/button.rs b/examples/src/bin/button.rs new file mode 100644 index 000000000..2abfe0a9f --- /dev/null +++ b/examples/src/bin/button.rs @@ -0,0 +1,21 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::gpio::{DriveStrength, Input, Pull, SlewRate}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("Button example"); + + let monitor = Input::new(p.P1_7, Pull::Disabled, DriveStrength::Normal, SlewRate::Slow); + + loop { + defmt::info!("Pin level is {:?}", monitor.get_level()); + Timer::after_millis(1000).await; + } +} -- cgit From afbf72fb7842c926a9ac9b62f794ed010d4f7b27 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 21 Nov 2025 11:42:11 -0800 Subject: Update to latest PAC (#39) It adds a complete Mux enum Co-authored-by: Felipe Balbi --- examples/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 14f472cbf..473ce2b3f 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -442,7 +442,7 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "mcxa-pac" version = "0.1.0" -source = "git+https://github.com/OpenDevicePartnership/mcxa-pac?rev=3ab4c868f75a9240bb8fdce24982d34f2273aabf#3ab4c868f75a9240bb8fdce24982d34f2273aabf" +source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#3b36508ab1ac397861bae3431cc95c204f3ca6e9" dependencies = [ "cortex-m", "cortex-m-rt", -- cgit From c552cf2434b847b7a8af06e15982eb29d07ad2fa Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 24 Nov 2025 17:37:57 +0100 Subject: Introduce clkout peripheral (#36) Introduces a ClockOut peripheral, allowing for ensuring that internal clocks are operating correctly. Also fixes some incorrect PLL/Div4 usage. --- examples/Cargo.toml | 2 +- examples/src/bin/clkout.rs | 69 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 examples/src/bin/clkout.rs (limited to 'examples') diff --git a/examples/Cargo.toml b/examples/Cargo.toml index d1c6a2071..4f15a6aff 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -6,7 +6,7 @@ license = "MIT OR Apache-2.0" [dependencies] cortex-m = { version = "0.7", features = ["critical-section-single-core"] } -cortex-m-rt = { version = "0.7" } +cortex-m-rt = { version = "0.7", features = ["set-sp", "set-vtor"] } critical-section = "1.2.0" defmt = "1.0" defmt-rtt = "1.0" diff --git a/examples/src/bin/clkout.rs b/examples/src/bin/clkout.rs new file mode 100644 index 000000000..bfd963540 --- /dev/null +++ b/examples/src/bin/clkout.rs @@ -0,0 +1,69 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; +use embassy_mcxa::clocks::PoweredClock; +use embassy_mcxa::gpio::{DriveStrength, SlewRate}; +use embassy_mcxa::{Level, Output}; +use embassy_time::Timer; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +/// Demonstrate CLKOUT, using Pin P4.2 +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + let mut pin = p.P4_2; + let mut clkout = p.CLKOUT; + + loop { + defmt::info!("Set Low..."); + let mut output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); + Timer::after_millis(500).await; + + defmt::info!("Set High..."); + output.set_high(); + Timer::after_millis(400).await; + + defmt::info!("Set Low..."); + output.set_low(); + Timer::after_millis(500).await; + + defmt::info!("16k..."); + // Run Clock Out with the 16K clock + let _clock_out = ClockOut::new( + clkout.reborrow(), + pin.reborrow(), + Config { + sel: ClockOutSel::Clk16K, + div: Div4::no_div(), + level: PoweredClock::NormalEnabledDeepSleepDisabled, + }, + ) + .unwrap(); + + Timer::after_millis(3000).await; + + defmt::info!("Set Low..."); + drop(_clock_out); + + let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); + Timer::after_millis(500).await; + + // Run Clock Out with the 12M clock, divided by 3 + defmt::info!("4M..."); + let _clock_out = ClockOut::new( + clkout.reborrow(), + pin.reborrow(), + Config { + sel: ClockOutSel::Fro12M, + div: const { Div4::from_divisor(3).unwrap() }, + level: PoweredClock::NormalEnabledDeepSleepDisabled, + }, + ) + .unwrap(); + + // Let it run for 3 seconds... + Timer::after_millis(3000).await; + } +} -- cgit From 6e1bc1139b7dcc8407fd1213bf0cb0788d26288e Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 24 Nov 2025 17:50:46 +0100 Subject: Update to patched PAC with corrected Div4 (#41) --- examples/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 473ce2b3f..56ae41d48 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -442,7 +442,7 @@ checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" [[package]] name = "mcxa-pac" version = "0.1.0" -source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#3b36508ab1ac397861bae3431cc95c204f3ca6e9" +source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#9a857ec9780527679978b42cc60288aeef03baa2" dependencies = [ "cortex-m", "cortex-m-rt", -- cgit From 7ee5cb570f0c0daeb2e6a9d5120fd96ee885025f Mon Sep 17 00:00:00 2001 From: James Munns Date: Mon, 24 Nov 2025 18:41:43 +0100 Subject: Remove the pac singleton function (#42) There will be a follow up PR that removes the unsafe `init` functions, but I wanted to squash this out first in case I don't get to it all today. --- examples/src/bin/adc_interrupt.rs | 4 ++-- examples/src/bin/adc_polling.rs | 11 ++--------- examples/src/bin/hello.rs | 2 +- examples/src/bin/lpuart_buffered.rs | 2 +- examples/src/bin/lpuart_polling.rs | 2 +- examples/src/bin/rtc_alarm.rs | 2 +- examples/src/lib.rs | 4 ++-- 7 files changed, 10 insertions(+), 17 deletions(-) (limited to 'examples') diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs index 9fed052fd..0d3a75a28 100644 --- a/examples/src/bin/adc_interrupt.rs +++ b/examples/src/bin/adc_interrupt.rs @@ -36,7 +36,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2_pins(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral @@ -48,7 +48,7 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); unsafe { - init_adc_pins(hal::pac()); + init_adc_pins(); } let adc_config = LpadcConfig { diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs index 545f8f77a..02ac321b5 100644 --- a/examples/src/bin/adc_polling.rs +++ b/examples/src/bin/adc_polling.rs @@ -22,10 +22,6 @@ const G_LPADC_RESULT_SHIFT: u32 = 0; async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); - unsafe { - init_uart2_pins(hal::pac()); - } - // Create UART configuration let config = Config { baudrate_bps: 115_200, @@ -36,7 +32,8 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { - init_uart2_pins(hal::pac()); + init_uart2_pins(); + init_adc_pins(); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral @@ -48,10 +45,6 @@ async fn main(_spawner: Spawner) { uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); - unsafe { - init_adc_pins(hal::pac()); - } - let adc_config = LpadcConfig { enable_in_doze_mode: true, conversion_average_mode: CalAvgs::Average128, diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs index e2d0b413d..0362480c1 100644 --- a/examples/src/bin/hello.rs +++ b/examples/src/bin/hello.rs @@ -28,7 +28,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2_pins(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs index b0d19ef16..4c9294f57 100644 --- a/examples/src/bin/lpuart_buffered.rs +++ b/examples/src/bin/lpuart_buffered.rs @@ -32,7 +32,7 @@ async fn main(_spawner: Spawner) { hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); unsafe { - init_uart2_pins(hal::pac()); + init_uart2_pins(); } // UART configuration (enable both TX and RX) diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs index 525d42e2c..c8666e64a 100644 --- a/examples/src/bin/lpuart_polling.rs +++ b/examples/src/bin/lpuart_polling.rs @@ -15,7 +15,7 @@ async fn main(_spawner: Spawner) { // Board-level init for UART2 clocks and pins. unsafe { - init_uart2_pins(hal::pac()); + init_uart2_pins(); } // Create UART configuration diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs index a54b4a817..6f8a77101 100644 --- a/examples/src/bin/rtc_alarm.rs +++ b/examples/src/bin/rtc_alarm.rs @@ -34,7 +34,7 @@ async fn main(_spawner: Spawner) { // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { - embassy_mcxa_examples::init_uart2_pins(hal::pac()); + embassy_mcxa_examples::init_uart2_pins(); } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral diff --git a/examples/src/lib.rs b/examples/src/lib.rs index 66b93450a..f5f6124c0 100644 --- a/examples/src/lib.rs +++ b/examples/src/lib.rs @@ -9,7 +9,7 @@ use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; /// Initialize clocks and pin muxing for UART2 debug console. /// Safe to call multiple times; writes are idempotent for our use. -pub unsafe fn init_uart2_pins(_p: &hal::pac::Peripherals) { +pub unsafe fn init_uart2_pins() { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. // GPIO has not. _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); @@ -17,7 +17,7 @@ pub unsafe fn init_uart2_pins(_p: &hal::pac::Peripherals) { } /// Initialize clocks and pin muxing for ADC. -pub unsafe fn init_adc_pins(_p: &hal::pac::Peripherals) { +pub unsafe fn init_adc_pins() { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. // GPIO has not. _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); -- cgit From 05bf2d0438fe8c41d0fe26b85106ff73a6e273e9 Mon Sep 17 00:00:00 2001 From: James Munns Date: Tue, 25 Nov 2025 18:08:13 +0100 Subject: Wire up Lpuart pins (#43) Allow the HAL lpuart driver to correctly configure pins as requested on init. --- examples/Cargo.lock | 2 +- examples/src/bin/adc_interrupt.rs | 26 +++----------------------- examples/src/bin/adc_polling.rs | 31 ++++--------------------------- examples/src/bin/hello.rs | 3 --- examples/src/bin/lpuart_buffered.rs | 29 +++++++++-------------------- examples/src/bin/lpuart_polling.rs | 12 +++++------- examples/src/bin/rtc_alarm.rs | 33 ++++++--------------------------- examples/src/lib.rs | 9 --------- 8 files changed, 28 insertions(+), 117 deletions(-) (limited to 'examples') 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" [[package]] name = "mcxa-pac" version = "0.1.0" -source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#9a857ec9780527679978b42cc60288aeef03baa2" +source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca" dependencies = [ "cortex-m", "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; use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; use hal::clocks::periph_helpers::{AdcClockSel, Div4}; use hal::clocks::PoweredClock; -use hal::lpuart::{Config, Lpuart}; use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; use hal::pac::adc1::ctrl::CalAvgs; @@ -26,26 +25,7 @@ static KEEP_ADC: unsafe extern "C" fn() = ADC1; async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - embassy_mcxa_examples::init_uart2_pins(); - } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - uart.write_str_blocking("\r\n=== ADC interrupt Example ===\r\n"); + defmt::info!("ADC interrupt Example"); unsafe { init_adc_pins(); @@ -81,7 +61,7 @@ async fn main(_spawner: Spawner) { conv_trigger_config.enable_hardware_trigger = false; adc.set_conv_trigger_config(0, &conv_trigger_config); - uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + defmt::info!("ADC configuration done..."); adc.enable_interrupt(0x1); @@ -98,7 +78,7 @@ async fn main(_spawner: Spawner) { while !adc.is_interrupt_triggered() { // Wait until the interrupt is triggered } - uart.write_str_blocking("\r\n*** ADC interrupt TRIGGERED! ***\r\n"); + defmt::info!("*** ADC interrupt TRIGGERED! ***"); //TBD need to print the value } } 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 @@ #![no_std] #![no_main] -use core::fmt::Write; - use embassy_executor::Spawner; -use embassy_mcxa_examples::{init_adc_pins, init_uart2_pins}; +use embassy_mcxa_examples::init_adc_pins; use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; use hal::clocks::periph_helpers::{AdcClockSel, Div4}; use hal::clocks::PoweredClock; -use hal::lpuart::{Config, Lpuart}; use hal::pac::adc1::cfg::{Pwrsel, Refsel}; use hal::pac::adc1::cmdl1::{Adch, Mode}; use hal::pac::adc1::ctrl::CalAvgs; use hal::pac::adc1::tctrl::Tcmd; -use heapless::String; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; const G_LPADC_RESULT_SHIFT: u32 = 0; @@ -22,28 +18,11 @@ const G_LPADC_RESULT_SHIFT: u32 = 0; async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX unsafe { - init_uart2_pins(); init_adc_pins(); } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - uart.write_str_blocking("\r\n=== ADC polling Example ===\r\n"); + defmt::info!("=== ADC polling Example ==="); let adc_config = LpadcConfig { enable_in_doze_mode: true, @@ -75,7 +54,7 @@ async fn main(_spawner: Spawner) { conv_trigger_config.enable_hardware_trigger = false; adc.set_conv_trigger_config(0, &conv_trigger_config); - uart.write_str_blocking("\r\n=== ADC configuration done... ===\r\n"); + defmt::info!("=== ADC configuration done... ==="); loop { adc.do_software_trigger(1); @@ -84,8 +63,6 @@ async fn main(_spawner: Spawner) { result = hal::adc::get_conv_result(); } let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; - let mut buf: String<16> = String::new(); // adjust size as needed - write!(buf, "\r\nvalue: {}\r\n", value).unwrap(); - uart.write_str_blocking(&buf); + defmt::info!("value: {=u16}", value); } } 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) { }; // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - embassy_mcxa_examples::init_uart2_pins(); - } let mut uart = Lpuart::new_blocking( p.LPUART2, // Peripheral 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 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa as hal; -use embassy_mcxa::interrupt::typelevel::Handler; +use embassy_mcxa::clocks::config::Div8; use embassy_mcxa::lpuart::buffered::BufferedLpuart; use embassy_mcxa::lpuart::Config; use embassy_mcxa::{bind_interrupts, lpuart}; -use embassy_mcxa_examples::init_uart2_pins; -use embedded_io_async::{Read, Write}; +use embedded_io_async::Write; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; // Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver bind_interrupts!(struct Irqs { LPUART2 => lpuart::buffered::BufferedInterruptHandler::; }); -// Wrapper function for the interrupt handler -unsafe extern "C" fn lpuart2_handler() { - lpuart::buffered::BufferedInterruptHandler::::on_interrupt(); -} - #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - unsafe { - hal::interrupt::install_irq_handler(hal::pac::Interrupt::LPUART2, lpuart2_handler); - } + let mut cfg = hal::config::Config::default(); + cfg.clock_cfg.sirc.fro_12m_enabled = true; + cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); + let p = hal::init(cfg); // Configure NVIC for LPUART2 hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); - unsafe { - init_uart2_pins(); - } - // UART configuration (enable both TX and RX) let config = Config { baudrate_bps: 115_200, @@ -69,7 +58,7 @@ async fn main(_spawner: Spawner) { // Echo loop let mut buf = [0u8; 4]; loop { - rx.read_exact(&mut buf[..]).await.unwrap(); - tx.write_all(&buf[..]).await.unwrap(); + let used = rx.read(&mut buf).await.unwrap(); + tx.write_all(&buf[..used]).await.unwrap(); } } 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 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa_examples::init_uart2_pins; +use embassy_mcxa::clocks::config::Div8; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; use crate::hal::lpuart::{Config, Lpuart}; #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); + let mut cfg = hal::config::Config::default(); + cfg.clock_cfg.sirc.fro_12m_enabled = true; + cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); + let p = hal::init(cfg); defmt::info!("boot"); - // Board-level init for UART2 clocks and pins. - unsafe { - init_uart2_pins(); - } - // Create UART configuration let config = Config { 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 @@ use embassy_executor::Spawner; use embassy_mcxa as hal; -use hal::lpuart::{Config, Lpuart}; use hal::rtc::{RtcDateTime, RtcInterruptEnable}; use hal::InterruptExt; @@ -24,27 +23,7 @@ static KEEP_RTC: unsafe extern "C" fn() = RTC; async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - unsafe { - embassy_mcxa_examples::init_uart2_pins(); - } - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - - uart.write_str_blocking("\r\n=== RTC Alarm Example ===\r\n"); + defmt::info!("=== RTC Alarm Example ==="); let rtc_config = hal::rtc::get_default_config(); @@ -61,14 +40,14 @@ async fn main(_spawner: Spawner) { rtc.stop(); - uart.write_str_blocking("Time set to: 2025-10-15 14:30:00\r\n"); + defmt::info!("Time set to: 2025-10-15 14:30:00"); rtc.set_datetime(now); let mut alarm = now; alarm.second += 10; rtc.set_alarm(alarm); - uart.write_str_blocking("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)\r\n"); + defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)"); rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE); @@ -82,14 +61,14 @@ async fn main(_spawner: Spawner) { rtc.start(); - uart.write_str_blocking("RTC started, waiting for alarm...\r\n"); + defmt::info!("RTC started, waiting for alarm..."); loop { if rtc.is_alarm_triggered() { - uart.write_str_blocking("\r\n*** ALARM TRIGGERED! ***\r\n"); + defmt::info!("*** ALARM TRIGGERED! ***"); break; } } - uart.write_str_blocking("Example complete - Test PASSED!\r\n"); + defmt::info!("Example complete - Test PASSED!"); } 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 @@ use hal::{clocks, pins}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; -/// Initialize clocks and pin muxing for UART2 debug console. -/// Safe to call multiple times; writes are idempotent for our use. -pub unsafe fn init_uart2_pins() { - // NOTE: Lpuart has been updated to properly enable + reset its own clocks. - // GPIO has not. - _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); - pins::configure_uart2_pins_port2(); -} - /// Initialize clocks and pin muxing for ADC. pub unsafe fn init_adc_pins() { // NOTE: Lpuart has been updated to properly enable + reset its own clocks. -- cgit From 1efaaa4025120413ec17de90106244445208804a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 25 Nov 2025 11:32:37 -0800 Subject: I2c Controller Blocking Driver (#27) * I2c Master Signed-off-by: Felipe Balbi * Fix review comments Signed-off-by: Felipe Balbi * More review comments Signed-off-by: Felipe Balbi --------- Signed-off-by: Felipe Balbi Co-authored-by: Felipe Balbi --- examples/Cargo.lock | 532 +++++++++++++++++++++++++++++++++- examples/Cargo.toml | 1 + examples/src/bin/i2c-blocking.rs | 31 ++ examples/src/bin/i2c-scan-blocking.rs | 34 +++ 4 files changed, 590 insertions(+), 8 deletions(-) create mode 100644 examples/src/bin/i2c-blocking.rs create mode 100644 examples/src/bin/i2c-scan-blocking.rs (limited to 'examples') diff --git a/examples/Cargo.lock b/examples/Cargo.lock index 263807120..cda1f9ec8 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -2,6 +2,49 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "askama" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" +dependencies = [ + "askama_parser", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "syn 2.0.110", +] + +[[package]] +name = "askama_parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" +dependencies = [ + "memchr", + "winnow 0.7.13", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -29,6 +72,24 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -41,6 +102,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "cortex-m" version = "0.7.7" @@ -71,7 +141,7 @@ checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.110", ] [[package]] @@ -101,7 +171,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn", + "syn 2.0.110", ] [[package]] @@ -112,7 +182,16 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", - "syn", + "syn 2.0.110", +] + +[[package]] +name = "dd-manifest-tree" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5793572036e0a6638977c7370c6afc423eac848ee8495f079b8fd3964de7b9f9" +dependencies = [ + "toml", ] [[package]] @@ -121,7 +200,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" dependencies = [ - "bitflags", + "bitflags 1.3.2", "defmt-macros", ] @@ -135,7 +214,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn", + "syn 2.0.110", ] [[package]] @@ -157,6 +236,46 @@ dependencies = [ "defmt", ] +[[package]] +name = "device-driver" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af0e43acfcbb0bb3b7435cc1b1dbb33596cacfec1eb243336b74a398e0bd6cbf" +dependencies = [ + "device-driver-macros", + "embedded-io", + "embedded-io-async", +] + +[[package]] +name = "device-driver-generation" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3935aec9cf5bb2ab927f59ca69faecf976190390b0ce34c6023889e9041040c0" +dependencies = [ + "anyhow", + "askama", + "bitvec", + "convert_case", + "dd-manifest-tree", + "itertools", + "kdl", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "device-driver-macros" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fdc68ed515c4eddff2e95371185b4becba066085bf36d50f07f09782af98e17" +dependencies = [ + "device-driver-generation", + "proc-macro2", + "syn 2.0.110", +] + [[package]] name = "document-features" version = "0.2.12" @@ -166,6 +285,12 @@ dependencies = [ "litrs", ] +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "embassy-embedded-hal" version = "0.5.0" @@ -205,7 +330,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn", + "syn 2.0.110", ] [[package]] @@ -274,6 +399,7 @@ dependencies = [ "embedded-io-async", "heapless 0.9.2", "panic-probe", + "tmp108", ] [[package]] @@ -380,12 +506,24 @@ dependencies = [ "embedded-storage", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + [[package]] name = "futures-core" version = "0.3.31" @@ -407,6 +545,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + [[package]] name = "heapless" version = "0.8.0" @@ -433,12 +577,85 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "kdl" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a29e7b50079ff44549f68c0becb1c73d7f6de2a4ea952da77966daf3d4761e" +dependencies = [ + "miette", + "num", + "winnow 0.6.24", +] + [[package]] name = "litrs" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 1.0.109", + "syn 2.0.110", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + +[[package]] +name = "maybe-async-cfg" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627" +dependencies = [ + "manyhow", + "proc-macro2", + "pulldown-cmark", + "quote", + "syn 1.0.109", +] + [[package]] name = "mcxa-pac" version = "0.1.0" @@ -447,9 +664,26 @@ dependencies = [ "cortex-m", "cortex-m-rt", "critical-section", + "defmt", "vcell", ] +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "cfg-if", + "unicode-width", +] + [[package]] name = "nb" version = "0.1.3" @@ -465,6 +699,70 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -490,6 +788,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -509,7 +813,18 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn", + "syn 2.0.110", +] + +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", ] [[package]] @@ -521,6 +836,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "pulldown-cmark" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" +dependencies = [ + "bitflags 2.10.0", + "memchr", + "unicase", +] + [[package]] name = "quote" version = "1.0.42" @@ -530,6 +856,18 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.2.3" @@ -539,6 +877,12 @@ dependencies = [ "semver", ] +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + [[package]] name = "semver" version = "0.9.0" @@ -554,6 +898,63 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -566,6 +967,17 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.110" @@ -577,6 +989,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + [[package]] name = "thiserror" version = "2.0.17" @@ -594,15 +1012,86 @@ checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.110", +] + +[[package]] +name = "tmp108" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d644cc97d3cee96793f454b834881f78b5d4e89c90ecf26b3690f42004d111" +dependencies = [ + "device-driver", + "embedded-hal 1.0.0", + "maybe-async-cfg", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", ] +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow 0.7.13", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + [[package]] name = "unicode-ident" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + [[package]] name = "vcell" version = "0.1.3" @@ -623,3 +1112,30 @@ checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" dependencies = [ "vcell", ] + +[[package]] +name = "winnow" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 4f15a6aff..1022e91df 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -19,6 +19,7 @@ embassy-time-driver = "0.2.1" embedded-io-async = "0.6.1" heapless = "0.9.2" panic-probe = { version = "1.0", features = ["print-defmt"] } +tmp108 = "0.4.0" [profile.release] lto = true # better optimizations diff --git a/examples/src/bin/i2c-blocking.rs b/examples/src/bin/i2c-blocking.rs new file mode 100644 index 000000000..0f6c8cbae --- /dev/null +++ b/examples/src/bin/i2c-blocking.rs @@ -0,0 +1,31 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::clocks::config::Div8; +use hal::config::Config; +use hal::i2c::controller::{self, I2c, Speed}; +use tmp108::Tmp108; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); + + let p = hal::init(config); + + defmt::info!("I2C example"); + + let mut config = controller::Config::default(); + config.speed = Speed::Standard; + let i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); + let mut tmp = Tmp108::new_with_a0_gnd(i2c); + + loop { + let temperature = tmp.temperature().unwrap(); + defmt::info!("Temperature: {}C", temperature); + Timer::after_secs(1).await; + } +} diff --git a/examples/src/bin/i2c-scan-blocking.rs b/examples/src/bin/i2c-scan-blocking.rs new file mode 100644 index 000000000..6d1247e7a --- /dev/null +++ b/examples/src/bin/i2c-scan-blocking.rs @@ -0,0 +1,34 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::clocks::config::Div8; +use hal::config::Config; +use hal::i2c::controller::{self, I2c, Speed}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); + + let p = hal::init(config); + + defmt::info!("I2C example"); + + let mut config = controller::Config::default(); + config.speed = Speed::Standard; + let mut i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); + + for addr in 0x01..=0x7f { + let result = i2c.blocking_write(addr, &[]); + if result.is_ok() { + defmt::info!("Device found at addr {:02x}", addr); + } + } + + loop { + Timer::after_secs(10).await; + } +} -- cgit From d12bc9785399991065e511efbea34f0138c7645e Mon Sep 17 00:00:00 2001 From: MathisDerooNXP <52401665+MathisDeroo@users.noreply.github.com> Date: Wed, 26 Nov 2025 10:05:16 -0800 Subject: Add GPIO interrupt support and embedded-hal-async trait implementation (#38) * Add GPIO interrupt support and embedded-hal-async trait implementation Signed-off-by: Mathis Deroo * Run cargo fmt * Improve GPIO driver interrupt mechanism and example - GPIO interrupt managed internally at the HAL level, - Renamed and cleaned gpio_interrupt example; now button_async.rs, - Use BitIter instead of simple for loop in the irq handler, - Fix comments and add "rt" wrappen to GPIO IRQ handler. Signed-off-by: Mathis Deroo * Modify INTERRUPT_DETECTED (AtomicBool to AtomicU32) to work with pin number and not only port number interrupt Signed-off-by: Mathis Deroo * add embedded_hal_async::digital::* traits Signed-off-by: Mathis Deroo * Update irq_handler with BitIter loop Co-authored-by: Felipe Balbi * Add suggested changes Signed-off-by: Mathis Deroo * cargo fmt Signed-off-by: Felipe Balbi * WIP: Modify Wakers from AtomicWaker to WaitMap, with pin number (per PORT) as key Signed-off-by: Mathis Deroo * Tweak maitake-sync usage * Improve docs * refactor a bit * Move all of the async+interrupt stuff into a module * Remove defmt debug traces Signed-off-by: Mathis Deroo * cargo vet * Move e-hal-async impls into the gated block * "rt", begone! --------- Signed-off-by: Mathis Deroo Signed-off-by: Felipe Balbi Co-authored-by: Felipe Balbi Co-authored-by: Felipe Balbi Co-authored-by: Felipe Balbi Co-authored-by: James Munns --- examples/Cargo.lock | 414 +++++++++++++++++++++++++++++++++++++++ examples/Cargo.toml | 2 +- examples/src/bin/button_async.rs | 28 +++ 3 files changed, 443 insertions(+), 1 deletion(-) create mode 100644 examples/src/bin/button_async.rs (limited to 'examples') diff --git a/examples/Cargo.lock b/examples/Cargo.lock index cda1f9ec8..c6e864df2 100644 --- a/examples/Cargo.lock +++ b/examples/Cargo.lock @@ -2,6 +2,15 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + [[package]] name = "anyhow" version = "1.0.100" @@ -96,6 +105,16 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +[[package]] +name = "cc" +version = "1.2.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" +dependencies = [ + "find-msvc-tools", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -111,6 +130,16 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "cordyceps" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" +dependencies = [ + "loom", + "tracing", +] + [[package]] name = "cortex-m" version = "0.7.7" @@ -376,6 +405,7 @@ dependencies = [ "embedded-io", "embedded-io-async", "heapless 0.8.0", + "maitake-sync", "mcxa-pac", "nb 1.1.0", "paste", @@ -512,6 +542,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + [[package]] name = "fnv" version = "1.0.7" @@ -536,6 +572,20 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + [[package]] name = "hash32" version = "0.3.1" @@ -613,12 +663,59 @@ dependencies = [ "winnow 0.6.24", ] +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + [[package]] name = "litrs" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "maitake-sync" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "748f86d9befd480b602c3bebc9ef30dbf2f3dfc8acc4a73d07b90f0117e6de3f" +dependencies = [ + "cordyceps", + "critical-section", + "loom", + "mutex-traits", + "mycelium-bitfield", + "pin-project", + "portable-atomic", + "tracing", +] + [[package]] name = "manyhow" version = "0.11.4" @@ -643,6 +740,15 @@ dependencies = [ "quote", ] +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + [[package]] name = "maybe-async-cfg" version = "0.2.5" @@ -684,6 +790,18 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "mutex-traits" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3929f2b5633d29cf7b6624992e5f3c1e9334f1193423e12d17be4faf678cde3f" + +[[package]] +name = "mycelium-bitfield" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e0cc5e2c585acbd15c5ce911dff71e1f4d5313f43345873311c4f5efd741cc" + [[package]] name = "nb" version = "0.1.3" @@ -699,6 +817,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + [[package]] name = "num" version = "0.4.3" @@ -772,6 +899,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + [[package]] name = "panic-probe" version = "1.0.0" @@ -794,6 +927,41 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +dependencies = [ + "critical-section", +] + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -862,6 +1030,23 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + [[package]] name = "rustc-hash" version = "2.1.1" @@ -877,12 +1062,24 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "ryu" version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + [[package]] name = "semver" version = "0.9.0" @@ -949,6 +1146,21 @@ dependencies = [ "serde", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "smallvec" version = "1.15.1" @@ -1015,6 +1227,15 @@ dependencies = [ "syn 2.0.110", ] +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + [[package]] name = "tmp108" version = "0.4.0" @@ -1068,6 +1289,67 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "tracing" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb41cbdb933e23b7929f47bb577710643157d7602ef3a2ebd3902b13ac5eda6" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "tracing-core" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + [[package]] name = "unicase" version = "2.8.1" @@ -1092,6 +1374,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + [[package]] name = "vcell" version = "0.1.3" @@ -1113,6 +1401,132 @@ dependencies = [ "vcell", ] +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "winnow" version = "0.6.24" diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 1022e91df..a1092c416 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -12,7 +12,7 @@ defmt = "1.0" defmt-rtt = "1.0" embassy-embedded-hal = "0.5.0" embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false } -embassy-mcxa = { path = "../", features = ["defmt", "rt", "unstable-pac", "time"] } +embassy-mcxa = { path = "../", features = ["defmt", "unstable-pac", "time"] } embassy-sync = "0.7.2" embassy-time = "0.5.0" embassy-time-driver = "0.2.1" diff --git a/examples/src/bin/button_async.rs b/examples/src/bin/button_async.rs new file mode 100644 index 000000000..1ecec2e48 --- /dev/null +++ b/examples/src/bin/button_async.rs @@ -0,0 +1,28 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::gpio::{DriveStrength, Input, Pull, SlewRate}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("GPIO interrupt example"); + + // This button is labeled "WAKEUP" on the FRDM-MCXA276 + let mut pin = Input::new(p.P1_7, Pull::Up, DriveStrength::Normal, SlewRate::Fast); + + let mut press_count = 0u32; + + loop { + pin.wait_for_falling_edge().await; + + press_count += 1; + + defmt::info!("Button pressed! Count: {}", press_count); + Timer::after_millis(50).await; + } +} -- cgit From 87c4eaf3380505ca15ef7ed1d5dc435e9af2200e Mon Sep 17 00:00:00 2001 From: James Munns Date: Fri, 28 Nov 2025 18:49:10 +0100 Subject: Fix LPI2C2 example (#56) Fix LPI2C2 example --- examples/src/bin/i2c-scan-blocking.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/src/bin/i2c-scan-blocking.rs b/examples/src/bin/i2c-scan-blocking.rs index 6d1247e7a..72f9d09e0 100644 --- a/examples/src/bin/i2c-scan-blocking.rs +++ b/examples/src/bin/i2c-scan-blocking.rs @@ -2,6 +2,8 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa::gpio::{DriveStrength, Pull, SlewRate}; +use embassy_mcxa::Input; use embassy_time::Timer; use hal::clocks::config::Div8; use hal::config::Config; @@ -19,7 +21,12 @@ async fn main(_spawner: Spawner) { let mut config = controller::Config::default(); config.speed = Speed::Standard; - let mut i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); + + // Note: P0_2 is connected to P1_8 on the FRDM_MCXA276 via a resistor, and + // defaults to SWO on the debug peripheral. Explicitly make it a high-z + // input. + let _pin = Input::new(p.P0_2, Pull::Disabled, DriveStrength::Normal, SlewRate::Slow); + let mut i2c = I2c::new_blocking(p.LPI2C2, p.P1_9, p.P1_8, config).unwrap(); for addr in 0x01..=0x7f { let result = i2c.blocking_write(addr, &[]); -- cgit From 3b239cb6de22b7bb8c2d87defb3205294653be7a Mon Sep 17 00:00:00 2001 From: James Munns Date: Sat, 29 Nov 2025 16:07:30 +0100 Subject: Remove Drive/Slew settings for Input pin (#57) * Don't set slew+strength for inputs * Update example --- examples/src/bin/button.rs | 6 ++++-- examples/src/bin/button_async.rs | 5 +++-- examples/src/bin/i2c-scan-blocking.rs | 4 ++-- 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'examples') diff --git a/examples/src/bin/button.rs b/examples/src/bin/button.rs index 2abfe0a9f..943edbb15 100644 --- a/examples/src/bin/button.rs +++ b/examples/src/bin/button.rs @@ -3,7 +3,7 @@ use embassy_executor::Spawner; use embassy_time::Timer; -use hal::gpio::{DriveStrength, Input, Pull, SlewRate}; +use hal::gpio::{Input, Pull}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; #[embassy_executor::main] @@ -12,7 +12,9 @@ async fn main(_spawner: Spawner) { defmt::info!("Button example"); - let monitor = Input::new(p.P1_7, Pull::Disabled, DriveStrength::Normal, SlewRate::Slow); + // This button is labeled "WAKEUP" on the FRDM-MCXA276 + // The board already has a 10K pullup + let monitor = Input::new(p.P1_7, Pull::Disabled); loop { defmt::info!("Pin level is {:?}", monitor.get_level()); diff --git a/examples/src/bin/button_async.rs b/examples/src/bin/button_async.rs index 1ecec2e48..6cc7b62cd 100644 --- a/examples/src/bin/button_async.rs +++ b/examples/src/bin/button_async.rs @@ -3,7 +3,7 @@ use embassy_executor::Spawner; use embassy_time::Timer; -use hal::gpio::{DriveStrength, Input, Pull, SlewRate}; +use hal::gpio::{Input, Pull}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; #[embassy_executor::main] @@ -13,7 +13,8 @@ async fn main(_spawner: Spawner) { defmt::info!("GPIO interrupt example"); // This button is labeled "WAKEUP" on the FRDM-MCXA276 - let mut pin = Input::new(p.P1_7, Pull::Up, DriveStrength::Normal, SlewRate::Fast); + // The board already has a 10K pullup + let mut pin = Input::new(p.P1_7, Pull::Disabled); let mut press_count = 0u32; diff --git a/examples/src/bin/i2c-scan-blocking.rs b/examples/src/bin/i2c-scan-blocking.rs index 72f9d09e0..4e203597b 100644 --- a/examples/src/bin/i2c-scan-blocking.rs +++ b/examples/src/bin/i2c-scan-blocking.rs @@ -2,7 +2,7 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa::gpio::{DriveStrength, Pull, SlewRate}; +use embassy_mcxa::gpio::Pull; use embassy_mcxa::Input; use embassy_time::Timer; use hal::clocks::config::Div8; @@ -25,7 +25,7 @@ async fn main(_spawner: Spawner) { // Note: P0_2 is connected to P1_8 on the FRDM_MCXA276 via a resistor, and // defaults to SWO on the debug peripheral. Explicitly make it a high-z // input. - let _pin = Input::new(p.P0_2, Pull::Disabled, DriveStrength::Normal, SlewRate::Slow); + let _pin = Input::new(p.P0_2, Pull::Disabled); let mut i2c = I2c::new_blocking(p.LPI2C2, p.P1_9, p.P1_8, config).unwrap(); for addr in 0x01..=0x7f { -- cgit From 717346f21a4cf4993c2a1f046e26b6bf647d89cb Mon Sep 17 00:00:00 2001 From: JanKomarekNXP <151725448+JanKomarekNXP@users.noreply.github.com> Date: Mon, 1 Dec 2025 18:07:58 +0100 Subject: Refactor LPUART driver constructors (#51) * Refactor LPUART driver constructors - Add new_with_rtscts(), new_with_rts(), new_with_cts() methods - Store RTS/CTS pins in TX/RX structs - Remove enable_tx, enable_rx, enable_rx_rts, enable_tx_cts config fields - Fix typo: msb_firs -> msb_first - Fix write_byte() return type to Result<()> * Update hello example for LPUART driver changes * Refactor buffered LPUART initialization logic - Split new_inner() into init_common() and separate helpers for full-duplex, TX-only, and RX-only - Replace assert!() with proper Error::InvalidArgument returns for empty buffers - Simplify constructor implementations by removing expect() calls --- examples/src/bin/hello.rs | 14 ++++++++------ examples/src/bin/lpuart_buffered.rs | 2 -- examples/src/bin/lpuart_polling.rs | 2 -- 3 files changed, 8 insertions(+), 10 deletions(-) (limited to 'examples') diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs index f426d1898..e371d9413 100644 --- a/examples/src/bin/hello.rs +++ b/examples/src/bin/hello.rs @@ -2,27 +2,29 @@ #![no_main] use embassy_executor::Spawner; +use embassy_mcxa::clocks::config::Div8; use hal::lpuart::{Blocking, Config, Lpuart}; use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; /// Simple helper to write a byte as hex to UART fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; - uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); - uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); + let _ = uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); + let _ = uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); } #[embassy_executor::main] async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); + let mut cfg = hal::config::Config::default(); + cfg.clock_cfg.sirc.fro_12m_enabled = true; + cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); + let p = hal::init(cfg); defmt::info!("boot"); // Create UART configuration let config = Config { baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, ..Default::default() }; @@ -97,7 +99,7 @@ async fn main(_spawner: Spawner) { // Regular character buffer[buf_idx] = byte; buf_idx += 1; - uart.write_byte(byte); + let _ = uart.write_byte(byte); } } } diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs index 7f77d557d..420589d00 100644 --- a/examples/src/bin/lpuart_buffered.rs +++ b/examples/src/bin/lpuart_buffered.rs @@ -27,8 +27,6 @@ async fn main(_spawner: Spawner) { // UART configuration (enable both TX and RX) let config = Config { baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, rx_fifo_watermark: 0, tx_fifo_watermark: 0, ..Default::default() diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs index 9cea418cc..b80668834 100644 --- a/examples/src/bin/lpuart_polling.rs +++ b/examples/src/bin/lpuart_polling.rs @@ -19,8 +19,6 @@ async fn main(_spawner: Spawner) { // Create UART configuration let config = Config { baudrate_bps: 115_200, - enable_tx: true, - enable_rx: true, ..Default::default() }; -- cgit From 8798306fb2c124efc06443c2913c3d7a4919dd83 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 3 Dec 2025 09:52:03 -0800 Subject: I2c Async (#50) * I2c Async Signed-off-by: Felipe Balbi * Fix i2c read bug Signed-off-by: Felipe Balbi * Introduce wait_for() Signed-off-by: Felipe Balbi * Review comments Signed-off-by: Felipe Balbi * more review comments Signed-off-by: Felipe Balbi * review comments Signed-off-by: Felipe Balbi * review comments Signed-off-by: Felipe Balbi * convert async fn to impl Future Signed-off-by: Felipe Balbi --------- Signed-off-by: Felipe Balbi Co-authored-by: Felipe Balbi --- examples/src/bin/i2c-async.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 examples/src/bin/i2c-async.rs (limited to 'examples') diff --git a/examples/src/bin/i2c-async.rs b/examples/src/bin/i2c-async.rs new file mode 100644 index 000000000..47b5f3cbe --- /dev/null +++ b/examples/src/bin/i2c-async.rs @@ -0,0 +1,39 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::bind_interrupts; +use hal::clocks::config::Div8; +use hal::config::Config; +use hal::i2c::controller::{self, I2c, Speed}; +use hal::i2c::InterruptHandler; +use hal::peripherals::LPI2C3; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!( + struct Irqs { + LPI2C3 => InterruptHandler; + } +); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); + + let p = hal::init(config); + + defmt::info!("I2C example"); + + let mut config = controller::Config::default(); + config.speed = Speed::Standard; + let mut i2c = I2c::new_async(p.LPI2C3, p.P3_27, p.P3_28, Irqs, config).unwrap(); + let mut buf = [0u8; 2]; + + loop { + i2c.async_write_read(0x48, &[0x00], &mut buf).await.unwrap(); + defmt::info!("Buffer: {:02x}", buf); + Timer::after_secs(1).await; + } +} -- cgit From 22bae2d80153003af4637c4b0cc26d52858f5228 Mon Sep 17 00:00:00 2001 From: MathisDerooNXP <52401665+MathisDeroo@users.noreply.github.com> Date: Thu, 4 Dec 2025 09:42:46 -0800 Subject: Rtc support v2 (#91) Signed-off-by: Mathis Deroo Signed-off-by: Felipe Balbi --- examples/src/bin/rtc_alarm.rs | 39 ++++++--------------------------------- 1 file changed, 6 insertions(+), 33 deletions(-) (limited to 'examples') diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs index a7800a2d1..fe355888b 100644 --- a/examples/src/bin/rtc_alarm.rs +++ b/examples/src/bin/rtc_alarm.rs @@ -2,23 +2,14 @@ #![no_main] use embassy_executor::Spawner; -use embassy_mcxa as hal; -use hal::rtc::{RtcDateTime, RtcInterruptEnable}; -use hal::InterruptExt; - -type MyRtc = hal::rtc::Rtc<'static, hal::rtc::Rtc0>; - use embassy_mcxa::bind_interrupts; -use {defmt_rtt as _, panic_probe as _}; +use hal::rtc::{InterruptHandler, Rtc, RtcDateTime}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; bind_interrupts!(struct Irqs { - RTC => hal::rtc::RtcHandler; + RTC => InterruptHandler; }); -#[used] -#[no_mangle] -static KEEP_RTC: unsafe extern "C" fn() = RTC; - #[embassy_executor::main] async fn main(_spawner: Spawner) { let p = hal::init(hal::config::Config::default()); @@ -27,7 +18,7 @@ async fn main(_spawner: Spawner) { let rtc_config = hal::rtc::get_default_config(); - let rtc = MyRtc::new(p.RTC0, rtc_config); + let mut rtc = Rtc::new(p.RTC0, Irqs, rtc_config); let now = RtcDateTime { year: 2025, @@ -46,29 +37,11 @@ async fn main(_spawner: Spawner) { let mut alarm = now; alarm.second += 10; - rtc.set_alarm(alarm); defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)"); - - rtc.set_interrupt(RtcInterruptEnable::RTC_ALARM_INTERRUPT_ENABLE); - - unsafe { - hal::interrupt::RTC.enable(); - } - - unsafe { - cortex_m::interrupt::enable(); - } - - rtc.start(); - defmt::info!("RTC started, waiting for alarm..."); - loop { - if rtc.is_alarm_triggered() { - defmt::info!("*** ALARM TRIGGERED! ***"); - break; - } - } + rtc.wait_for_alarm(alarm).await; + defmt::info!("*** ALARM TRIGGERED! ***"); defmt::info!("Example complete - Test PASSED!"); } -- cgit From dc6bf5d44675f6f2013ddfab6b14df25a996a965 Mon Sep 17 00:00:00 2001 From: James Munns Date: Thu, 4 Dec 2025 18:37:01 +0100 Subject: Move to subfolder --- examples/.cargo/config.toml | 17 - examples/.gitignore | 1 - examples/Cargo.lock | 1555 --------------------------------- examples/Cargo.toml | 26 - examples/build.rs | 20 - examples/memory.x | 5 - examples/src/bin/adc_interrupt.rs | 84 -- examples/src/bin/adc_polling.rs | 68 -- examples/src/bin/blinky.rs | 36 - examples/src/bin/button.rs | 23 - examples/src/bin/button_async.rs | 29 - examples/src/bin/clkout.rs | 69 -- examples/src/bin/hello.rs | 119 --- examples/src/bin/i2c-async.rs | 39 - examples/src/bin/i2c-blocking.rs | 31 - examples/src/bin/i2c-scan-blocking.rs | 41 - examples/src/bin/lpuart_buffered.rs | 62 -- examples/src/bin/lpuart_polling.rs | 47 - examples/src/bin/rtc_alarm.rs | 47 - examples/src/lib.rs | 16 - 20 files changed, 2335 deletions(-) delete mode 100644 examples/.cargo/config.toml delete mode 100644 examples/.gitignore delete mode 100644 examples/Cargo.lock delete mode 100644 examples/Cargo.toml delete mode 100644 examples/build.rs delete mode 100644 examples/memory.x delete mode 100644 examples/src/bin/adc_interrupt.rs delete mode 100644 examples/src/bin/adc_polling.rs delete mode 100644 examples/src/bin/blinky.rs delete mode 100644 examples/src/bin/button.rs delete mode 100644 examples/src/bin/button_async.rs delete mode 100644 examples/src/bin/clkout.rs delete mode 100644 examples/src/bin/hello.rs delete mode 100644 examples/src/bin/i2c-async.rs delete mode 100644 examples/src/bin/i2c-blocking.rs delete mode 100644 examples/src/bin/i2c-scan-blocking.rs delete mode 100644 examples/src/bin/lpuart_buffered.rs delete mode 100644 examples/src/bin/lpuart_polling.rs delete mode 100644 examples/src/bin/rtc_alarm.rs delete mode 100644 examples/src/lib.rs (limited to 'examples') diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml deleted file mode 100644 index aedc55b06..000000000 --- a/examples/.cargo/config.toml +++ /dev/null @@ -1,17 +0,0 @@ -[target.thumbv8m.main-none-eabihf] -runner = 'probe-rs run --chip MCXA276 --preverify --verify --protocol swd --speed 12000' - -rustflags = [ - "-C", "linker=flip-link", - "-C", "link-arg=-Tlink.x", - "-C", "link-arg=-Tdefmt.x", - # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x - # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 - "-C", "link-arg=--nmagic", -] - -[build] -target = "thumbv8m.main-none-eabihf" # Cortex-M33 - -[env] -DEFMT_LOG = "trace" diff --git a/examples/.gitignore b/examples/.gitignore deleted file mode 100644 index 2f7896d1d..000000000 --- a/examples/.gitignore +++ /dev/null @@ -1 +0,0 @@ -target/ diff --git a/examples/Cargo.lock b/examples/Cargo.lock deleted file mode 100644 index c6e864df2..000000000 --- a/examples/Cargo.lock +++ /dev/null @@ -1,1555 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "anyhow" -version = "1.0.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" - -[[package]] -name = "askama" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" -dependencies = [ - "askama_derive", - "itoa", - "percent-encoding", - "serde", - "serde_json", -] - -[[package]] -name = "askama_derive" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" -dependencies = [ - "askama_parser", - "memchr", - "proc-macro2", - "quote", - "rustc-hash", - "syn 2.0.110", -] - -[[package]] -name = "askama_parser" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" -dependencies = [ - "memchr", - "winnow 0.7.13", -] - -[[package]] -name = "autocfg" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" - -[[package]] -name = "bare-metal" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "bitfield" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - -[[package]] -name = "byteorder" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" - -[[package]] -name = "cc" -version = "1.2.47" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" -dependencies = [ - "find-msvc-tools", - "shlex", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[package]] -name = "cordyceps" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" -dependencies = [ - "loom", - "tracing", -] - -[[package]] -name = "cortex-m" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" -dependencies = [ - "bare-metal", - "bitfield", - "critical-section", - "embedded-hal 0.2.7", - "volatile-register", -] - -[[package]] -name = "cortex-m-rt" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" -dependencies = [ - "cortex-m-rt-macros", -] - -[[package]] -name = "cortex-m-rt-macros" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.110", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "dd-manifest-tree" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5793572036e0a6638977c7370c6afc423eac848ee8495f079b8fd3964de7b9f9" -dependencies = [ - "toml", -] - -[[package]] -name = "defmt" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" -dependencies = [ - "bitflags 1.3.2", - "defmt-macros", -] - -[[package]] -name = "defmt-macros" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" -dependencies = [ - "defmt-parser", - "proc-macro-error2", - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "defmt-parser" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" -dependencies = [ - "thiserror", -] - -[[package]] -name = "defmt-rtt" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d5a25c99d89c40f5676bec8cefe0614f17f0f40e916f98e345dae941807f9e" -dependencies = [ - "critical-section", - "defmt", -] - -[[package]] -name = "device-driver" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af0e43acfcbb0bb3b7435cc1b1dbb33596cacfec1eb243336b74a398e0bd6cbf" -dependencies = [ - "device-driver-macros", - "embedded-io", - "embedded-io-async", -] - -[[package]] -name = "device-driver-generation" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3935aec9cf5bb2ab927f59ca69faecf976190390b0ce34c6023889e9041040c0" -dependencies = [ - "anyhow", - "askama", - "bitvec", - "convert_case", - "dd-manifest-tree", - "itertools", - "kdl", - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "device-driver-macros" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fdc68ed515c4eddff2e95371185b4becba066085bf36d50f07f09782af98e17" -dependencies = [ - "device-driver-generation", - "proc-macro2", - "syn 2.0.110", -] - -[[package]] -name = "document-features" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" -dependencies = [ - "litrs", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[package]] -name = "embassy-embedded-hal" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" -dependencies = [ - "embassy-futures", - "embassy-hal-internal", - "embassy-sync", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-storage", - "embedded-storage-async", - "nb 1.1.0", -] - -[[package]] -name = "embassy-executor" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" -dependencies = [ - "cortex-m", - "critical-section", - "document-features", - "embassy-executor-macros", - "embassy-executor-timer-queue", -] - -[[package]] -name = "embassy-executor-macros" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "embassy-executor-timer-queue" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" - -[[package]] -name = "embassy-futures" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" - -[[package]] -name = "embassy-hal-internal" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" -dependencies = [ - "cortex-m", - "critical-section", - "num-traits", -] - -[[package]] -name = "embassy-mcxa" -version = "0.1.0" -dependencies = [ - "cortex-m", - "cortex-m-rt", - "critical-section", - "defmt", - "embassy-embedded-hal", - "embassy-hal-internal", - "embassy-sync", - "embassy-time", - "embassy-time-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "embedded-hal-nb", - "embedded-io", - "embedded-io-async", - "heapless 0.8.0", - "maitake-sync", - "mcxa-pac", - "nb 1.1.0", - "paste", -] - -[[package]] -name = "embassy-mcxa-examples" -version = "0.1.0" -dependencies = [ - "cortex-m", - "cortex-m-rt", - "critical-section", - "defmt", - "defmt-rtt", - "embassy-embedded-hal", - "embassy-executor", - "embassy-mcxa", - "embassy-sync", - "embassy-time", - "embassy-time-driver", - "embedded-io-async", - "heapless 0.9.2", - "panic-probe", - "tmp108", -] - -[[package]] -name = "embassy-sync" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" -dependencies = [ - "cfg-if", - "critical-section", - "embedded-io-async", - "futures-core", - "futures-sink", - "heapless 0.8.0", -] - -[[package]] -name = "embassy-time" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" -dependencies = [ - "cfg-if", - "critical-section", - "document-features", - "embassy-time-driver", - "embedded-hal 0.2.7", - "embedded-hal 1.0.0", - "embedded-hal-async", - "futures-core", -] - -[[package]] -name = "embassy-time-driver" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" -dependencies = [ - "document-features", -] - -[[package]] -name = "embedded-hal" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" -dependencies = [ - "nb 0.1.3", - "void", -] - -[[package]] -name = "embedded-hal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" - -[[package]] -name = "embedded-hal-async" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" -dependencies = [ - "embedded-hal 1.0.0", -] - -[[package]] -name = "embedded-hal-nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" -dependencies = [ - "embedded-hal 1.0.0", - "nb 1.1.0", -] - -[[package]] -name = "embedded-io" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" - -[[package]] -name = "embedded-io-async" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" -dependencies = [ - "embedded-io", -] - -[[package]] -name = "embedded-storage" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" - -[[package]] -name = "embedded-storage-async" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" -dependencies = [ - "embedded-storage", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "find-msvc-tools" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-sink" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" - -[[package]] -name = "generator" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" -dependencies = [ - "cc", - "cfg-if", - "libc", - "log", - "rustversion", - "windows", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" - -[[package]] -name = "heapless" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "heapless" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" -dependencies = [ - "hash32", - "stable_deref_trait", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "indexmap" -version = "2.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "kdl" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a29e7b50079ff44549f68c0becb1c73d7f6de2a4ea952da77966daf3d4761e" -dependencies = [ - "miette", - "num", - "winnow 0.6.24", -] - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.177" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" - -[[package]] -name = "litrs" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" - -[[package]] -name = "log" -version = "0.4.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - -[[package]] -name = "loom" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" -dependencies = [ - "cfg-if", - "generator", - "scoped-tls", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "maitake-sync" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "748f86d9befd480b602c3bebc9ef30dbf2f3dfc8acc4a73d07b90f0117e6de3f" -dependencies = [ - "cordyceps", - "critical-section", - "loom", - "mutex-traits", - "mycelium-bitfield", - "pin-project", - "portable-atomic", - "tracing", -] - -[[package]] -name = "manyhow" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" -dependencies = [ - "manyhow-macros", - "proc-macro2", - "quote", - "syn 1.0.109", - "syn 2.0.110", -] - -[[package]] -name = "manyhow-macros" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" -dependencies = [ - "proc-macro-utils", - "proc-macro2", - "quote", -] - -[[package]] -name = "matchers" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" -dependencies = [ - "regex-automata", -] - -[[package]] -name = "maybe-async-cfg" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627" -dependencies = [ - "manyhow", - "proc-macro2", - "pulldown-cmark", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "mcxa-pac" -version = "0.1.0" -source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca" -dependencies = [ - "cortex-m", - "cortex-m-rt", - "critical-section", - "defmt", - "vcell", -] - -[[package]] -name = "memchr" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" - -[[package]] -name = "miette" -version = "7.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" -dependencies = [ - "cfg-if", - "unicode-width", -] - -[[package]] -name = "mutex-traits" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3929f2b5633d29cf7b6624992e5f3c1e9334f1193423e12d17be4faf678cde3f" - -[[package]] -name = "mycelium-bitfield" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e0cc5e2c585acbd15c5ce911dff71e1f4d5313f43345873311c4f5efd741cc" - -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.1.0", -] - -[[package]] -name = "nb" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" - -[[package]] -name = "nu-ansi-term" -version = "0.50.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" -dependencies = [ - "windows-sys", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" -dependencies = [ - "autocfg", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[package]] -name = "panic-probe" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a" -dependencies = [ - "cortex-m", - "defmt", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "percent-encoding" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" - -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "portable-atomic" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" -dependencies = [ - "critical-section", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "proc-macro-error2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" -dependencies = [ - "proc-macro-error-attr2", - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "proc-macro-utils" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" -dependencies = [ - "proc-macro2", - "quote", - "smallvec", -] - -[[package]] -name = "proc-macro2" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "pulldown-cmark" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" -dependencies = [ - "bitflags 2.10.0", - "memchr", - "unicase", -] - -[[package]] -name = "quote" -version = "1.0.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "regex-automata" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" - -[[package]] -name = "rustc-hash" -version = "2.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" - -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "serde_json" -version = "1.0.145" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", - "serde_core", -] - -[[package]] -name = "serde_spanned" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" -dependencies = [ - "serde", -] - -[[package]] -name = "sharded-slab" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" -dependencies = [ - "lazy_static", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "smallvec" -version = "1.15.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "stable_deref_trait" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.110" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "tap" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" - -[[package]] -name = "thiserror" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "thread_local" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "tmp108" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d644cc97d3cee96793f454b834881f78b5d4e89c90ecf26b3690f42004d111" -dependencies = [ - "device-driver", - "embedded-hal 1.0.0", - "maybe-async-cfg", -] - -[[package]] -name = "toml" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit", -] - -[[package]] -name = "toml_datetime" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.22.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" -dependencies = [ - "indexmap", - "serde", - "serde_spanned", - "toml_datetime", - "toml_write", - "winnow 0.7.13", -] - -[[package]] -name = "toml_write" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" - -[[package]] -name = "tracing" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb41cbdb933e23b7929f47bb577710643157d7602ef3a2ebd3902b13ac5eda6" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "tracing-core" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-log" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" -dependencies = [ - "log", - "once_cell", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" -dependencies = [ - "matchers", - "nu-ansi-term", - "once_cell", - "regex-automata", - "sharded-slab", - "smallvec", - "thread_local", - "tracing", - "tracing-core", - "tracing-log", -] - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-ident" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "vcell" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" - -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "volatile-register" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" -dependencies = [ - "vcell", -] - -[[package]] -name = "windows" -version = "0.61.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" -dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-link 0.1.3", - "windows-numerics", -] - -[[package]] -name = "windows-collections" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" -dependencies = [ - "windows-core", -] - -[[package]] -name = "windows-core" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" -dependencies = [ - "windows-implement", - "windows-interface", - "windows-link 0.1.3", - "windows-result", - "windows-strings", -] - -[[package]] -name = "windows-future" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" -dependencies = [ - "windows-core", - "windows-link 0.1.3", - "windows-threading", -] - -[[package]] -name = "windows-implement" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "windows-interface" -version = "0.59.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.110", -] - -[[package]] -name = "windows-link" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-numerics" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" -dependencies = [ - "windows-core", - "windows-link 0.1.3", -] - -[[package]] -name = "windows-result" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-strings" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link 0.2.1", -] - -[[package]] -name = "windows-threading" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" -dependencies = [ - "windows-link 0.1.3", -] - -[[package]] -name = "winnow" -version = "0.6.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.7.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" -dependencies = [ - "memchr", -] - -[[package]] -name = "wyz" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" -dependencies = [ - "tap", -] diff --git a/examples/Cargo.toml b/examples/Cargo.toml deleted file mode 100644 index a1092c416..000000000 --- a/examples/Cargo.toml +++ /dev/null @@ -1,26 +0,0 @@ -[package] -name = "embassy-mcxa-examples" -version = "0.1.0" -edition = "2021" -license = "MIT OR Apache-2.0" - -[dependencies] -cortex-m = { version = "0.7", features = ["critical-section-single-core"] } -cortex-m-rt = { version = "0.7", features = ["set-sp", "set-vtor"] } -critical-section = "1.2.0" -defmt = "1.0" -defmt-rtt = "1.0" -embassy-embedded-hal = "0.5.0" -embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false } -embassy-mcxa = { path = "../", features = ["defmt", "unstable-pac", "time"] } -embassy-sync = "0.7.2" -embassy-time = "0.5.0" -embassy-time-driver = "0.2.1" -embedded-io-async = "0.6.1" -heapless = "0.9.2" -panic-probe = { version = "1.0", features = ["print-defmt"] } -tmp108 = "0.4.0" - -[profile.release] -lto = true # better optimizations -debug = 2 # enough information for defmt/rtt locations diff --git a/examples/build.rs b/examples/build.rs deleted file mode 100644 index f076bba9f..000000000 --- a/examples/build.rs +++ /dev/null @@ -1,20 +0,0 @@ -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; - -fn main() { - let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); - - // Generate memory.x - put "FLASH" at start of RAM, RAM after "FLASH" - // cortex-m-rt expects FLASH for code, RAM for data/bss/stack - // Both are in RAM, but separated to satisfy cortex-m-rt's expectations - // MCXA256 has 128KB RAM total - File::create(out.join("memory.x")) - .unwrap() - .write_all(include_bytes!("memory.x")) - .unwrap(); - - println!("cargo:rustc-link-search={}", out.display()); - println!("cargo:rerun-if-changed=memory.x"); -} diff --git a/examples/memory.x b/examples/memory.x deleted file mode 100644 index 315ced58a..000000000 --- a/examples/memory.x +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - FLASH : ORIGIN = 0x00000000, LENGTH = 1M - RAM : ORIGIN = 0x20000000, LENGTH = 128K -} diff --git a/examples/src/bin/adc_interrupt.rs b/examples/src/bin/adc_interrupt.rs deleted file mode 100644 index 83d8046b3..000000000 --- a/examples/src/bin/adc_interrupt.rs +++ /dev/null @@ -1,84 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa_examples::init_adc_pins; -use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; -use hal::clocks::periph_helpers::{AdcClockSel, Div4}; -use hal::clocks::PoweredClock; -use hal::pac::adc1::cfg::{Pwrsel, Refsel}; -use hal::pac::adc1::cmdl1::{Adch, Mode}; -use hal::pac::adc1::ctrl::CalAvgs; -use hal::pac::adc1::tctrl::Tcmd; -use hal::{bind_interrupts, InterruptExt}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -bind_interrupts!(struct Irqs { - ADC1 => hal::adc::AdcHandler; -}); - -#[used] -#[no_mangle] -static KEEP_ADC: unsafe extern "C" fn() = ADC1; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - defmt::info!("ADC interrupt Example"); - - unsafe { - init_adc_pins(); - } - - let adc_config = LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::Average128, - enable_analog_preliminary: true, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option3, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, - power: PoweredClock::NormalEnabledDeepSleepDisabled, - source: AdcClockSel::FroLfDiv, - div: Div4::no_div(), - }; - let adc = hal::adc::Adc::::new(p.ADC1, adc_config); - - adc.do_offset_calibration(); - adc.do_auto_calibration(); - - let mut conv_command_config = adc.get_default_conv_command_config(); - conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; - conv_command_config.conversion_resolution_mode = Mode::Data16Bits; - adc.set_conv_command_config(1, &conv_command_config); - - let mut conv_trigger_config = adc.get_default_conv_trigger_config(); - conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; - conv_trigger_config.enable_hardware_trigger = false; - adc.set_conv_trigger_config(0, &conv_trigger_config); - - defmt::info!("ADC configuration done..."); - - adc.enable_interrupt(0x1); - - unsafe { - hal::interrupt::ADC1.enable(); - } - - unsafe { - cortex_m::interrupt::enable(); - } - - loop { - adc.do_software_trigger(1); - while !adc.is_interrupt_triggered() { - // Wait until the interrupt is triggered - } - defmt::info!("*** ADC interrupt TRIGGERED! ***"); - //TBD need to print the value - } -} diff --git a/examples/src/bin/adc_polling.rs b/examples/src/bin/adc_polling.rs deleted file mode 100644 index ddf3f586b..000000000 --- a/examples/src/bin/adc_polling.rs +++ /dev/null @@ -1,68 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa_examples::init_adc_pins; -use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; -use hal::clocks::periph_helpers::{AdcClockSel, Div4}; -use hal::clocks::PoweredClock; -use hal::pac::adc1::cfg::{Pwrsel, Refsel}; -use hal::pac::adc1::cmdl1::{Adch, Mode}; -use hal::pac::adc1::ctrl::CalAvgs; -use hal::pac::adc1::tctrl::Tcmd; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -const G_LPADC_RESULT_SHIFT: u32 = 0; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - unsafe { - init_adc_pins(); - } - - defmt::info!("=== ADC polling Example ==="); - - let adc_config = LpadcConfig { - enable_in_doze_mode: true, - conversion_average_mode: CalAvgs::Average128, - enable_analog_preliminary: true, - power_up_delay: 0x80, - reference_voltage_source: Refsel::Option3, - power_level_mode: Pwrsel::Lowest, - trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, - enable_conv_pause: false, - conv_pause_delay: 0, - fifo_watermark: 0, - power: PoweredClock::NormalEnabledDeepSleepDisabled, - source: AdcClockSel::FroLfDiv, - div: Div4::no_div(), - }; - let adc = hal::adc::Adc::::new(p.ADC1, adc_config); - - adc.do_offset_calibration(); - adc.do_auto_calibration(); - - let mut conv_command_config = adc.get_default_conv_command_config(); - conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; - conv_command_config.conversion_resolution_mode = Mode::Data16Bits; - adc.set_conv_command_config(1, &conv_command_config); - - let mut conv_trigger_config = adc.get_default_conv_trigger_config(); - conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; - conv_trigger_config.enable_hardware_trigger = false; - adc.set_conv_trigger_config(0, &conv_trigger_config); - - defmt::info!("=== ADC configuration done... ==="); - - loop { - adc.do_software_trigger(1); - let mut result: Option = None; - while result.is_none() { - result = hal::adc::get_conv_result(); - } - let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; - defmt::info!("value: {=u16}", value); - } -} diff --git a/examples/src/bin/blinky.rs b/examples/src/bin/blinky.rs deleted file mode 100644 index dd08ec0d9..000000000 --- a/examples/src/bin/blinky.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::Timer; -use hal::gpio::{DriveStrength, Level, Output, SlewRate}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - defmt::info!("Blink example"); - - let mut red = Output::new(p.P3_18, Level::High, DriveStrength::Normal, SlewRate::Fast); - let mut green = Output::new(p.P3_19, Level::High, DriveStrength::Normal, SlewRate::Fast); - let mut blue = Output::new(p.P3_21, Level::High, DriveStrength::Normal, SlewRate::Fast); - - loop { - defmt::info!("Toggle LEDs"); - - red.toggle(); - Timer::after_millis(250).await; - - red.toggle(); - green.toggle(); - Timer::after_millis(250).await; - - green.toggle(); - blue.toggle(); - Timer::after_millis(250).await; - blue.toggle(); - - Timer::after_millis(250).await; - } -} diff --git a/examples/src/bin/button.rs b/examples/src/bin/button.rs deleted file mode 100644 index 943edbb15..000000000 --- a/examples/src/bin/button.rs +++ /dev/null @@ -1,23 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::Timer; -use hal::gpio::{Input, Pull}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - defmt::info!("Button example"); - - // This button is labeled "WAKEUP" on the FRDM-MCXA276 - // The board already has a 10K pullup - let monitor = Input::new(p.P1_7, Pull::Disabled); - - loop { - defmt::info!("Pin level is {:?}", monitor.get_level()); - Timer::after_millis(1000).await; - } -} diff --git a/examples/src/bin/button_async.rs b/examples/src/bin/button_async.rs deleted file mode 100644 index 6cc7b62cd..000000000 --- a/examples/src/bin/button_async.rs +++ /dev/null @@ -1,29 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::Timer; -use hal::gpio::{Input, Pull}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - defmt::info!("GPIO interrupt example"); - - // This button is labeled "WAKEUP" on the FRDM-MCXA276 - // The board already has a 10K pullup - let mut pin = Input::new(p.P1_7, Pull::Disabled); - - let mut press_count = 0u32; - - loop { - pin.wait_for_falling_edge().await; - - press_count += 1; - - defmt::info!("Button pressed! Count: {}", press_count); - Timer::after_millis(50).await; - } -} diff --git a/examples/src/bin/clkout.rs b/examples/src/bin/clkout.rs deleted file mode 100644 index bfd963540..000000000 --- a/examples/src/bin/clkout.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; -use embassy_mcxa::clocks::PoweredClock; -use embassy_mcxa::gpio::{DriveStrength, SlewRate}; -use embassy_mcxa::{Level, Output}; -use embassy_time::Timer; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -/// Demonstrate CLKOUT, using Pin P4.2 -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - let mut pin = p.P4_2; - let mut clkout = p.CLKOUT; - - loop { - defmt::info!("Set Low..."); - let mut output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); - Timer::after_millis(500).await; - - defmt::info!("Set High..."); - output.set_high(); - Timer::after_millis(400).await; - - defmt::info!("Set Low..."); - output.set_low(); - Timer::after_millis(500).await; - - defmt::info!("16k..."); - // Run Clock Out with the 16K clock - let _clock_out = ClockOut::new( - clkout.reborrow(), - pin.reborrow(), - Config { - sel: ClockOutSel::Clk16K, - div: Div4::no_div(), - level: PoweredClock::NormalEnabledDeepSleepDisabled, - }, - ) - .unwrap(); - - Timer::after_millis(3000).await; - - defmt::info!("Set Low..."); - drop(_clock_out); - - let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); - Timer::after_millis(500).await; - - // Run Clock Out with the 12M clock, divided by 3 - defmt::info!("4M..."); - let _clock_out = ClockOut::new( - clkout.reborrow(), - pin.reborrow(), - Config { - sel: ClockOutSel::Fro12M, - div: const { Div4::from_divisor(3).unwrap() }, - level: PoweredClock::NormalEnabledDeepSleepDisabled, - }, - ) - .unwrap(); - - // Let it run for 3 seconds... - Timer::after_millis(3000).await; - } -} diff --git a/examples/src/bin/hello.rs b/examples/src/bin/hello.rs deleted file mode 100644 index e371d9413..000000000 --- a/examples/src/bin/hello.rs +++ /dev/null @@ -1,119 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::clocks::config::Div8; -use hal::lpuart::{Blocking, Config, Lpuart}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -/// Simple helper to write a byte as hex to UART -fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { - const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; - let _ = uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); - let _ = uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); -} - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let mut cfg = hal::config::Config::default(); - cfg.clock_cfg.sirc.fro_12m_enabled = true; - cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); - let p = hal::init(cfg); - - defmt::info!("boot"); - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - let mut uart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - - // Print welcome message before any async delays to guarantee early console output - uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); - uart.write_str_blocking("Available commands:\r\n"); - uart.write_str_blocking(" help - Show this help\r\n"); - uart.write_str_blocking(" echo - Echo back the text\r\n"); - uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); - uart.write_str_blocking("Type a command: "); - - let mut buffer = [0u8; 64]; - let mut buf_idx = 0; - - loop { - // Read a byte from UART - let byte = uart.read_byte_blocking(); - - // Echo the character back - if byte == b'\r' || byte == b'\n' { - // Enter pressed - process command - uart.write_str_blocking("\r\n"); - - if buf_idx > 0 { - let command = &buffer[0..buf_idx]; - - if command == b"help" { - uart.write_str_blocking("Available commands:\r\n"); - uart.write_str_blocking(" help - Show this help\r\n"); - uart.write_str_blocking(" echo - Echo back the text\r\n"); - uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); - } else if command.starts_with(b"echo ") && command.len() > 5 { - uart.write_str_blocking("Echo: "); - uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or("")); - uart.write_str_blocking("\r\n"); - } else if command.starts_with(b"hex ") && command.len() > 4 { - // Parse the byte value - let num_str = &command[4..]; - if let Ok(num) = parse_u8(num_str) { - uart.write_str_blocking("Hex: 0x"); - write_hex_byte(&mut uart, num); - uart.write_str_blocking("\r\n"); - } else { - uart.write_str_blocking("Invalid number for hex command\r\n"); - } - } else if !command.is_empty() { - uart.write_str_blocking("Unknown command: "); - uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); - uart.write_str_blocking("\r\n"); - } - } - - // Reset buffer and prompt - buf_idx = 0; - uart.write_str_blocking("Type a command: "); - } else if byte == 8 || byte == 127 { - // Backspace - if buf_idx > 0 { - buf_idx -= 1; - uart.write_str_blocking("\x08 \x08"); // Erase character - } - } else if buf_idx < buffer.len() - 1 { - // Regular character - buffer[buf_idx] = byte; - buf_idx += 1; - let _ = uart.write_byte(byte); - } - } -} - -/// Simple parser for u8 from ASCII bytes -fn parse_u8(bytes: &[u8]) -> Result { - let mut result = 0u8; - for &b in bytes { - if b.is_ascii_digit() { - result = result.checked_mul(10).ok_or(())?; - result = result.checked_add(b - b'0').ok_or(())?; - } else { - return Err(()); - } - } - Ok(result) -} diff --git a/examples/src/bin/i2c-async.rs b/examples/src/bin/i2c-async.rs deleted file mode 100644 index 47b5f3cbe..000000000 --- a/examples/src/bin/i2c-async.rs +++ /dev/null @@ -1,39 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::Timer; -use hal::bind_interrupts; -use hal::clocks::config::Div8; -use hal::config::Config; -use hal::i2c::controller::{self, I2c, Speed}; -use hal::i2c::InterruptHandler; -use hal::peripherals::LPI2C3; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -bind_interrupts!( - struct Irqs { - LPI2C3 => InterruptHandler; - } -); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let mut config = Config::default(); - config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); - - let p = hal::init(config); - - defmt::info!("I2C example"); - - let mut config = controller::Config::default(); - config.speed = Speed::Standard; - let mut i2c = I2c::new_async(p.LPI2C3, p.P3_27, p.P3_28, Irqs, config).unwrap(); - let mut buf = [0u8; 2]; - - loop { - i2c.async_write_read(0x48, &[0x00], &mut buf).await.unwrap(); - defmt::info!("Buffer: {:02x}", buf); - Timer::after_secs(1).await; - } -} diff --git a/examples/src/bin/i2c-blocking.rs b/examples/src/bin/i2c-blocking.rs deleted file mode 100644 index 0f6c8cbae..000000000 --- a/examples/src/bin/i2c-blocking.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_time::Timer; -use hal::clocks::config::Div8; -use hal::config::Config; -use hal::i2c::controller::{self, I2c, Speed}; -use tmp108::Tmp108; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let mut config = Config::default(); - config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); - - let p = hal::init(config); - - defmt::info!("I2C example"); - - let mut config = controller::Config::default(); - config.speed = Speed::Standard; - let i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); - let mut tmp = Tmp108::new_with_a0_gnd(i2c); - - loop { - let temperature = tmp.temperature().unwrap(); - defmt::info!("Temperature: {}C", temperature); - Timer::after_secs(1).await; - } -} diff --git a/examples/src/bin/i2c-scan-blocking.rs b/examples/src/bin/i2c-scan-blocking.rs deleted file mode 100644 index 4e203597b..000000000 --- a/examples/src/bin/i2c-scan-blocking.rs +++ /dev/null @@ -1,41 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::gpio::Pull; -use embassy_mcxa::Input; -use embassy_time::Timer; -use hal::clocks::config::Div8; -use hal::config::Config; -use hal::i2c::controller::{self, I2c, Speed}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let mut config = Config::default(); - config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); - - let p = hal::init(config); - - defmt::info!("I2C example"); - - let mut config = controller::Config::default(); - config.speed = Speed::Standard; - - // Note: P0_2 is connected to P1_8 on the FRDM_MCXA276 via a resistor, and - // defaults to SWO on the debug peripheral. Explicitly make it a high-z - // input. - let _pin = Input::new(p.P0_2, Pull::Disabled); - let mut i2c = I2c::new_blocking(p.LPI2C2, p.P1_9, p.P1_8, config).unwrap(); - - for addr in 0x01..=0x7f { - let result = i2c.blocking_write(addr, &[]); - if result.is_ok() { - defmt::info!("Device found at addr {:02x}", addr); - } - } - - loop { - Timer::after_secs(10).await; - } -} diff --git a/examples/src/bin/lpuart_buffered.rs b/examples/src/bin/lpuart_buffered.rs deleted file mode 100644 index 420589d00..000000000 --- a/examples/src/bin/lpuart_buffered.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::clocks::config::Div8; -use embassy_mcxa::lpuart::buffered::BufferedLpuart; -use embassy_mcxa::lpuart::Config; -use embassy_mcxa::{bind_interrupts, lpuart}; -use embedded_io_async::Write; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver -bind_interrupts!(struct Irqs { - LPUART2 => lpuart::buffered::BufferedInterruptHandler::; -}); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let mut cfg = hal::config::Config::default(); - cfg.clock_cfg.sirc.fro_12m_enabled = true; - cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); - let p = hal::init(cfg); - - // Configure NVIC for LPUART2 - hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); - - // UART configuration (enable both TX and RX) - let config = Config { - baudrate_bps: 115_200, - rx_fifo_watermark: 0, - tx_fifo_watermark: 0, - ..Default::default() - }; - - let mut tx_buf = [0u8; 256]; - let mut rx_buf = [0u8; 256]; - - // Create a buffered LPUART2 instance with both TX and RX - let mut uart = BufferedLpuart::new( - p.LPUART2, - p.P2_2, // TX pin - p.P2_3, // RX pin - Irqs, - &mut tx_buf, - &mut rx_buf, - config, - ) - .unwrap(); - - // Split into TX and RX parts - let (tx, rx) = uart.split_ref(); - - tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); - tx.write(b"Type characters to echo them back.\r\n").await.unwrap(); - - // Echo loop - let mut buf = [0u8; 4]; - loop { - let used = rx.read(&mut buf).await.unwrap(); - tx.write_all(&buf[..used]).await.unwrap(); - } -} diff --git a/examples/src/bin/lpuart_polling.rs b/examples/src/bin/lpuart_polling.rs deleted file mode 100644 index b80668834..000000000 --- a/examples/src/bin/lpuart_polling.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::clocks::config::Div8; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -use crate::hal::lpuart::{Config, Lpuart}; - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let mut cfg = hal::config::Config::default(); - cfg.clock_cfg.sirc.fro_12m_enabled = true; - cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); - let p = hal::init(cfg); - - defmt::info!("boot"); - - // Create UART configuration - let config = Config { - baudrate_bps: 115_200, - ..Default::default() - }; - - // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX - let lpuart = Lpuart::new_blocking( - p.LPUART2, // Peripheral - p.P2_2, // TX pin - p.P2_3, // RX pin - config, - ) - .unwrap(); - - // Split into separate TX and RX parts - let (mut tx, mut rx) = lpuart.split(); - - // Write hello messages - tx.blocking_write(b"Hello world.\r\n").unwrap(); - tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap(); - - // Echo loop - loop { - let mut buf = [0u8; 1]; - rx.blocking_read(&mut buf).unwrap(); - tx.blocking_write(&buf).unwrap(); - } -} diff --git a/examples/src/bin/rtc_alarm.rs b/examples/src/bin/rtc_alarm.rs deleted file mode 100644 index fe355888b..000000000 --- a/examples/src/bin/rtc_alarm.rs +++ /dev/null @@ -1,47 +0,0 @@ -#![no_std] -#![no_main] - -use embassy_executor::Spawner; -use embassy_mcxa::bind_interrupts; -use hal::rtc::{InterruptHandler, Rtc, RtcDateTime}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -bind_interrupts!(struct Irqs { - RTC => InterruptHandler; -}); - -#[embassy_executor::main] -async fn main(_spawner: Spawner) { - let p = hal::init(hal::config::Config::default()); - - defmt::info!("=== RTC Alarm Example ==="); - - let rtc_config = hal::rtc::get_default_config(); - - let mut rtc = Rtc::new(p.RTC0, Irqs, rtc_config); - - let now = RtcDateTime { - year: 2025, - month: 10, - day: 15, - hour: 14, - minute: 30, - second: 0, - }; - - rtc.stop(); - - defmt::info!("Time set to: 2025-10-15 14:30:00"); - rtc.set_datetime(now); - - let mut alarm = now; - alarm.second += 10; - - defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)"); - defmt::info!("RTC started, waiting for alarm..."); - - rtc.wait_for_alarm(alarm).await; - defmt::info!("*** ALARM TRIGGERED! ***"); - - defmt::info!("Example complete - Test PASSED!"); -} diff --git a/examples/src/lib.rs b/examples/src/lib.rs deleted file mode 100644 index 2573a6adc..000000000 --- a/examples/src/lib.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![no_std] -#![allow(clippy::missing_safety_doc)] - -//! Shared board-specific helpers for the FRDM-MCXA276 examples. -//! These live with the examples so the HAL stays generic. - -use hal::{clocks, pins}; -use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; - -/// Initialize clocks and pin muxing for ADC. -pub unsafe fn init_adc_pins() { - // NOTE: Lpuart has been updated to properly enable + reset its own clocks. - // GPIO has not. - _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); - pins::configure_adc_pins(); -} -- cgit From 277ab0d2e8714edf37a0ee84cda1059d9944ecef Mon Sep 17 00:00:00 2001 From: James Munns Date: Thu, 4 Dec 2025 18:41:46 +0100 Subject: Move examples to top level example folder --- examples/mcxa/.cargo/config.toml | 17 + examples/mcxa/.gitignore | 1 + examples/mcxa/Cargo.lock | 1555 ++++++++++++++++++++++++++++ examples/mcxa/Cargo.toml | 26 + examples/mcxa/build.rs | 20 + examples/mcxa/memory.x | 5 + examples/mcxa/src/bin/adc_interrupt.rs | 84 ++ examples/mcxa/src/bin/adc_polling.rs | 68 ++ examples/mcxa/src/bin/blinky.rs | 36 + examples/mcxa/src/bin/button.rs | 23 + examples/mcxa/src/bin/button_async.rs | 29 + examples/mcxa/src/bin/clkout.rs | 69 ++ examples/mcxa/src/bin/hello.rs | 119 +++ examples/mcxa/src/bin/i2c-async.rs | 39 + examples/mcxa/src/bin/i2c-blocking.rs | 31 + examples/mcxa/src/bin/i2c-scan-blocking.rs | 41 + examples/mcxa/src/bin/lpuart_buffered.rs | 62 ++ examples/mcxa/src/bin/lpuart_polling.rs | 47 + examples/mcxa/src/bin/rtc_alarm.rs | 47 + examples/mcxa/src/lib.rs | 16 + 20 files changed, 2335 insertions(+) create mode 100644 examples/mcxa/.cargo/config.toml create mode 100644 examples/mcxa/.gitignore create mode 100644 examples/mcxa/Cargo.lock create mode 100644 examples/mcxa/Cargo.toml create mode 100644 examples/mcxa/build.rs create mode 100644 examples/mcxa/memory.x create mode 100644 examples/mcxa/src/bin/adc_interrupt.rs create mode 100644 examples/mcxa/src/bin/adc_polling.rs create mode 100644 examples/mcxa/src/bin/blinky.rs create mode 100644 examples/mcxa/src/bin/button.rs create mode 100644 examples/mcxa/src/bin/button_async.rs create mode 100644 examples/mcxa/src/bin/clkout.rs create mode 100644 examples/mcxa/src/bin/hello.rs create mode 100644 examples/mcxa/src/bin/i2c-async.rs create mode 100644 examples/mcxa/src/bin/i2c-blocking.rs create mode 100644 examples/mcxa/src/bin/i2c-scan-blocking.rs create mode 100644 examples/mcxa/src/bin/lpuart_buffered.rs create mode 100644 examples/mcxa/src/bin/lpuart_polling.rs create mode 100644 examples/mcxa/src/bin/rtc_alarm.rs create mode 100644 examples/mcxa/src/lib.rs (limited to 'examples') diff --git a/examples/mcxa/.cargo/config.toml b/examples/mcxa/.cargo/config.toml new file mode 100644 index 000000000..aedc55b06 --- /dev/null +++ b/examples/mcxa/.cargo/config.toml @@ -0,0 +1,17 @@ +[target.thumbv8m.main-none-eabihf] +runner = 'probe-rs run --chip MCXA276 --preverify --verify --protocol swd --speed 12000' + +rustflags = [ + "-C", "linker=flip-link", + "-C", "link-arg=-Tlink.x", + "-C", "link-arg=-Tdefmt.x", + # This is needed if your flash or ram addresses are not aligned to 0x10000 in memory.x + # See https://github.com/rust-embedded/cortex-m-quickstart/pull/95 + "-C", "link-arg=--nmagic", +] + +[build] +target = "thumbv8m.main-none-eabihf" # Cortex-M33 + +[env] +DEFMT_LOG = "trace" diff --git a/examples/mcxa/.gitignore b/examples/mcxa/.gitignore new file mode 100644 index 000000000..2f7896d1d --- /dev/null +++ b/examples/mcxa/.gitignore @@ -0,0 +1 @@ +target/ diff --git a/examples/mcxa/Cargo.lock b/examples/mcxa/Cargo.lock new file mode 100644 index 000000000..c6e864df2 --- /dev/null +++ b/examples/mcxa/Cargo.lock @@ -0,0 +1,1555 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" + +[[package]] +name = "askama" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f75363874b771be265f4ffe307ca705ef6f3baa19011c149da8674a87f1b75c4" +dependencies = [ + "askama_derive", + "itoa", + "percent-encoding", + "serde", + "serde_json", +] + +[[package]] +name = "askama_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "129397200fe83088e8a68407a8e2b1f826cf0086b21ccdb866a722c8bcd3a94f" +dependencies = [ + "askama_parser", + "memchr", + "proc-macro2", + "quote", + "rustc-hash", + "syn 2.0.110", +] + +[[package]] +name = "askama_parser" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ab5630b3d5eaf232620167977f95eb51f3432fc76852328774afbd242d4358" +dependencies = [ + "memchr", + "winnow 0.7.13", +] + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "bare-metal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" +dependencies = [ + "rustc_version", +] + +[[package]] +name = "bitfield" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "cc" +version = "1.2.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cordyceps" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" +dependencies = [ + "loom", + "tracing", +] + +[[package]] +name = "cortex-m" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" +dependencies = [ + "bare-metal", + "bitfield", + "critical-section", + "embedded-hal 0.2.7", + "volatile-register", +] + +[[package]] +name = "cortex-m-rt" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d4dec46b34c299ccf6b036717ae0fce602faa4f4fe816d9013b9a7c9f5ba6" +dependencies = [ + "cortex-m-rt-macros", +] + +[[package]] +name = "cortex-m-rt-macros" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e37549a379a9e0e6e576fd208ee60394ccb8be963889eebba3ffe0980364f472" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.110", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "dd-manifest-tree" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5793572036e0a6638977c7370c6afc423eac848ee8495f079b8fd3964de7b9f9" +dependencies = [ + "toml", +] + +[[package]] +name = "defmt" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "548d977b6da32fa1d1fda2876453da1e7df63ad0304c8b3dae4dbe7b96f39b78" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d4fc12a85bcf441cfe44344c4b72d58493178ce635338a3f3b78943aceb258e" +dependencies = [ + "defmt-parser", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "defmt-rtt" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d5a25c99d89c40f5676bec8cefe0614f17f0f40e916f98e345dae941807f9e" +dependencies = [ + "critical-section", + "defmt", +] + +[[package]] +name = "device-driver" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af0e43acfcbb0bb3b7435cc1b1dbb33596cacfec1eb243336b74a398e0bd6cbf" +dependencies = [ + "device-driver-macros", + "embedded-io", + "embedded-io-async", +] + +[[package]] +name = "device-driver-generation" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3935aec9cf5bb2ab927f59ca69faecf976190390b0ce34c6023889e9041040c0" +dependencies = [ + "anyhow", + "askama", + "bitvec", + "convert_case", + "dd-manifest-tree", + "itertools", + "kdl", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "device-driver-macros" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fdc68ed515c4eddff2e95371185b4becba066085bf36d50f07f09782af98e17" +dependencies = [ + "device-driver-generation", + "proc-macro2", + "syn 2.0.110", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "embassy-embedded-hal" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "554e3e840696f54b4c9afcf28a0f24da431c927f4151040020416e7393d6d0d8" +dependencies = [ + "embassy-futures", + "embassy-hal-internal", + "embassy-sync", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-storage", + "embedded-storage-async", + "nb 1.1.0", +] + +[[package]] +name = "embassy-executor" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06070468370195e0e86f241c8e5004356d696590a678d47d6676795b2e439c6b" +dependencies = [ + "cortex-m", + "critical-section", + "document-features", + "embassy-executor-macros", + "embassy-executor-timer-queue", +] + +[[package]] +name = "embassy-executor-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfdddc3a04226828316bf31393b6903ee162238576b1584ee2669af215d55472" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "embassy-executor-timer-queue" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc328bf943af66b80b98755db9106bf7e7471b0cf47dc8559cd9a6be504cc9c" + +[[package]] +name = "embassy-futures" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc2d050bdc5c21e0862a89256ed8029ae6c290a93aecefc73084b3002cdebb01" + +[[package]] +name = "embassy-hal-internal" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95285007a91b619dc9f26ea8f55452aa6c60f7115a4edc05085cd2bd3127cd7a" +dependencies = [ + "cortex-m", + "critical-section", + "num-traits", +] + +[[package]] +name = "embassy-mcxa" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "embassy-embedded-hal", + "embassy-hal-internal", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "embedded-hal-nb", + "embedded-io", + "embedded-io-async", + "heapless 0.8.0", + "maitake-sync", + "mcxa-pac", + "nb 1.1.0", + "paste", +] + +[[package]] +name = "embassy-mcxa-examples" +version = "0.1.0" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "defmt-rtt", + "embassy-embedded-hal", + "embassy-executor", + "embassy-mcxa", + "embassy-sync", + "embassy-time", + "embassy-time-driver", + "embedded-io-async", + "heapless 0.9.2", + "panic-probe", + "tmp108", +] + +[[package]] +name = "embassy-sync" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73974a3edbd0bd286759b3d483540f0ebef705919a5f56f4fc7709066f71689b" +dependencies = [ + "cfg-if", + "critical-section", + "embedded-io-async", + "futures-core", + "futures-sink", + "heapless 0.8.0", +] + +[[package]] +name = "embassy-time" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4fa65b9284d974dad7a23bb72835c4ec85c0b540d86af7fc4098c88cff51d65" +dependencies = [ + "cfg-if", + "critical-section", + "document-features", + "embassy-time-driver", + "embedded-hal 0.2.7", + "embedded-hal 1.0.0", + "embedded-hal-async", + "futures-core", +] + +[[package]] +name = "embassy-time-driver" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0a244c7dc22c8d0289379c8d8830cae06bb93d8f990194d0de5efb3b5ae7ba6" +dependencies = [ + "document-features", +] + +[[package]] +name = "embedded-hal" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" +dependencies = [ + "nb 0.1.3", + "void", +] + +[[package]] +name = "embedded-hal" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" + +[[package]] +name = "embedded-hal-async" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4c685bbef7fe13c3c6dd4da26841ed3980ef33e841cddfa15ce8a8fb3f1884" +dependencies = [ + "embedded-hal 1.0.0", +] + +[[package]] +name = "embedded-hal-nb" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fba4268c14288c828995299e59b12babdbe170f6c6d73731af1b4648142e8605" +dependencies = [ + "embedded-hal 1.0.0", + "nb 1.1.0", +] + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "embedded-io-async" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff09972d4073aa8c299395be75161d582e7629cd663171d62af73c8d50dba3f" +dependencies = [ + "embedded-io", +] + +[[package]] +name = "embedded-storage" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" + +[[package]] +name = "embedded-storage-async" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1763775e2323b7d5f0aa6090657f5e21cfa02ede71f5dc40eead06d64dcd15cc" +dependencies = [ + "embedded-storage", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "generator" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows", +] + +[[package]] +name = "hash32" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hashbrown" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419bdc4f6a9207fbeba6d11b604d481addf78ecd10c11ad51e76c2f6482748d" + +[[package]] +name = "heapless" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af2455f757db2b292a9b1768c4b70186d443bcb3b316252d6b540aec1cd89ed" +dependencies = [ + "hash32", + "stable_deref_trait", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717a8d2a5a929a1a2eb43a12812498ed141a0bcfb7e8f7844fbdbe4303bba9f" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "kdl" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81a29e7b50079ff44549f68c0becb1c73d7f6de2a4ea952da77966daf3d4761e" +dependencies = [ + "miette", + "num", + "winnow 0.6.24", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "maitake-sync" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "748f86d9befd480b602c3bebc9ef30dbf2f3dfc8acc4a73d07b90f0117e6de3f" +dependencies = [ + "cordyceps", + "critical-section", + "loom", + "mutex-traits", + "mycelium-bitfield", + "pin-project", + "portable-atomic", + "tracing", +] + +[[package]] +name = "manyhow" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b33efb3ca6d3b07393750d4030418d594ab1139cee518f0dc88db70fec873587" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 1.0.109", + "syn 2.0.110", +] + +[[package]] +name = "manyhow-macros" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fce34d199b78b6e6073abf984c9cf5fd3e9330145a93ee0738a7443e371495" +dependencies = [ + "proc-macro-utils", + "proc-macro2", + "quote", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "maybe-async-cfg" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8dbfaa67a76e2623580df07d6bb5e7956c0a4bae4b418314083a9c619bd66627" +dependencies = [ + "manyhow", + "proc-macro2", + "pulldown-cmark", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "mcxa-pac" +version = "0.1.0" +source = "git+https://github.com/OpenDevicePartnership/mcxa-pac#e18dfb52500ca77b8d8326662b966a80251182ca" +dependencies = [ + "cortex-m", + "cortex-m-rt", + "critical-section", + "defmt", + "vcell", +] + +[[package]] +name = "memchr" +version = "2.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" + +[[package]] +name = "miette" +version = "7.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" +dependencies = [ + "cfg-if", + "unicode-width", +] + +[[package]] +name = "mutex-traits" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3929f2b5633d29cf7b6624992e5f3c1e9334f1193423e12d17be4faf678cde3f" + +[[package]] +name = "mycelium-bitfield" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e0cc5e2c585acbd15c5ce911dff71e1f4d5313f43345873311c4f5efd741cc" + +[[package]] +name = "nb" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" +dependencies = [ + "nb 1.1.0", +] + +[[package]] +name = "nb" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d5439c4ad607c3c23abf66de8c8bf57ba8adcd1f129e699851a6e43935d339d" + +[[package]] +name = "nu-ansi-term" +version = "0.50.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "panic-probe" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd402d00b0fb94c5aee000029204a46884b1262e0c443f166d86d2c0747e1a1a" +dependencies = [ + "cortex-m", + "defmt", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +dependencies = [ + "critical-section", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "pulldown-cmark" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625" +dependencies = [ + "bitflags 2.10.0", + "memchr", + "unicase", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "regex-automata" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "serde_json" +version = "1.0.145" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", + "serde_core", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.110" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "thiserror" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "tmp108" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d644cc97d3cee96793f454b834881f78b5d4e89c90ecf26b3690f42004d111" +dependencies = [ + "device-driver", + "embedded-hal 1.0.0", + "maybe-async-cfg", +] + +[[package]] +name = "toml" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "toml_write", + "winnow 0.7.13", +] + +[[package]] +name = "toml_write" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" + +[[package]] +name = "tracing" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eb41cbdb933e23b7929f47bb577710643157d7602ef3a2ebd3902b13ac5eda6" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "tracing-core" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex-automata", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-width" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcell" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" + +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" + +[[package]] +name = "volatile-register" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de437e2a6208b014ab52972a27e59b33fa2920d3e00fe05026167a1c509d19cc" +dependencies = [ + "vcell", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.110", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core", + "windows-link 0.1.3", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link 0.2.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "winnow" +version = "0.6.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] diff --git a/examples/mcxa/Cargo.toml b/examples/mcxa/Cargo.toml new file mode 100644 index 000000000..4da94811f --- /dev/null +++ b/examples/mcxa/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "embassy-mcxa-examples" +version = "0.1.0" +edition = "2021" +license = "MIT OR Apache-2.0" + +[dependencies] +cortex-m = { version = "0.7", features = ["critical-section-single-core"] } +cortex-m-rt = { version = "0.7", features = ["set-sp", "set-vtor"] } +critical-section = "1.2.0" +defmt = "1.0" +defmt-rtt = "1.0" +embassy-embedded-hal = "0.5.0" +embassy-executor = { version = "0.9.0", features = ["arch-cortex-m", "executor-interrupt", "executor-thread"], default-features = false } +embassy-mcxa = { path = "../../embassy-mcxa", features = ["defmt", "unstable-pac", "time"] } +embassy-sync = "0.7.2" +embassy-time = "0.5.0" +embassy-time-driver = "0.2.1" +embedded-io-async = "0.6.1" +heapless = "0.9.2" +panic-probe = { version = "1.0", features = ["print-defmt"] } +tmp108 = "0.4.0" + +[profile.release] +lto = true # better optimizations +debug = 2 # enough information for defmt/rtt locations diff --git a/examples/mcxa/build.rs b/examples/mcxa/build.rs new file mode 100644 index 000000000..f076bba9f --- /dev/null +++ b/examples/mcxa/build.rs @@ -0,0 +1,20 @@ +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + // Generate memory.x - put "FLASH" at start of RAM, RAM after "FLASH" + // cortex-m-rt expects FLASH for code, RAM for data/bss/stack + // Both are in RAM, but separated to satisfy cortex-m-rt's expectations + // MCXA256 has 128KB RAM total + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); + println!("cargo:rerun-if-changed=memory.x"); +} diff --git a/examples/mcxa/memory.x b/examples/mcxa/memory.x new file mode 100644 index 000000000..315ced58a --- /dev/null +++ b/examples/mcxa/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 1M + RAM : ORIGIN = 0x20000000, LENGTH = 128K +} diff --git a/examples/mcxa/src/bin/adc_interrupt.rs b/examples/mcxa/src/bin/adc_interrupt.rs new file mode 100644 index 000000000..83d8046b3 --- /dev/null +++ b/examples/mcxa/src/bin/adc_interrupt.rs @@ -0,0 +1,84 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa_examples::init_adc_pins; +use hal::adc::{LpadcConfig, TriggerPriorityPolicy}; +use hal::clocks::periph_helpers::{AdcClockSel, Div4}; +use hal::clocks::PoweredClock; +use hal::pac::adc1::cfg::{Pwrsel, Refsel}; +use hal::pac::adc1::cmdl1::{Adch, Mode}; +use hal::pac::adc1::ctrl::CalAvgs; +use hal::pac::adc1::tctrl::Tcmd; +use hal::{bind_interrupts, InterruptExt}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!(struct Irqs { + ADC1 => hal::adc::AdcHandler; +}); + +#[used] +#[no_mangle] +static KEEP_ADC: unsafe extern "C" fn() = ADC1; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("ADC interrupt Example"); + + unsafe { + init_adc_pins(); + } + + let adc_config = LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: AdcClockSel::FroLfDiv, + div: Div4::no_div(), + }; + let adc = hal::adc::Adc::::new(p.ADC1, adc_config); + + adc.do_offset_calibration(); + adc.do_auto_calibration(); + + let mut conv_command_config = adc.get_default_conv_command_config(); + conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; + conv_command_config.conversion_resolution_mode = Mode::Data16Bits; + adc.set_conv_command_config(1, &conv_command_config); + + let mut conv_trigger_config = adc.get_default_conv_trigger_config(); + conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; + conv_trigger_config.enable_hardware_trigger = false; + adc.set_conv_trigger_config(0, &conv_trigger_config); + + defmt::info!("ADC configuration done..."); + + adc.enable_interrupt(0x1); + + unsafe { + hal::interrupt::ADC1.enable(); + } + + unsafe { + cortex_m::interrupt::enable(); + } + + loop { + adc.do_software_trigger(1); + while !adc.is_interrupt_triggered() { + // Wait until the interrupt is triggered + } + defmt::info!("*** ADC interrupt TRIGGERED! ***"); + //TBD need to print the value + } +} diff --git a/examples/mcxa/src/bin/adc_polling.rs b/examples/mcxa/src/bin/adc_polling.rs new file mode 100644 index 000000000..ddf3f586b --- /dev/null +++ b/examples/mcxa/src/bin/adc_polling.rs @@ -0,0 +1,68 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa_examples::init_adc_pins; +use hal::adc::{ConvResult, LpadcConfig, TriggerPriorityPolicy}; +use hal::clocks::periph_helpers::{AdcClockSel, Div4}; +use hal::clocks::PoweredClock; +use hal::pac::adc1::cfg::{Pwrsel, Refsel}; +use hal::pac::adc1::cmdl1::{Adch, Mode}; +use hal::pac::adc1::ctrl::CalAvgs; +use hal::pac::adc1::tctrl::Tcmd; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +const G_LPADC_RESULT_SHIFT: u32 = 0; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + unsafe { + init_adc_pins(); + } + + defmt::info!("=== ADC polling Example ==="); + + let adc_config = LpadcConfig { + enable_in_doze_mode: true, + conversion_average_mode: CalAvgs::Average128, + enable_analog_preliminary: true, + power_up_delay: 0x80, + reference_voltage_source: Refsel::Option3, + power_level_mode: Pwrsel::Lowest, + trigger_priority_policy: TriggerPriorityPolicy::ConvPreemptImmediatelyNotAutoResumed, + enable_conv_pause: false, + conv_pause_delay: 0, + fifo_watermark: 0, + power: PoweredClock::NormalEnabledDeepSleepDisabled, + source: AdcClockSel::FroLfDiv, + div: Div4::no_div(), + }; + let adc = hal::adc::Adc::::new(p.ADC1, adc_config); + + adc.do_offset_calibration(); + adc.do_auto_calibration(); + + let mut conv_command_config = adc.get_default_conv_command_config(); + conv_command_config.channel_number = Adch::SelectCorrespondingChannel8; + conv_command_config.conversion_resolution_mode = Mode::Data16Bits; + adc.set_conv_command_config(1, &conv_command_config); + + let mut conv_trigger_config = adc.get_default_conv_trigger_config(); + conv_trigger_config.target_command_id = Tcmd::ExecuteCmd1; + conv_trigger_config.enable_hardware_trigger = false; + adc.set_conv_trigger_config(0, &conv_trigger_config); + + defmt::info!("=== ADC configuration done... ==="); + + loop { + adc.do_software_trigger(1); + let mut result: Option = None; + while result.is_none() { + result = hal::adc::get_conv_result(); + } + let value = result.unwrap().conv_value >> G_LPADC_RESULT_SHIFT; + defmt::info!("value: {=u16}", value); + } +} diff --git a/examples/mcxa/src/bin/blinky.rs b/examples/mcxa/src/bin/blinky.rs new file mode 100644 index 000000000..dd08ec0d9 --- /dev/null +++ b/examples/mcxa/src/bin/blinky.rs @@ -0,0 +1,36 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::gpio::{DriveStrength, Level, Output, SlewRate}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("Blink example"); + + let mut red = Output::new(p.P3_18, Level::High, DriveStrength::Normal, SlewRate::Fast); + let mut green = Output::new(p.P3_19, Level::High, DriveStrength::Normal, SlewRate::Fast); + let mut blue = Output::new(p.P3_21, Level::High, DriveStrength::Normal, SlewRate::Fast); + + loop { + defmt::info!("Toggle LEDs"); + + red.toggle(); + Timer::after_millis(250).await; + + red.toggle(); + green.toggle(); + Timer::after_millis(250).await; + + green.toggle(); + blue.toggle(); + Timer::after_millis(250).await; + blue.toggle(); + + Timer::after_millis(250).await; + } +} diff --git a/examples/mcxa/src/bin/button.rs b/examples/mcxa/src/bin/button.rs new file mode 100644 index 000000000..943edbb15 --- /dev/null +++ b/examples/mcxa/src/bin/button.rs @@ -0,0 +1,23 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::gpio::{Input, Pull}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("Button example"); + + // This button is labeled "WAKEUP" on the FRDM-MCXA276 + // The board already has a 10K pullup + let monitor = Input::new(p.P1_7, Pull::Disabled); + + loop { + defmt::info!("Pin level is {:?}", monitor.get_level()); + Timer::after_millis(1000).await; + } +} diff --git a/examples/mcxa/src/bin/button_async.rs b/examples/mcxa/src/bin/button_async.rs new file mode 100644 index 000000000..6cc7b62cd --- /dev/null +++ b/examples/mcxa/src/bin/button_async.rs @@ -0,0 +1,29 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::gpio::{Input, Pull}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("GPIO interrupt example"); + + // This button is labeled "WAKEUP" on the FRDM-MCXA276 + // The board already has a 10K pullup + let mut pin = Input::new(p.P1_7, Pull::Disabled); + + let mut press_count = 0u32; + + loop { + pin.wait_for_falling_edge().await; + + press_count += 1; + + defmt::info!("Button pressed! Count: {}", press_count); + Timer::after_millis(50).await; + } +} diff --git a/examples/mcxa/src/bin/clkout.rs b/examples/mcxa/src/bin/clkout.rs new file mode 100644 index 000000000..bfd963540 --- /dev/null +++ b/examples/mcxa/src/bin/clkout.rs @@ -0,0 +1,69 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::clkout::{ClockOut, ClockOutSel, Config, Div4}; +use embassy_mcxa::clocks::PoweredClock; +use embassy_mcxa::gpio::{DriveStrength, SlewRate}; +use embassy_mcxa::{Level, Output}; +use embassy_time::Timer; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +/// Demonstrate CLKOUT, using Pin P4.2 +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + let mut pin = p.P4_2; + let mut clkout = p.CLKOUT; + + loop { + defmt::info!("Set Low..."); + let mut output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); + Timer::after_millis(500).await; + + defmt::info!("Set High..."); + output.set_high(); + Timer::after_millis(400).await; + + defmt::info!("Set Low..."); + output.set_low(); + Timer::after_millis(500).await; + + defmt::info!("16k..."); + // Run Clock Out with the 16K clock + let _clock_out = ClockOut::new( + clkout.reborrow(), + pin.reborrow(), + Config { + sel: ClockOutSel::Clk16K, + div: Div4::no_div(), + level: PoweredClock::NormalEnabledDeepSleepDisabled, + }, + ) + .unwrap(); + + Timer::after_millis(3000).await; + + defmt::info!("Set Low..."); + drop(_clock_out); + + let _output = Output::new(pin.reborrow(), Level::Low, DriveStrength::Normal, SlewRate::Slow); + Timer::after_millis(500).await; + + // Run Clock Out with the 12M clock, divided by 3 + defmt::info!("4M..."); + let _clock_out = ClockOut::new( + clkout.reborrow(), + pin.reborrow(), + Config { + sel: ClockOutSel::Fro12M, + div: const { Div4::from_divisor(3).unwrap() }, + level: PoweredClock::NormalEnabledDeepSleepDisabled, + }, + ) + .unwrap(); + + // Let it run for 3 seconds... + Timer::after_millis(3000).await; + } +} diff --git a/examples/mcxa/src/bin/hello.rs b/examples/mcxa/src/bin/hello.rs new file mode 100644 index 000000000..e371d9413 --- /dev/null +++ b/examples/mcxa/src/bin/hello.rs @@ -0,0 +1,119 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::clocks::config::Div8; +use hal::lpuart::{Blocking, Config, Lpuart}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +/// Simple helper to write a byte as hex to UART +fn write_hex_byte(uart: &mut Lpuart<'_, Blocking>, byte: u8) { + const HEX_DIGITS: &[u8] = b"0123456789ABCDEF"; + let _ = uart.write_byte(HEX_DIGITS[(byte >> 4) as usize]); + let _ = uart.write_byte(HEX_DIGITS[(byte & 0xF) as usize]); +} + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut cfg = hal::config::Config::default(); + cfg.clock_cfg.sirc.fro_12m_enabled = true; + cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); + let p = hal::init(cfg); + + defmt::info!("boot"); + + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + ..Default::default() + }; + + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX + let mut uart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.P2_2, // TX pin + p.P2_3, // RX pin + config, + ) + .unwrap(); + + // Print welcome message before any async delays to guarantee early console output + uart.write_str_blocking("\r\n=== MCXA276 UART Echo Demo ===\r\n"); + uart.write_str_blocking("Available commands:\r\n"); + uart.write_str_blocking(" help - Show this help\r\n"); + uart.write_str_blocking(" echo - Echo back the text\r\n"); + uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); + uart.write_str_blocking("Type a command: "); + + let mut buffer = [0u8; 64]; + let mut buf_idx = 0; + + loop { + // Read a byte from UART + let byte = uart.read_byte_blocking(); + + // Echo the character back + if byte == b'\r' || byte == b'\n' { + // Enter pressed - process command + uart.write_str_blocking("\r\n"); + + if buf_idx > 0 { + let command = &buffer[0..buf_idx]; + + if command == b"help" { + uart.write_str_blocking("Available commands:\r\n"); + uart.write_str_blocking(" help - Show this help\r\n"); + uart.write_str_blocking(" echo - Echo back the text\r\n"); + uart.write_str_blocking(" hex - Display byte in hex (0-255)\r\n"); + } else if command.starts_with(b"echo ") && command.len() > 5 { + uart.write_str_blocking("Echo: "); + uart.write_str_blocking(core::str::from_utf8(&command[5..]).unwrap_or("")); + uart.write_str_blocking("\r\n"); + } else if command.starts_with(b"hex ") && command.len() > 4 { + // Parse the byte value + let num_str = &command[4..]; + if let Ok(num) = parse_u8(num_str) { + uart.write_str_blocking("Hex: 0x"); + write_hex_byte(&mut uart, num); + uart.write_str_blocking("\r\n"); + } else { + uart.write_str_blocking("Invalid number for hex command\r\n"); + } + } else if !command.is_empty() { + uart.write_str_blocking("Unknown command: "); + uart.write_str_blocking(core::str::from_utf8(command).unwrap_or("")); + uart.write_str_blocking("\r\n"); + } + } + + // Reset buffer and prompt + buf_idx = 0; + uart.write_str_blocking("Type a command: "); + } else if byte == 8 || byte == 127 { + // Backspace + if buf_idx > 0 { + buf_idx -= 1; + uart.write_str_blocking("\x08 \x08"); // Erase character + } + } else if buf_idx < buffer.len() - 1 { + // Regular character + buffer[buf_idx] = byte; + buf_idx += 1; + let _ = uart.write_byte(byte); + } + } +} + +/// Simple parser for u8 from ASCII bytes +fn parse_u8(bytes: &[u8]) -> Result { + let mut result = 0u8; + for &b in bytes { + if b.is_ascii_digit() { + result = result.checked_mul(10).ok_or(())?; + result = result.checked_add(b - b'0').ok_or(())?; + } else { + return Err(()); + } + } + Ok(result) +} diff --git a/examples/mcxa/src/bin/i2c-async.rs b/examples/mcxa/src/bin/i2c-async.rs new file mode 100644 index 000000000..47b5f3cbe --- /dev/null +++ b/examples/mcxa/src/bin/i2c-async.rs @@ -0,0 +1,39 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::bind_interrupts; +use hal::clocks::config::Div8; +use hal::config::Config; +use hal::i2c::controller::{self, I2c, Speed}; +use hal::i2c::InterruptHandler; +use hal::peripherals::LPI2C3; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!( + struct Irqs { + LPI2C3 => InterruptHandler; + } +); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); + + let p = hal::init(config); + + defmt::info!("I2C example"); + + let mut config = controller::Config::default(); + config.speed = Speed::Standard; + let mut i2c = I2c::new_async(p.LPI2C3, p.P3_27, p.P3_28, Irqs, config).unwrap(); + let mut buf = [0u8; 2]; + + loop { + i2c.async_write_read(0x48, &[0x00], &mut buf).await.unwrap(); + defmt::info!("Buffer: {:02x}", buf); + Timer::after_secs(1).await; + } +} diff --git a/examples/mcxa/src/bin/i2c-blocking.rs b/examples/mcxa/src/bin/i2c-blocking.rs new file mode 100644 index 000000000..0f6c8cbae --- /dev/null +++ b/examples/mcxa/src/bin/i2c-blocking.rs @@ -0,0 +1,31 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_time::Timer; +use hal::clocks::config::Div8; +use hal::config::Config; +use hal::i2c::controller::{self, I2c, Speed}; +use tmp108::Tmp108; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); + + let p = hal::init(config); + + defmt::info!("I2C example"); + + let mut config = controller::Config::default(); + config.speed = Speed::Standard; + let i2c = I2c::new_blocking(p.LPI2C3, p.P3_27, p.P3_28, config).unwrap(); + let mut tmp = Tmp108::new_with_a0_gnd(i2c); + + loop { + let temperature = tmp.temperature().unwrap(); + defmt::info!("Temperature: {}C", temperature); + Timer::after_secs(1).await; + } +} diff --git a/examples/mcxa/src/bin/i2c-scan-blocking.rs b/examples/mcxa/src/bin/i2c-scan-blocking.rs new file mode 100644 index 000000000..4e203597b --- /dev/null +++ b/examples/mcxa/src/bin/i2c-scan-blocking.rs @@ -0,0 +1,41 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::gpio::Pull; +use embassy_mcxa::Input; +use embassy_time::Timer; +use hal::clocks::config::Div8; +use hal::config::Config; +use hal::i2c::controller::{self, I2c, Speed}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut config = Config::default(); + config.clock_cfg.sirc.fro_lf_div = Div8::from_divisor(1); + + let p = hal::init(config); + + defmt::info!("I2C example"); + + let mut config = controller::Config::default(); + config.speed = Speed::Standard; + + // Note: P0_2 is connected to P1_8 on the FRDM_MCXA276 via a resistor, and + // defaults to SWO on the debug peripheral. Explicitly make it a high-z + // input. + let _pin = Input::new(p.P0_2, Pull::Disabled); + let mut i2c = I2c::new_blocking(p.LPI2C2, p.P1_9, p.P1_8, config).unwrap(); + + for addr in 0x01..=0x7f { + let result = i2c.blocking_write(addr, &[]); + if result.is_ok() { + defmt::info!("Device found at addr {:02x}", addr); + } + } + + loop { + Timer::after_secs(10).await; + } +} diff --git a/examples/mcxa/src/bin/lpuart_buffered.rs b/examples/mcxa/src/bin/lpuart_buffered.rs new file mode 100644 index 000000000..420589d00 --- /dev/null +++ b/examples/mcxa/src/bin/lpuart_buffered.rs @@ -0,0 +1,62 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::clocks::config::Div8; +use embassy_mcxa::lpuart::buffered::BufferedLpuart; +use embassy_mcxa::lpuart::Config; +use embassy_mcxa::{bind_interrupts, lpuart}; +use embedded_io_async::Write; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +// Bind OS_EVENT for timers plus LPUART2 IRQ for the buffered driver +bind_interrupts!(struct Irqs { + LPUART2 => lpuart::buffered::BufferedInterruptHandler::; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut cfg = hal::config::Config::default(); + cfg.clock_cfg.sirc.fro_12m_enabled = true; + cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); + let p = hal::init(cfg); + + // Configure NVIC for LPUART2 + hal::interrupt::LPUART2.configure_for_uart(hal::interrupt::Priority::P3); + + // UART configuration (enable both TX and RX) + let config = Config { + baudrate_bps: 115_200, + rx_fifo_watermark: 0, + tx_fifo_watermark: 0, + ..Default::default() + }; + + let mut tx_buf = [0u8; 256]; + let mut rx_buf = [0u8; 256]; + + // Create a buffered LPUART2 instance with both TX and RX + let mut uart = BufferedLpuart::new( + p.LPUART2, + p.P2_2, // TX pin + p.P2_3, // RX pin + Irqs, + &mut tx_buf, + &mut rx_buf, + config, + ) + .unwrap(); + + // Split into TX and RX parts + let (tx, rx) = uart.split_ref(); + + tx.write(b"Hello buffered LPUART.\r\n").await.unwrap(); + tx.write(b"Type characters to echo them back.\r\n").await.unwrap(); + + // Echo loop + let mut buf = [0u8; 4]; + loop { + let used = rx.read(&mut buf).await.unwrap(); + tx.write_all(&buf[..used]).await.unwrap(); + } +} diff --git a/examples/mcxa/src/bin/lpuart_polling.rs b/examples/mcxa/src/bin/lpuart_polling.rs new file mode 100644 index 000000000..b80668834 --- /dev/null +++ b/examples/mcxa/src/bin/lpuart_polling.rs @@ -0,0 +1,47 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::clocks::config::Div8; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +use crate::hal::lpuart::{Config, Lpuart}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let mut cfg = hal::config::Config::default(); + cfg.clock_cfg.sirc.fro_12m_enabled = true; + cfg.clock_cfg.sirc.fro_lf_div = Some(Div8::no_div()); + let p = hal::init(cfg); + + defmt::info!("boot"); + + // Create UART configuration + let config = Config { + baudrate_bps: 115_200, + ..Default::default() + }; + + // Create UART instance using LPUART2 with P2_2 as TX and P2_3 as RX + let lpuart = Lpuart::new_blocking( + p.LPUART2, // Peripheral + p.P2_2, // TX pin + p.P2_3, // RX pin + config, + ) + .unwrap(); + + // Split into separate TX and RX parts + let (mut tx, mut rx) = lpuart.split(); + + // Write hello messages + tx.blocking_write(b"Hello world.\r\n").unwrap(); + tx.blocking_write(b"Echoing. Type characters...\r\n").unwrap(); + + // Echo loop + loop { + let mut buf = [0u8; 1]; + rx.blocking_read(&mut buf).unwrap(); + tx.blocking_write(&buf).unwrap(); + } +} diff --git a/examples/mcxa/src/bin/rtc_alarm.rs b/examples/mcxa/src/bin/rtc_alarm.rs new file mode 100644 index 000000000..fe355888b --- /dev/null +++ b/examples/mcxa/src/bin/rtc_alarm.rs @@ -0,0 +1,47 @@ +#![no_std] +#![no_main] + +use embassy_executor::Spawner; +use embassy_mcxa::bind_interrupts; +use hal::rtc::{InterruptHandler, Rtc, RtcDateTime}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +bind_interrupts!(struct Irqs { + RTC => InterruptHandler; +}); + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = hal::init(hal::config::Config::default()); + + defmt::info!("=== RTC Alarm Example ==="); + + let rtc_config = hal::rtc::get_default_config(); + + let mut rtc = Rtc::new(p.RTC0, Irqs, rtc_config); + + let now = RtcDateTime { + year: 2025, + month: 10, + day: 15, + hour: 14, + minute: 30, + second: 0, + }; + + rtc.stop(); + + defmt::info!("Time set to: 2025-10-15 14:30:00"); + rtc.set_datetime(now); + + let mut alarm = now; + alarm.second += 10; + + defmt::info!("Alarm set for: 2025-10-15 14:30:10 (+10 seconds)"); + defmt::info!("RTC started, waiting for alarm..."); + + rtc.wait_for_alarm(alarm).await; + defmt::info!("*** ALARM TRIGGERED! ***"); + + defmt::info!("Example complete - Test PASSED!"); +} diff --git a/examples/mcxa/src/lib.rs b/examples/mcxa/src/lib.rs new file mode 100644 index 000000000..2573a6adc --- /dev/null +++ b/examples/mcxa/src/lib.rs @@ -0,0 +1,16 @@ +#![no_std] +#![allow(clippy::missing_safety_doc)] + +//! Shared board-specific helpers for the FRDM-MCXA276 examples. +//! These live with the examples so the HAL stays generic. + +use hal::{clocks, pins}; +use {defmt_rtt as _, embassy_mcxa as hal, panic_probe as _}; + +/// Initialize clocks and pin muxing for ADC. +pub unsafe fn init_adc_pins() { + // NOTE: Lpuart has been updated to properly enable + reset its own clocks. + // GPIO has not. + _ = clocks::enable_and_reset::(&clocks::periph_helpers::NoConfig); + pins::configure_adc_pins(); +} -- cgit