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#![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
28// This module contains the LiteX SoC configuration options, register
29// positions, interrupt mappings and other implementation details of
30// the generated bitstream.
31//
32// Its values are used throughout the file, hence import it under a
33// short name.
34use litex_generated_constants as socc;
35
36/// Structure for dynamic interrupt mapping, depending on the SoC
37/// configuration
38///
39/// This struct is deliberately kept in the board crate. Because of
40/// the configurable nature of LiteX, it does not make sense to define
41/// a default interrupt mapping, as the interrupt numbers are
42/// generated sequentially for all softcores.
43struct 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    // Resolve any recursive dependencies and set up deferred calls:
60    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
91/// Static variables used by io.rs.
92static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
93
94// Reference to the chip and UART hardware for panic dumps
95struct 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
106// How should the kernel respond when a process faults.
107const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
108    capsules_system::process_policies::PanicFaultPolicy {};
109
110/// Dummy buffer that causes the linker to reserve enough space for the stack.
111#[no_mangle]
112#[link_section = ".stack_buffer"]
113static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
114
115/// A structure representing this platform that holds references to all
116/// capsules for this platform.
117struct 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
177/// Mapping of integer syscalls to objects that implement syscalls.
178impl 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/// This is in a separate, inline(never) function so that its stack frame is
252/// removed when this function returns. Otherwise, the stack space used for
253/// these static_inits is wasted.
254#[inline(never)]
255unsafe fn start() -> (
256    &'static kernel::Kernel,
257    LiteXSim,
258    &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
259) {
260    // These symbols are defined in the linker script.
261    extern "C" {
262        /// Beginning of the ROM region containing app images.
263        static _sapps: u8;
264        /// End of the ROM region containing app images.
265        static _eapps: u8;
266        /// Beginning of the RAM region for app memory.
267        static mut _sappmem: u8;
268        /// End of the RAM region for app memory.
269        static _eappmem: u8;
270        /// The start of the kernel text (Included only for kernel PMP)
271        static _stext: u8;
272        /// The end of the kernel text (Included only for kernel PMP)
273        static _etext: u8;
274        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
275        static _sflash: u8;
276        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
277        static _eflash: u8;
278        /// The start of the kernel / app RAM (Included only for kernel PMP)
279        static _ssram: u8;
280        /// The end of the kernel / app RAM (Included only for kernel PMP)
281        static _esram: u8;
282    }
283
284    // ---------- BASIC INITIALIZATION ----------
285
286    // Basic setup of the riscv platform.
287    rv32i::configure_trap_handler();
288
289    // Set up memory protection immediately after setting the trap handler, to
290    // ensure that much of the board initialization routine runs with PMP kernel
291    // memory protection.
292    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, // start
310                0x10000000,              // size
311            )
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    // initialize capabilities
325    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
326    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
327
328    // Create an array to hold process references.
329    let processes = components::process_array::ProcessArrayComponent::new()
330        .finalize(components::process_array_component_static!(NUM_PROCS));
331    PROCESSES = Some(processes);
332
333    // Setup space to store the core kernel data structure.
334    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
335
336    // --------- TIMER & UPTIME CORE; ALARM INITIALIZATION ----------
337
338    // Initialize the hardware timer
339    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    // The SoC is expected to feature the 64-bit uptime extension to the timer hardware
348    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    // Create the LiteXAlarm based on the hardware LiteXTimer core and
358    // the uptime peripheral
359    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    // Create a shared virtualization mux layer on top of a single hardware
372    // alarm.
373    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    // Userspace alarm driver
388    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    // Systick virtual alarm for scheduling
423    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    // ---------- UART ----------
453
454    // Initialize the HW UART
455    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, // LiteX simulator has no UART phy
463        )
464    );
465    uart0.initialize();
466
467    PANIC_REFERENCES.uart = Some(uart0);
468
469    // Create a shared UART channel for the console and for kernel debug.
470    //
471    // The baudrate is ingnored, as no UART phy is present in the
472    // verilated simulation.
473    let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
474        .finalize(components::uart_mux_component_static!());
475
476    // ---------- ETHERNET ----------
477
478    // ETHMAC peripheral
479    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    // Initialize the ETHMAC controller
495    ethmac0.initialize();
496
497    // --------- GPIO CONTROLLER ----------
498    type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
499
500    // GPIO hardware controller
501    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, // 32 GPIOs in the simulation
509        ),
510    );
511    gpio0.initialize();
512
513    // --------- GPIO DRIVER ----------
514
515    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    // ---------- LED DRIVER ----------
541
542    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    // ---------- BUTTON ----------
570
571    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    // ---------- INITIALIZE CHIP, ENABLE INTERRUPTS ----------
621
622    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    // Enable RISC-V interrupts globally
652    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    // Unmask all interrupt sources in the interrupt controller
658    chip.unmask_interrupts();
659
660    // Setup the console.
661    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    // Create the debugger object that handles calls to `debug!()`.
668    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/// Main function called after RAM initialized.
734#[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}