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