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<'static, socc::SoCRegisterFmt>,
55}
56
57impl LiteXSimInterruptablePeripherals {
58 pub fn init(&'static self) {
60 kernel::deferred_call::DeferredCallClient::register(self.uart0);
61 }
62}
63
64impl InterruptService for LiteXSimInterruptablePeripherals {
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 socc::GPIO_INTERRUPT => {
80 self.gpio0.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 LiteXSimPanicReferences {
97 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
98 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
99 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
100}
101static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
102 chip: None,
103 uart: 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 LiteXSim {
119 gpio_driver: &'static capsules_core::gpio::GPIO<
120 'static,
121 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
122 >,
123 button_driver: &'static capsules_core::button::Button<
124 'static,
125 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
126 >,
127 led_driver: &'static capsules_core::led::LedDriver<
128 'static,
129 LedHigh<
130 'static,
131 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
132 >,
133 8,
134 >,
135 console: &'static capsules_core::console::Console<'static>,
136 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
137 'static,
138 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
139 >,
140 alarm: &'static capsules_core::alarm::AlarmDriver<
141 'static,
142 VirtualMuxAlarm<
143 'static,
144 litex_vexriscv::timer::LiteXAlarm<
145 'static,
146 'static,
147 socc::SoCRegisterFmt,
148 socc::ClockFrequency,
149 >,
150 >,
151 >,
152 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
153 scheduler: &'static MLFQSched<
154 'static,
155 VirtualMuxAlarm<
156 'static,
157 litex_vexriscv::timer::LiteXAlarm<
158 'static,
159 'static,
160 socc::SoCRegisterFmt,
161 socc::ClockFrequency,
162 >,
163 >,
164 >,
165 scheduler_timer: &'static VirtualSchedulerTimer<
166 VirtualMuxAlarm<
167 'static,
168 litex_vexriscv::timer::LiteXAlarm<
169 'static,
170 'static,
171 socc::SoCRegisterFmt,
172 socc::ClockFrequency,
173 >,
174 >,
175 >,
176}
177
178impl SyscallDriverLookup for LiteXSim {
180 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
181 where
182 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
183 {
184 match driver_num {
185 capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
186 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
187 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
188 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
189 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
190 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
191 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
192 _ => f(None),
193 }
194 }
195}
196
197impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
198 for LiteXSim
199{
200 type SyscallDriverLookup = Self;
201 type SyscallFilter = ();
202 type ProcessFault = ();
203 type Scheduler = MLFQSched<
204 'static,
205 VirtualMuxAlarm<
206 'static,
207 litex_vexriscv::timer::LiteXAlarm<
208 'static,
209 'static,
210 socc::SoCRegisterFmt,
211 socc::ClockFrequency,
212 >,
213 >,
214 >;
215 type SchedulerTimer = VirtualSchedulerTimer<
216 VirtualMuxAlarm<
217 'static,
218 litex_vexriscv::timer::LiteXAlarm<
219 'static,
220 'static,
221 socc::SoCRegisterFmt,
222 socc::ClockFrequency,
223 >,
224 >,
225 >;
226 type WatchDog = ();
227 type ContextSwitchCallback = ();
228
229 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
230 self
231 }
232 fn syscall_filter(&self) -> &Self::SyscallFilter {
233 &()
234 }
235 fn process_fault(&self) -> &Self::ProcessFault {
236 &()
237 }
238 fn scheduler(&self) -> &Self::Scheduler {
239 self.scheduler
240 }
241 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
242 self.scheduler_timer
243 }
244 fn watchdog(&self) -> &Self::WatchDog {
245 &()
246 }
247 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
248 &()
249 }
250}
251
252#[inline(never)]
256unsafe fn start() -> (
257 &'static kernel::Kernel,
258 LiteXSim,
259 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
260) {
261 extern "C" {
263 static _sapps: u8;
265 static _eapps: u8;
267 static mut _sappmem: u8;
269 static _eappmem: u8;
271 static _stext: u8;
273 static _etext: u8;
275 static _sflash: u8;
277 static _eflash: u8;
279 static _ssram: u8;
281 static _esram: u8;
283 }
284
285 rv32i::configure_trap_handler();
289
290 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
294 rv32i::pmp::kernel_protection::FlashRegion(
295 rv32i::pmp::NAPOTRegionSpec::new(
296 core::ptr::addr_of!(_sflash),
297 core::ptr::addr_of!(_eflash) as usize - core::ptr::addr_of!(_sflash) as usize,
298 )
299 .unwrap(),
300 ),
301 rv32i::pmp::kernel_protection::RAMRegion(
302 rv32i::pmp::NAPOTRegionSpec::new(
303 core::ptr::addr_of!(_ssram),
304 core::ptr::addr_of!(_esram) as usize - core::ptr::addr_of!(_ssram) as usize,
305 )
306 .unwrap(),
307 ),
308 rv32i::pmp::kernel_protection::MMIORegion(
309 rv32i::pmp::NAPOTRegionSpec::new(
310 0xf0000000 as *const u8, 0x10000000, )
313 .unwrap(),
314 ),
315 rv32i::pmp::kernel_protection::KernelTextRegion(
316 rv32i::pmp::TORRegionSpec::new(
317 core::ptr::addr_of!(_stext),
318 core::ptr::addr_of!(_etext),
319 )
320 .unwrap(),
321 ),
322 )
323 .unwrap();
324
325 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
327 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
328
329 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
330
331 let timer0 = static_init!(
335 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
336 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
337 socc::CSR_TIMER0_BASE
338 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
339 ),)
340 );
341
342 let timer0_uptime = static_init!(
344 litex_vexriscv::timer::LiteXTimerUptime<
345 'static,
346 socc::SoCRegisterFmt,
347 socc::ClockFrequency,
348 >,
349 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
350 );
351
352 let litex_alarm = static_init!(
355 litex_vexriscv::timer::LiteXAlarm<
356 'static,
357 'static,
358 socc::SoCRegisterFmt,
359 socc::ClockFrequency,
360 >,
361 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
362 );
363 timer0.set_timer_client(litex_alarm);
364 litex_alarm.initialize();
365
366 let mux_alarm = static_init!(
369 MuxAlarm<
370 'static,
371 litex_vexriscv::timer::LiteXAlarm<
372 'static,
373 'static,
374 socc::SoCRegisterFmt,
375 socc::ClockFrequency,
376 >,
377 >,
378 MuxAlarm::new(litex_alarm)
379 );
380 litex_alarm.set_alarm_client(mux_alarm);
381
382 let virtual_alarm_user = static_init!(
384 VirtualMuxAlarm<
385 'static,
386 litex_vexriscv::timer::LiteXAlarm<
387 'static,
388 'static,
389 socc::SoCRegisterFmt,
390 socc::ClockFrequency,
391 >,
392 >,
393 VirtualMuxAlarm::new(mux_alarm)
394 );
395 virtual_alarm_user.setup();
396
397 let alarm = static_init!(
398 capsules_core::alarm::AlarmDriver<
399 'static,
400 VirtualMuxAlarm<
401 'static,
402 litex_vexriscv::timer::LiteXAlarm<
403 'static,
404 'static,
405 socc::SoCRegisterFmt,
406 socc::ClockFrequency,
407 >,
408 >,
409 >,
410 capsules_core::alarm::AlarmDriver::new(
411 virtual_alarm_user,
412 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
413 )
414 );
415 virtual_alarm_user.set_alarm_client(alarm);
416
417 let systick_virtual_alarm = static_init!(
419 VirtualMuxAlarm<
420 'static,
421 litex_vexriscv::timer::LiteXAlarm<
422 'static,
423 'static,
424 socc::SoCRegisterFmt,
425 socc::ClockFrequency,
426 >,
427 >,
428 VirtualMuxAlarm::new(mux_alarm)
429 );
430 systick_virtual_alarm.setup();
431
432 let scheduler_timer = static_init!(
433 VirtualSchedulerTimer<
434 VirtualMuxAlarm<
435 'static,
436 litex_vexriscv::timer::LiteXAlarm<
437 'static,
438 'static,
439 socc::SoCRegisterFmt,
440 socc::ClockFrequency,
441 >,
442 >,
443 >,
444 VirtualSchedulerTimer::new(systick_virtual_alarm)
445 );
446
447 let uart0 = static_init!(
451 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
452 litex_vexriscv::uart::LiteXUart::new(
453 StaticRef::new(
454 socc::CSR_UART_BASE
455 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
456 ),
457 None, )
459 );
460 uart0.initialize();
461
462 PANIC_REFERENCES.uart = Some(uart0);
463
464 let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
469 .finalize(components::uart_mux_component_static!());
470
471 let ethmac0_rxbuf0 = static_init!([u8; 1522], [0; 1522]);
475
476 let ethmac0 = static_init!(
478 litex_vexriscv::liteeth::LiteEth<socc::SoCRegisterFmt>,
479 litex_vexriscv::liteeth::LiteEth::new(
480 StaticRef::new(
481 socc::CSR_ETHMAC_BASE
482 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
483 ),
484 socc::MEM_ETHMAC_BASE,
485 socc::MEM_ETHMAC_SIZE,
486 socc::ETHMAC_SLOT_SIZE,
487 socc::ETHMAC_RX_SLOTS,
488 socc::ETHMAC_TX_SLOTS,
489 ethmac0_rxbuf0,
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}