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::chip::Chip;
24use kernel::platform::{KernelResources, SyscallDriverLookup};
25use kernel::utilities::single_thread_value::SingleThreadValue;
26use kernel::{create_capability, static_init};
27
28use imxrt10xx::iomuxc::DriveStrength;
29use imxrt10xx::iomuxc::MuxMode;
30use imxrt10xx::iomuxc::OpenDrainEn;
31use imxrt10xx::iomuxc::PadId;
32use imxrt10xx::iomuxc::PullKeepEn;
33use imxrt10xx::iomuxc::PullUpDown;
34use imxrt10xx::iomuxc::Sion;
35use imxrt10xx::iomuxc::Speed;
36
37pub mod io;
43
44pub mod boot_header;
46
47const NUM_PROCS: usize = 4;
49
50type ChipHw = imxrt10xx::chip::Imxrt10xx<imxrt10xx::chip::Imxrt10xxDefaultPeripherals>;
51type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
52
53static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
55 SingleThreadValue::new();
56
57const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
59 capsules_system::process_policies::PanicFaultPolicy {};
60
61#[cfg_attr(not(target_os = "macos"), link_section = ".boot_hdr")]
67#[used]
68static BOOT_HDR: [u8; 8192] = boot_header::BOOT_HDR;
69
70kernel::stack_size! {0x2000}
71
72type SchedulerInUse = components::sched::round_robin::RoundRobinComponentType;
73
74struct Imxrt1050EVKB {
79 alarm: &'static capsules_core::alarm::AlarmDriver<
80 'static,
81 VirtualMuxAlarm<'static, imxrt10xx::gpt::Gpt1<'static>>,
82 >,
83 button: &'static capsules_core::button::Button<'static, imxrt10xx::gpio::Pin<'static>>,
84 console: &'static capsules_core::console::Console<'static>,
85 gpio: &'static capsules_core::gpio::GPIO<'static, imxrt10xx::gpio::Pin<'static>>,
86 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
87 led: &'static capsules_core::led::LedDriver<
88 'static,
89 LedLow<'static, imxrt10xx::gpio::Pin<'static>>,
90 1,
91 >,
92 ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
93
94 scheduler: &'static SchedulerInUse,
95 systick: cortexm7::systick::SysTick,
96}
97
98impl SyscallDriverLookup for Imxrt1050EVKB {
100 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
101 where
102 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
103 {
104 match driver_num {
105 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
106 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
107 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
108 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
109 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
110 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
111 capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
112 _ => f(None),
113 }
114 }
115}
116
117impl KernelResources<imxrt10xx::chip::Imxrt10xx<imxrt10xx::chip::Imxrt10xxDefaultPeripherals>>
118 for Imxrt1050EVKB
119{
120 type SyscallDriverLookup = Self;
121 type SyscallFilter = ();
122 type ProcessFault = ();
123 type Scheduler = SchedulerInUse;
124 type SchedulerTimer = cortexm7::systick::SysTick;
125 type WatchDog = ();
126 type ContextSwitchCallback = ();
127
128 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
129 self
130 }
131 fn syscall_filter(&self) -> &Self::SyscallFilter {
132 &()
133 }
134 fn process_fault(&self) -> &Self::ProcessFault {
135 &()
136 }
137 fn scheduler(&self) -> &Self::Scheduler {
138 self.scheduler
139 }
140 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
141 &self.systick
142 }
143 fn watchdog(&self) -> &Self::WatchDog {
144 &()
145 }
146 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
147 &()
148 }
149}
150
151unsafe fn set_pin_primary_functions(
153 peripherals: &'static imxrt10xx::chip::Imxrt10xxDefaultPeripherals,
154) {
155 use imxrt10xx::gpio::PinId;
156
157 peripherals.ccm.enable_iomuxc_clock();
158 peripherals.ccm.enable_iomuxc_snvs_clock();
159
160 peripherals.ports.gpio1.enable_clock();
161
162 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
168 PadId::AdB0,
169 MuxMode::ALT5, Sion::Disabled,
171 9,
172 );
173
174 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
177 PadId::AdB0,
178 9,
179 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
185
186 let pin = peripherals.ports.pin(PinId::AdB0_09);
188 pin.make_output();
189 let debug_gpios = static_init!([&'static dyn kernel::hil::gpio::Pin; 1], [pin]);
190 kernel::debug::initialize_debug_gpio::<
191 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
192 >();
193 kernel::debug::assign_gpios(debug_gpios);
194
195 peripherals.ports.gpio5.enable_clock();
197
198 peripherals.iomuxc_snvs.enable_sw_mux_ctl_pad_gpio(
201 MuxMode::ALT5, Sion::Disabled,
203 0,
204 );
205
206 peripherals.ports.pin(PinId::Wakeup).make_input();
208}
209
210unsafe fn setup_peripherals(peripherals: &imxrt10xx::chip::Imxrt10xxDefaultPeripherals) {
212 cortexm7::nvic::Nvic::new(imxrt10xx::nvic::LPUART1).enable();
214
215 peripherals.gpt1.enable_clock();
217 peripherals.gpt1.start(
218 peripherals.ccm.perclk_sel(),
219 peripherals.ccm.perclk_divider(),
220 );
221 cortexm7::nvic::Nvic::new(imxrt10xx::nvic::GPT1).enable();
222}
223
224#[inline(never)]
228unsafe fn start() -> (
229 &'static kernel::Kernel,
230 Imxrt1050EVKB,
231 &'static imxrt10xx::chip::Imxrt10xx<imxrt10xx::chip::Imxrt10xxDefaultPeripherals>,
232) {
233 ChipHw::init();
234
235 kernel::deferred_call::initialize_deferred_call_state::<
237 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
238 >();
239
240 let _ = PANIC_RESOURCES
242 .bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>(
243 PanicResources::new(),
244 );
245
246 let ccm = static_init!(imxrt10xx::ccm::Ccm, imxrt10xx::ccm::Ccm::new());
247 let peripherals = static_init!(
248 imxrt10xx::chip::Imxrt10xxDefaultPeripherals,
249 imxrt10xx::chip::Imxrt10xxDefaultPeripherals::new(ccm)
250 );
251 peripherals.ccm.set_low_power_mode();
252 peripherals.lpuart1.disable_clock();
253 peripherals.lpuart2.disable_clock();
254 peripherals
255 .ccm
256 .set_uart_clock_sel(imxrt10xx::ccm::UartClockSelection::PLL3);
257 peripherals.ccm.set_uart_clock_podf(1);
258 peripherals.lpuart1.set_baud();
259
260 set_pin_primary_functions(peripherals);
261
262 setup_peripherals(peripherals);
263
264 let processes = components::process_array::ProcessArrayComponent::new()
266 .finalize(components::process_array_component_static!(NUM_PROCS));
267 PANIC_RESOURCES.get().map(|resources| {
268 resources.processes.put(processes.as_slice());
269 });
270
271 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
273
274 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
275 PANIC_RESOURCES.get().map(|resources| {
276 resources.chip.put(chip);
277 });
278
279 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
289 PadId::AdB0,
290 MuxMode::ALT2, Sion::Disabled,
292 13,
293 );
294 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
295 PadId::AdB0,
296 MuxMode::ALT2, Sion::Disabled,
298 14,
299 );
300
301 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
304 PadId::AdB0,
305 13,
306 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
312 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
313 PadId::AdB0,
314 14,
315 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
321
322 peripherals.lpuart1.enable_clock();
324
325 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
326 .finalize(components::uart_mux_component_static!());
327 (*addr_of_mut!(io::WRITER)).set_initialized();
328
329 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
332 let process_management_capability =
333 create_capability!(capabilities::ProcessManagementCapability);
334
335 let console = components::console::ConsoleComponent::new(
337 board_kernel,
338 capsules_core::console::DRIVER_NUM,
339 lpuart_mux,
340 )
341 .finalize(components::console_component_static!());
342 components::debug_writer::DebugWriterComponent::new::<
344 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
345 >(
346 lpuart_mux,
347 create_capability!(capabilities::SetDebugWriterCapability),
348 )
349 .finalize(components::debug_writer_component_static!());
350
351 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
355 LedLow<'static, imxrt10xx::gpio::Pin<'static>>,
356 LedLow::new(peripherals.ports.pin(imxrt10xx::gpio::PinId::AdB0_09)),
357 ));
358
359 let button = components::button::ButtonComponent::new(
361 board_kernel,
362 capsules_core::button::DRIVER_NUM,
363 components::button_component_helper!(
364 imxrt10xx::gpio::Pin,
365 (
366 peripherals.ports.pin(imxrt10xx::gpio::PinId::Wakeup),
367 kernel::hil::gpio::ActivationMode::ActiveHigh,
368 kernel::hil::gpio::FloatingState::PullDown
369 )
370 ),
371 )
372 .finalize(components::button_component_static!(imxrt10xx::gpio::Pin));
373
374 let gpt1 = &peripherals.gpt1;
376 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
377 components::alarm_mux_component_static!(imxrt10xx::gpt::Gpt1),
378 );
379
380 let alarm = components::alarm::AlarmDriverComponent::new(
381 board_kernel,
382 capsules_core::alarm::DRIVER_NUM,
383 mux_alarm,
384 )
385 .finalize(components::alarm_component_static!(imxrt10xx::gpt::Gpt1));
386
387 let gpio = GpioComponent::new(
390 board_kernel,
391 capsules_core::gpio::DRIVER_NUM,
392 components::gpio_component_helper!(
393 imxrt10xx::gpio::Pin<'static>,
394 0 => peripherals.ports.pin(imxrt10xx::gpio::PinId::AdB0_09)
396 ),
397 )
398 .finalize(components::gpio_component_static!(
399 imxrt10xx::gpio::Pin<'static>
400 ));
401
402 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
410 PadId::AdB1,
411 MuxMode::ALT3, Sion::Enabled,
413 0,
414 );
415 peripherals.iomuxc.enable_lpi2c_scl_select_input();
417
418 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
419 PadId::AdB1,
420 MuxMode::ALT3, Sion::Enabled,
422 1,
423 );
424 peripherals.iomuxc.enable_lpi2c_sda_select_input();
426
427 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
430 PadId::AdB1,
431 0,
432 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
438
439 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
440 PadId::AdB1,
441 1,
442 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
448
449 peripherals.lpi2c1.enable_clock();
451 peripherals
452 .lpi2c1
453 .set_speed(imxrt10xx::lpi2c::Lpi2cSpeed::Speed100k, 8);
454
455 use imxrt10xx::gpio::PinId;
456 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
457 components::i2c_mux_component_static!(imxrt10xx::lpi2c::Lpi2c),
458 );
459
460 let fxos8700 = components::fxos8700::Fxos8700Component::new(
462 mux_i2c,
463 0x1f,
464 peripherals.ports.pin(PinId::AdB1_00),
465 )
466 .finalize(components::fxos8700_component_static!(
467 imxrt10xx::lpi2c::Lpi2c
468 ));
469
470 let ninedof = components::ninedof::NineDofComponent::new(
472 board_kernel,
473 capsules_extra::ninedof::DRIVER_NUM,
474 )
475 .finalize(components::ninedof_component_static!(fxos8700));
476
477 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
478 .finalize(components::round_robin_component_static!(NUM_PROCS));
479
480 let imxrt1050 = Imxrt1050EVKB {
481 console,
482 ipc: kernel::ipc::IPC::new(
483 board_kernel,
484 kernel::ipc::DRIVER_NUM,
485 &memory_allocation_capability,
486 ),
487 led,
488 button,
489 ninedof,
490 alarm,
491 gpio,
492
493 scheduler,
494 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
495 };
496
497 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
506 .finalize(components::process_printer_text_component_static!());
507 PANIC_RESOURCES.get().map(|resources| {
508 resources.printer.put(process_printer);
509 });
510
511 let process_console = components::process_console::ProcessConsoleComponent::new(
512 board_kernel,
513 lpuart_mux,
514 mux_alarm,
515 process_printer,
516 None,
517 )
518 .finalize(components::process_console_component_static!(
519 imxrt10xx::gpt::Gpt1
520 ));
521 let _ = process_console.start();
522
523 debug!("Tock OS initialization complete. Entering main loop");
524
525 extern "C" {
526 static _sapps: u8;
530 static _eapps: u8;
534 static mut _sappmem: u8;
536 static _eappmem: u8;
538 }
539
540 kernel::process::load_processes(
541 board_kernel,
542 chip,
543 core::slice::from_raw_parts(
544 core::ptr::addr_of!(_sapps),
545 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
546 ),
547 core::slice::from_raw_parts_mut(
548 core::ptr::addr_of_mut!(_sappmem),
549 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
550 ),
551 &FAULT_RESPONSE,
552 &process_management_capability,
553 )
554 .unwrap_or_else(|err| {
555 debug!("Error loading processes!");
556 debug!("{:?}", err);
557 });
558
559 (board_kernel, imxrt1050, chip)
560}
561
562#[no_mangle]
564pub unsafe fn main() {
565 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
566
567 let (board_kernel, board, chip) = start();
568 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
569}