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::hil::gpio::Configure;
21use kernel::hil::led::LedLow;
22use kernel::platform::{KernelResources, SyscallDriverLookup};
23use kernel::process::ProcessArray;
24use kernel::scheduler::round_robin::RoundRobinSched;
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>;
53
54static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
56static mut CHIP: Option<&'static ChipHw> = None;
57static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
58 None;
59
60const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
62 capsules_system::process_policies::PanicFaultPolicy {};
63
64#[cfg_attr(not(target_os = "macos"), link_section = ".boot_hdr")]
70#[used]
71static BOOT_HDR: [u8; 8192] = boot_header::BOOT_HDR;
72
73kernel::stack_size! {0x2000}
74
75struct Imxrt1050EVKB {
80 alarm: &'static capsules_core::alarm::AlarmDriver<
81 'static,
82 VirtualMuxAlarm<'static, imxrt1050::gpt::Gpt1<'static>>,
83 >,
84 button: &'static capsules_core::button::Button<'static, imxrt1050::gpio::Pin<'static>>,
85 console: &'static capsules_core::console::Console<'static>,
86 gpio: &'static capsules_core::gpio::GPIO<'static, imxrt1050::gpio::Pin<'static>>,
87 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
88 led: &'static capsules_core::led::LedDriver<
89 'static,
90 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
91 1,
92 >,
93 ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
94
95 scheduler: &'static RoundRobinSched<'static>,
96 systick: cortexm7::systick::SysTick,
97}
98
99impl SyscallDriverLookup for Imxrt1050EVKB {
101 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
102 where
103 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
104 {
105 match driver_num {
106 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
107 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
108 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
109 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
110 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
111 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
112 capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
113 _ => f(None),
114 }
115 }
116}
117
118impl KernelResources<imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>>
119 for Imxrt1050EVKB
120{
121 type SyscallDriverLookup = Self;
122 type SyscallFilter = ();
123 type ProcessFault = ();
124 type Scheduler = RoundRobinSched<'static>;
125 type SchedulerTimer = cortexm7::systick::SysTick;
126 type WatchDog = ();
127 type ContextSwitchCallback = ();
128
129 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
130 self
131 }
132 fn syscall_filter(&self) -> &Self::SyscallFilter {
133 &()
134 }
135 fn process_fault(&self) -> &Self::ProcessFault {
136 &()
137 }
138 fn scheduler(&self) -> &Self::Scheduler {
139 self.scheduler
140 }
141 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
142 &self.systick
143 }
144 fn watchdog(&self) -> &Self::WatchDog {
145 &()
146 }
147 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
148 &()
149 }
150}
151
152unsafe fn set_pin_primary_functions(
159 peripherals: &'static imxrt1050::chip::Imxrt10xxDefaultPeripherals,
160) {
161 use imxrt1050::gpio::PinId;
162
163 peripherals.ccm.enable_iomuxc_clock();
164 peripherals.ccm.enable_iomuxc_snvs_clock();
165
166 peripherals.ports.gpio1.enable_clock();
167
168 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
174 PadId::AdB0,
175 MuxMode::ALT5, Sion::Disabled,
177 9,
178 );
179
180 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
183 PadId::AdB0,
184 9,
185 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
191
192 let pin = peripherals.ports.pin(PinId::AdB0_09);
194 pin.make_output();
195 let debug_gpios = static_init!([&'static dyn kernel::hil::gpio::Pin; 1], [pin]);
196 kernel::debug::initialize_debug_gpio::<
197 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
198 >();
199 kernel::debug::assign_gpios(debug_gpios);
200
201 peripherals.ports.gpio5.enable_clock();
203
204 peripherals.iomuxc_snvs.enable_sw_mux_ctl_pad_gpio(
207 MuxMode::ALT5, Sion::Disabled,
209 0,
210 );
211
212 peripherals.ports.pin(PinId::Wakeup).make_input();
214}
215
216unsafe fn setup_peripherals(peripherals: &imxrt1050::chip::Imxrt10xxDefaultPeripherals) {
218 cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable();
220
221 peripherals.gpt1.enable_clock();
223 peripherals.gpt1.start(
224 peripherals.ccm.perclk_sel(),
225 peripherals.ccm.perclk_divider(),
226 );
227 cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable();
228}
229
230#[inline(never)]
234unsafe fn start() -> (
235 &'static kernel::Kernel,
236 Imxrt1050EVKB,
237 &'static imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>,
238) {
239 imxrt1050::init();
240
241 kernel::deferred_call::initialize_deferred_call_state::<
243 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
244 >();
245
246 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
247 let peripherals = static_init!(
248 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
249 imxrt1050::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(imxrt1050::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 PROCESSES = Some(processes);
268
269 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
271
272 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
273 CHIP = Some(chip);
274
275 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
285 PadId::AdB0,
286 MuxMode::ALT2, Sion::Disabled,
288 13,
289 );
290 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
291 PadId::AdB0,
292 MuxMode::ALT2, Sion::Disabled,
294 14,
295 );
296
297 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
300 PadId::AdB0,
301 13,
302 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
308 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
309 PadId::AdB0,
310 14,
311 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
317
318 peripherals.lpuart1.enable_clock();
320
321 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
322 .finalize(components::uart_mux_component_static!());
323 (*addr_of_mut!(io::WRITER)).set_initialized();
324
325 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
328 let process_management_capability =
329 create_capability!(capabilities::ProcessManagementCapability);
330
331 let console = components::console::ConsoleComponent::new(
333 board_kernel,
334 capsules_core::console::DRIVER_NUM,
335 lpuart_mux,
336 )
337 .finalize(components::console_component_static!());
338 components::debug_writer::DebugWriterComponent::new::<
340 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
341 >(
342 lpuart_mux,
343 create_capability!(capabilities::SetDebugWriterCapability),
344 )
345 .finalize(components::debug_writer_component_static!());
346
347 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
351 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
352 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
353 ));
354
355 let button = components::button::ButtonComponent::new(
357 board_kernel,
358 capsules_core::button::DRIVER_NUM,
359 components::button_component_helper!(
360 imxrt1050::gpio::Pin,
361 (
362 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
363 kernel::hil::gpio::ActivationMode::ActiveHigh,
364 kernel::hil::gpio::FloatingState::PullDown
365 )
366 ),
367 )
368 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
369
370 let gpt1 = &peripherals.gpt1;
372 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
373 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
374 );
375
376 let alarm = components::alarm::AlarmDriverComponent::new(
377 board_kernel,
378 capsules_core::alarm::DRIVER_NUM,
379 mux_alarm,
380 )
381 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
382
383 let gpio = GpioComponent::new(
386 board_kernel,
387 capsules_core::gpio::DRIVER_NUM,
388 components::gpio_component_helper!(
389 imxrt1050::gpio::Pin<'static>,
390 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
392 ),
393 )
394 .finalize(components::gpio_component_static!(
395 imxrt1050::gpio::Pin<'static>
396 ));
397
398 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
406 PadId::AdB1,
407 MuxMode::ALT3, Sion::Enabled,
409 0,
410 );
411 peripherals.iomuxc.enable_lpi2c_scl_select_input();
413
414 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
415 PadId::AdB1,
416 MuxMode::ALT3, Sion::Enabled,
418 1,
419 );
420 peripherals.iomuxc.enable_lpi2c_sda_select_input();
422
423 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
426 PadId::AdB1,
427 0,
428 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
434
435 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
436 PadId::AdB1,
437 1,
438 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
444
445 peripherals.lpi2c1.enable_clock();
447 peripherals
448 .lpi2c1
449 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
450
451 use imxrt1050::gpio::PinId;
452 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
453 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
454 );
455
456 let fxos8700 = components::fxos8700::Fxos8700Component::new(
458 mux_i2c,
459 0x1f,
460 peripherals.ports.pin(PinId::AdB1_00),
461 )
462 .finalize(components::fxos8700_component_static!(
463 imxrt1050::lpi2c::Lpi2c
464 ));
465
466 let ninedof = components::ninedof::NineDofComponent::new(
468 board_kernel,
469 capsules_extra::ninedof::DRIVER_NUM,
470 )
471 .finalize(components::ninedof_component_static!(fxos8700));
472
473 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
474 .finalize(components::round_robin_component_static!(NUM_PROCS));
475
476 let imxrt1050 = Imxrt1050EVKB {
477 console,
478 ipc: kernel::ipc::IPC::new(
479 board_kernel,
480 kernel::ipc::DRIVER_NUM,
481 &memory_allocation_capability,
482 ),
483 led,
484 button,
485 ninedof,
486 alarm,
487 gpio,
488
489 scheduler,
490 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
491 };
492
493 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
502 .finalize(components::process_printer_text_component_static!());
503 PROCESS_PRINTER = Some(process_printer);
504
505 let process_console = components::process_console::ProcessConsoleComponent::new(
506 board_kernel,
507 lpuart_mux,
508 mux_alarm,
509 process_printer,
510 None,
511 )
512 .finalize(components::process_console_component_static!(
513 imxrt1050::gpt::Gpt1
514 ));
515 let _ = process_console.start();
516
517 debug!("Tock OS initialization complete. Entering main loop");
518
519 extern "C" {
520 static _sapps: u8;
524 static _eapps: u8;
528 static mut _sappmem: u8;
530 static _eappmem: u8;
532 }
533
534 kernel::process::load_processes(
535 board_kernel,
536 chip,
537 core::slice::from_raw_parts(
538 core::ptr::addr_of!(_sapps),
539 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
540 ),
541 core::slice::from_raw_parts_mut(
542 core::ptr::addr_of_mut!(_sappmem),
543 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
544 ),
545 &FAULT_RESPONSE,
546 &process_management_capability,
547 )
548 .unwrap_or_else(|err| {
549 debug!("Error loading processes!");
550 debug!("{:?}", err);
551 });
552
553 (board_kernel, imxrt1050, chip)
554}
555
556#[no_mangle]
558pub unsafe fn main() {
559 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
560
561 let (board_kernel, board, chip) = start();
562 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
563}