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