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