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::scheduler::round_robin::RoundRobinSched;
25use kernel::utilities::single_thread_value::SingleThreadValue;
26use kernel::{create_capability, static_init};
27
28use imxrt1050::iomuxc::DriveStrength;
31use imxrt1050::iomuxc::MuxMode;
32use imxrt1050::iomuxc::OpenDrainEn;
33use imxrt1050::iomuxc::PadId;
34use imxrt1050::iomuxc::PullKeepEn;
35use imxrt1050::iomuxc::PullUpDown;
36use imxrt1050::iomuxc::Sion;
37use imxrt1050::iomuxc::Speed;
38use imxrt10xx as imxrt1050;
39
40pub mod io;
46
47pub mod boot_header;
49
50const NUM_PROCS: usize = 4;
52
53type ChipHw = imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>;
54type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
55
56static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
58 SingleThreadValue::new(PanicResources::new());
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 PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
248
249 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
250 let peripherals = static_init!(
251 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
252 imxrt1050::chip::Imxrt10xxDefaultPeripherals::new(ccm)
253 );
254 peripherals.ccm.set_low_power_mode();
255 peripherals.lpuart1.disable_clock();
256 peripherals.lpuart2.disable_clock();
257 peripherals
258 .ccm
259 .set_uart_clock_sel(imxrt1050::ccm::UartClockSelection::PLL3);
260 peripherals.ccm.set_uart_clock_podf(1);
261 peripherals.lpuart1.set_baud();
262
263 set_pin_primary_functions(peripherals);
264
265 setup_peripherals(peripherals);
266
267 let processes = components::process_array::ProcessArrayComponent::new()
269 .finalize(components::process_array_component_static!(NUM_PROCS));
270 PANIC_RESOURCES.get().map(|resources| {
271 resources.processes.put(processes.as_slice());
272 });
273
274 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
276
277 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
278 PANIC_RESOURCES.get().map(|resources| {
279 resources.chip.put(chip);
280 });
281
282 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
292 PadId::AdB0,
293 MuxMode::ALT2, Sion::Disabled,
295 13,
296 );
297 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
298 PadId::AdB0,
299 MuxMode::ALT2, Sion::Disabled,
301 14,
302 );
303
304 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
307 PadId::AdB0,
308 13,
309 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
315 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
316 PadId::AdB0,
317 14,
318 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
324
325 peripherals.lpuart1.enable_clock();
327
328 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
329 .finalize(components::uart_mux_component_static!());
330 (*addr_of_mut!(io::WRITER)).set_initialized();
331
332 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
335 let process_management_capability =
336 create_capability!(capabilities::ProcessManagementCapability);
337
338 let console = components::console::ConsoleComponent::new(
340 board_kernel,
341 capsules_core::console::DRIVER_NUM,
342 lpuart_mux,
343 )
344 .finalize(components::console_component_static!());
345 components::debug_writer::DebugWriterComponent::new::<
347 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
348 >(
349 lpuart_mux,
350 create_capability!(capabilities::SetDebugWriterCapability),
351 )
352 .finalize(components::debug_writer_component_static!());
353
354 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
358 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
359 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
360 ));
361
362 let button = components::button::ButtonComponent::new(
364 board_kernel,
365 capsules_core::button::DRIVER_NUM,
366 components::button_component_helper!(
367 imxrt1050::gpio::Pin,
368 (
369 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
370 kernel::hil::gpio::ActivationMode::ActiveHigh,
371 kernel::hil::gpio::FloatingState::PullDown
372 )
373 ),
374 )
375 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
376
377 let gpt1 = &peripherals.gpt1;
379 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
380 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
381 );
382
383 let alarm = components::alarm::AlarmDriverComponent::new(
384 board_kernel,
385 capsules_core::alarm::DRIVER_NUM,
386 mux_alarm,
387 )
388 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
389
390 let gpio = GpioComponent::new(
393 board_kernel,
394 capsules_core::gpio::DRIVER_NUM,
395 components::gpio_component_helper!(
396 imxrt1050::gpio::Pin<'static>,
397 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
399 ),
400 )
401 .finalize(components::gpio_component_static!(
402 imxrt1050::gpio::Pin<'static>
403 ));
404
405 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
413 PadId::AdB1,
414 MuxMode::ALT3, Sion::Enabled,
416 0,
417 );
418 peripherals.iomuxc.enable_lpi2c_scl_select_input();
420
421 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
422 PadId::AdB1,
423 MuxMode::ALT3, Sion::Enabled,
425 1,
426 );
427 peripherals.iomuxc.enable_lpi2c_sda_select_input();
429
430 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
433 PadId::AdB1,
434 0,
435 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
441
442 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
443 PadId::AdB1,
444 1,
445 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
451
452 peripherals.lpi2c1.enable_clock();
454 peripherals
455 .lpi2c1
456 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
457
458 use imxrt1050::gpio::PinId;
459 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
460 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
461 );
462
463 let fxos8700 = components::fxos8700::Fxos8700Component::new(
465 mux_i2c,
466 0x1f,
467 peripherals.ports.pin(PinId::AdB1_00),
468 )
469 .finalize(components::fxos8700_component_static!(
470 imxrt1050::lpi2c::Lpi2c
471 ));
472
473 let ninedof = components::ninedof::NineDofComponent::new(
475 board_kernel,
476 capsules_extra::ninedof::DRIVER_NUM,
477 )
478 .finalize(components::ninedof_component_static!(fxos8700));
479
480 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
481 .finalize(components::round_robin_component_static!(NUM_PROCS));
482
483 let imxrt1050 = Imxrt1050EVKB {
484 console,
485 ipc: kernel::ipc::IPC::new(
486 board_kernel,
487 kernel::ipc::DRIVER_NUM,
488 &memory_allocation_capability,
489 ),
490 led,
491 button,
492 ninedof,
493 alarm,
494 gpio,
495
496 scheduler,
497 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
498 };
499
500 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
509 .finalize(components::process_printer_text_component_static!());
510 PANIC_RESOURCES.get().map(|resources| {
511 resources.printer.put(process_printer);
512 });
513
514 let process_console = components::process_console::ProcessConsoleComponent::new(
515 board_kernel,
516 lpuart_mux,
517 mux_alarm,
518 process_printer,
519 None,
520 )
521 .finalize(components::process_console_component_static!(
522 imxrt1050::gpt::Gpt1
523 ));
524 let _ = process_console.start();
525
526 debug!("Tock OS initialization complete. Entering main loop");
527
528 extern "C" {
529 static _sapps: u8;
533 static _eapps: u8;
537 static mut _sappmem: u8;
539 static _eappmem: u8;
541 }
542
543 kernel::process::load_processes(
544 board_kernel,
545 chip,
546 core::slice::from_raw_parts(
547 core::ptr::addr_of!(_sapps),
548 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
549 ),
550 core::slice::from_raw_parts_mut(
551 core::ptr::addr_of_mut!(_sappmem),
552 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
553 ),
554 &FAULT_RESPONSE,
555 &process_management_capability,
556 )
557 .unwrap_or_else(|err| {
558 debug!("Error loading processes!");
559 debug!("{:?}", err);
560 });
561
562 (board_kernel, imxrt1050, chip)
563}
564
565#[no_mangle]
567pub unsafe fn main() {
568 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
569
570 let (board_kernel, board, chip) = start();
571 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
572}