1#![no_std]
9#![no_main]
10
11use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
12
13use kernel::capabilities;
14use kernel::component::Component;
15use kernel::hil::time::{Alarm, Timer};
16use kernel::platform::chip::InterruptService;
17use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
18use kernel::platform::{KernelResources, SyscallDriverLookup};
19use kernel::process::ProcessArray;
20use kernel::scheduler::mlfq::MLFQSched;
21use kernel::utilities::registers::interfaces::ReadWriteable;
22use kernel::utilities::StaticRef;
23use kernel::{create_capability, debug, static_init};
24use rv32i::csr;
25
26mod io;
27mod litex_generated_constants;
28
29use litex_generated_constants as socc;
36
37struct LiteXArtyInterruptablePeripherals {
45 uart0: &'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>,
46 timer0: &'static litex_vexriscv::timer::LiteXTimer<
47 'static,
48 socc::SoCRegisterFmt,
49 socc::ClockFrequency,
50 >,
51 ethmac0: &'static litex_vexriscv::liteeth::LiteEth<
52 'static,
53 { socc::ETHMAC_TX_SLOTS },
54 socc::SoCRegisterFmt,
55 >,
56}
57
58impl LiteXArtyInterruptablePeripherals {
59 pub fn init(&'static self) {
61 kernel::deferred_call::DeferredCallClient::register(self.uart0);
62 }
63}
64
65impl InterruptService for LiteXArtyInterruptablePeripherals {
66 unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
67 match interrupt as usize {
68 socc::UART_INTERRUPT => {
69 self.uart0.service_interrupt();
70 true
71 }
72 socc::TIMER0_INTERRUPT => {
73 self.timer0.service_interrupt();
74 true
75 }
76 socc::ETHMAC_INTERRUPT => {
77 self.ethmac0.service_interrupt();
78 true
79 }
80 _ => false,
81 }
82 }
83}
84
85const NUM_PROCS: usize = 4;
86
87static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
89
90struct LiteXArtyPanicReferences {
93 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>>,
94 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
95 led_controller:
96 Option<&'static litex_vexriscv::led_controller::LiteXLedController<socc::SoCRegisterFmt>>,
97 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
98}
99static mut PANIC_REFERENCES: LiteXArtyPanicReferences = LiteXArtyPanicReferences {
100 chip: None,
101 uart: None,
102 led_controller: None,
103 process_printer: None,
104};
105
106const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
108 capsules_system::process_policies::PanicFaultPolicy {};
109
110#[no_mangle]
112#[link_section = ".stack_buffer"]
113static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
114
115struct LiteXArty {
118 led_driver: &'static capsules_core::led::LedDriver<
119 'static,
120 litex_vexriscv::led_controller::LiteXLed<'static, socc::SoCRegisterFmt>,
121 4,
122 >,
123 console: &'static capsules_core::console::Console<'static>,
124 pconsole: &'static capsules_core::process_console::ProcessConsole<
125 'static,
126 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
127 VirtualMuxAlarm<
128 'static,
129 litex_vexriscv::timer::LiteXAlarm<
130 'static,
131 'static,
132 socc::SoCRegisterFmt,
133 socc::ClockFrequency,
134 >,
135 >,
136 components::process_console::Capability,
137 >,
138 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
139 'static,
140 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
141 >,
142 alarm: &'static capsules_core::alarm::AlarmDriver<
143 'static,
144 VirtualMuxAlarm<
145 'static,
146 litex_vexriscv::timer::LiteXAlarm<
147 'static,
148 'static,
149 socc::SoCRegisterFmt,
150 socc::ClockFrequency,
151 >,
152 >,
153 >,
154 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
155 scheduler: &'static MLFQSched<
156 'static,
157 VirtualMuxAlarm<
158 'static,
159 litex_vexriscv::timer::LiteXAlarm<
160 'static,
161 'static,
162 socc::SoCRegisterFmt,
163 socc::ClockFrequency,
164 >,
165 >,
166 >,
167 scheduler_timer: &'static VirtualSchedulerTimer<
168 VirtualMuxAlarm<
169 'static,
170 litex_vexriscv::timer::LiteXAlarm<
171 'static,
172 'static,
173 socc::SoCRegisterFmt,
174 socc::ClockFrequency,
175 >,
176 >,
177 >,
178}
179
180impl SyscallDriverLookup for LiteXArty {
182 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
183 where
184 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
185 {
186 match driver_num {
187 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
188 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
189 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
190 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
191 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
192 _ => f(None),
193 }
194 }
195}
196
197impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>>
198 for LiteXArty
199{
200 type SyscallDriverLookup = Self;
201 type SyscallFilter = ();
202 type ProcessFault = ();
203 type Scheduler = MLFQSched<
204 'static,
205 VirtualMuxAlarm<
206 'static,
207 litex_vexriscv::timer::LiteXAlarm<
208 'static,
209 'static,
210 socc::SoCRegisterFmt,
211 socc::ClockFrequency,
212 >,
213 >,
214 >;
215 type SchedulerTimer = VirtualSchedulerTimer<
216 VirtualMuxAlarm<
217 'static,
218 litex_vexriscv::timer::LiteXAlarm<
219 'static,
220 'static,
221 socc::SoCRegisterFmt,
222 socc::ClockFrequency,
223 >,
224 >,
225 >;
226 type WatchDog = ();
227 type ContextSwitchCallback = ();
228
229 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
230 self
231 }
232 fn syscall_filter(&self) -> &Self::SyscallFilter {
233 &()
234 }
235 fn process_fault(&self) -> &Self::ProcessFault {
236 &()
237 }
238 fn scheduler(&self) -> &Self::Scheduler {
239 self.scheduler
240 }
241 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
242 self.scheduler_timer
243 }
244 fn watchdog(&self) -> &Self::WatchDog {
245 &()
246 }
247 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
248 &()
249 }
250}
251
252#[inline(never)]
256unsafe fn start() -> (
257 &'static kernel::Kernel,
258 LiteXArty,
259 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>,
260) {
261 extern "C" {
263 static _sapps: u8;
265 static _eapps: u8;
267 static mut _sappmem: u8;
269 static _eappmem: u8;
271 static _stext: u8;
273 static _etext: u8;
275 static _sflash: u8;
277 static _eflash: u8;
279 static _ssram: u8;
281 static _esram: u8;
283 }
284
285 rv32i::configure_trap_handler();
289
290 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
294 rv32i::pmp::kernel_protection::FlashRegion(
295 rv32i::pmp::NAPOTRegionSpec::from_start_end(
296 core::ptr::addr_of!(_sflash),
297 core::ptr::addr_of!(_eflash),
298 )
299 .unwrap(),
300 ),
301 rv32i::pmp::kernel_protection::RAMRegion(
302 rv32i::pmp::NAPOTRegionSpec::from_start_end(
303 core::ptr::addr_of!(_ssram),
304 core::ptr::addr_of!(_esram),
305 )
306 .unwrap(),
307 ),
308 rv32i::pmp::kernel_protection::MMIORegion(
309 rv32i::pmp::NAPOTRegionSpec::from_start_size(
310 0xf0000000 as *const u8, 0x10000000, )
313 .unwrap(),
314 ),
315 rv32i::pmp::kernel_protection::KernelTextRegion(
316 rv32i::pmp::TORRegionSpec::from_start_end(
317 core::ptr::addr_of!(_stext),
318 core::ptr::addr_of!(_etext),
319 )
320 .unwrap(),
321 ),
322 )
323 .unwrap();
324
325 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
327 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
328
329 let processes = components::process_array::ProcessArrayComponent::new()
331 .finalize(components::process_array_component_static!(NUM_PROCS));
332 PROCESSES = Some(processes);
333
334 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
336
337 let led0 = static_init!(
342 litex_vexriscv::led_controller::LiteXLedController<socc::SoCRegisterFmt>,
343 litex_vexriscv::led_controller::LiteXLedController::new(
344 StaticRef::new(
345 socc::CSR_LEDS_BASE
346 as *const litex_vexriscv::led_controller::LiteXLedRegisters<
347 socc::SoCRegisterFmt,
348 >
349 ),
350 4, )
352 );
353 led0.initialize();
354
355 PANIC_REFERENCES.led_controller = Some(led0);
356
357 let timer0 = static_init!(
361 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
362 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
363 socc::CSR_TIMER0_BASE
364 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
365 ),)
366 );
367
368 let timer0_uptime = static_init!(
370 litex_vexriscv::timer::LiteXTimerUptime<
371 'static,
372 socc::SoCRegisterFmt,
373 socc::ClockFrequency,
374 >,
375 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
376 );
377
378 let litex_alarm = static_init!(
381 litex_vexriscv::timer::LiteXAlarm<
382 'static,
383 'static,
384 socc::SoCRegisterFmt,
385 socc::ClockFrequency,
386 >,
387 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
388 );
389 timer0.set_timer_client(litex_alarm);
390 litex_alarm.initialize();
391
392 let mux_alarm = static_init!(
395 MuxAlarm<
396 'static,
397 litex_vexriscv::timer::LiteXAlarm<
398 'static,
399 'static,
400 socc::SoCRegisterFmt,
401 socc::ClockFrequency,
402 >,
403 >,
404 MuxAlarm::new(litex_alarm)
405 );
406 litex_alarm.set_alarm_client(mux_alarm);
407
408 let virtual_alarm_user = static_init!(
410 VirtualMuxAlarm<
411 'static,
412 litex_vexriscv::timer::LiteXAlarm<
413 'static,
414 'static,
415 socc::SoCRegisterFmt,
416 socc::ClockFrequency,
417 >,
418 >,
419 VirtualMuxAlarm::new(mux_alarm)
420 );
421 virtual_alarm_user.setup();
422
423 let alarm = static_init!(
424 capsules_core::alarm::AlarmDriver<
425 'static,
426 VirtualMuxAlarm<
427 'static,
428 litex_vexriscv::timer::LiteXAlarm<
429 'static,
430 'static,
431 socc::SoCRegisterFmt,
432 socc::ClockFrequency,
433 >,
434 >,
435 >,
436 capsules_core::alarm::AlarmDriver::new(
437 virtual_alarm_user,
438 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
439 )
440 );
441 virtual_alarm_user.set_alarm_client(alarm);
442
443 let systick_virtual_alarm = static_init!(
445 VirtualMuxAlarm<
446 'static,
447 litex_vexriscv::timer::LiteXAlarm<
448 'static,
449 'static,
450 socc::SoCRegisterFmt,
451 socc::ClockFrequency,
452 >,
453 >,
454 VirtualMuxAlarm::new(mux_alarm)
455 );
456 systick_virtual_alarm.setup();
457
458 let scheduler_timer = static_init!(
459 VirtualSchedulerTimer<
460 VirtualMuxAlarm<
461 'static,
462 litex_vexriscv::timer::LiteXAlarm<
463 'static,
464 'static,
465 socc::SoCRegisterFmt,
466 socc::ClockFrequency,
467 >,
468 >,
469 >,
470 VirtualSchedulerTimer::new(systick_virtual_alarm)
471 );
472
473 let uart0 = static_init!(
477 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
478 litex_vexriscv::uart::LiteXUart::new(
479 StaticRef::new(
480 socc::CSR_UART_BASE
481 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
482 ),
483 None,
487 )
488 );
489 uart0.initialize();
490
491 PANIC_REFERENCES.uart = Some(uart0);
492
493 let uart_mux = components::console::UartMuxComponent::new(uart0, socc::UART_BAUDRATE)
495 .finalize(components::uart_mux_component_static!());
496
497 let ethmac0 = static_init!(
501 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
502 litex_vexriscv::liteeth::LiteEth::new(
503 StaticRef::new(
504 socc::CSR_ETHMAC_BASE
505 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
506 ),
507 socc::MEM_ETHMAC_BASE,
508 socc::MEM_ETHMAC_SIZE,
509 socc::ETHMAC_SLOT_SIZE,
510 socc::ETHMAC_RX_SLOTS,
511 socc::ETHMAC_TX_SLOTS,
512 )
513 );
514
515 ethmac0.initialize();
517
518 let led_driver =
522 components::led::LedsComponent::new().finalize(components::led_component_static!(
523 litex_vexriscv::led_controller::LiteXLed<'static, socc::SoCRegisterFmt>,
524 led0.get_led(0).unwrap(),
525 led0.get_led(1).unwrap(),
526 led0.get_led(2).unwrap(),
527 led0.get_led(3).unwrap(),
528 ));
529
530 let interrupt_service = static_init!(
533 LiteXArtyInterruptablePeripherals,
534 LiteXArtyInterruptablePeripherals {
535 uart0,
536 timer0,
537 ethmac0,
538 }
539 );
540 interrupt_service.init();
541
542 let chip = static_init!(
543 litex_vexriscv::chip::LiteXVexRiscv<
544 LiteXArtyInterruptablePeripherals,
545 >,
546 litex_vexriscv::chip::LiteXVexRiscv::new(
547 "LiteX on Arty A7",
548 interrupt_service,
549 pmp,
550 )
551 );
552
553 PANIC_REFERENCES.chip = Some(chip);
554
555 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
556 .finalize(components::process_printer_text_component_static!());
557
558 PANIC_REFERENCES.process_printer = Some(process_printer);
559
560 csr::CSR
562 .mie
563 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
564 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
565
566 chip.unmask_interrupts();
568
569 let pconsole = components::process_console::ProcessConsoleComponent::new(
571 board_kernel,
572 uart_mux,
573 mux_alarm,
574 process_printer,
575 None,
576 )
577 .finalize(components::process_console_component_static!(
578 litex_vexriscv::timer::LiteXAlarm<
579 'static,
580 'static,
581 socc::SoCRegisterFmt,
582 socc::ClockFrequency,
583 >
584 ));
585
586 let console = components::console::ConsoleComponent::new(
588 board_kernel,
589 capsules_core::console::DRIVER_NUM,
590 uart_mux,
591 )
592 .finalize(components::console_component_static!());
593
594 components::debug_writer::DebugWriterComponent::new(
596 uart_mux,
597 create_capability!(capabilities::SetDebugWriterCapability),
598 )
599 .finalize(components::debug_writer_component_static!());
600
601 let lldb = components::lldb::LowLevelDebugComponent::new(
602 board_kernel,
603 capsules_core::low_level_debug::DRIVER_NUM,
604 uart_mux,
605 )
606 .finalize(components::low_level_debug_component_static!());
607
608 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes).finalize(
609 components::mlfq_component_static!(
610 litex_vexriscv::timer::LiteXAlarm<
611 'static,
612 'static,
613 socc::SoCRegisterFmt,
614 socc::ClockFrequency,
615 >,
616 NUM_PROCS
617 ),
618 );
619
620 let litex_arty = LiteXArty {
621 console,
622 pconsole,
623 alarm,
624 lldb,
625 led_driver,
626 scheduler,
627 scheduler_timer,
628 ipc: kernel::ipc::IPC::new(
629 board_kernel,
630 kernel::ipc::DRIVER_NUM,
631 &memory_allocation_cap,
632 ),
633 };
634
635 debug!("LiteX+VexRiscv on ArtyA7: initialization complete, entering main loop.");
636 let _ = litex_arty.pconsole.start();
637
638 kernel::process::load_processes(
639 board_kernel,
640 chip,
641 core::slice::from_raw_parts(
642 core::ptr::addr_of!(_sapps),
643 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
644 ),
645 core::slice::from_raw_parts_mut(
646 core::ptr::addr_of_mut!(_sappmem),
647 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
648 ),
649 &FAULT_RESPONSE,
650 &process_mgmt_cap,
651 )
652 .unwrap_or_else(|err| {
653 debug!("Error loading processes!");
654 debug!("{:?}", err);
655 });
656
657 (board_kernel, litex_arty, chip)
658}
659
660#[no_mangle]
662pub unsafe fn main() {
663 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
664
665 let (board_kernel, board, chip) = start();
666 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
667}