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