1#![no_std]
14#![no_main]
15
16mod fcb;
17mod io;
18
19use imxrt1060::gpio::PinId;
20use imxrt1060::iomuxc::{MuxMode, PadId, Sion};
21use imxrt10xx as imxrt1060;
22use kernel::capabilities;
23use kernel::component::Component;
24use kernel::debug::PanicResources;
25use kernel::hil::{gpio::Configure, led::LedHigh};
26use kernel::platform::chip::ClockInterface;
27use kernel::platform::{KernelResources, SyscallDriverLookup};
28use kernel::scheduler::round_robin::RoundRobinSched;
29use kernel::utilities::single_thread_value::SingleThreadValue;
30use kernel::{create_capability, static_init};
31
32const NUM_PROCS: usize = 4;
34
35type ChipHw = imxrt1060::chip::Imxrt10xx<imxrt1060::chip::Imxrt10xxDefaultPeripherals>;
36type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
37
38static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
40 SingleThreadValue::new(PanicResources::new());
41
42const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
44 capsules_system::process_policies::PanicFaultPolicy {};
45
46struct Teensy40 {
48 led: &'static capsules_core::led::LedDriver<
49 'static,
50 LedHigh<'static, imxrt1060::gpio::Pin<'static>>,
51 1,
52 >,
53 console: &'static capsules_core::console::Console<'static>,
54 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
55 alarm: &'static capsules_core::alarm::AlarmDriver<
56 'static,
57 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
58 'static,
59 imxrt1060::gpt::Gpt1<'static>,
60 >,
61 >,
62
63 scheduler: &'static RoundRobinSched<'static>,
64 systick: cortexm7::systick::SysTick,
65}
66
67impl SyscallDriverLookup for Teensy40 {
68 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
69 where
70 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
71 {
72 match driver_num {
73 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
74 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
75 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
76 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
77 _ => f(None),
78 }
79 }
80}
81
82impl KernelResources<imxrt1060::chip::Imxrt10xx<imxrt1060::chip::Imxrt10xxDefaultPeripherals>>
83 for Teensy40
84{
85 type SyscallDriverLookup = Self;
86 type SyscallFilter = ();
87 type ProcessFault = ();
88 type Scheduler = RoundRobinSched<'static>;
89 type SchedulerTimer = cortexm7::systick::SysTick;
90 type WatchDog = ();
91 type ContextSwitchCallback = ();
92
93 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
94 self
95 }
96 fn syscall_filter(&self) -> &Self::SyscallFilter {
97 &()
98 }
99 fn process_fault(&self) -> &Self::ProcessFault {
100 &()
101 }
102 fn scheduler(&self) -> &Self::Scheduler {
103 self.scheduler
104 }
105 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
106 &self.systick
107 }
108 fn watchdog(&self) -> &Self::WatchDog {
109 &()
110 }
111 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
112 &()
113 }
114}
115
116mod dma_config {
120 use super::imxrt1060::nvic;
121
122 pub const LPUART2_RX: usize = 7;
124 pub const LPUART2_TX: usize = 8;
126
127 const DMA_INTERRUPTS: &[u32] = &[nvic::DMA7_23, nvic::DMA8_24];
129
130 #[inline(always)]
132 pub fn enable_interrupts() {
133 DMA_INTERRUPTS
134 .iter()
135 .copied()
136 .map(|vector| unsafe { cortexm7::nvic::Nvic::new(vector) })
138 .for_each(|intr| intr.enable());
139 }
140}
141
142fn set_arm_clock(ccm: &imxrt1060::ccm::Ccm, ccm_analog: &imxrt1060::ccm_analog::CcmAnalog) {
147 use imxrt1060::ccm::{
148 PeripheralClock2Selection, PeripheralClockSelection, PrePeripheralClockSelection,
149 };
150
151 ccm.set_peripheral_clock2_divider(1);
153 ccm.set_peripheral_clock2_selection(PeripheralClock2Selection::Oscillator);
154 ccm.set_peripheral_clock_selection(PeripheralClockSelection::PeripheralClock2Divided);
155
156 ccm_analog.restart_pll1(100);
163
164 ccm.set_arm_divider(2);
167
168 ccm.set_ahb_divider(1);
170
171 ccm.set_pre_peripheral_clock_selection(PrePeripheralClockSelection::Pll1);
173 ccm.set_peripheral_clock_selection(PeripheralClockSelection::PrePeripheralClock);
174}
175
176#[inline(never)]
180unsafe fn start() -> (&'static kernel::Kernel, Teensy40, &'static ChipHw) {
181 imxrt1060::init();
182
183 kernel::deferred_call::initialize_deferred_call_state::<
185 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
186 >();
187
188 PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
190
191 let ccm = static_init!(imxrt1060::ccm::Ccm, imxrt1060::ccm::Ccm::new());
192 let peripherals = static_init!(
193 imxrt1060::chip::Imxrt10xxDefaultPeripherals,
194 imxrt1060::chip::Imxrt10xxDefaultPeripherals::new(ccm)
195 );
196
197 peripherals.ccm.set_low_power_mode();
198
199 peripherals.dcdc.clock().enable();
200 peripherals.dcdc.set_target_vdd_soc(1250);
201 set_arm_clock(peripherals.ccm, &peripherals.ccm_analog);
202 peripherals.ccm.set_ipg_divider(4);
204
205 peripherals.lpuart1.disable_clock();
206 peripherals.lpuart2.disable_clock();
207 peripherals
208 .ccm
209 .set_uart_clock_sel(imxrt1060::ccm::UartClockSelection::PLL3);
210 peripherals.ccm.set_uart_clock_podf(1);
211
212 peripherals.ccm.enable_iomuxc_clock();
213 peripherals.ccm.enable_iomuxc_snvs_clock();
214
215 peripherals
216 .ccm
217 .set_perclk_sel(imxrt1060::ccm::PerclkClockSel::Oscillator);
218 peripherals.ccm.set_perclk_divider(8);
219
220 peripherals.ports.pin(PinId::B0_03).make_output();
221
222 peripherals
224 .iomuxc
225 .enable_sw_mux_ctl_pad_gpio(PadId::B0, MuxMode::ALT5, Sion::Disabled, 3);
226
227 peripherals
229 .iomuxc
230 .enable_sw_mux_ctl_pad_gpio(PadId::AdB1, MuxMode::ALT2, Sion::Disabled, 2);
231 peripherals
232 .iomuxc
233 .enable_sw_mux_ctl_pad_gpio(PadId::AdB1, MuxMode::ALT2, Sion::Disabled, 3);
234
235 peripherals.iomuxc.enable_lpuart2_tx_select_input();
236 peripherals.iomuxc.enable_lpuart2_rx_select_input();
237
238 peripherals.lpuart2.enable_clock();
239 peripherals.lpuart2.set_baud();
240
241 peripherals.gpt1.enable_clock();
242 peripherals.gpt1.start(
243 peripherals.ccm.perclk_sel(),
244 peripherals.ccm.perclk_divider(),
245 );
246
247 peripherals.dma.clock().enable();
248 peripherals.dma.reset_tcds();
249 peripherals
250 .lpuart2
251 .set_rx_dma_channel(&peripherals.dma.channels[dma_config::LPUART2_RX]);
252 peripherals
253 .lpuart2
254 .set_tx_dma_channel(&peripherals.dma.channels[dma_config::LPUART2_TX]);
255
256 cortexm7::nvic::Nvic::new(imxrt1060::nvic::GPT1).enable();
257 dma_config::enable_interrupts();
258
259 let chip = static_init!(ChipHw, ChipHw::new(peripherals));
260 PANIC_RESOURCES.get().map(|resources| {
261 resources.chip.put(chip);
262 });
263
264 let processes = components::process_array::ProcessArrayComponent::new()
268 .finalize(components::process_array_component_static!(NUM_PROCS));
269 PANIC_RESOURCES.get().map(|resources| {
270 resources.processes.put(processes.as_slice());
271 });
272
273 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
275
276 let uart_mux = components::console::UartMuxComponent::new(&peripherals.lpuart2, 115_200)
279 .finalize(components::uart_mux_component_static!());
280 components::debug_writer::DebugWriterComponent::new::<
282 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
283 >(
284 uart_mux,
285 create_capability!(capabilities::SetDebugWriterCapability),
286 )
287 .finalize(components::debug_writer_component_static!());
288
289 let console = components::console::ConsoleComponent::new(
291 board_kernel,
292 capsules_core::console::DRIVER_NUM,
293 uart_mux,
294 )
295 .finalize(components::console_component_static!());
296
297 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
299 LedHigh<imxrt1060::gpio::Pin>,
300 LedHigh::new(peripherals.ports.pin(PinId::B0_03))
301 ));
302
303 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.gpt1).finalize(
305 components::alarm_mux_component_static!(imxrt1060::gpt::Gpt1),
306 );
307 let alarm = components::alarm::AlarmDriverComponent::new(
308 board_kernel,
309 capsules_core::alarm::DRIVER_NUM,
310 mux_alarm,
311 )
312 .finalize(components::alarm_component_static!(imxrt1060::gpt::Gpt1));
313
314 let memory_allocation_capability = create_capability!(capabilities::MemoryAllocationCapability);
318 let process_management_capability =
319 create_capability!(capabilities::ProcessManagementCapability);
320
321 let ipc = kernel::ipc::IPC::new(
322 board_kernel,
323 kernel::ipc::DRIVER_NUM,
324 &memory_allocation_capability,
325 );
326
327 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
328 .finalize(components::process_printer_text_component_static!());
329 PANIC_RESOURCES.get().map(|resources| {
330 resources.printer.put(process_printer);
331 });
332
333 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
334 .finalize(components::round_robin_component_static!(NUM_PROCS));
335
336 let teensy40 = Teensy40 {
340 led,
341 console,
342 ipc,
343 alarm,
344
345 scheduler,
346 systick: cortexm7::systick::SysTick::new_with_calibration(792_000_000),
347 };
348
349 extern "C" {
353 static _sapps: u8;
357 static _eapps: u8;
361 static mut _sappmem: u8;
363 static _eappmem: u8;
365 }
366
367 kernel::process::load_processes(
368 board_kernel,
369 chip,
370 core::slice::from_raw_parts(
371 core::ptr::addr_of!(_sapps),
372 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
373 ),
374 core::slice::from_raw_parts_mut(
375 core::ptr::addr_of_mut!(_sappmem),
376 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
377 ),
378 &FAULT_RESPONSE,
379 &process_management_capability,
380 )
381 .unwrap();
382
383 (board_kernel, teensy40, chip)
384}
385
386#[no_mangle]
388pub unsafe fn main() {
389 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
390
391 let (board_kernel, platform, chip) = start();
392 board_kernel.kernel_loop(&platform, chip, Some(&platform.ipc), &main_loop_capability);
393}
394
395kernel::stack_size! {0x2000}
396
397const FCB_SIZE: usize = core::mem::size_of::<fcb::FCB>();
398
399#[cfg_attr(not(target_os = "macos"), link_section = ".fcb_buffer")]
411#[no_mangle]
412#[used]
413static mut FCB_BUFFER: [u8; 0x1000 - FCB_SIZE] = [0xFF; 0x1000 - FCB_SIZE];