1#![no_std]
8#![no_main]
9
10use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
11use kernel::capabilities;
12use kernel::component::Component;
13use kernel::hil::led::LedHigh;
14use kernel::hil::time::{Alarm, Timer};
15use kernel::platform::chip::InterruptService;
16use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
17use kernel::platform::{KernelResources, SyscallDriverLookup};
18use kernel::process::ProcessArray;
19use kernel::scheduler::mlfq::MLFQSched;
20use kernel::utilities::registers::interfaces::ReadWriteable;
21use kernel::utilities::StaticRef;
22use kernel::{create_capability, debug, static_init};
23use rv32i::csr;
24
25mod io;
26mod litex_generated_constants;
27
28use litex_generated_constants as socc;
35
36struct LiteXSimInterruptablePeripherals {
44 gpio0: &'static litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
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 LiteXSimInterruptablePeripherals {
59 pub fn init(&'static self) {
61 kernel::deferred_call::DeferredCallClient::register(self.uart0);
62 }
63}
64
65impl InterruptService for LiteXSimInterruptablePeripherals {
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 socc::GPIO_INTERRUPT => {
81 self.gpio0.service_interrupt();
82 true
83 }
84 _ => false,
85 }
86 }
87}
88
89const NUM_PROCS: usize = 4;
90
91type ChipHw = litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>;
92
93static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
95
96struct LiteXSimPanicReferences {
98 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
99 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
100 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
101}
102static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
103 chip: None,
104 uart: None,
105 process_printer: None,
106};
107
108const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
110 capsules_system::process_policies::PanicFaultPolicy {};
111
112kernel::stack_size! {0x2000}
113
114struct LiteXSim {
117 gpio_driver: &'static capsules_core::gpio::GPIO<
118 'static,
119 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
120 >,
121 button_driver: &'static capsules_core::button::Button<
122 'static,
123 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
124 >,
125 led_driver: &'static capsules_core::led::LedDriver<
126 'static,
127 LedHigh<
128 'static,
129 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
130 >,
131 8,
132 >,
133 console: &'static capsules_core::console::Console<'static>,
134 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
135 'static,
136 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
137 >,
138 alarm: &'static capsules_core::alarm::AlarmDriver<
139 'static,
140 VirtualMuxAlarm<
141 'static,
142 litex_vexriscv::timer::LiteXAlarm<
143 'static,
144 'static,
145 socc::SoCRegisterFmt,
146 socc::ClockFrequency,
147 >,
148 >,
149 >,
150 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
151 scheduler: &'static MLFQSched<
152 'static,
153 VirtualMuxAlarm<
154 'static,
155 litex_vexriscv::timer::LiteXAlarm<
156 'static,
157 'static,
158 socc::SoCRegisterFmt,
159 socc::ClockFrequency,
160 >,
161 >,
162 >,
163 scheduler_timer: &'static VirtualSchedulerTimer<
164 VirtualMuxAlarm<
165 'static,
166 litex_vexriscv::timer::LiteXAlarm<
167 'static,
168 'static,
169 socc::SoCRegisterFmt,
170 socc::ClockFrequency,
171 >,
172 >,
173 >,
174}
175
176impl SyscallDriverLookup for LiteXSim {
178 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
179 where
180 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
181 {
182 match driver_num {
183 capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
184 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
185 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
186 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
187 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
188 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
189 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
190 _ => f(None),
191 }
192 }
193}
194
195impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
196 for LiteXSim
197{
198 type SyscallDriverLookup = Self;
199 type SyscallFilter = ();
200 type ProcessFault = ();
201 type Scheduler = MLFQSched<
202 'static,
203 VirtualMuxAlarm<
204 'static,
205 litex_vexriscv::timer::LiteXAlarm<
206 'static,
207 'static,
208 socc::SoCRegisterFmt,
209 socc::ClockFrequency,
210 >,
211 >,
212 >;
213 type SchedulerTimer = VirtualSchedulerTimer<
214 VirtualMuxAlarm<
215 'static,
216 litex_vexriscv::timer::LiteXAlarm<
217 'static,
218 'static,
219 socc::SoCRegisterFmt,
220 socc::ClockFrequency,
221 >,
222 >,
223 >;
224 type WatchDog = ();
225 type ContextSwitchCallback = ();
226
227 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
228 self
229 }
230 fn syscall_filter(&self) -> &Self::SyscallFilter {
231 &()
232 }
233 fn process_fault(&self) -> &Self::ProcessFault {
234 &()
235 }
236 fn scheduler(&self) -> &Self::Scheduler {
237 self.scheduler
238 }
239 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
240 self.scheduler_timer
241 }
242 fn watchdog(&self) -> &Self::WatchDog {
243 &()
244 }
245 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
246 &()
247 }
248}
249
250#[inline(never)]
254unsafe fn start() -> (
255 &'static kernel::Kernel,
256 LiteXSim,
257 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
258) {
259 extern "C" {
261 static _sapps: u8;
263 static _eapps: u8;
265 static mut _sappmem: u8;
267 static _eappmem: u8;
269 static _stext: u8;
271 static _etext: u8;
273 static _sflash: u8;
275 static _eflash: u8;
277 static _ssram: u8;
279 static _esram: u8;
281 }
282
283 rv32i::configure_trap_handler();
287
288 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
292 rv32i::pmp::kernel_protection::FlashRegion(
293 rv32i::pmp::NAPOTRegionSpec::from_start_end(
294 core::ptr::addr_of!(_sflash),
295 core::ptr::addr_of!(_eflash),
296 )
297 .unwrap(),
298 ),
299 rv32i::pmp::kernel_protection::RAMRegion(
300 rv32i::pmp::NAPOTRegionSpec::from_start_end(
301 core::ptr::addr_of!(_ssram),
302 core::ptr::addr_of!(_esram),
303 )
304 .unwrap(),
305 ),
306 rv32i::pmp::kernel_protection::MMIORegion(
307 rv32i::pmp::NAPOTRegionSpec::from_start_size(
308 0xf0000000 as *const u8, 0x10000000, )
311 .unwrap(),
312 ),
313 rv32i::pmp::kernel_protection::KernelTextRegion(
314 rv32i::pmp::TORRegionSpec::from_start_end(
315 core::ptr::addr_of!(_stext),
316 core::ptr::addr_of!(_etext),
317 )
318 .unwrap(),
319 ),
320 )
321 .unwrap();
322
323 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
325 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
326
327 let processes = components::process_array::ProcessArrayComponent::new()
329 .finalize(components::process_array_component_static!(NUM_PROCS));
330 PROCESSES = Some(processes);
331
332 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
334
335 let timer0 = static_init!(
339 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
340 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
341 socc::CSR_TIMER0_BASE
342 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
343 ),)
344 );
345
346 let timer0_uptime = static_init!(
348 litex_vexriscv::timer::LiteXTimerUptime<
349 'static,
350 socc::SoCRegisterFmt,
351 socc::ClockFrequency,
352 >,
353 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
354 );
355
356 let litex_alarm = static_init!(
359 litex_vexriscv::timer::LiteXAlarm<
360 'static,
361 'static,
362 socc::SoCRegisterFmt,
363 socc::ClockFrequency,
364 >,
365 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
366 );
367 timer0.set_timer_client(litex_alarm);
368 litex_alarm.initialize();
369
370 let mux_alarm = static_init!(
373 MuxAlarm<
374 'static,
375 litex_vexriscv::timer::LiteXAlarm<
376 'static,
377 'static,
378 socc::SoCRegisterFmt,
379 socc::ClockFrequency,
380 >,
381 >,
382 MuxAlarm::new(litex_alarm)
383 );
384 litex_alarm.set_alarm_client(mux_alarm);
385
386 let virtual_alarm_user = static_init!(
388 VirtualMuxAlarm<
389 'static,
390 litex_vexriscv::timer::LiteXAlarm<
391 'static,
392 'static,
393 socc::SoCRegisterFmt,
394 socc::ClockFrequency,
395 >,
396 >,
397 VirtualMuxAlarm::new(mux_alarm)
398 );
399 virtual_alarm_user.setup();
400
401 let alarm = static_init!(
402 capsules_core::alarm::AlarmDriver<
403 'static,
404 VirtualMuxAlarm<
405 'static,
406 litex_vexriscv::timer::LiteXAlarm<
407 'static,
408 'static,
409 socc::SoCRegisterFmt,
410 socc::ClockFrequency,
411 >,
412 >,
413 >,
414 capsules_core::alarm::AlarmDriver::new(
415 virtual_alarm_user,
416 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
417 )
418 );
419 virtual_alarm_user.set_alarm_client(alarm);
420
421 let systick_virtual_alarm = static_init!(
423 VirtualMuxAlarm<
424 'static,
425 litex_vexriscv::timer::LiteXAlarm<
426 'static,
427 'static,
428 socc::SoCRegisterFmt,
429 socc::ClockFrequency,
430 >,
431 >,
432 VirtualMuxAlarm::new(mux_alarm)
433 );
434 systick_virtual_alarm.setup();
435
436 let scheduler_timer = static_init!(
437 VirtualSchedulerTimer<
438 VirtualMuxAlarm<
439 'static,
440 litex_vexriscv::timer::LiteXAlarm<
441 'static,
442 'static,
443 socc::SoCRegisterFmt,
444 socc::ClockFrequency,
445 >,
446 >,
447 >,
448 VirtualSchedulerTimer::new(systick_virtual_alarm)
449 );
450
451 let uart0 = static_init!(
455 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
456 litex_vexriscv::uart::LiteXUart::new(
457 StaticRef::new(
458 socc::CSR_UART_BASE
459 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
460 ),
461 None, )
463 );
464 uart0.initialize();
465
466 PANIC_REFERENCES.uart = Some(uart0);
467
468 let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
473 .finalize(components::uart_mux_component_static!());
474
475 let ethmac0 = static_init!(
479 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
480 litex_vexriscv::liteeth::LiteEth::new(
481 StaticRef::new(
482 socc::CSR_ETHMAC_BASE
483 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
484 ),
485 socc::MEM_ETHMAC_BASE,
486 socc::MEM_ETHMAC_SIZE,
487 socc::ETHMAC_SLOT_SIZE,
488 socc::ETHMAC_RX_SLOTS,
489 socc::ETHMAC_TX_SLOTS,
490 )
491 );
492
493 ethmac0.initialize();
495
496 type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
498
499 let gpio0 = static_init!(
501 litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
502 litex_vexriscv::gpio::LiteXGPIOController::new(
503 StaticRef::new(
504 socc::CSR_GPIO_BASE
505 as *const litex_vexriscv::gpio::LiteXGPIORegisters<socc::SoCRegisterFmt>
506 ),
507 32, ),
509 );
510 gpio0.initialize();
511
512 let gpio_driver = components::gpio::GpioComponent::new(
515 board_kernel,
516 capsules_core::gpio::DRIVER_NUM,
517 components::gpio_component_helper_owned!(
518 GPIOPin,
519 16 => gpio0.get_gpio_pin(16).unwrap(),
520 17 => gpio0.get_gpio_pin(17).unwrap(),
521 18 => gpio0.get_gpio_pin(18).unwrap(),
522 19 => gpio0.get_gpio_pin(19).unwrap(),
523 20 => gpio0.get_gpio_pin(20).unwrap(),
524 21 => gpio0.get_gpio_pin(21).unwrap(),
525 22 => gpio0.get_gpio_pin(22).unwrap(),
526 23 => gpio0.get_gpio_pin(23).unwrap(),
527 24 => gpio0.get_gpio_pin(24).unwrap(),
528 25 => gpio0.get_gpio_pin(25).unwrap(),
529 26 => gpio0.get_gpio_pin(26).unwrap(),
530 27 => gpio0.get_gpio_pin(27).unwrap(),
531 28 => gpio0.get_gpio_pin(28).unwrap(),
532 29 => gpio0.get_gpio_pin(29).unwrap(),
533 30 => gpio0.get_gpio_pin(30).unwrap(),
534 31 => gpio0.get_gpio_pin(31).unwrap(),
535 ),
536 )
537 .finalize(components::gpio_component_static!(GPIOPin));
538
539 let led_gpios = static_init!(
542 [GPIOPin; 8],
543 [
544 gpio0.get_gpio_pin(0).unwrap(),
545 gpio0.get_gpio_pin(1).unwrap(),
546 gpio0.get_gpio_pin(2).unwrap(),
547 gpio0.get_gpio_pin(3).unwrap(),
548 gpio0.get_gpio_pin(4).unwrap(),
549 gpio0.get_gpio_pin(5).unwrap(),
550 gpio0.get_gpio_pin(6).unwrap(),
551 gpio0.get_gpio_pin(7).unwrap(),
552 ]
553 );
554
555 let led_driver =
556 components::led::LedsComponent::new().finalize(components::led_component_static!(
557 kernel::hil::led::LedHigh<GPIOPin>,
558 LedHigh::new(&led_gpios[0]),
559 LedHigh::new(&led_gpios[1]),
560 LedHigh::new(&led_gpios[2]),
561 LedHigh::new(&led_gpios[3]),
562 LedHigh::new(&led_gpios[4]),
563 LedHigh::new(&led_gpios[5]),
564 LedHigh::new(&led_gpios[6]),
565 LedHigh::new(&led_gpios[7]),
566 ));
567
568 let button_driver = components::button::ButtonComponent::new(
571 board_kernel,
572 capsules_core::button::DRIVER_NUM,
573 components::button_component_helper_owned!(
574 GPIOPin,
575 (
576 gpio0.get_gpio_pin(8).unwrap(),
577 kernel::hil::gpio::ActivationMode::ActiveHigh,
578 kernel::hil::gpio::FloatingState::PullNone
579 ),
580 (
581 gpio0.get_gpio_pin(9).unwrap(),
582 kernel::hil::gpio::ActivationMode::ActiveHigh,
583 kernel::hil::gpio::FloatingState::PullNone
584 ),
585 (
586 gpio0.get_gpio_pin(10).unwrap(),
587 kernel::hil::gpio::ActivationMode::ActiveHigh,
588 kernel::hil::gpio::FloatingState::PullNone
589 ),
590 (
591 gpio0.get_gpio_pin(11).unwrap(),
592 kernel::hil::gpio::ActivationMode::ActiveHigh,
593 kernel::hil::gpio::FloatingState::PullNone
594 ),
595 (
596 gpio0.get_gpio_pin(12).unwrap(),
597 kernel::hil::gpio::ActivationMode::ActiveHigh,
598 kernel::hil::gpio::FloatingState::PullNone
599 ),
600 (
601 gpio0.get_gpio_pin(13).unwrap(),
602 kernel::hil::gpio::ActivationMode::ActiveHigh,
603 kernel::hil::gpio::FloatingState::PullNone
604 ),
605 (
606 gpio0.get_gpio_pin(14).unwrap(),
607 kernel::hil::gpio::ActivationMode::ActiveHigh,
608 kernel::hil::gpio::FloatingState::PullNone
609 ),
610 (
611 gpio0.get_gpio_pin(15).unwrap(),
612 kernel::hil::gpio::ActivationMode::ActiveHigh,
613 kernel::hil::gpio::FloatingState::PullNone
614 ),
615 ),
616 )
617 .finalize(components::button_component_static!(GPIOPin));
618
619 let interrupt_service = static_init!(
622 LiteXSimInterruptablePeripherals,
623 LiteXSimInterruptablePeripherals {
624 gpio0,
625 uart0,
626 timer0,
627 ethmac0,
628 }
629 );
630 interrupt_service.init();
631
632 let chip = static_init!(
633 litex_vexriscv::chip::LiteXVexRiscv<
634 LiteXSimInterruptablePeripherals,
635 >,
636 litex_vexriscv::chip::LiteXVexRiscv::new(
637 "Verilated LiteX on VexRiscv",
638 interrupt_service,
639 pmp,
640 )
641 );
642
643 PANIC_REFERENCES.chip = Some(chip);
644
645 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
646 .finalize(components::process_printer_text_component_static!());
647
648 PANIC_REFERENCES.process_printer = Some(process_printer);
649
650 csr::CSR
652 .mie
653 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
654 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
655
656 chip.unmask_interrupts();
658
659 let console = components::console::ConsoleComponent::new(
661 board_kernel,
662 capsules_core::console::DRIVER_NUM,
663 uart_mux,
664 )
665 .finalize(components::console_component_static!());
666 components::debug_writer::DebugWriterComponent::new_unsafe(
668 uart_mux,
669 create_capability!(capabilities::SetDebugWriterCapability),
670 || unsafe {
671 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
672 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
673 >();
674 },
675 )
676 .finalize(components::debug_writer_component_static!());
677
678 let lldb = components::lldb::LowLevelDebugComponent::new(
679 board_kernel,
680 capsules_core::low_level_debug::DRIVER_NUM,
681 uart_mux,
682 )
683 .finalize(components::low_level_debug_component_static!());
684
685 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes).finalize(
686 components::mlfq_component_static!(
687 litex_vexriscv::timer::LiteXAlarm<
688 'static,
689 'static,
690 socc::SoCRegisterFmt,
691 socc::ClockFrequency,
692 >,
693 NUM_PROCS
694 ),
695 );
696
697 let litex_sim = LiteXSim {
698 gpio_driver,
699 button_driver,
700 led_driver,
701 console,
702 alarm,
703 lldb,
704 ipc: kernel::ipc::IPC::new(
705 board_kernel,
706 kernel::ipc::DRIVER_NUM,
707 &memory_allocation_cap,
708 ),
709 scheduler,
710 scheduler_timer,
711 };
712
713 debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
714
715 kernel::process::load_processes(
716 board_kernel,
717 chip,
718 core::slice::from_raw_parts(
719 core::ptr::addr_of!(_sapps),
720 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
721 ),
722 core::slice::from_raw_parts_mut(
723 core::ptr::addr_of_mut!(_sappmem),
724 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
725 ),
726 &FAULT_RESPONSE,
727 &process_mgmt_cap,
728 )
729 .unwrap_or_else(|err| {
730 debug!("Error loading processes!");
731 debug!("{:?}", err);
732 });
733
734 (board_kernel, litex_sim, chip)
735}
736
737#[no_mangle]
739pub unsafe fn main() {
740 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
741
742 let (board_kernel, board, chip) = start();
743 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
744}