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 Chip = imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>;
53
54static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
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
69kernel::stack_size! {0x2000}
70
71struct Imxrt1050EVKB {
76 alarm: &'static capsules_core::alarm::AlarmDriver<
77 'static,
78 VirtualMuxAlarm<'static, imxrt1050::gpt::Gpt1<'static>>,
79 >,
80 button: &'static capsules_core::button::Button<'static, imxrt1050::gpio::Pin<'static>>,
81 console: &'static capsules_core::console::Console<'static>,
82 gpio: &'static capsules_core::gpio::GPIO<'static, imxrt1050::gpio::Pin<'static>>,
83 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
84 led: &'static capsules_core::led::LedDriver<
85 'static,
86 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
87 1,
88 >,
89 ninedof: &'static capsules_extra::ninedof::NineDof<'static>,
90
91 scheduler: &'static RoundRobinSched<'static>,
92 systick: cortexm7::systick::SysTick,
93}
94
95impl SyscallDriverLookup for Imxrt1050EVKB {
97 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
98 where
99 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
100 {
101 match driver_num {
102 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
103 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
104 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
105 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
106 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
107 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
108 capsules_extra::ninedof::DRIVER_NUM => f(Some(self.ninedof)),
109 _ => f(None),
110 }
111 }
112}
113
114impl KernelResources<imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>>
115 for Imxrt1050EVKB
116{
117 type SyscallDriverLookup = Self;
118 type SyscallFilter = ();
119 type ProcessFault = ();
120 type Scheduler = RoundRobinSched<'static>;
121 type SchedulerTimer = cortexm7::systick::SysTick;
122 type WatchDog = ();
123 type ContextSwitchCallback = ();
124
125 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
126 self
127 }
128 fn syscall_filter(&self) -> &Self::SyscallFilter {
129 &()
130 }
131 fn process_fault(&self) -> &Self::ProcessFault {
132 &()
133 }
134 fn scheduler(&self) -> &Self::Scheduler {
135 self.scheduler
136 }
137 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
138 &self.systick
139 }
140 fn watchdog(&self) -> &Self::WatchDog {
141 &()
142 }
143 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
144 &()
145 }
146}
147
148unsafe fn set_pin_primary_functions(
155 peripherals: &'static imxrt1050::chip::Imxrt10xxDefaultPeripherals,
156) {
157 use imxrt1050::gpio::PinId;
158
159 peripherals.ccm.enable_iomuxc_clock();
160 peripherals.ccm.enable_iomuxc_snvs_clock();
161
162 peripherals.ports.gpio1.enable_clock();
163
164 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
170 PadId::AdB0,
171 MuxMode::ALT5, Sion::Disabled,
173 9,
174 );
175
176 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
179 PadId::AdB0,
180 9,
181 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
187
188 let pin = peripherals.ports.pin(PinId::AdB0_09);
190 pin.make_output();
191 kernel::debug::assign_gpios(Some(pin), None, None);
192
193 peripherals.ports.gpio5.enable_clock();
195
196 peripherals.iomuxc_snvs.enable_sw_mux_ctl_pad_gpio(
199 MuxMode::ALT5, Sion::Disabled,
201 0,
202 );
203
204 peripherals.ports.pin(PinId::Wakeup).make_input();
206}
207
208unsafe fn setup_peripherals(peripherals: &imxrt1050::chip::Imxrt10xxDefaultPeripherals) {
210 cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable();
212
213 peripherals.gpt1.enable_clock();
215 peripherals.gpt1.start(
216 peripherals.ccm.perclk_sel(),
217 peripherals.ccm.perclk_divider(),
218 );
219 cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable();
220}
221
222#[inline(never)]
226unsafe fn start() -> (
227 &'static kernel::Kernel,
228 Imxrt1050EVKB,
229 &'static imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>,
230) {
231 imxrt1050::init();
232
233 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
234 let peripherals = static_init!(
235 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
236 imxrt1050::chip::Imxrt10xxDefaultPeripherals::new(ccm)
237 );
238 peripherals.ccm.set_low_power_mode();
239 peripherals.lpuart1.disable_clock();
240 peripherals.lpuart2.disable_clock();
241 peripherals
242 .ccm
243 .set_uart_clock_sel(imxrt1050::ccm::UartClockSelection::PLL3);
244 peripherals.ccm.set_uart_clock_podf(1);
245 peripherals.lpuart1.set_baud();
246
247 set_pin_primary_functions(peripherals);
248
249 setup_peripherals(peripherals);
250
251 let processes = components::process_array::ProcessArrayComponent::new()
253 .finalize(components::process_array_component_static!(NUM_PROCS));
254 PROCESSES = Some(processes);
255
256 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
258
259 let chip = static_init!(Chip, Chip::new(peripherals));
260 CHIP = Some(chip);
261
262 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
272 PadId::AdB0,
273 MuxMode::ALT2, Sion::Disabled,
275 13,
276 );
277 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
278 PadId::AdB0,
279 MuxMode::ALT2, Sion::Disabled,
281 14,
282 );
283
284 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
287 PadId::AdB0,
288 13,
289 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
295 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
296 PadId::AdB0,
297 14,
298 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
304
305 peripherals.lpuart1.enable_clock();
307
308 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
309 .finalize(components::uart_mux_component_static!());
310 (*addr_of_mut!(io::WRITER)).set_initialized();
311
312 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
315 let process_management_capability =
316 create_capability!(capabilities::ProcessManagementCapability);
317
318 let console = components::console::ConsoleComponent::new(
320 board_kernel,
321 capsules_core::console::DRIVER_NUM,
322 lpuart_mux,
323 )
324 .finalize(components::console_component_static!());
325 components::debug_writer::DebugWriterComponent::new(
327 lpuart_mux,
328 create_capability!(capabilities::SetDebugWriterCapability),
329 )
330 .finalize(components::debug_writer_component_static!());
331
332 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
336 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
337 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
338 ));
339
340 let button = components::button::ButtonComponent::new(
342 board_kernel,
343 capsules_core::button::DRIVER_NUM,
344 components::button_component_helper!(
345 imxrt1050::gpio::Pin,
346 (
347 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
348 kernel::hil::gpio::ActivationMode::ActiveHigh,
349 kernel::hil::gpio::FloatingState::PullDown
350 )
351 ),
352 )
353 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
354
355 let gpt1 = &peripherals.gpt1;
357 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
358 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
359 );
360
361 let alarm = components::alarm::AlarmDriverComponent::new(
362 board_kernel,
363 capsules_core::alarm::DRIVER_NUM,
364 mux_alarm,
365 )
366 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
367
368 let gpio = GpioComponent::new(
371 board_kernel,
372 capsules_core::gpio::DRIVER_NUM,
373 components::gpio_component_helper!(
374 imxrt1050::gpio::Pin<'static>,
375 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
377 ),
378 )
379 .finalize(components::gpio_component_static!(
380 imxrt1050::gpio::Pin<'static>
381 ));
382
383 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
391 PadId::AdB1,
392 MuxMode::ALT3, Sion::Enabled,
394 0,
395 );
396 peripherals.iomuxc.enable_lpi2c_scl_select_input();
398
399 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
400 PadId::AdB1,
401 MuxMode::ALT3, Sion::Enabled,
403 1,
404 );
405 peripherals.iomuxc.enable_lpi2c_sda_select_input();
407
408 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
411 PadId::AdB1,
412 0,
413 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
419
420 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
421 PadId::AdB1,
422 1,
423 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
429
430 peripherals.lpi2c1.enable_clock();
432 peripherals
433 .lpi2c1
434 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
435
436 use imxrt1050::gpio::PinId;
437 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
438 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
439 );
440
441 let fxos8700 = components::fxos8700::Fxos8700Component::new(
443 mux_i2c,
444 0x1f,
445 peripherals.ports.pin(PinId::AdB1_00),
446 )
447 .finalize(components::fxos8700_component_static!(
448 imxrt1050::lpi2c::Lpi2c
449 ));
450
451 let ninedof = components::ninedof::NineDofComponent::new(
453 board_kernel,
454 capsules_extra::ninedof::DRIVER_NUM,
455 )
456 .finalize(components::ninedof_component_static!(fxos8700));
457
458 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
459 .finalize(components::round_robin_component_static!(NUM_PROCS));
460
461 let imxrt1050 = Imxrt1050EVKB {
462 console,
463 ipc: kernel::ipc::IPC::new(
464 board_kernel,
465 kernel::ipc::DRIVER_NUM,
466 &memory_allocation_capability,
467 ),
468 led,
469 button,
470 ninedof,
471 alarm,
472 gpio,
473
474 scheduler,
475 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
476 };
477
478 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
487 .finalize(components::process_printer_text_component_static!());
488 PROCESS_PRINTER = Some(process_printer);
489
490 let process_console = components::process_console::ProcessConsoleComponent::new(
491 board_kernel,
492 lpuart_mux,
493 mux_alarm,
494 process_printer,
495 None,
496 )
497 .finalize(components::process_console_component_static!(
498 imxrt1050::gpt::Gpt1
499 ));
500 let _ = process_console.start();
501
502 debug!("Tock OS initialization complete. Entering main loop");
503
504 extern "C" {
505 static _sapps: u8;
509 static _eapps: u8;
513 static mut _sappmem: u8;
515 static _eappmem: u8;
517 }
518
519 kernel::process::load_processes(
520 board_kernel,
521 chip,
522 core::slice::from_raw_parts(
523 core::ptr::addr_of!(_sapps),
524 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
525 ),
526 core::slice::from_raw_parts_mut(
527 core::ptr::addr_of_mut!(_sappmem),
528 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
529 ),
530 &FAULT_RESPONSE,
531 &process_management_capability,
532 )
533 .unwrap_or_else(|err| {
534 debug!("Error loading processes!");
535 debug!("{:?}", err);
536 });
537
538 (board_kernel, imxrt1050, chip)
539}
540
541#[no_mangle]
543pub unsafe fn main() {
544 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
545
546 let (board_kernel, board, chip) = start();
547 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
548}