1#![no_std]
8#![no_main]
9
10use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
11use kernel::capabilities;
12use kernel::component::Component;
13use kernel::debug::PanicResources;
14use kernel::hil::led::LedHigh;
15use kernel::hil::time::{Alarm, Timer};
16use kernel::platform::chip::InterruptService;
17use kernel::platform::{KernelResources, SyscallDriverLookup};
18use kernel::utilities::registers::interfaces::ReadWriteable;
19use kernel::utilities::single_thread_value::SingleThreadValue;
20use kernel::utilities::StaticRef;
21use kernel::{create_capability, debug, static_init};
22use rv32i::csr;
23
24mod io;
25mod litex_generated_constants;
26
27use litex_generated_constants as socc;
34
35struct LiteXSimInterruptablePeripherals {
43 gpio0: &'static litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
44 uart0: &'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>,
45 timer0: &'static litex_vexriscv::timer::LiteXTimer<
46 'static,
47 socc::SoCRegisterFmt,
48 socc::ClockFrequency,
49 >,
50 ethmac0: &'static litex_vexriscv::liteeth::LiteEth<
51 'static,
52 { socc::ETHMAC_TX_SLOTS },
53 socc::SoCRegisterFmt,
54 >,
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
90type ChipHw = litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>;
91type AlarmHw =
92 litex_vexriscv::timer::LiteXAlarm<'static, 'static, socc::SoCRegisterFmt, socc::ClockFrequency>;
93type SchedulerTimerHw =
94 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
95type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
96type SchedulerInUse = components::sched::mlfq::MLFQComponentType<AlarmHw>;
97
98static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
100 SingleThreadValue::new();
101
102const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
104 capsules_system::process_policies::PanicFaultPolicy {};
105
106kernel::stack_size! {0x2000}
107
108struct LiteXSim {
111 gpio_driver: &'static capsules_core::gpio::GPIO<
112 'static,
113 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
114 >,
115 button_driver: &'static capsules_core::button::Button<
116 'static,
117 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
118 >,
119 led_driver: &'static capsules_core::led::LedDriver<
120 'static,
121 LedHigh<
122 'static,
123 litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
124 >,
125 8,
126 >,
127 console: &'static capsules_core::console::Console<'static>,
128 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
129 'static,
130 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
131 >,
132 alarm: &'static capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
133 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
134 scheduler: &'static SchedulerInUse,
135 scheduler_timer: &'static SchedulerTimerHw,
136}
137
138impl SyscallDriverLookup for LiteXSim {
140 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
141 where
142 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
143 {
144 match driver_num {
145 capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
146 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
147 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
148 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
149 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
150 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
151 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
152 _ => f(None),
153 }
154 }
155}
156
157impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
158 for LiteXSim
159{
160 type SyscallDriverLookup = Self;
161 type SyscallFilter = ();
162 type ProcessFault = ();
163 type Scheduler = SchedulerInUse;
164 type SchedulerTimer = SchedulerTimerHw;
165 type WatchDog = ();
166 type ContextSwitchCallback = ();
167
168 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
169 self
170 }
171 fn syscall_filter(&self) -> &Self::SyscallFilter {
172 &()
173 }
174 fn process_fault(&self) -> &Self::ProcessFault {
175 &()
176 }
177 fn scheduler(&self) -> &Self::Scheduler {
178 self.scheduler
179 }
180 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
181 self.scheduler_timer
182 }
183 fn watchdog(&self) -> &Self::WatchDog {
184 &()
185 }
186 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
187 &()
188 }
189}
190
191#[inline(never)]
195unsafe fn start() -> (
196 &'static kernel::Kernel,
197 LiteXSim,
198 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
199) {
200 extern "C" {
202 static _sapps: u8;
204 static _eapps: u8;
206 static mut _sappmem: u8;
208 static _eappmem: u8;
210 static _stext: u8;
212 static _etext: u8;
214 static _sflash: u8;
216 static _eflash: u8;
218 static _ssram: u8;
220 static _esram: u8;
222 }
223
224 rv32i::configure_trap_handler();
228
229 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
231 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
232 >();
233
234 let _ = PANIC_RESOURCES
236 .bind_to_thread_unsafe::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>(
237 PanicResources::new(),
238 );
239
240 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
244 rv32i::pmp::kernel_protection::FlashRegion(
245 rv32i::pmp::NAPOTRegionSpec::from_start_end(
246 core::ptr::addr_of!(_sflash),
247 core::ptr::addr_of!(_eflash),
248 )
249 .unwrap(),
250 ),
251 rv32i::pmp::kernel_protection::RAMRegion(
252 rv32i::pmp::NAPOTRegionSpec::from_start_end(
253 core::ptr::addr_of!(_ssram),
254 core::ptr::addr_of!(_esram),
255 )
256 .unwrap(),
257 ),
258 rv32i::pmp::kernel_protection::MMIORegion(
259 rv32i::pmp::NAPOTRegionSpec::from_start_size(
260 0xf0000000 as *const u8, 0x10000000, )
263 .unwrap(),
264 ),
265 rv32i::pmp::kernel_protection::KernelTextRegion(
266 rv32i::pmp::TORRegionSpec::from_start_end(
267 core::ptr::addr_of!(_stext),
268 core::ptr::addr_of!(_etext),
269 )
270 .unwrap(),
271 ),
272 )
273 .unwrap();
274
275 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
277 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
278
279 let processes = components::process_array::ProcessArrayComponent::new()
281 .finalize(components::process_array_component_static!(NUM_PROCS));
282 PANIC_RESOURCES.get().map(|resources| {
283 resources.processes.put(processes.as_slice());
284 });
285
286 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
288
289 let timer0 = static_init!(
293 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
294 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
295 socc::CSR_TIMER0_BASE
296 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
297 ),)
298 );
299
300 let timer0_uptime = static_init!(
302 litex_vexriscv::timer::LiteXTimerUptime<
303 'static,
304 socc::SoCRegisterFmt,
305 socc::ClockFrequency,
306 >,
307 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
308 );
309
310 let litex_alarm = static_init!(
313 AlarmHw,
314 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
315 );
316 timer0.set_timer_client(litex_alarm);
317 litex_alarm.initialize();
318
319 let mux_alarm = static_init!(MuxAlarm<'static, AlarmHw>, MuxAlarm::new(litex_alarm));
322 litex_alarm.set_alarm_client(mux_alarm);
323
324 let virtual_alarm_user = static_init!(
326 VirtualMuxAlarm<'static, AlarmHw>,
327 VirtualMuxAlarm::new(mux_alarm)
328 );
329 virtual_alarm_user.setup();
330
331 let alarm = static_init!(
332 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
333 capsules_core::alarm::AlarmDriver::new(
334 virtual_alarm_user,
335 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
336 )
337 );
338 virtual_alarm_user.set_alarm_client(alarm);
339
340 let scheduler_timer =
341 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
342 .finalize(components::virtual_scheduler_timer_component_static!(
343 AlarmHw
344 ));
345
346 let uart0 = static_init!(
350 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
351 litex_vexriscv::uart::LiteXUart::new(
352 StaticRef::new(
353 socc::CSR_UART_BASE
354 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
355 ),
356 None, )
358 );
359 uart0.initialize();
360
361 let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
366 .finalize(components::uart_mux_component_static!());
367
368 let ethmac0 = static_init!(
372 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
373 litex_vexriscv::liteeth::LiteEth::new(
374 StaticRef::new(
375 socc::CSR_ETHMAC_BASE
376 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
377 ),
378 socc::MEM_ETHMAC_BASE,
379 socc::MEM_ETHMAC_SIZE,
380 socc::ETHMAC_SLOT_SIZE,
381 socc::ETHMAC_RX_SLOTS,
382 socc::ETHMAC_TX_SLOTS,
383 )
384 );
385
386 ethmac0.initialize();
388
389 type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
391
392 let gpio0 = static_init!(
394 litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
395 litex_vexriscv::gpio::LiteXGPIOController::new(
396 StaticRef::new(
397 socc::CSR_GPIO_BASE
398 as *const litex_vexriscv::gpio::LiteXGPIORegisters<socc::SoCRegisterFmt>
399 ),
400 32, ),
402 );
403 gpio0.initialize();
404
405 let gpio_driver = components::gpio::GpioComponent::new(
408 board_kernel,
409 capsules_core::gpio::DRIVER_NUM,
410 components::gpio_component_helper_owned!(
411 GPIOPin,
412 16 => gpio0.get_gpio_pin(16).unwrap(),
413 17 => gpio0.get_gpio_pin(17).unwrap(),
414 18 => gpio0.get_gpio_pin(18).unwrap(),
415 19 => gpio0.get_gpio_pin(19).unwrap(),
416 20 => gpio0.get_gpio_pin(20).unwrap(),
417 21 => gpio0.get_gpio_pin(21).unwrap(),
418 22 => gpio0.get_gpio_pin(22).unwrap(),
419 23 => gpio0.get_gpio_pin(23).unwrap(),
420 24 => gpio0.get_gpio_pin(24).unwrap(),
421 25 => gpio0.get_gpio_pin(25).unwrap(),
422 26 => gpio0.get_gpio_pin(26).unwrap(),
423 27 => gpio0.get_gpio_pin(27).unwrap(),
424 28 => gpio0.get_gpio_pin(28).unwrap(),
425 29 => gpio0.get_gpio_pin(29).unwrap(),
426 30 => gpio0.get_gpio_pin(30).unwrap(),
427 31 => gpio0.get_gpio_pin(31).unwrap(),
428 ),
429 )
430 .finalize(components::gpio_component_static!(GPIOPin));
431
432 let led_gpios = static_init!(
435 [GPIOPin; 8],
436 [
437 gpio0.get_gpio_pin(0).unwrap(),
438 gpio0.get_gpio_pin(1).unwrap(),
439 gpio0.get_gpio_pin(2).unwrap(),
440 gpio0.get_gpio_pin(3).unwrap(),
441 gpio0.get_gpio_pin(4).unwrap(),
442 gpio0.get_gpio_pin(5).unwrap(),
443 gpio0.get_gpio_pin(6).unwrap(),
444 gpio0.get_gpio_pin(7).unwrap(),
445 ]
446 );
447
448 let led_driver =
449 components::led::LedsComponent::new().finalize(components::led_component_static!(
450 kernel::hil::led::LedHigh<GPIOPin>,
451 LedHigh::new(&led_gpios[0]),
452 LedHigh::new(&led_gpios[1]),
453 LedHigh::new(&led_gpios[2]),
454 LedHigh::new(&led_gpios[3]),
455 LedHigh::new(&led_gpios[4]),
456 LedHigh::new(&led_gpios[5]),
457 LedHigh::new(&led_gpios[6]),
458 LedHigh::new(&led_gpios[7]),
459 ));
460
461 let button_driver = components::button::ButtonComponent::new(
464 board_kernel,
465 capsules_core::button::DRIVER_NUM,
466 components::button_component_helper_owned!(
467 GPIOPin,
468 (
469 gpio0.get_gpio_pin(8).unwrap(),
470 kernel::hil::gpio::ActivationMode::ActiveHigh,
471 kernel::hil::gpio::FloatingState::PullNone
472 ),
473 (
474 gpio0.get_gpio_pin(9).unwrap(),
475 kernel::hil::gpio::ActivationMode::ActiveHigh,
476 kernel::hil::gpio::FloatingState::PullNone
477 ),
478 (
479 gpio0.get_gpio_pin(10).unwrap(),
480 kernel::hil::gpio::ActivationMode::ActiveHigh,
481 kernel::hil::gpio::FloatingState::PullNone
482 ),
483 (
484 gpio0.get_gpio_pin(11).unwrap(),
485 kernel::hil::gpio::ActivationMode::ActiveHigh,
486 kernel::hil::gpio::FloatingState::PullNone
487 ),
488 (
489 gpio0.get_gpio_pin(12).unwrap(),
490 kernel::hil::gpio::ActivationMode::ActiveHigh,
491 kernel::hil::gpio::FloatingState::PullNone
492 ),
493 (
494 gpio0.get_gpio_pin(13).unwrap(),
495 kernel::hil::gpio::ActivationMode::ActiveHigh,
496 kernel::hil::gpio::FloatingState::PullNone
497 ),
498 (
499 gpio0.get_gpio_pin(14).unwrap(),
500 kernel::hil::gpio::ActivationMode::ActiveHigh,
501 kernel::hil::gpio::FloatingState::PullNone
502 ),
503 (
504 gpio0.get_gpio_pin(15).unwrap(),
505 kernel::hil::gpio::ActivationMode::ActiveHigh,
506 kernel::hil::gpio::FloatingState::PullNone
507 ),
508 ),
509 )
510 .finalize(components::button_component_static!(GPIOPin));
511
512 let interrupt_service = static_init!(
515 LiteXSimInterruptablePeripherals,
516 LiteXSimInterruptablePeripherals {
517 gpio0,
518 uart0,
519 timer0,
520 ethmac0,
521 }
522 );
523 interrupt_service.init();
524
525 let chip = static_init!(
526 litex_vexriscv::chip::LiteXVexRiscv<
527 LiteXSimInterruptablePeripherals,
528 >,
529 litex_vexriscv::chip::LiteXVexRiscv::new(
530 "Verilated LiteX on VexRiscv",
531 interrupt_service,
532 pmp,
533 )
534 );
535 PANIC_RESOURCES.get().map(|resources| {
536 resources.chip.put(chip);
537 });
538
539 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
540 .finalize(components::process_printer_text_component_static!());
541 PANIC_RESOURCES.get().map(|resources| {
542 resources.printer.put(process_printer);
543 });
544
545 csr::CSR
547 .mie
548 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
549 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
550
551 chip.unmask_interrupts();
553
554 let console = components::console::ConsoleComponent::new(
556 board_kernel,
557 capsules_core::console::DRIVER_NUM,
558 uart_mux,
559 )
560 .finalize(components::console_component_static!());
561 components::debug_writer::DebugWriterComponent::new_unsafe(
563 uart_mux,
564 create_capability!(capabilities::SetDebugWriterCapability),
565 || unsafe {
566 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
567 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
568 >();
569 },
570 )
571 .finalize(components::debug_writer_component_static!());
572
573 let lldb = components::lldb::LowLevelDebugComponent::new(
574 board_kernel,
575 capsules_core::low_level_debug::DRIVER_NUM,
576 uart_mux,
577 )
578 .finalize(components::low_level_debug_component_static!());
579
580 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes)
581 .finalize(components::mlfq_component_static!(AlarmHw, NUM_PROCS));
582
583 let litex_sim = LiteXSim {
584 gpio_driver,
585 button_driver,
586 led_driver,
587 console,
588 alarm,
589 lldb,
590 ipc: kernel::ipc::IPC::new(
591 board_kernel,
592 kernel::ipc::DRIVER_NUM,
593 &memory_allocation_cap,
594 ),
595 scheduler,
596 scheduler_timer,
597 };
598
599 debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
600
601 kernel::process::load_processes(
602 board_kernel,
603 chip,
604 core::slice::from_raw_parts(
605 core::ptr::addr_of!(_sapps),
606 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
607 ),
608 core::slice::from_raw_parts_mut(
609 core::ptr::addr_of_mut!(_sappmem),
610 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
611 ),
612 &FAULT_RESPONSE,
613 &process_mgmt_cap,
614 )
615 .unwrap_or_else(|err| {
616 debug!("Error loading processes!");
617 debug!("{:?}", err);
618 });
619
620 (board_kernel, litex_sim, chip)
621}
622
623#[no_mangle]
625pub unsafe fn main() {
626 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
627
628 let (board_kernel, board, chip) = start();
629 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
630}