1#![no_std]
8#![cfg_attr(not(doc), no_main)]
11
12use core::ptr::{addr_of, addr_of_mut};
13
14use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
15use kernel::capabilities;
16use kernel::component::Component;
17use kernel::hil::led::LedHigh;
18use kernel::hil::time::{Alarm, Timer};
19use kernel::platform::chip::InterruptService;
20use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
21use kernel::platform::{KernelResources, SyscallDriverLookup};
22use kernel::scheduler::mlfq::MLFQSched;
23use kernel::utilities::registers::interfaces::ReadWriteable;
24use kernel::utilities::StaticRef;
25use kernel::{create_capability, debug, static_init};
26use rv32i::csr;
27
28mod io;
29mod litex_generated_constants;
30
31use litex_generated_constants as socc;
38
39struct LiteXSimInterruptablePeripherals {
47 gpio0: &'static litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
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 LiteXSimInterruptablePeripherals {
62 pub fn init(&'static self) {
64 kernel::deferred_call::DeferredCallClient::register(self.uart0);
65 }
66}
67
68impl InterruptService for LiteXSimInterruptablePeripherals {
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 socc::GPIO_INTERRUPT => {
84 self.gpio0.service_interrupt();
85 true
86 }
87 _ => false,
88 }
89 }
90}
91
92const NUM_PROCS: usize = 4;
93
94static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
97 [None; NUM_PROCS];
98
99struct LiteXSimPanicReferences {
101 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
102 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
103 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
104}
105static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
106 chip: None,
107 uart: 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 LiteXSim {
123 gpio_driver: &'static capsules_core::gpio::GPIO<
124 'static,
125 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
126 >,
127 button_driver: &'static capsules_core::button::Button<
128 'static,
129 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
130 >,
131 led_driver: &'static capsules_core::led::LedDriver<
132 'static,
133 LedHigh<
134 'static,
135 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
136 >,
137 8,
138 >,
139 console: &'static capsules_core::console::Console<'static>,
140 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
141 'static,
142 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
143 >,
144 alarm: &'static capsules_core::alarm::AlarmDriver<
145 'static,
146 VirtualMuxAlarm<
147 'static,
148 litex_vexriscv::timer::LiteXAlarm<
149 'static,
150 'static,
151 socc::SoCRegisterFmt,
152 socc::ClockFrequency,
153 >,
154 >,
155 >,
156 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
157 scheduler: &'static MLFQSched<
158 'static,
159 VirtualMuxAlarm<
160 'static,
161 litex_vexriscv::timer::LiteXAlarm<
162 'static,
163 'static,
164 socc::SoCRegisterFmt,
165 socc::ClockFrequency,
166 >,
167 >,
168 >,
169 scheduler_timer: &'static VirtualSchedulerTimer<
170 VirtualMuxAlarm<
171 'static,
172 litex_vexriscv::timer::LiteXAlarm<
173 'static,
174 'static,
175 socc::SoCRegisterFmt,
176 socc::ClockFrequency,
177 >,
178 >,
179 >,
180}
181
182impl SyscallDriverLookup for LiteXSim {
184 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
185 where
186 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
187 {
188 match driver_num {
189 capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
190 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
191 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
192 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
193 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
194 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
195 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
196 _ => f(None),
197 }
198 }
199}
200
201impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
202 for LiteXSim
203{
204 type SyscallDriverLookup = Self;
205 type SyscallFilter = ();
206 type ProcessFault = ();
207 type Scheduler = MLFQSched<
208 'static,
209 VirtualMuxAlarm<
210 'static,
211 litex_vexriscv::timer::LiteXAlarm<
212 'static,
213 'static,
214 socc::SoCRegisterFmt,
215 socc::ClockFrequency,
216 >,
217 >,
218 >;
219 type SchedulerTimer = VirtualSchedulerTimer<
220 VirtualMuxAlarm<
221 'static,
222 litex_vexriscv::timer::LiteXAlarm<
223 'static,
224 'static,
225 socc::SoCRegisterFmt,
226 socc::ClockFrequency,
227 >,
228 >,
229 >;
230 type WatchDog = ();
231 type ContextSwitchCallback = ();
232
233 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
234 self
235 }
236 fn syscall_filter(&self) -> &Self::SyscallFilter {
237 &()
238 }
239 fn process_fault(&self) -> &Self::ProcessFault {
240 &()
241 }
242 fn scheduler(&self) -> &Self::Scheduler {
243 self.scheduler
244 }
245 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
246 self.scheduler_timer
247 }
248 fn watchdog(&self) -> &Self::WatchDog {
249 &()
250 }
251 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
252 &()
253 }
254}
255
256#[inline(never)]
260unsafe fn start() -> (
261 &'static kernel::Kernel,
262 LiteXSim,
263 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
264) {
265 extern "C" {
267 static _sapps: u8;
269 static _eapps: u8;
271 static mut _sappmem: u8;
273 static _eappmem: u8;
275 static _stext: u8;
277 static _etext: u8;
279 static _sflash: u8;
281 static _eflash: u8;
283 static _ssram: u8;
285 static _esram: u8;
287 }
288
289 rv32i::configure_trap_handler();
293
294 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
298 rv32i::pmp::kernel_protection::FlashRegion(
299 rv32i::pmp::NAPOTRegionSpec::from_start_end(
300 core::ptr::addr_of!(_sflash),
301 core::ptr::addr_of!(_eflash),
302 )
303 .unwrap(),
304 ),
305 rv32i::pmp::kernel_protection::RAMRegion(
306 rv32i::pmp::NAPOTRegionSpec::from_start_end(
307 core::ptr::addr_of!(_ssram),
308 core::ptr::addr_of!(_esram),
309 )
310 .unwrap(),
311 ),
312 rv32i::pmp::kernel_protection::MMIORegion(
313 rv32i::pmp::NAPOTRegionSpec::from_start_size(
314 0xf0000000 as *const u8, 0x10000000, )
317 .unwrap(),
318 ),
319 rv32i::pmp::kernel_protection::KernelTextRegion(
320 rv32i::pmp::TORRegionSpec::from_start_end(
321 core::ptr::addr_of!(_stext),
322 core::ptr::addr_of!(_etext),
323 )
324 .unwrap(),
325 ),
326 )
327 .unwrap();
328
329 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
331 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
332
333 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
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(uart_mux)
668 .finalize(components::debug_writer_component_static!());
669
670 let lldb = components::lldb::LowLevelDebugComponent::new(
671 board_kernel,
672 capsules_core::low_level_debug::DRIVER_NUM,
673 uart_mux,
674 )
675 .finalize(components::low_level_debug_component_static!());
676
677 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, &*addr_of!(PROCESSES))
678 .finalize(components::mlfq_component_static!(
679 litex_vexriscv::timer::LiteXAlarm<
680 'static,
681 'static,
682 socc::SoCRegisterFmt,
683 socc::ClockFrequency,
684 >,
685 NUM_PROCS
686 ));
687
688 let litex_sim = LiteXSim {
689 gpio_driver,
690 button_driver,
691 led_driver,
692 console,
693 alarm,
694 lldb,
695 ipc: kernel::ipc::IPC::new(
696 board_kernel,
697 kernel::ipc::DRIVER_NUM,
698 &memory_allocation_cap,
699 ),
700 scheduler,
701 scheduler_timer,
702 };
703
704 debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
705
706 kernel::process::load_processes(
707 board_kernel,
708 chip,
709 core::slice::from_raw_parts(
710 core::ptr::addr_of!(_sapps),
711 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
712 ),
713 core::slice::from_raw_parts_mut(
714 core::ptr::addr_of_mut!(_sappmem),
715 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
716 ),
717 &mut *addr_of_mut!(PROCESSES),
718 &FAULT_RESPONSE,
719 &process_mgmt_cap,
720 )
721 .unwrap_or_else(|err| {
722 debug!("Error loading processes!");
723 debug!("{:?}", err);
724 });
725
726 (board_kernel, litex_sim, chip)
727}
728
729#[no_mangle]
731pub unsafe fn main() {
732 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
733
734 let (board_kernel, board, chip) = start();
735 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
736}