#![no_std]
#![allow(async_fn_in_trait)]
#![doc = include_str!("../README.md")]
// //! ## Feature flags
// #![doc = document_features::document_features!(feature_label = r#"{feature}"#)]
pub mod clocks; // still provide clock helpers
pub mod dma;
pub mod gpio;
pub mod adc;
pub mod clkout;
pub mod config;
pub mod crc;
pub mod i2c;
pub mod interrupt;
pub mod lpuart;
pub mod ostimer;
pub mod reset_reason;
pub mod rtc;
use crate::interrupt::InterruptExt;
pub use crate::pac::NVIC_PRIO_BITS;
#[rustfmt::skip]
embassy_hal_internal::peripherals!(
ADC0,
ADC1,
ADC2,
ADC3,
AOI0,
AOI1,
CAN0,
CAN1,
CDOG0,
CDOG1,
// CLKOUT is not specifically a peripheral (it's part of SYSCON),
// but we still want it to be a singleton.
CLKOUT,
CMC,
CMP0,
CMP1,
CRC0,
CTIMER0,
CTIMER1,
CTIMER2,
CTIMER3,
CTIMER4,
DBGMAILBOX,
DMA0,
DMA_CH0,
DMA_CH1,
DMA_CH2,
DMA_CH3,
DMA_CH4,
DMA_CH5,
DMA_CH6,
DMA_CH7,
EDMA0_TCD0,
EIM0,
EQDC0,
EQDC1,
ERM0,
FLEXIO0,
FLEXPWM0,
FLEXPWM1,
FMC0,
FMU0,
FREQME0,
GLIKEY0,
GPIO0,
GPIO1,
GPIO2,
GPIO3,
GPIO4,
I3C0,
INPUTMUX0,
LPI2C0,
LPI2C1,
LPI2C2,
LPI2C3,
LPSPI0,
LPSPI1,
LPTMR0,
LPUART0,
LPUART1,
LPUART2,
LPUART3,
LPUART4,
LPUART5,
MAU0,
MBC0,
MRCC0,
OPAMP0,
#[cfg(not(feature = "time"))]
OSTIMER0,
P0_0,
P0_1,
P0_2,
P0_3,
P0_4,
P0_5,
P0_6,
P0_7,
P0_8,
P0_9,
P0_10,
P0_11,
P0_12,
P0_13,
P0_14,
P0_15,
P0_16,
P0_17,
P0_18,
P0_19,
P0_20,
P0_21,
P0_22,
P0_23,
P0_24,
P0_25,
P0_26,
P0_27,
P0_28,
P0_29,
P0_30,
P0_31,
P1_0,
P1_1,
P1_2,
P1_3,
P1_4,
P1_5,
P1_6,
P1_7,
P1_8,
P1_9,
P1_10,
P1_11,
P1_12,
P1_13,
P1_14,
P1_15,
P1_16,
P1_17,
P1_18,
P1_19,
P1_20,
P1_21,
P1_22,
P1_23,
P1_24,
P1_25,
P1_26,
P1_27,
P1_28,
P1_29,
P1_30,
P1_31,
P2_0,
P2_1,
P2_2,
P2_3,
P2_4,
P2_5,
P2_6,
P2_7,
P2_8,
P2_9,
P2_10,
P2_11,
P2_12,
P2_13,
P2_14,
P2_15,
P2_16,
P2_17,
P2_18,
P2_19,
P2_20,
P2_21,
P2_22,
P2_23,
P2_24,
P2_25,
P2_26,
P2_27,
P2_28,
P2_29,
P2_30,
P2_31,
P3_0,
P3_1,
P3_2,
P3_3,
P3_4,
P3_5,
P3_6,
P3_7,
P3_8,
P3_9,
P3_10,
P3_11,
P3_12,
P3_13,
P3_14,
P3_15,
P3_16,
P3_17,
P3_18,
P3_19,
P3_20,
P3_21,
P3_22,
P3_23,
P3_24,
P3_25,
P3_26,
P3_27,
P3_28,
P3_29,
P3_30,
P3_31,
P4_0,
P4_1,
P4_2,
P4_3,
P4_4,
P4_5,
P4_6,
P4_7,
P4_8,
P4_9,
P4_10,
P4_11,
P4_12,
P4_13,
P4_14,
P4_15,
P4_16,
P4_17,
P4_18,
P4_19,
P4_20,
P4_21,
P4_22,
P4_23,
P4_24,
P4_25,
P4_26,
P4_27,
P4_28,
P4_29,
P4_30,
P4_31,
P5_0,
P5_1,
P5_2,
P5_3,
P5_4,
P5_5,
P5_6,
P5_7,
P5_8,
P5_9,
P5_10,
P5_11,
P5_12,
P5_13,
P5_14,
P5_15,
P5_16,
P5_17,
P5_18,
P5_19,
P5_20,
P5_21,
P5_22,
P5_23,
P5_24,
P5_25,
P5_26,
P5_27,
P5_28,
P5_29,
P5_30,
P5_31,
PKC0,
PORT0,
PORT1,
PORT2,
PORT3,
PORT4,
RTC0,
SAU,
SCG0,
SCN_SCB,
SGI0,
SMARTDMA0,
SPC0,
SYSCON,
TDET0,
TRNG0,
UDF0,
USB0,
UTICK0,
VBAT0,
WAKETIMER0,
WUU0,
WWDT0,
);
// Use cortex-m-rt's #[interrupt] attribute directly; PAC does not re-export it.
// Re-export interrupt traits and types
#[cfg(feature = "unstable-pac")]
pub use mcxa_pac as pac;
#[cfg(not(feature = "unstable-pac"))]
pub(crate) use mcxa_pac as pac;
/// Initialize HAL with configuration (mirrors embassy-imxrt style). Minimal: just take peripherals.
/// Also applies configurable NVIC priority for the OSTIMER OS_EVENT interrupt (no enabling).
pub fn init(cfg: crate::config::Config) -> Peripherals {
let peripherals = Peripherals::take();
// Apply user-configured priority early; enabling is left to examples/apps
#[cfg(feature = "time")]
crate::interrupt::OS_EVENT.set_priority(cfg.time_interrupt_priority);
// Apply user-configured priority early; enabling is left to examples/apps
crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority);
// Apply user-configured priority early; enabling is left to examples/apps
crate::interrupt::GPIO0.set_priority(cfg.gpio_interrupt_priority);
// Apply user-configured priority early; enabling is left to examples/apps
crate::interrupt::GPIO1.set_priority(cfg.gpio_interrupt_priority);
// Apply user-configured priority early; enabling is left to examples/apps
crate::interrupt::GPIO2.set_priority(cfg.gpio_interrupt_priority);
// Apply user-configured priority early; enabling is left to examples/apps
crate::interrupt::GPIO3.set_priority(cfg.gpio_interrupt_priority);
// Apply user-configured priority early; enabling is left to examples/apps
crate::interrupt::GPIO4.set_priority(cfg.gpio_interrupt_priority);
// Configure clocks
crate::clocks::init(cfg.clock_cfg).unwrap();
unsafe {
crate::gpio::init();
}
// Initialize DMA controller (clock, reset, configuration)
crate::dma::init();
// Initialize embassy-time global driver backed by OSTIMER0
#[cfg(feature = "time")]
crate::ostimer::time_driver::init(crate::config::Config::default().time_interrupt_priority, 1_000_000);
// Enable GPIO clocks
unsafe {
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
_ = crate::clocks::enable_and_reset::(&crate::clocks::periph_helpers::NoConfig);
}
peripherals
}
/// Macro to bind interrupts to handlers, similar to embassy-imxrt.
///
/// Example:
/// - Bind OS_EVENT to the OSTIMER time-driver handler
/// bind_interrupts!(struct Irqs { OS_EVENT => crate::ostimer::time_driver::OsEventHandler; });
#[macro_export]
macro_rules! bind_interrupts {
($(#[$attr:meta])* $vis:vis struct $name:ident {
$(
$(#[cfg($cond_irq:meta)])?
$irq:ident => $(
$(#[cfg($cond_handler:meta)])?
$handler:ty
),*;
)*
}) => {
#[derive(Copy, Clone)]
$(#[$attr])*
$vis struct $name;
$(
#[allow(non_snake_case)]
#[no_mangle]
$(#[cfg($cond_irq)])?
unsafe extern "C" fn $irq() {
unsafe {
$(
$(#[cfg($cond_handler)])?
<$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
)*
}
}
$(#[cfg($cond_irq)])?
$crate::bind_interrupts!(@inner
$(
$(#[cfg($cond_handler)])?
unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
)*
);
)*
};
(@inner $($t:tt)*) => {
$($t)*
}
}