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(
324 lpuart_mux,
325 create_capability!(capabilities::SetDebugWriterCapability),
326 )
327 .finalize(components::debug_writer_component_static!());
328
329 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
333 LedLow<'static, imxrt1050::gpio::Pin<'static>>,
334 LedLow::new(peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)),
335 ));
336
337 let button = components::button::ButtonComponent::new(
339 board_kernel,
340 capsules_core::button::DRIVER_NUM,
341 components::button_component_helper!(
342 imxrt1050::gpio::Pin,
343 (
344 peripherals.ports.pin(imxrt1050::gpio::PinId::Wakeup),
345 kernel::hil::gpio::ActivationMode::ActiveHigh,
346 kernel::hil::gpio::FloatingState::PullDown
347 )
348 ),
349 )
350 .finalize(components::button_component_static!(imxrt1050::gpio::Pin));
351
352 let gpt1 = &peripherals.gpt1;
354 let mux_alarm = components::alarm::AlarmMuxComponent::new(gpt1).finalize(
355 components::alarm_mux_component_static!(imxrt1050::gpt::Gpt1),
356 );
357
358 let alarm = components::alarm::AlarmDriverComponent::new(
359 board_kernel,
360 capsules_core::alarm::DRIVER_NUM,
361 mux_alarm,
362 )
363 .finalize(components::alarm_component_static!(imxrt1050::gpt::Gpt1));
364
365 let gpio = GpioComponent::new(
368 board_kernel,
369 capsules_core::gpio::DRIVER_NUM,
370 components::gpio_component_helper!(
371 imxrt1050::gpio::Pin<'static>,
372 0 => peripherals.ports.pin(imxrt1050::gpio::PinId::AdB0_09)
374 ),
375 )
376 .finalize(components::gpio_component_static!(
377 imxrt1050::gpio::Pin<'static>
378 ));
379
380 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
388 PadId::AdB1,
389 MuxMode::ALT3, Sion::Enabled,
391 0,
392 );
393 peripherals.iomuxc.enable_lpi2c_scl_select_input();
395
396 peripherals.iomuxc.enable_sw_mux_ctl_pad_gpio(
397 PadId::AdB1,
398 MuxMode::ALT3, Sion::Enabled,
400 1,
401 );
402 peripherals.iomuxc.enable_lpi2c_sda_select_input();
404
405 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
408 PadId::AdB1,
409 0,
410 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
416
417 peripherals.iomuxc.configure_sw_pad_ctl_pad_gpio(
418 PadId::AdB1,
419 1,
420 PullUpDown::Pus3_22kOhmPullUp, PullKeepEn::Pke1PullKeeperEnabled, OpenDrainEn::Ode1OpenDrainEnabled, Speed::Medium2, DriveStrength::DSE6, );
426
427 peripherals.lpi2c1.enable_clock();
429 peripherals
430 .lpi2c1
431 .set_speed(imxrt1050::lpi2c::Lpi2cSpeed::Speed100k, 8);
432
433 use imxrt1050::gpio::PinId;
434 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.lpi2c1, None).finalize(
435 components::i2c_mux_component_static!(imxrt1050::lpi2c::Lpi2c),
436 );
437
438 let fxos8700 = components::fxos8700::Fxos8700Component::new(
440 mux_i2c,
441 0x1f,
442 peripherals.ports.pin(PinId::AdB1_00),
443 )
444 .finalize(components::fxos8700_component_static!(
445 imxrt1050::lpi2c::Lpi2c
446 ));
447
448 let ninedof = components::ninedof::NineDofComponent::new(
450 board_kernel,
451 capsules_extra::ninedof::DRIVER_NUM,
452 )
453 .finalize(components::ninedof_component_static!(fxos8700));
454
455 let scheduler = components::sched::round_robin::RoundRobinComponent::new(&*addr_of!(PROCESSES))
456 .finalize(components::round_robin_component_static!(NUM_PROCS));
457
458 let imxrt1050 = Imxrt1050EVKB {
459 console,
460 ipc: kernel::ipc::IPC::new(
461 board_kernel,
462 kernel::ipc::DRIVER_NUM,
463 &memory_allocation_capability,
464 ),
465 led,
466 button,
467 ninedof,
468 alarm,
469 gpio,
470
471 scheduler,
472 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
473 };
474
475 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
484 .finalize(components::process_printer_text_component_static!());
485 PROCESS_PRINTER = Some(process_printer);
486
487 let process_console = components::process_console::ProcessConsoleComponent::new(
488 board_kernel,
489 lpuart_mux,
490 mux_alarm,
491 process_printer,
492 None,
493 )
494 .finalize(components::process_console_component_static!(
495 imxrt1050::gpt::Gpt1
496 ));
497 let _ = process_console.start();
498
499 debug!("Tock OS initialization complete. Entering main loop");
500
501 extern "C" {
502 static _sapps: u8;
506 static _eapps: u8;
510 static mut _sappmem: u8;
512 static _eappmem: u8;
514 }
515
516 kernel::process::load_processes(
517 board_kernel,
518 chip,
519 core::slice::from_raw_parts(
520 core::ptr::addr_of!(_sapps),
521 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
522 ),
523 core::slice::from_raw_parts_mut(
524 core::ptr::addr_of_mut!(_sappmem),
525 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
526 ),
527 &mut *addr_of_mut!(PROCESSES),
528 &FAULT_RESPONSE,
529 &process_management_capability,
530 )
531 .unwrap_or_else(|err| {
532 debug!("Error loading processes!");
533 debug!("{:?}", err);
534 });
535
536 (board_kernel, imxrt1050, chip)
537}
538
539#[no_mangle]
541pub unsafe fn main() {
542 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
543
544 let (board_kernel, board, chip) = start();
545 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
546}