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 kernel::debug::assign_gpios(Some(pin), None, None);
196
197 peripherals.ports.gpio5.enable_clock();
199
200 peripherals.iomuxc_snvs.enable_sw_mux_ctl_pad_gpio(
203 MuxMode::ALT5, Sion::Disabled,
205 0,
206 );
207
208 peripherals.ports.pin(PinId::Wakeup).make_input();
210}
211
212unsafe fn setup_peripherals(peripherals: &imxrt1050::chip::Imxrt10xxDefaultPeripherals) {
214 cortexm7::nvic::Nvic::new(imxrt1050::nvic::LPUART1).enable();
216
217 peripherals.gpt1.enable_clock();
219 peripherals.gpt1.start(
220 peripherals.ccm.perclk_sel(),
221 peripherals.ccm.perclk_divider(),
222 );
223 cortexm7::nvic::Nvic::new(imxrt1050::nvic::GPT1).enable();
224}
225
226#[inline(never)]
230unsafe fn start() -> (
231 &'static kernel::Kernel,
232 Imxrt1050EVKB,
233 &'static imxrt1050::chip::Imxrt10xx<imxrt1050::chip::Imxrt10xxDefaultPeripherals>,
234) {
235 imxrt1050::init();
236
237 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
238 let peripherals = static_init!(
239 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
240 imxrt1050::chip::Imxrt10xxDefaultPeripherals::new(ccm)
241 );
242 peripherals.ccm.set_low_power_mode();
243 peripherals.lpuart1.disable_clock();
244 peripherals.lpuart2.disable_clock();
245 peripherals
246 .ccm
247 .set_uart_clock_sel(imxrt1050::ccm::UartClockSelection::PLL3);
248 peripherals.ccm.set_uart_clock_podf(1);
249 peripherals.lpuart1.set_baud();
250
251 set_pin_primary_functions(peripherals);
252
253 setup_peripherals(peripherals);
254
255 let processes = components::process_array::ProcessArrayComponent::new()
257 .finalize(components::process_array_component_static!(NUM_PROCS));
258 PROCESSES = Some(processes);
259
260 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
262
263 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
264 CHIP = Some(chip);
265
266 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
276 PadId::AdB0,
277 MuxMode::ALT2, Sion::Disabled,
279 13,
280 );
281 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
282 PadId::AdB0,
283 MuxMode::ALT2, Sion::Disabled,
285 14,
286 );
287
288 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
291 PadId::AdB0,
292 13,
293 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
299 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
300 PadId::AdB0,
301 14,
302 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
308
309 peripherals.lpuart1.enable_clock();
311
312 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
313 .finalize(components::uart_mux_component_static!());
314 (*addr_of_mut!(io::WRITER)).set_initialized();
315
316 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
319 let process_management_capability =
320 create_capability!(capabilities::ProcessManagementCapability);
321
322 let console = components::console::ConsoleComponent::new(
324 board_kernel,
325 capsules_core::console::DRIVER_NUM,
326 lpuart_mux,
327 )
328 .finalize(components::console_component_static!());
329 components::debug_writer::DebugWriterComponent::new::<
331 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
332 >(
333 lpuart_mux,
334 create_capability!(capabilities::SetDebugWriterCapability),
335 )
336 .finalize(components::debug_writer_component_static!());
337
338 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
342 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
343 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
344 ));
345
346 let button = components::button::ButtonComponent::new(
348 board_kernel,
349 capsules_core::button::DRIVER_NUM,
350 components::button_component_helper!(
351 imxrt1050::gpio::Pin,
352 (
353 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
354 kernel::hil::gpio::ActivationMode::ActiveHigh,
355 kernel::hil::gpio::FloatingState::PullDown
356 )
357 ),
358 )
359 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
360
361 let gpt1 = &peripherals.gpt1;
363 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
364 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
365 );
366
367 let alarm = components::alarm::AlarmDriverComponent::new(
368 board_kernel,
369 capsules_core::alarm::DRIVER_NUM,
370 mux_alarm,
371 )
372 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
373
374 let gpio = GpioComponent::new(
377 board_kernel,
378 capsules_core::gpio::DRIVER_NUM,
379 components::gpio_component_helper!(
380 imxrt1050::gpio::Pin<'static>,
381 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
383 ),
384 )
385 .finalize(components::gpio_component_static!(
386 imxrt1050::gpio::Pin<'static>
387 ));
388
389 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
397 PadId::AdB1,
398 MuxMode::ALT3, Sion::Enabled,
400 0,
401 );
402 peripherals.iomuxc.enable_lpi2c_scl_select_input();
404
405 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
406 PadId::AdB1,
407 MuxMode::ALT3, Sion::Enabled,
409 1,
410 );
411 peripherals.iomuxc.enable_lpi2c_sda_select_input();
413
414 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
417 PadId::AdB1,
418 0,
419 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
425
426 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
427 PadId::AdB1,
428 1,
429 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
435
436 peripherals.lpi2c1.enable_clock();
438 peripherals
439 .lpi2c1
440 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
441
442 use imxrt1050::gpio::PinId;
443 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
444 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
445 );
446
447 let fxos8700 = components::fxos8700::Fxos8700Component::new(
449 mux_i2c,
450 0x1f,
451 peripherals.ports.pin(PinId::AdB1_00),
452 )
453 .finalize(components::fxos8700_component_static!(
454 imxrt1050::lpi2c::Lpi2c
455 ));
456
457 let ninedof = components::ninedof::NineDofComponent::new(
459 board_kernel,
460 capsules_extra::ninedof::DRIVER_NUM,
461 )
462 .finalize(components::ninedof_component_static!(fxos8700));
463
464 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
465 .finalize(components::round_robin_component_static!(NUM_PROCS));
466
467 let imxrt1050 = Imxrt1050EVKB {
468 console,
469 ipc: kernel::ipc::IPC::new(
470 board_kernel,
471 kernel::ipc::DRIVER_NUM,
472 &memory_allocation_capability,
473 ),
474 led,
475 button,
476 ninedof,
477 alarm,
478 gpio,
479
480 scheduler,
481 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
482 };
483
484 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
493 .finalize(components::process_printer_text_component_static!());
494 PROCESS_PRINTER = Some(process_printer);
495
496 let process_console = components::process_console::ProcessConsoleComponent::new(
497 board_kernel,
498 lpuart_mux,
499 mux_alarm,
500 process_printer,
501 None,
502 )
503 .finalize(components::process_console_component_static!(
504 imxrt1050::gpt::Gpt1
505 ));
506 let _ = process_console.start();
507
508 debug!("Tock OS initialization complete. Entering main loop");
509
510 extern "C" {
511 static _sapps: u8;
515 static _eapps: u8;
519 static mut _sappmem: u8;
521 static _eappmem: u8;
523 }
524
525 kernel::process::load_processes(
526 board_kernel,
527 chip,
528 core::slice::from_raw_parts(
529 core::ptr::addr_of!(_sapps),
530 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
531 ),
532 core::slice::from_raw_parts_mut(
533 core::ptr::addr_of_mut!(_sappmem),
534 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
535 ),
536 &FAULT_RESPONSE,
537 &process_management_capability,
538 )
539 .unwrap_or_else(|err| {
540 debug!("Error loading processes!");
541 debug!("{:?}", err);
542 });
543
544 (board_kernel, imxrt1050, chip)
545}
546
547#[no_mangle]
549pub unsafe fn main() {
550 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
551
552 let (board_kernel, board, chip) = start();
553 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
554}