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<'static, socc::SoCRegisterFmt>,
55}
56
57impl LiteXArtyInterruptablePeripherals {
58 pub fn init(&'static self) {
60 kernel::deferred_call::DeferredCallClient::register(self.uart0);
61 }
62}
63
64impl InterruptService for LiteXArtyInterruptablePeripherals {
65 unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
66 match interrupt as usize {
67 socc::UART_INTERRUPT => {
68 self.uart0.service_interrupt();
69 true
70 }
71 socc::TIMER0_INTERRUPT => {
72 self.timer0.service_interrupt();
73 true
74 }
75 socc::ETHMAC_INTERRUPT => {
76 self.ethmac0.service_interrupt();
77 true
78 }
79 _ => false,
80 }
81 }
82}
83
84const NUM_PROCS: usize = 4;
85
86static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
89 [None; NUM_PROCS];
90
91struct LiteXArtyPanicReferences {
94 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>>,
95 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
96 led_controller:
97 Option<&'static litex_vexriscv::led_controller::LiteXLedController<socc::SoCRegisterFmt>>,
98 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
99}
100static mut PANIC_REFERENCES: LiteXArtyPanicReferences = LiteXArtyPanicReferences {
101 chip: None,
102 uart: None,
103 led_controller: None,
104 process_printer: None,
105};
106
107const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
109 capsules_system::process_policies::PanicFaultPolicy {};
110
111#[no_mangle]
113#[link_section = ".stack_buffer"]
114pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
115
116struct LiteXArty {
119 led_driver: &'static capsules_core::led::LedDriver<
120 'static,
121 litex_vexriscv::led_controller::LiteXLed<'static, socc::SoCRegisterFmt>,
122 4,
123 >,
124 console: &'static capsules_core::console::Console<'static>,
125 pconsole: &'static capsules_core::process_console::ProcessConsole<
126 'static,
127 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
128 VirtualMuxAlarm<
129 'static,
130 litex_vexriscv::timer::LiteXAlarm<
131 'static,
132 'static,
133 socc::SoCRegisterFmt,
134 socc::ClockFrequency,
135 >,
136 >,
137 components::process_console::Capability,
138 >,
139 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
140 'static,
141 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
142 >,
143 alarm: &'static capsules_core::alarm::AlarmDriver<
144 'static,
145 VirtualMuxAlarm<
146 'static,
147 litex_vexriscv::timer::LiteXAlarm<
148 'static,
149 'static,
150 socc::SoCRegisterFmt,
151 socc::ClockFrequency,
152 >,
153 >,
154 >,
155 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
156 scheduler: &'static MLFQSched<
157 'static,
158 VirtualMuxAlarm<
159 'static,
160 litex_vexriscv::timer::LiteXAlarm<
161 'static,
162 'static,
163 socc::SoCRegisterFmt,
164 socc::ClockFrequency,
165 >,
166 >,
167 >,
168 scheduler_timer: &'static VirtualSchedulerTimer<
169 VirtualMuxAlarm<
170 'static,
171 litex_vexriscv::timer::LiteXAlarm<
172 'static,
173 'static,
174 socc::SoCRegisterFmt,
175 socc::ClockFrequency,
176 >,
177 >,
178 >,
179}
180
181impl SyscallDriverLookup for LiteXArty {
183 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
184 where
185 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
186 {
187 match driver_num {
188 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
189 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
190 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
191 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
192 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
193 _ => f(None),
194 }
195 }
196}
197
198impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>>
199 for LiteXArty
200{
201 type SyscallDriverLookup = Self;
202 type SyscallFilter = ();
203 type ProcessFault = ();
204 type Scheduler = MLFQSched<
205 'static,
206 VirtualMuxAlarm<
207 'static,
208 litex_vexriscv::timer::LiteXAlarm<
209 'static,
210 'static,
211 socc::SoCRegisterFmt,
212 socc::ClockFrequency,
213 >,
214 >,
215 >;
216 type SchedulerTimer = VirtualSchedulerTimer<
217 VirtualMuxAlarm<
218 'static,
219 litex_vexriscv::timer::LiteXAlarm<
220 'static,
221 'static,
222 socc::SoCRegisterFmt,
223 socc::ClockFrequency,
224 >,
225 >,
226 >;
227 type WatchDog = ();
228 type ContextSwitchCallback = ();
229
230 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
231 self
232 }
233 fn syscall_filter(&self) -> &Self::SyscallFilter {
234 &()
235 }
236 fn process_fault(&self) -> &Self::ProcessFault {
237 &()
238 }
239 fn scheduler(&self) -> &Self::Scheduler {
240 self.scheduler
241 }
242 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
243 self.scheduler_timer
244 }
245 fn watchdog(&self) -> &Self::WatchDog {
246 &()
247 }
248 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
249 &()
250 }
251}
252
253#[inline(never)]
257unsafe fn start() -> (
258 &'static kernel::Kernel,
259 LiteXArty,
260 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>,
261) {
262 extern "C" {
264 static _sapps: u8;
266 static _eapps: u8;
268 static mut _sappmem: u8;
270 static _eappmem: u8;
272 static _stext: u8;
274 static _etext: u8;
276 static _sflash: u8;
278 static _eflash: u8;
280 static _ssram: u8;
282 static _esram: u8;
284 }
285
286 rv32i::configure_trap_handler();
290
291 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
295 rv32i::pmp::kernel_protection::FlashRegion(
296 rv32i::pmp::NAPOTRegionSpec::new(
297 core::ptr::addr_of!(_sflash),
298 core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize,
299 )
300 .unwrap(),
301 ),
302 rv32i::pmp::kernel_protection::RAMRegion(
303 rv32i::pmp::NAPOTRegionSpec::new(
304 core::ptr::addr_of!(_ssram),
305 core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize,
306 )
307 .unwrap(),
308 ),
309 rv32i::pmp::kernel_protection::MMIORegion(
310 rv32i::pmp::NAPOTRegionSpec::new(
311 0xf0000000 as *const u8, 0x10000000, )
314 .unwrap(),
315 ),
316 rv32i::pmp::kernel_protection::KernelTextRegion(
317 rv32i::pmp::TORRegionSpec::new(
318 core::ptr::addr_of!(_stext),
319 core::ptr::addr_of!(_etext),
320 )
321 .unwrap(),
322 ),
323 )
324 .unwrap();
325
326 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
328 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
329
330 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
331
332 let led0 = static_init!(
337 litex_vexriscv::led_controller::LiteXLedController<socc::SoCRegisterFmt>,
338 litex_vexriscv::led_controller::LiteXLedController::new(
339 StaticRef::new(
340 socc::CSR_LEDS_BASE
341 as *const litex_vexriscv::led_controller::LiteXLedRegisters<
342 socc::SoCRegisterFmt,
343 >
344 ),
345 4, )
347 );
348 led0.initialize();
349
350 PANIC_REFERENCES.led_controller = Some(led0);
351
352 let timer0 = static_init!(
356 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
357 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
358 socc::CSR_TIMER0_BASE
359 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
360 ),)
361 );
362
363 let timer0_uptime = static_init!(
365 litex_vexriscv::timer::LiteXTimerUptime<
366 'static,
367 socc::SoCRegisterFmt,
368 socc::ClockFrequency,
369 >,
370 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
371 );
372
373 let litex_alarm = static_init!(
376 litex_vexriscv::timer::LiteXAlarm<
377 'static,
378 'static,
379 socc::SoCRegisterFmt,
380 socc::ClockFrequency,
381 >,
382 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
383 );
384 timer0.set_timer_client(litex_alarm);
385 litex_alarm.initialize();
386
387 let mux_alarm = static_init!(
390 MuxAlarm<
391 'static,
392 litex_vexriscv::timer::LiteXAlarm<
393 'static,
394 'static,
395 socc::SoCRegisterFmt,
396 socc::ClockFrequency,
397 >,
398 >,
399 MuxAlarm::new(litex_alarm)
400 );
401 litex_alarm.set_alarm_client(mux_alarm);
402
403 let virtual_alarm_user = static_init!(
405 VirtualMuxAlarm<
406 'static,
407 litex_vexriscv::timer::LiteXAlarm<
408 'static,
409 'static,
410 socc::SoCRegisterFmt,
411 socc::ClockFrequency,
412 >,
413 >,
414 VirtualMuxAlarm::new(mux_alarm)
415 );
416 virtual_alarm_user.setup();
417
418 let alarm = static_init!(
419 capsules_core::alarm::AlarmDriver<
420 'static,
421 VirtualMuxAlarm<
422 'static,
423 litex_vexriscv::timer::LiteXAlarm<
424 'static,
425 'static,
426 socc::SoCRegisterFmt,
427 socc::ClockFrequency,
428 >,
429 >,
430 >,
431 capsules_core::alarm::AlarmDriver::new(
432 virtual_alarm_user,
433 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
434 )
435 );
436 virtual_alarm_user.set_alarm_client(alarm);
437
438 let systick_virtual_alarm = static_init!(
440 VirtualMuxAlarm<
441 'static,
442 litex_vexriscv::timer::LiteXAlarm<
443 'static,
444 'static,
445 socc::SoCRegisterFmt,
446 socc::ClockFrequency,
447 >,
448 >,
449 VirtualMuxAlarm::new(mux_alarm)
450 );
451 systick_virtual_alarm.setup();
452
453 let scheduler_timer = static_init!(
454 VirtualSchedulerTimer<
455 VirtualMuxAlarm<
456 'static,
457 litex_vexriscv::timer::LiteXAlarm<
458 'static,
459 'static,
460 socc::SoCRegisterFmt,
461 socc::ClockFrequency,
462 >,
463 >,
464 >,
465 VirtualSchedulerTimer::new(systick_virtual_alarm)
466 );
467
468 let uart0 = static_init!(
472 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
473 litex_vexriscv::uart::LiteXUart::new(
474 StaticRef::new(
475 socc::CSR_UART_BASE
476 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
477 ),
478 None,
482 )
483 );
484 uart0.initialize();
485
486 PANIC_REFERENCES.uart = Some(uart0);
487
488 let uart_mux = components::console::UartMuxComponent::new(uart0, socc::UART_BAUDRATE)
490 .finalize(components::uart_mux_component_static!());
491
492 let ethmac0_rxbuf0 = static_init!([u8; 1522], [0; 1522]);
496
497 let ethmac0 = static_init!(
499 litex_vexriscv::liteeth::LiteEth<socc::SoCRegisterFmt>,
500 litex_vexriscv::liteeth::LiteEth::new(
501 StaticRef::new(
502 socc::CSR_ETHMAC_BASE
503 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
504 ),
505 socc::MEM_ETHMAC_BASE,
506 socc::MEM_ETHMAC_SIZE,
507 socc::ETHMAC_SLOT_SIZE,
508 socc::ETHMAC_RX_SLOTS,
509 socc::ETHMAC_TX_SLOTS,
510 ethmac0_rxbuf0,
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}