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