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
69#[no_mangle]
71#[link_section = ".stack_buffer"]
72static 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 processes = components::process_array::ProcessArrayComponent::new()
256 .finalize(components::process_array_component_static!(NUM_PROCS));
257 PROCESSES = Some(processes);
258
259 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
261
262 let chip = static_init!(Chip, Chip::new(peripherals));
263 CHIP = Some(chip);
264
265 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
275 PadId::AdB0,
276 MuxMode::ALT2, Sion::Disabled,
278 13,
279 );
280 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
281 PadId::AdB0,
282 MuxMode::ALT2, Sion::Disabled,
284 14,
285 );
286
287 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
290 PadId::AdB0,
291 13,
292 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
298 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
299 PadId::AdB0,
300 14,
301 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
307
308 peripherals.lpuart1.enable_clock();
310
311 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
312 .finalize(components::uart_mux_component_static!());
313 (*addr_of_mut!(io::WRITER)).set_initialized();
314
315 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
318 let process_management_capability =
319 create_capability!(capabilities::ProcessManagementCapability);
320
321 let console = components::console::ConsoleComponent::new(
323 board_kernel,
324 capsules_core::console::DRIVER_NUM,
325 lpuart_mux,
326 )
327 .finalize(components::console_component_static!());
328 components::debug_writer::DebugWriterComponent::new(
330 lpuart_mux,
331 create_capability!(capabilities::SetDebugWriterCapability),
332 )
333 .finalize(components::debug_writer_component_static!());
334
335 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
339 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
340 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
341 ));
342
343 let button = components::button::ButtonComponent::new(
345 board_kernel,
346 capsules_core::button::DRIVER_NUM,
347 components::button_component_helper!(
348 imxrt1050::gpio::Pin,
349 (
350 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
351 kernel::hil::gpio::ActivationMode::ActiveHigh,
352 kernel::hil::gpio::FloatingState::PullDown
353 )
354 ),
355 )
356 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
357
358 let gpt1 = &peripherals.gpt1;
360 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
361 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
362 );
363
364 let alarm = components::alarm::AlarmDriverComponent::new(
365 board_kernel,
366 capsules_core::alarm::DRIVER_NUM,
367 mux_alarm,
368 )
369 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
370
371 let gpio = GpioComponent::new(
374 board_kernel,
375 capsules_core::gpio::DRIVER_NUM,
376 components::gpio_component_helper!(
377 imxrt1050::gpio::Pin<'static>,
378 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
380 ),
381 )
382 .finalize(components::gpio_component_static!(
383 imxrt1050::gpio::Pin<'static>
384 ));
385
386 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
394 PadId::AdB1,
395 MuxMode::ALT3, Sion::Enabled,
397 0,
398 );
399 peripherals.iomuxc.enable_lpi2c_scl_select_input();
401
402 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
403 PadId::AdB1,
404 MuxMode::ALT3, Sion::Enabled,
406 1,
407 );
408 peripherals.iomuxc.enable_lpi2c_sda_select_input();
410
411 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
414 PadId::AdB1,
415 0,
416 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
422
423 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
424 PadId::AdB1,
425 1,
426 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
432
433 peripherals.lpi2c1.enable_clock();
435 peripherals
436 .lpi2c1
437 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
438
439 use imxrt1050::gpio::PinId;
440 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
441 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
442 );
443
444 let fxos8700 = components::fxos8700::Fxos8700Component::new(
446 mux_i2c,
447 0x1f,
448 peripherals.ports.pin(PinId::AdB1_00),
449 )
450 .finalize(components::fxos8700_component_static!(
451 imxrt1050::lpi2c::Lpi2c
452 ));
453
454 let ninedof = components::ninedof::NineDofComponent::new(
456 board_kernel,
457 capsules_extra::ninedof::DRIVER_NUM,
458 )
459 .finalize(components::ninedof_component_static!(fxos8700));
460
461 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
462 .finalize(components::round_robin_component_static!(NUM_PROCS));
463
464 let imxrt1050 = Imxrt1050EVKB {
465 console,
466 ipc: kernel::ipc::IPC::new(
467 board_kernel,
468 kernel::ipc::DRIVER_NUM,
469 &memory_allocation_capability,
470 ),
471 led,
472 button,
473 ninedof,
474 alarm,
475 gpio,
476
477 scheduler,
478 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
479 };
480
481 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
490 .finalize(components::process_printer_text_component_static!());
491 PROCESS_PRINTER = Some(process_printer);
492
493 let process_console = components::process_console::ProcessConsoleComponent::new(
494 board_kernel,
495 lpuart_mux,
496 mux_alarm,
497 process_printer,
498 None,
499 )
500 .finalize(components::process_console_component_static!(
501 imxrt1050::gpt::Gpt1
502 ));
503 let _ = process_console.start();
504
505 debug!("Tock OS initialization complete. Entering main loop");
506
507 extern "C" {
508 static _sapps: u8;
512 static _eapps: u8;
516 static mut _sappmem: u8;
518 static _eappmem: u8;
520 }
521
522 kernel::process::load_processes(
523 board_kernel,
524 chip,
525 core::slice::from_raw_parts(
526 core::ptr::addr_of!(_sapps),
527 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
528 ),
529 core::slice::from_raw_parts_mut(
530 core::ptr::addr_of_mut!(_sappmem),
531 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
532 ),
533 &FAULT_RESPONSE,
534 &process_management_capability,
535 )
536 .unwrap_or_else(|err| {
537 debug!("Error loading processes!");
538 debug!("{:?}", err);
539 });
540
541 (board_kernel, imxrt1050, chip)
542}
543
544#[no_mangle]
546pub unsafe fn main() {
547 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
548
549 let (board_kernel, board, chip) = start();
550 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
551}