aboutsummaryrefslogtreecommitdiff
path: root/embassy-mcxa/src/lib.rs
diff options
context:
space:
mode:
authorJames Munns <[email protected]>2025-12-04 18:37:01 +0100
committerJames Munns <[email protected]>2025-12-04 18:43:11 +0100
commitdc6bf5d44675f6f2013ddfab6b14df25a996a965 (patch)
treeab593af8f4b2be502a809833f80e4f3b741b8fad /embassy-mcxa/src/lib.rs
parent22bae2d80153003af4637c4b0cc26d52858f5228 (diff)
Move to subfolder
Diffstat (limited to 'embassy-mcxa/src/lib.rs')
-rw-r--r--embassy-mcxa/src/lib.rs471
1 files changed, 471 insertions, 0 deletions
diff --git a/embassy-mcxa/src/lib.rs b/embassy-mcxa/src/lib.rs
new file mode 100644
index 000000000..c6d8adc8f
--- /dev/null
+++ b/embassy-mcxa/src/lib.rs
@@ -0,0 +1,471 @@
1#![no_std]
2#![allow(async_fn_in_trait)]
3#![doc = include_str!("../README.md")]
4
5// //! ## Feature flags
6// #![doc = document_features::document_features!(feature_label = r#"<span class="stab portability"><code>{feature}</code></span>"#)]
7
8pub mod clocks; // still provide clock helpers
9pub mod gpio;
10pub mod pins; // pin mux helpers
11
12pub mod adc;
13pub mod clkout;
14pub mod config;
15pub mod i2c;
16pub mod interrupt;
17pub mod lpuart;
18pub mod ostimer;
19pub mod rtc;
20
21pub use crate::pac::NVIC_PRIO_BITS;
22
23#[rustfmt::skip]
24embassy_hal_internal::peripherals!(
25 ADC0,
26 ADC1,
27
28 AOI0,
29 AOI1,
30
31 CAN0,
32 CAN1,
33
34 CDOG0,
35 CDOG1,
36
37 // CLKOUT is not specifically a peripheral (it's part of SYSCON),
38 // but we still want it to be a singleton.
39 CLKOUT,
40
41 CMC,
42 CMP0,
43 CMP1,
44 CRC0,
45
46 CTIMER0,
47 CTIMER1,
48 CTIMER2,
49 CTIMER3,
50 CTIMER4,
51
52 DBGMAILBOX,
53 DMA0,
54 EDMA0_TCD0,
55 EIM0,
56 EQDC0,
57 EQDC1,
58 ERM0,
59 FLEXIO0,
60 FLEXPWM0,
61 FLEXPWM1,
62 FMC0,
63 FMU0,
64 FREQME0,
65 GLIKEY0,
66
67 GPIO0,
68 GPIO1,
69 GPIO2,
70 GPIO3,
71 GPIO4,
72
73 I3C0,
74 INPUTMUX0,
75
76 LPI2C0,
77 LPI2C1,
78 LPI2C2,
79 LPI2C3,
80
81 LPSPI0,
82 LPSPI1,
83
84 LPTMR0,
85
86 LPUART0,
87 LPUART1,
88 LPUART2,
89 LPUART3,
90 LPUART4,
91 LPUART5,
92
93 MAU0,
94 MBC0,
95 MRCC0,
96 OPAMP0,
97
98 #[cfg(not(feature = "time"))]
99 OSTIMER0,
100
101 P0_0,
102 P0_1,
103 P0_2,
104 P0_3,
105 P0_4,
106 P0_5,
107 P0_6,
108 P0_7,
109 P0_8,
110 P0_9,
111 P0_10,
112 P0_11,
113 P0_12,
114 P0_13,
115 P0_14,
116 P0_15,
117 P0_16,
118 P0_17,
119 P0_18,
120 P0_19,
121 P0_20,
122 P0_21,
123 P0_22,
124 P0_23,
125 P0_24,
126 P0_25,
127 P0_26,
128 P0_27,
129 P0_28,
130 P0_29,
131 P0_30,
132 P0_31,
133
134 P1_0,
135 P1_1,
136 P1_2,
137 P1_3,
138 P1_4,
139 P1_5,
140 P1_6,
141 P1_7,
142 P1_8,
143 P1_9,
144 P1_10,
145 P1_11,
146 P1_12,
147 P1_13,
148 P1_14,
149 P1_15,
150 P1_16,
151 P1_17,
152 P1_18,
153 P1_19,
154 P1_20,
155 P1_21,
156 P1_22,
157 P1_23,
158 P1_24,
159 P1_25,
160 P1_26,
161 P1_27,
162 P1_28,
163 P1_29,
164 P1_30,
165 P1_31,
166
167 P2_0,
168 P2_1,
169 P2_2,
170 P2_3,
171 P2_4,
172 P2_5,
173 P2_6,
174 P2_7,
175 P2_8,
176 P2_9,
177 P2_10,
178 P2_11,
179 P2_12,
180 P2_13,
181 P2_14,
182 P2_15,
183 P2_16,
184 P2_17,
185 P2_18,
186 P2_19,
187 P2_20,
188 P2_21,
189 P2_22,
190 P2_23,
191 P2_24,
192 P2_25,
193 P2_26,
194 P2_27,
195 P2_28,
196 P2_29,
197 P2_30,
198 P2_31,
199
200 P3_0,
201 P3_1,
202 P3_2,
203 P3_3,
204 P3_4,
205 P3_5,
206 P3_6,
207 P3_7,
208 P3_8,
209 P3_9,
210 P3_10,
211 P3_11,
212 P3_12,
213 P3_13,
214 P3_14,
215 P3_15,
216 P3_16,
217 P3_17,
218 P3_18,
219 P3_19,
220 P3_20,
221 P3_21,
222 P3_22,
223 P3_23,
224 P3_24,
225 P3_25,
226 P3_26,
227 P3_27,
228 P3_28,
229 P3_29,
230 P3_30,
231 P3_31,
232
233 P4_0,
234 P4_1,
235 P4_2,
236 P4_3,
237 P4_4,
238 P4_5,
239 P4_6,
240 P4_7,
241 P4_8,
242 P4_9,
243 P4_10,
244 P4_11,
245 P4_12,
246 P4_13,
247 P4_14,
248 P4_15,
249 P4_16,
250 P4_17,
251 P4_18,
252 P4_19,
253 P4_20,
254 P4_21,
255 P4_22,
256 P4_23,
257 P4_24,
258 P4_25,
259 P4_26,
260 P4_27,
261 P4_28,
262 P4_29,
263 P4_30,
264 P4_31,
265
266 P5_0,
267 P5_1,
268 P5_2,
269 P5_3,
270 P5_4,
271 P5_5,
272 P5_6,
273 P5_7,
274 P5_8,
275 P5_9,
276 P5_10,
277 P5_11,
278 P5_12,
279 P5_13,
280 P5_14,
281 P5_15,
282 P5_16,
283 P5_17,
284 P5_18,
285 P5_19,
286 P5_20,
287 P5_21,
288 P5_22,
289 P5_23,
290 P5_24,
291 P5_25,
292 P5_26,
293 P5_27,
294 P5_28,
295 P5_29,
296 P5_30,
297 P5_31,
298
299 PKC0,
300
301 PORT0,
302 PORT1,
303 PORT2,
304 PORT3,
305 PORT4,
306
307 RTC0,
308 SAU,
309 SCG0,
310 SCN_SCB,
311 SGI0,
312 SMARTDMA0,
313 SPC0,
314 SYSCON,
315 TDET0,
316 TRNG0,
317 UDF0,
318 USB0,
319 UTICK0,
320 VBAT0,
321 WAKETIMER0,
322 WUU0,
323 WWDT0,
324);
325
326// Use cortex-m-rt's #[interrupt] attribute directly; PAC does not re-export it.
327
328// Re-export interrupt traits and types
329pub use adc::Adc1 as Adc1Token;
330pub use gpio::{AnyPin, Flex, Gpio as GpioToken, Input, Level, Output};
331pub use interrupt::InterruptExt;
332#[cfg(feature = "unstable-pac")]
333pub use mcxa_pac as pac;
334#[cfg(not(feature = "unstable-pac"))]
335pub(crate) use mcxa_pac as pac;
336
337/// Initialize HAL with configuration (mirrors embassy-imxrt style). Minimal: just take peripherals.
338/// Also applies configurable NVIC priority for the OSTIMER OS_EVENT interrupt (no enabling).
339pub fn init(cfg: crate::config::Config) -> Peripherals {
340 let peripherals = Peripherals::take();
341 // Apply user-configured priority early; enabling is left to examples/apps
342 #[cfg(feature = "time")]
343 crate::interrupt::OS_EVENT.set_priority(cfg.time_interrupt_priority);
344 // Apply user-configured priority early; enabling is left to examples/apps
345 crate::interrupt::RTC.set_priority(cfg.rtc_interrupt_priority);
346 // Apply user-configured priority early; enabling is left to examples/apps
347 crate::interrupt::ADC1.set_priority(cfg.adc_interrupt_priority);
348 // Apply user-configured priority early; enabling is left to examples/apps
349 crate::interrupt::GPIO0.set_priority(cfg.gpio_interrupt_priority);
350 // Apply user-configured priority early; enabling is left to examples/apps
351 crate::interrupt::GPIO1.set_priority(cfg.gpio_interrupt_priority);
352 // Apply user-configured priority early; enabling is left to examples/apps
353 crate::interrupt::GPIO2.set_priority(cfg.gpio_interrupt_priority);
354 // Apply user-configured priority early; enabling is left to examples/apps
355 crate::interrupt::GPIO3.set_priority(cfg.gpio_interrupt_priority);
356 // Apply user-configured priority early; enabling is left to examples/apps
357 crate::interrupt::GPIO4.set_priority(cfg.gpio_interrupt_priority);
358
359 // Configure clocks
360 crate::clocks::init(cfg.clock_cfg).unwrap();
361
362 unsafe {
363 crate::gpio::init();
364 }
365
366 // Initialize embassy-time global driver backed by OSTIMER0
367 #[cfg(feature = "time")]
368 crate::ostimer::time_driver::init(crate::config::Config::default().time_interrupt_priority, 1_000_000);
369
370 // Enable GPIO clocks
371 unsafe {
372 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT0>(&crate::clocks::periph_helpers::NoConfig);
373 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO0>(&crate::clocks::periph_helpers::NoConfig);
374
375 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT1>(&crate::clocks::periph_helpers::NoConfig);
376 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO1>(&crate::clocks::periph_helpers::NoConfig);
377
378 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT2>(&crate::clocks::periph_helpers::NoConfig);
379 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO2>(&crate::clocks::periph_helpers::NoConfig);
380
381 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT3>(&crate::clocks::periph_helpers::NoConfig);
382 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO3>(&crate::clocks::periph_helpers::NoConfig);
383
384 _ = crate::clocks::enable_and_reset::<crate::peripherals::PORT4>(&crate::clocks::periph_helpers::NoConfig);
385 _ = crate::clocks::enable_and_reset::<crate::peripherals::GPIO4>(&crate::clocks::periph_helpers::NoConfig);
386 }
387
388 peripherals
389}
390
391// /// Optional hook called by cortex-m-rt before RAM init.
392// /// We proactively mask and clear all NVIC IRQs to avoid wedges from stale state
393// /// left by soft resets/debug sessions.
394// ///
395// /// NOTE: Manual VTOR setup is required for RAM execution. The cortex-m-rt 'set-vtor'
396// /// feature is incompatible with our setup because it expects __vector_table to be
397// /// defined differently than how our RAM-based linker script arranges it.
398// #[no_mangle]
399// pub unsafe extern "C" fn __pre_init() {
400// // Set the VTOR to point to the interrupt vector table in RAM
401// // This is required since code runs from RAM on this MCU
402// crate::interrupt::vtor_set_ram_vector_base(0x2000_0000 as *const u32);
403
404// // Mask and clear pending for all NVIC lines (0..127) to avoid stale state across runs.
405// let nvic = &*cortex_m::peripheral::NVIC::PTR;
406// for i in 0..4 {
407// // 4 words x 32 = 128 IRQs
408// nvic.icer[i].write(0xFFFF_FFFF);
409// nvic.icpr[i].write(0xFFFF_FFFF);
410// }
411// // Do NOT touch peripheral registers here: clocks may be off and accesses can fault.
412// crate::interrupt::clear_default_handler_snapshot();
413// }
414
415/// Internal helper to dispatch a type-level interrupt handler.
416#[inline(always)]
417#[doc(hidden)]
418pub unsafe fn __handle_interrupt<T, H>()
419where
420 T: crate::interrupt::typelevel::Interrupt,
421 H: crate::interrupt::typelevel::Handler<T>,
422{
423 H::on_interrupt();
424}
425
426/// Macro to bind interrupts to handlers, similar to embassy-imxrt.
427///
428/// Example:
429/// - Bind OS_EVENT to the OSTIMER time-driver handler
430/// bind_interrupts!(struct Irqs { OS_EVENT => crate::ostimer::time_driver::OsEventHandler; });
431#[macro_export]
432macro_rules! bind_interrupts {
433 ($(#[$attr:meta])* $vis:vis struct $name:ident {
434 $(
435 $(#[cfg($cond_irq:meta)])?
436 $irq:ident => $(
437 $(#[cfg($cond_handler:meta)])?
438 $handler:ty
439 ),*;
440 )*
441 }) => {
442 #[derive(Copy, Clone)]
443 $(#[$attr])*
444 $vis struct $name;
445
446 $(
447 #[allow(non_snake_case)]
448 #[no_mangle]
449 $(#[cfg($cond_irq)])?
450 unsafe extern "C" fn $irq() {
451 unsafe {
452 $(
453 $(#[cfg($cond_handler)])?
454 <$handler as $crate::interrupt::typelevel::Handler<$crate::interrupt::typelevel::$irq>>::on_interrupt();
455 )*
456 }
457 }
458
459 $(#[cfg($cond_irq)])?
460 $crate::bind_interrupts!(@inner
461 $(
462 $(#[cfg($cond_handler)])?
463 unsafe impl $crate::interrupt::typelevel::Binding<$crate::interrupt::typelevel::$irq, $handler> for $name {}
464 )*
465 );
466 )*
467 };
468 (@inner $($t:tt)*) => {
469 $($t)*
470 }
471}