1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::addr_of_mut;
14
15use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
16use components::gpio::GpioComponent;
17use kernel::capabilities;
18use kernel::component::Component;
19use kernel::debug;
20use kernel::debug::PanicResources;
21use kernel::hil::gpio::Configure;
22use kernel::hil::led::LedLow;
23use kernel::platform::{KernelResources, SyscallDriverLookup};
24use kernel::utilities::single_thread_value::SingleThreadValue;
25use kernel::{create_capability, static_init};
26
27use imxrt1050::iomuxc::DriveStrength;
30use imxrt1050::iomuxc::MuxMode;
31use imxrt1050::iomuxc::OpenDrainEn;
32use imxrt1050::iomuxc::PadId;
33use imxrt1050::iomuxc::PullKeepEn;
34use imxrt1050::iomuxc::PullUpDown;
35use imxrt1050::iomuxc::Sion;
36use imxrt1050::iomuxc::Speed;
37use imxrt10xx as imxrt1050;
38
39pub mod io;
45
46pub mod boot_header;
48
49const NUM_PROCS: usize = 4;
51
52type ChipHw = imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>;
53type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
54
55static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
57 SingleThreadValue::new(PanicResources::new());
58
59const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
61 capsules_system::process_policies::PanicFaultPolicy {};
62
63#[cfg_attr(not(target_os = "macos"), link_section = ".boot_hdr")]
69#[used]
70static BOOT_HDR: [u8; 8192] = boot_header::BOOT_HDR;
71
72kernel::stack_size! {0x2000}
73
74type SchedulerInUse = components::sched::round_robin::RoundRobinComponentType;
75
76struct Imxrt1050EVKB {
81 alarm: &'static capsules_core::alarm::AlarmDriver<
82 'static,
83 VirtualMuxAlarm<'static, imxrt1050::gpt::Gpt1<'static>>,
84 >,
85 button: &'static capsules_core::button::Button<'static, imxrt1050::gpio::Pin<'static>>,
86 console: &'static capsules_core::console::Console<'static>,
87 gpio: &'static capsules_core::gpio::GPIO<'static, imxrt1050::gpio::Pin<'static>>,
88 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
89 led: &'static capsules_core::led::LedDriver<
90 'static,
91 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
92 1,
93 >,
94 ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
95
96 scheduler: &'static SchedulerInUse,
97 systick: cortexm7::systick::SysTick,
98}
99
100impl SyscallDriverLookup for Imxrt1050EVKB {
102 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
103 where
104 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
105 {
106 match driver_num {
107 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
108 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
109 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
110 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
111 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
112 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
113 capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
114 _ => f(None),
115 }
116 }
117}
118
119impl KernelResources<imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>>
120 for Imxrt1050EVKB
121{
122 type SyscallDriverLookup = Self;
123 type SyscallFilter = ();
124 type ProcessFault = ();
125 type Scheduler = SchedulerInUse;
126 type SchedulerTimer = cortexm7::systick::SysTick;
127 type WatchDog = ();
128 type ContextSwitchCallback = ();
129
130 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
131 self
132 }
133 fn syscall_filter(&self) -> &Self::SyscallFilter {
134 &()
135 }
136 fn process_fault(&self) -> &Self::ProcessFault {
137 &()
138 }
139 fn scheduler(&self) -> &Self::Scheduler {
140 self.scheduler
141 }
142 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
143 &self.systick
144 }
145 fn watchdog(&self) -> &Self::WatchDog {
146 &()
147 }
148 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
149 &()
150 }
151}
152
153unsafe fn set_pin_primary_functions(
160 peripherals: &'static imxrt1050::chip::Imxrt10xxDefaultPeripherals,
161) {
162 use imxrt1050::gpio::PinId;
163
164 peripherals.ccm.enable_iomuxc_clock();
165 peripherals.ccm.enable_iomuxc_snvs_clock();
166
167 peripherals.ports.gpio1.enable_clock();
168
169 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
175 PadId::AdB0,
176 MuxMode::ALT5, Sion::Disabled,
178 9,
179 );
180
181 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
184 PadId::AdB0,
185 9,
186 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
192
193 let pin = peripherals.ports.pin(PinId::AdB0_09);
195 pin.make_output();
196 let debug_gpios = static_init!([&'static dyn kernel::hil::gpio::Pin; 1], [pin]);
197 kernel::debug::initialize_debug_gpio::<
198 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
199 >();
200 kernel::debug::assign_gpios(debug_gpios);
201
202 peripherals.ports.gpio5.enable_clock();
204
205 peripherals.iomuxc_snvs.enable_sw_mux_ctl_pad_gpio(
208 MuxMode::ALT5, Sion::Disabled,
210 0,
211 );
212
213 peripherals.ports.pin(PinId::Wakeup).make_input();
215}
216
217unsafe fn setup_peripherals(peripherals: &imxrt1050::chip::Imxrt10xxDefaultPeripherals) {
219 cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable();
221
222 peripherals.gpt1.enable_clock();
224 peripherals.gpt1.start(
225 peripherals.ccm.perclk_sel(),
226 peripherals.ccm.perclk_divider(),
227 );
228 cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable();
229}
230
231#[inline(never)]
235unsafe fn start() -> (
236 &'static kernel::Kernel,
237 Imxrt1050EVKB,
238 &'static imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>,
239) {
240 imxrt1050::init();
241
242 kernel::deferred_call::initialize_deferred_call_state::<
244 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
245 >();
246
247 PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
249
250 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
251 let peripherals = static_init!(
252 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
253 imxrt1050::chip::Imxrt10xxDefaultPeripherals::new(ccm)
254 );
255 peripherals.ccm.set_low_power_mode();
256 peripherals.lpuart1.disable_clock();
257 peripherals.lpuart2.disable_clock();
258 peripherals
259 .ccm
260 .set_uart_clock_sel(imxrt1050::ccm::UartClockSelection::PLL3);
261 peripherals.ccm.set_uart_clock_podf(1);
262 peripherals.lpuart1.set_baud();
263
264 set_pin_primary_functions(peripherals);
265
266 setup_peripherals(peripherals);
267
268 let processes = components::process_array::ProcessArrayComponent::new()
270 .finalize(components::process_array_component_static!(NUM_PROCS));
271 PANIC_RESOURCES.get().map(|resources| {
272 resources.processes.put(processes.as_slice());
273 });
274
275 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
277
278 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
279 PANIC_RESOURCES.get().map(|resources| {
280 resources.chip.put(chip);
281 });
282
283 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
293 PadId::AdB0,
294 MuxMode::ALT2, Sion::Disabled,
296 13,
297 );
298 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
299 PadId::AdB0,
300 MuxMode::ALT2, Sion::Disabled,
302 14,
303 );
304
305 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
308 PadId::AdB0,
309 13,
310 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
316 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
317 PadId::AdB0,
318 14,
319 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
325
326 peripherals.lpuart1.enable_clock();
328
329 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
330 .finalize(components::uart_mux_component_static!());
331 (*addr_of_mut!(io::WRITER)).set_initialized();
332
333 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
336 let process_management_capability =
337 create_capability!(capabilities::ProcessManagementCapability);
338
339 let console = components::console::ConsoleComponent::new(
341 board_kernel,
342 capsules_core::console::DRIVER_NUM,
343 lpuart_mux,
344 )
345 .finalize(components::console_component_static!());
346 components::debug_writer::DebugWriterComponent::new::<
348 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
349 >(
350 lpuart_mux,
351 create_capability!(capabilities::SetDebugWriterCapability),
352 )
353 .finalize(components::debug_writer_component_static!());
354
355 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
359 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
360 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
361 ));
362
363 let button = components::button::ButtonComponent::new(
365 board_kernel,
366 capsules_core::button::DRIVER_NUM,
367 components::button_component_helper!(
368 imxrt1050::gpio::Pin,
369 (
370 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
371 kernel::hil::gpio::ActivationMode::ActiveHigh,
372 kernel::hil::gpio::FloatingState::PullDown
373 )
374 ),
375 )
376 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
377
378 let gpt1 = &peripherals.gpt1;
380 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
381 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
382 );
383
384 let alarm = components::alarm::AlarmDriverComponent::new(
385 board_kernel,
386 capsules_core::alarm::DRIVER_NUM,
387 mux_alarm,
388 )
389 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
390
391 let gpio = GpioComponent::new(
394 board_kernel,
395 capsules_core::gpio::DRIVER_NUM,
396 components::gpio_component_helper!(
397 imxrt1050::gpio::Pin<'static>,
398 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
400 ),
401 )
402 .finalize(components::gpio_component_static!(
403 imxrt1050::gpio::Pin<'static>
404 ));
405
406 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
414 PadId::AdB1,
415 MuxMode::ALT3, Sion::Enabled,
417 0,
418 );
419 peripherals.iomuxc.enable_lpi2c_scl_select_input();
421
422 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
423 PadId::AdB1,
424 MuxMode::ALT3, Sion::Enabled,
426 1,
427 );
428 peripherals.iomuxc.enable_lpi2c_sda_select_input();
430
431 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
434 PadId::AdB1,
435 0,
436 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
442
443 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
444 PadId::AdB1,
445 1,
446 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
452
453 peripherals.lpi2c1.enable_clock();
455 peripherals
456 .lpi2c1
457 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
458
459 use imxrt1050::gpio::PinId;
460 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
461 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
462 );
463
464 let fxos8700 = components::fxos8700::Fxos8700Component::new(
466 mux_i2c,
467 0x1f,
468 peripherals.ports.pin(PinId::AdB1_00),
469 )
470 .finalize(components::fxos8700_component_static!(
471 imxrt1050::lpi2c::Lpi2c
472 ));
473
474 let ninedof = components::ninedof::NineDofComponent::new(
476 board_kernel,
477 capsules_extra::ninedof::DRIVER_NUM,
478 )
479 .finalize(components::ninedof_component_static!(fxos8700));
480
481 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
482 .finalize(components::round_robin_component_static!(NUM_PROCS));
483
484 let imxrt1050 = Imxrt1050EVKB {
485 console,
486 ipc: kernel::ipc::IPC::new(
487 board_kernel,
488 kernel::ipc::DRIVER_NUM,
489 &memory_allocation_capability,
490 ),
491 led,
492 button,
493 ninedof,
494 alarm,
495 gpio,
496
497 scheduler,
498 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
499 };
500
501 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
510 .finalize(components::process_printer_text_component_static!());
511 PANIC_RESOURCES.get().map(|resources| {
512 resources.printer.put(process_printer);
513 });
514
515 let process_console = components::process_console::ProcessConsoleComponent::new(
516 board_kernel,
517 lpuart_mux,
518 mux_alarm,
519 process_printer,
520 None,
521 )
522 .finalize(components::process_console_component_static!(
523 imxrt1050::gpt::Gpt1
524 ));
525 let _ = process_console.start();
526
527 debug!("Tock OS initialization complete. Entering main loop");
528
529 extern "C" {
530 static _sapps: u8;
534 static _eapps: u8;
538 static mut _sappmem: u8;
540 static _eappmem: u8;
542 }
543
544 kernel::process::load_processes(
545 board_kernel,
546 chip,
547 core::slice::from_raw_parts(
548 core::ptr::addr_of!(_sapps),
549 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
550 ),
551 core::slice::from_raw_parts_mut(
552 core::ptr::addr_of_mut!(_sappmem),
553 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
554 ),
555 &FAULT_RESPONSE,
556 &process_management_capability,
557 )
558 .unwrap_or_else(|err| {
559 debug!("Error loading processes!");
560 debug!("{:?}", err);
561 });
562
563 (board_kernel, imxrt1050, chip)
564}
565
566#[no_mangle]
568pub unsafe fn main() {
569 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
570
571 let (board_kernel, board, chip) = start();
572 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
573}