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 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 let ccm = static_init!(imxrt1050::ccm::Ccm, imxrt1050::ccm::Ccm::new());
242 let peripherals = static_init!(
243 imxrt1050::chip::Imxrt10xxDefaultPeripherals,
244 imxrt1050::chip::Imxrt10xxDefaultPeripherals::new(ccm)
245 );
246 peripherals.ccm.set_low_power_mode();
247 peripherals.lpuart1.disable_clock();
248 peripherals.lpuart2.disable_clock();
249 peripherals
250 .ccm
251 .set_uart_clock_sel(imxrt1050::ccm::UartClockSelection::PLL3);
252 peripherals.ccm.set_uart_clock_podf(1);
253 peripherals.lpuart1.set_baud();
254
255 set_pin_primary_functions(peripherals);
256
257 setup_peripherals(peripherals);
258
259 let processes = components::process_array::ProcessArrayComponent::new()
261 .finalize(components::process_array_component_static!(NUM_PROCS));
262 PROCESSES = Some(processes);
263
264 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
266
267 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
268 CHIP = Some(chip);
269
270 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
280 PadId::AdB0,
281 MuxMode::ALT2, Sion::Disabled,
283 13,
284 );
285 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
286 PadId::AdB0,
287 MuxMode::ALT2, Sion::Disabled,
289 14,
290 );
291
292 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
295 PadId::AdB0,
296 13,
297 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
303 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
304 PadId::AdB0,
305 14,
306 PullUpDown::Pus0_100kOhmPullDown, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode0OpenDrainDisabled, Speed::Medium2, DriveStrength::DSE6, );
312
313 peripherals.lpuart1.enable_clock();
315
316 let lpuart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart1, 115200)
317 .finalize(components::uart_mux_component_static!());
318 (*addr_of_mut!(io::WRITER)).set_initialized();
319
320 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
323 let process_management_capability =
324 create_capability!(capabilities::ProcessManagementCapability);
325
326 let console = components::console::ConsoleComponent::new(
328 board_kernel,
329 capsules_core::console::DRIVER_NUM,
330 lpuart_mux,
331 )
332 .finalize(components::console_component_static!());
333 components::debug_writer::DebugWriterComponent::new::<
335 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
336 >(
337 lpuart_mux,
338 create_capability!(capabilities::SetDebugWriterCapability),
339 )
340 .finalize(components::debug_writer_component_static!());
341
342 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
346 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
347 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
348 ));
349
350 let button = components::button::ButtonComponent::new(
352 board_kernel,
353 capsules_core::button::DRIVER_NUM,
354 components::button_component_helper!(
355 imxrt1050::gpio::Pin,
356 (
357 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
358 kernel::hil::gpio::ActivationMode::ActiveHigh,
359 kernel::hil::gpio::FloatingState::PullDown
360 )
361 ),
362 )
363 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
364
365 let gpt1 = &peripherals.gpt1;
367 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
368 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
369 );
370
371 let alarm = components::alarm::AlarmDriverComponent::new(
372 board_kernel,
373 capsules_core::alarm::DRIVER_NUM,
374 mux_alarm,
375 )
376 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
377
378 let gpio = GpioComponent::new(
381 board_kernel,
382 capsules_core::gpio::DRIVER_NUM,
383 components::gpio_component_helper!(
384 imxrt1050::gpio::Pin<'static>,
385 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
387 ),
388 )
389 .finalize(components::gpio_component_static!(
390 imxrt1050::gpio::Pin<'static>
391 ));
392
393 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
401 PadId::AdB1,
402 MuxMode::ALT3, Sion::Enabled,
404 0,
405 );
406 peripherals.iomuxc.enable_lpi2c_scl_select_input();
408
409 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
410 PadId::AdB1,
411 MuxMode::ALT3, Sion::Enabled,
413 1,
414 );
415 peripherals.iomuxc.enable_lpi2c_sda_select_input();
417
418 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
421 PadId::AdB1,
422 0,
423 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
429
430 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
431 PadId::AdB1,
432 1,
433 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
439
440 peripherals.lpi2c1.enable_clock();
442 peripherals
443 .lpi2c1
444 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
445
446 use imxrt1050::gpio::PinId;
447 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
448 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
449 );
450
451 let fxos8700 = components::fxos8700::Fxos8700Component::new(
453 mux_i2c,
454 0x1f,
455 peripherals.ports.pin(PinId::AdB1_00),
456 )
457 .finalize(components::fxos8700_component_static!(
458 imxrt1050::lpi2c::Lpi2c
459 ));
460
461 let ninedof = components::ninedof::NineDofComponent::new(
463 board_kernel,
464 capsules_extra::ninedof::DRIVER_NUM,
465 )
466 .finalize(components::ninedof_component_static!(fxos8700));
467
468 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
469 .finalize(components::round_robin_component_static!(NUM_PROCS));
470
471 let imxrt1050 = Imxrt1050EVKB {
472 console,
473 ipc: kernel::ipc::IPC::new(
474 board_kernel,
475 kernel::ipc::DRIVER_NUM,
476 &memory_allocation_capability,
477 ),
478 led,
479 button,
480 ninedof,
481 alarm,
482 gpio,
483
484 scheduler,
485 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
486 };
487
488 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
497 .finalize(components::process_printer_text_component_static!());
498 PROCESS_PRINTER = Some(process_printer);
499
500 let process_console = components::process_console::ProcessConsoleComponent::new(
501 board_kernel,
502 lpuart_mux,
503 mux_alarm,
504 process_printer,
505 None,
506 )
507 .finalize(components::process_console_component_static!(
508 imxrt1050::gpt::Gpt1
509 ));
510 let _ = process_console.start();
511
512 debug!("Tock OS initialization complete. Entering main loop");
513
514 extern "C" {
515 static _sapps: u8;
519 static _eapps: u8;
523 static mut _sappmem: u8;
525 static _eappmem: u8;
527 }
528
529 kernel::process::load_processes(
530 board_kernel,
531 chip,
532 core::slice::from_raw_parts(
533 core::ptr::addr_of!(_sapps),
534 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
535 ),
536 core::slice::from_raw_parts_mut(
537 core::ptr::addr_of_mut!(_sappmem),
538 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
539 ),
540 &FAULT_RESPONSE,
541 &process_management_capability,
542 )
543 .unwrap_or_else(|err| {
544 debug!("Error loading processes!");
545 debug!("{:?}", err);
546 });
547
548 (board_kernel, imxrt1050, chip)
549}
550
551#[no_mangle]
553pub unsafe fn main() {
554 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
555
556 let (board_kernel, board, chip) = start();
557 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
558}