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