litex_sim/
main.rs

1// Licensed under the Apache License, Version 2.0 or the MIT License.
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3// Copyright Tock Contributors 2022.
4
5//! Board file for a LiteX SoC running in a Verilated simulation
6
7#![no_std]
8// Disable this attribute when documenting, as a workaround for
9// https://github.com/rust-lang/rust/issues/62184.
10#![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
31// This module contains the LiteX SoC configuration options, register
32// positions, interrupt mappings and other implementation details of
33// the generated bitstream.
34//
35// Its values are used throughout the file, hence import it under a
36// short name.
37use litex_generated_constants as socc;
38
39/// Structure for dynamic interrupt mapping, depending on the SoC
40/// configuration
41///
42/// This struct is deliberately kept in the board crate. Because of
43/// the configurable nature of LiteX, it does not make sense to define
44/// a default interrupt mapping, as the interrupt numbers are
45/// generated sequentially for all softcores.
46struct 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    // Resolve any recursive dependencies and set up deferred calls:
59    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
90// Actual memory for holding the active process structures. Need an
91// empty list at least.
92static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
93    [None; NUM_PROCS];
94
95// Reference to the chip and UART hardware for panic dumps
96struct 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
107// How should the kernel respond when a process faults.
108const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
109    capsules_system::process_policies::PanicFaultPolicy {};
110
111/// Dummy buffer that causes the linker to reserve enough space for the stack.
112#[no_mangle]
113#[link_section = ".stack_buffer"]
114pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
115
116/// A structure representing this platform that holds references to all
117/// capsules for this platform.
118struct 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
178/// Mapping of integer syscalls to objects that implement syscalls.
179impl 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/// This is in a separate, inline(never) function so that its stack frame is
253/// removed when this function returns. Otherwise, the stack space used for
254/// these static_inits is wasted.
255#[inline(never)]
256unsafe fn start() -> (
257    &'static kernel::Kernel,
258    LiteXSim,
259    &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
260) {
261    // These symbols are defined in the linker script.
262    extern "C" {
263        /// Beginning of the ROM region containing app images.
264        static _sapps: u8;
265        /// End of the ROM region containing app images.
266        static _eapps: u8;
267        /// Beginning of the RAM region for app memory.
268        static mut _sappmem: u8;
269        /// End of the RAM region for app memory.
270        static _eappmem: u8;
271        /// The start of the kernel text (Included only for kernel PMP)
272        static _stext: u8;
273        /// The end of the kernel text (Included only for kernel PMP)
274        static _etext: u8;
275        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
276        static _sflash: u8;
277        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
278        static _eflash: u8;
279        /// The start of the kernel / app RAM (Included only for kernel PMP)
280        static _ssram: u8;
281        /// The end of the kernel / app RAM (Included only for kernel PMP)
282        static _esram: u8;
283    }
284
285    // ---------- BASIC INITIALIZATION ----------
286
287    // Basic setup of the riscv platform.
288    rv32i::configure_trap_handler();
289
290    // Set up memory protection immediately after setting the trap handler, to
291    // ensure that much of the board initialization routine runs with PMP kernel
292    // memory protection.
293    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, // start
311                0x10000000,              // size
312            )
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    // initialize capabilities
326    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    // --------- TIMER & UPTIME CORE; ALARM INITIALIZATION ----------
332
333    // Initialize the hardware timer
334    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    // The SoC is expected to feature the 64-bit uptime extension to the timer hardware
343    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    // Create the LiteXAlarm based on the hardware LiteXTimer core and
353    // the uptime peripheral
354    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    // Create a shared virtualization mux layer on top of a single hardware
367    // alarm.
368    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    // Userspace alarm driver
383    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    // Systick virtual alarm for scheduling
418    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    // ---------- UART ----------
448
449    // Initialize the HW UART
450    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, // LiteX simulator has no UART phy
458        )
459    );
460    uart0.initialize();
461
462    PANIC_REFERENCES.uart = Some(uart0);
463
464    // Create a shared UART channel for the console and for kernel debug.
465    //
466    // The baudrate is ingnored, as no UART phy is present in the
467    // verilated simulation.
468    let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
469        .finalize(components::uart_mux_component_static!());
470
471    // ---------- ETHERNET ----------
472
473    // Packet receive buffer
474    let ethmac0_rxbuf0 = static_init!([u8; 1522], [0; 1522]);
475
476    // ETHMAC peripheral
477    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    // Initialize the ETHMAC controller
494    ethmac0.initialize();
495
496    // --------- GPIO CONTROLLER ----------
497    type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
498
499    // GPIO hardware controller
500    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, // 32 GPIOs in the simulation
508        ),
509    );
510    gpio0.initialize();
511
512    // --------- GPIO DRIVER ----------
513
514    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    // ---------- LED DRIVER ----------
540
541    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    // ---------- BUTTON ----------
569
570    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    // ---------- INITIALIZE CHIP, ENABLE INTERRUPTS ----------
620
621    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    // Enable RISC-V interrupts globally
651    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    // Unmask all interrupt sources in the interrupt controller
657    chip.unmask_interrupts();
658
659    // Setup the console.
660    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    // Create the debugger object that handles calls to `debug!()`.
667    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/// Main function called after RAM initialized.
730#[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}