1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12
13use core::ptr::{addr_of, 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::scheduler::round_robin::RoundRobinSched;
24use kernel::{create_capability, static_init};
25
26use imxrt1050::iomuxc::DriveStrength;
29use imxrt1050::iomuxc::MuxMode;
30use imxrt1050::iomuxc::OpenDrainEn;
31use imxrt1050::iomuxc::PadId;
32use imxrt1050::iomuxc::PullKeepEn;
33use imxrt1050::iomuxc::PullUpDown;
34use imxrt1050::iomuxc::Sion;
35use imxrt1050::iomuxc::Speed;
36use imxrt10xx as imxrt1050;
37
38pub mod io;
44
45pub mod boot_header;
47
48const NUM_PROCS: usize = 4;
50
51static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
53 [None; NUM_PROCS];
54
55type Chip = imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>;
56static mut CHIP: Option<&'static Chip> = 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#[used]
66#[link_section = ".boot_hdr"]
67static BOOT_HDR: [u8; 8192] = boot_header::BOOT_HDR;
68
69#[no_mangle]
71#[link_section = ".stack_buffer"]
72pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
73
74struct Imxrt1050EVKB {
79 alarm: &'static capsules_core::alarm::AlarmDriver<
80 'static,
81 VirtualMuxAlarm<'static, imxrt1050::gpt::Gpt1<'static>>,
82 >,
83 button: &'static capsules_core::button::Button<'static, imxrt1050::gpio::Pin<'static>>,
84 console: &'static capsules_core::console::Console<'static>,
85 gpio: &'static capsules_core::gpio::GPIO<'static, imxrt1050::gpio::Pin<'static>>,
86 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
87 led: &'static capsules_core::led::LedDriver<
88 'static,
89 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
90 1,
91 >,
92 ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
93
94 scheduler: &'static RoundRobinSched<'static>,
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<imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>>
118 for Imxrt1050EVKB
119{
120 type SyscallDriverLookup = Self;
121 type SyscallFilter = ();
122 type ProcessFault = ();
123 type Scheduler = RoundRobinSched<'static>;
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(
158 peripherals: &'static imxrt1050::chip::Imxrt10xxDefaultPeripherals,
159) {
160 use imxrt1050::gpio::PinId;
161
162 peripherals.ccm.enable_iomuxc_clock();
163 peripherals.ccm.enable_iomuxc_snvs_clock();
164
165 peripherals.ports.gpio1.enable_clock();
166
167 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
173 PadId::AdB0,
174 MuxMode::ALT5, Sion::Disabled,
176 9,
177 );
178
179 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
182 PadId::AdB0,
183 9,
184 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
190
191 let pin = peripherals.ports.pin(PinId::AdB0_09);
193 pin.make_output();
194 kernel::debug::assign_gpios(Some(pin), None, None);
195
196 peripherals.ports.gpio5.enable_clock();
198
199 peripherals.iomuxc_snvs.enable_sw_mux_ctl_pad_gpio(
202 MuxMode::ALT5, Sion::Disabled,
204 0,
205 );
206
207 peripherals.ports.pin(PinId::Wakeup).make_input();
209}
210
211unsafe fn setup_peripherals(peripherals: &imxrt1050::chip::Imxrt10xxDefaultPeripherals) {
213 cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable();
215
216 peripherals.gpt1.enable_clock();
218 peripherals.gpt1.start(
219 peripherals.ccm.perclk_sel(),
220 peripherals.ccm.perclk_divider(),
221 );
222 cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable();
223}
224
225#[inline(never)]
229unsafe fn start() -> (
230 &'static kernel::Kernel,
231 Imxrt1050EVKB,
232 &'static imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>,
233) {
234 imxrt1050::init();
235
236 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
237 let peripherals = static_init!(
238 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
239 imxrt1050::chip::Imxrt10xxDefaultPeripherals::new(ccm)
240 );
241 peripherals.ccm.set_low_power_mode();
242 peripherals.lpuart1.disable_clock();
243 peripherals.lpuart2.disable_clock();
244 peripherals
245 .ccm
246 .set_uart_clock_sel(imxrt1050::ccm::UartClockSelection::PLL3);
247 peripherals.ccm.set_uart_clock_podf(1);
248 peripherals.lpuart1.set_baud();
249
250 set_pin_primary_functions(peripherals);
251
252 setup_peripherals(peripherals);
253
254 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
255
256 let chip = static_init!(Chip, Chip::new(peripherals));
257 CHIP = Some(chip);
258
259 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
269 PadId::AdB0,
270 MuxMode::ALT2, Sion::Disabled,
272 13,
273 );
274 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
275 PadId::AdB0,
276 MuxMode::ALT2, Sion::Disabled,
278 14,
279 );
280
281 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
284 PadId::AdB0,
285 13,
286 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
292 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
293 PadId::AdB0,
294 14,
295 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
301
302 peripherals.lpuart1.enable_clock();
304
305 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
306 .finalize(components::uart_mux_component_static!());
307 (*addr_of_mut!(io::WRITER)).set_initialized();
308
309 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
312 let process_management_capability =
313 create_capability!(capabilities::ProcessManagementCapability);
314
315 let console = components::console::ConsoleComponent::new(
317 board_kernel,
318 capsules_core::console::DRIVER_NUM,
319 lpuart_mux,
320 )
321 .finalize(components::console_component_static!());
322 components::debug_writer::DebugWriterComponent::new(lpuart_mux)
324 .finalize(components::debug_writer_component_static!());
325
326 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
330 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
331 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
332 ));
333
334 let button = components::button::ButtonComponent::new(
336 board_kernel,
337 capsules_core::button::DRIVER_NUM,
338 components::button_component_helper!(
339 imxrt1050::gpio::Pin,
340 (
341 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
342 kernel::hil::gpio::ActivationMode::ActiveHigh,
343 kernel::hil::gpio::FloatingState::PullDown
344 )
345 ),
346 )
347 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
348
349 let gpt1 = &peripherals.gpt1;
351 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
352 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
353 );
354
355 let alarm = components::alarm::AlarmDriverComponent::new(
356 board_kernel,
357 capsules_core::alarm::DRIVER_NUM,
358 mux_alarm,
359 )
360 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
361
362 let gpio = GpioComponent::new(
365 board_kernel,
366 capsules_core::gpio::DRIVER_NUM,
367 components::gpio_component_helper!(
368 imxrt1050::gpio::Pin<'static>,
369 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
371 ),
372 )
373 .finalize(components::gpio_component_static!(
374 imxrt1050::gpio::Pin<'static>
375 ));
376
377 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
385 PadId::AdB1,
386 MuxMode::ALT3, Sion::Enabled,
388 0,
389 );
390 peripherals.iomuxc.enable_lpi2c_scl_select_input();
392
393 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
394 PadId::AdB1,
395 MuxMode::ALT3, Sion::Enabled,
397 1,
398 );
399 peripherals.iomuxc.enable_lpi2c_sda_select_input();
401
402 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
405 PadId::AdB1,
406 0,
407 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
413
414 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
415 PadId::AdB1,
416 1,
417 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
423
424 peripherals.lpi2c1.enable_clock();
426 peripherals
427 .lpi2c1
428 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
429
430 use imxrt1050::gpio::PinId;
431 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
432 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
433 );
434
435 let fxos8700 = components::fxos8700::Fxos8700Component::new(
437 mux_i2c,
438 0x1f,
439 peripherals.ports.pin(PinId::AdB1_00),
440 )
441 .finalize(components::fxos8700_component_static!(
442 imxrt1050::lpi2c::Lpi2c
443 ));
444
445 let ninedof = components::ninedof::NineDofComponent::new(
447 board_kernel,
448 capsules_extra::ninedof::DRIVER_NUM,
449 )
450 .finalize(components::ninedof_component_static!(fxos8700));
451
452 let scheduler = components::sched::round_robin::RoundRobinComponent::new(&*addr_of!(PROCESSES))
453 .finalize(components::round_robin_component_static!(NUM_PROCS));
454
455 let imxrt1050 = Imxrt1050EVKB {
456 console,
457 ipc: kernel::ipc::IPC::new(
458 board_kernel,
459 kernel::ipc::DRIVER_NUM,
460 &memory_allocation_capability,
461 ),
462 led,
463 button,
464 ninedof,
465 alarm,
466 gpio,
467
468 scheduler,
469 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
470 };
471
472 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
481 .finalize(components::process_printer_text_component_static!());
482 PROCESS_PRINTER = Some(process_printer);
483
484 let process_console = components::process_console::ProcessConsoleComponent::new(
485 board_kernel,
486 lpuart_mux,
487 mux_alarm,
488 process_printer,
489 None,
490 )
491 .finalize(components::process_console_component_static!(
492 imxrt1050::gpt::Gpt1
493 ));
494 let _ = process_console.start();
495
496 debug!("Tock OS initialization complete. Entering main loop");
497
498 extern "C" {
499 static _sapps: u8;
503 static _eapps: u8;
507 static mut _sappmem: u8;
509 static _eappmem: u8;
511 }
512
513 kernel::process::load_processes(
514 board_kernel,
515 chip,
516 core::slice::from_raw_parts(
517 core::ptr::addr_of!(_sapps),
518 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
519 ),
520 core::slice::from_raw_parts_mut(
521 core::ptr::addr_of_mut!(_sappmem),
522 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
523 ),
524 &mut *addr_of_mut!(PROCESSES),
525 &FAULT_RESPONSE,
526 &process_management_capability,
527 )
528 .unwrap_or_else(|err| {
529 debug!("Error loading processes!");
530 debug!("{:?}", err);
531 });
532
533 (board_kernel, imxrt1050, chip)
534}
535
536#[no_mangle]
538pub unsafe fn main() {
539 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
540
541 let (board_kernel, board, chip) = start();
542 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
543}