1#![no_std]
9#![no_main]
10
11use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
12use kernel::capabilities;
13use kernel::component::Component;
14use kernel::hil::time::{Alarm, Timer};
15use kernel::platform::chip::InterruptService;
16use kernel::platform::{KernelResources, SyscallDriverLookup};
17use kernel::process::ProcessArray;
18use kernel::scheduler::mlfq::MLFQSched;
19use kernel::utilities::registers::interfaces::ReadWriteable;
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 LiteXArtyInterruptablePeripherals {
43 uart0: &'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>,
44 timer0: &'static litex_vexriscv::timer::LiteXTimer<
45 'static,
46 socc::SoCRegisterFmt,
47 socc::ClockFrequency,
48 >,
49 ethmac0: &'static litex_vexriscv::liteeth::LiteEth<
50 'static,
51 { socc::ETHMAC_TX_SLOTS },
52 socc::SoCRegisterFmt,
53 >,
54}
55
56impl LiteXArtyInterruptablePeripherals {
57 pub fn init(&'static self) {
59 kernel::deferred_call::DeferredCallClient::register(self.uart0);
60 }
61}
62
63impl InterruptService for LiteXArtyInterruptablePeripherals {
64 unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
65 match interrupt as usize {
66 socc::UART_INTERRUPT => {
67 self.uart0.service_interrupt();
68 true
69 }
70 socc::TIMER0_INTERRUPT => {
71 self.timer0.service_interrupt();
72 true
73 }
74 socc::ETHMAC_INTERRUPT => {
75 self.ethmac0.service_interrupt();
76 true
77 }
78 _ => false,
79 }
80 }
81}
82
83const NUM_PROCS: usize = 4;
84
85type ChipHw = litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>;
86type AlarmHw =
87 litex_vexriscv::timer::LiteXAlarm<'static, 'static, socc::SoCRegisterFmt, socc::ClockFrequency>;
88type SchedulerTimerHw =
89 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
90
91static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
93
94struct LiteXArtyPanicReferences {
97 chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>>,
98 uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
99 led_controller:
100 Option<&'static litex_vexriscv::led_controller::LiteXLedController<socc::SoCRegisterFmt>>,
101 process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
102}
103static mut PANIC_REFERENCES: LiteXArtyPanicReferences = LiteXArtyPanicReferences {
104 chip: None,
105 uart: None,
106 led_controller: None,
107 process_printer: None,
108};
109
110const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
112 capsules_system::process_policies::PanicFaultPolicy {};
113
114kernel::stack_size! {0x2000}
115
116struct LiteXArty {
119 led_driver: &'static capsules_core::led::LedDriver<
120 'static,
121 litex_vexriscv::led_controller::LiteXLed<'static, socc::SoCRegisterFmt>,
122 4,
123 >,
124 console: &'static capsules_core::console::Console<'static>,
125 pconsole: &'static capsules_core::process_console::ProcessConsole<
126 'static,
127 { capsules_core::process_console::DEFAULT_COMMAND_HISTORY_LEN },
128 VirtualMuxAlarm<'static, AlarmHw>,
129 components::process_console::Capability,
130 >,
131 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
132 'static,
133 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
134 >,
135 alarm: &'static capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
136 ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
137 scheduler: &'static MLFQSched<'static, VirtualMuxAlarm<'static, AlarmHw>>,
138 scheduler_timer: &'static SchedulerTimerHw,
139}
140
141impl SyscallDriverLookup for LiteXArty {
143 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
144 where
145 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
146 {
147 match driver_num {
148 capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
149 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
150 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
151 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
152 kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
153 _ => f(None),
154 }
155 }
156}
157
158impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>>
159 for LiteXArty
160{
161 type SyscallDriverLookup = Self;
162 type SyscallFilter = ();
163 type ProcessFault = ();
164 type Scheduler = MLFQSched<'static, VirtualMuxAlarm<'static, AlarmHw>>;
165 type SchedulerTimer = SchedulerTimerHw;
166 type WatchDog = ();
167 type ContextSwitchCallback = ();
168
169 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
170 self
171 }
172 fn syscall_filter(&self) -> &Self::SyscallFilter {
173 &()
174 }
175 fn process_fault(&self) -> &Self::ProcessFault {
176 &()
177 }
178 fn scheduler(&self) -> &Self::Scheduler {
179 self.scheduler
180 }
181 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
182 self.scheduler_timer
183 }
184 fn watchdog(&self) -> &Self::WatchDog {
185 &()
186 }
187 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
188 &()
189 }
190}
191
192#[inline(never)]
196unsafe fn start() -> (
197 &'static kernel::Kernel,
198 LiteXArty,
199 &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXArtyInterruptablePeripherals>,
200) {
201 extern "C" {
203 static _sapps: u8;
205 static _eapps: u8;
207 static mut _sappmem: u8;
209 static _eappmem: u8;
211 static _stext: u8;
213 static _etext: u8;
215 static _sflash: u8;
217 static _eflash: u8;
219 static _ssram: u8;
221 static _esram: u8;
223 }
224
225 rv32i::configure_trap_handler();
229
230 kernel::deferred_call::initialize_deferred_call_state_unsafe::<
232 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
233 >();
234
235 let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
239 rv32i::pmp::kernel_protection::FlashRegion(
240 rv32i::pmp::NAPOTRegionSpec::from_start_end(
241 core::ptr::addr_of!(_sflash),
242 core::ptr::addr_of!(_eflash),
243 )
244 .unwrap(),
245 ),
246 rv32i::pmp::kernel_protection::RAMRegion(
247 rv32i::pmp::NAPOTRegionSpec::from_start_end(
248 core::ptr::addr_of!(_ssram),
249 core::ptr::addr_of!(_esram),
250 )
251 .unwrap(),
252 ),
253 rv32i::pmp::kernel_protection::MMIORegion(
254 rv32i::pmp::NAPOTRegionSpec::from_start_size(
255 0xf0000000 as *const u8, 0x10000000, )
258 .unwrap(),
259 ),
260 rv32i::pmp::kernel_protection::KernelTextRegion(
261 rv32i::pmp::TORRegionSpec::from_start_end(
262 core::ptr::addr_of!(_stext),
263 core::ptr::addr_of!(_etext),
264 )
265 .unwrap(),
266 ),
267 )
268 .unwrap();
269
270 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
272 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
273
274 let processes = components::process_array::ProcessArrayComponent::new()
276 .finalize(components::process_array_component_static!(NUM_PROCS));
277 PROCESSES = Some(processes);
278
279 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
281
282 let led0 = static_init!(
287 litex_vexriscv::led_controller::LiteXLedController<socc::SoCRegisterFmt>,
288 litex_vexriscv::led_controller::LiteXLedController::new(
289 StaticRef::new(
290 socc::CSR_LEDS_BASE
291 as *const litex_vexriscv::led_controller::LiteXLedRegisters<
292 socc::SoCRegisterFmt,
293 >
294 ),
295 4, )
297 );
298 led0.initialize();
299
300 PANIC_REFERENCES.led_controller = Some(led0);
301
302 let timer0 = static_init!(
306 litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
307 litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
308 socc::CSR_TIMER0_BASE
309 as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
310 ),)
311 );
312
313 let timer0_uptime = static_init!(
315 litex_vexriscv::timer::LiteXTimerUptime<
316 'static,
317 socc::SoCRegisterFmt,
318 socc::ClockFrequency,
319 >,
320 litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
321 );
322
323 let litex_alarm = static_init!(
326 AlarmHw,
327 litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
328 );
329 timer0.set_timer_client(litex_alarm);
330 litex_alarm.initialize();
331
332 let mux_alarm = static_init!(MuxAlarm<'static, AlarmHw>, MuxAlarm::new(litex_alarm));
335 litex_alarm.set_alarm_client(mux_alarm);
336
337 let virtual_alarm_user = static_init!(
339 VirtualMuxAlarm<'static, AlarmHw>,
340 VirtualMuxAlarm::new(mux_alarm)
341 );
342 virtual_alarm_user.setup();
343
344 let alarm = static_init!(
345 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, AlarmHw>>,
346 capsules_core::alarm::AlarmDriver::new(
347 virtual_alarm_user,
348 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
349 )
350 );
351 virtual_alarm_user.set_alarm_client(alarm);
352
353 let scheduler_timer =
354 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
355 .finalize(components::virtual_scheduler_timer_component_static!(
356 AlarmHw
357 ));
358
359 let uart0 = static_init!(
363 litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
364 litex_vexriscv::uart::LiteXUart::new(
365 StaticRef::new(
366 socc::CSR_UART_BASE
367 as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
368 ),
369 None,
373 )
374 );
375 uart0.initialize();
376
377 PANIC_REFERENCES.uart = Some(uart0);
378
379 let uart_mux = components::console::UartMuxComponent::new(uart0, socc::UART_BAUDRATE)
381 .finalize(components::uart_mux_component_static!());
382
383 let ethmac0 = static_init!(
387 litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
388 litex_vexriscv::liteeth::LiteEth::new(
389 StaticRef::new(
390 socc::CSR_ETHMAC_BASE
391 as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
392 ),
393 socc::MEM_ETHMAC_BASE,
394 socc::MEM_ETHMAC_SIZE,
395 socc::ETHMAC_SLOT_SIZE,
396 socc::ETHMAC_RX_SLOTS,
397 socc::ETHMAC_TX_SLOTS,
398 )
399 );
400
401 ethmac0.initialize();
403
404 let led_driver =
408 components::led::LedsComponent::new().finalize(components::led_component_static!(
409 litex_vexriscv::led_controller::LiteXLed<'static, socc::SoCRegisterFmt>,
410 led0.get_led(0).unwrap(),
411 led0.get_led(1).unwrap(),
412 led0.get_led(2).unwrap(),
413 led0.get_led(3).unwrap(),
414 ));
415
416 let interrupt_service = static_init!(
419 LiteXArtyInterruptablePeripherals,
420 LiteXArtyInterruptablePeripherals {
421 uart0,
422 timer0,
423 ethmac0,
424 }
425 );
426 interrupt_service.init();
427
428 let chip = static_init!(
429 litex_vexriscv::chip::LiteXVexRiscv<
430 LiteXArtyInterruptablePeripherals,
431 >,
432 litex_vexriscv::chip::LiteXVexRiscv::new(
433 "LiteX on Arty A7",
434 interrupt_service,
435 pmp,
436 )
437 );
438
439 PANIC_REFERENCES.chip = Some(chip);
440
441 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
442 .finalize(components::process_printer_text_component_static!());
443
444 PANIC_REFERENCES.process_printer = Some(process_printer);
445
446 csr::CSR
448 .mie
449 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
450 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
451
452 chip.unmask_interrupts();
454
455 let pconsole = components::process_console::ProcessConsoleComponent::new(
457 board_kernel,
458 uart_mux,
459 mux_alarm,
460 process_printer,
461 None,
462 )
463 .finalize(components::process_console_component_static!(AlarmHw));
464
465 let console = components::console::ConsoleComponent::new(
467 board_kernel,
468 capsules_core::console::DRIVER_NUM,
469 uart_mux,
470 )
471 .finalize(components::console_component_static!());
472
473 components::debug_writer::DebugWriterComponent::new_unsafe(
475 uart_mux,
476 create_capability!(capabilities::SetDebugWriterCapability),
477 || unsafe {
478 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
479 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
480 >();
481 },
482 )
483 .finalize(components::debug_writer_component_static!());
484
485 let lldb = components::lldb::LowLevelDebugComponent::new(
486 board_kernel,
487 capsules_core::low_level_debug::DRIVER_NUM,
488 uart_mux,
489 )
490 .finalize(components::low_level_debug_component_static!());
491
492 let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes).finalize(
493 components::mlfq_component_static!(
494 litex_vexriscv::timer::LiteXAlarm<
495 'static,
496 'static,
497 socc::SoCRegisterFmt,
498 socc::ClockFrequency,
499 >,
500 NUM_PROCS
501 ),
502 );
503
504 let litex_arty = LiteXArty {
505 console,
506 pconsole,
507 alarm,
508 lldb,
509 led_driver,
510 scheduler,
511 scheduler_timer,
512 ipc: kernel::ipc::IPC::new(
513 board_kernel,
514 kernel::ipc::DRIVER_NUM,
515 &memory_allocation_cap,
516 ),
517 };
518
519 debug!("LiteX+VexRiscv on ArtyA7: initialization complete, entering main loop.");
520 let _ = litex_arty.pconsole.start();
521
522 kernel::process::load_processes(
523 board_kernel,
524 chip,
525 core::slice::from_raw_parts(
526 core::ptr::addr_of!(_sapps),
527 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
528 ),
529 core::slice::from_raw_parts_mut(
530 core::ptr::addr_of_mut!(_sappmem),
531 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
532 ),
533 &FAULT_RESPONSE,
534 &process_mgmt_cap,
535 )
536 .unwrap_or_else(|err| {
537 debug!("Error loading processes!");
538 debug!("{:?}", err);
539 });
540
541 (board_kernel, litex_arty, chip)
542}
543
544#[no_mangle]
546pub unsafe fn main() {
547 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
548
549 let (board_kernel, board, chip) = start();
550 board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
551}