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<
55        'static,
56        { socc::ETHMAC_TX_SLOTS },
57        socc::SoCRegisterFmt,
58    >,
59}
60
61impl LiteXSimInterruptablePeripherals {
62    // Resolve any recursive dependencies and set up deferred calls:
63    pub fn init(&'static self) {
64        kernel::deferred_call::DeferredCallClient::register(self.uart0);
65    }
66}
67
68impl InterruptService for LiteXSimInterruptablePeripherals {
69    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
70        match interrupt as usize {
71            socc::UART_INTERRUPT => {
72                self.uart0.service_interrupt();
73                true
74            }
75            socc::TIMER0_INTERRUPT => {
76                self.timer0.service_interrupt();
77                true
78            }
79            socc::ETHMAC_INTERRUPT => {
80                self.ethmac0.service_interrupt();
81                true
82            }
83            socc::GPIO_INTERRUPT => {
84                self.gpio0.service_interrupt();
85                true
86            }
87            _ => false,
88        }
89    }
90}
91
92const NUM_PROCS: usize = 4;
93
94// Actual memory for holding the active process structures. Need an
95// empty list at least.
96static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
97    [None; NUM_PROCS];
98
99// Reference to the chip and UART hardware for panic dumps
100struct LiteXSimPanicReferences {
101    chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
102    uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
103    process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
104}
105static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
106    chip: None,
107    uart: None,
108    process_printer: None,
109};
110
111// How should the kernel respond when a process faults.
112const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
113    capsules_system::process_policies::PanicFaultPolicy {};
114
115/// Dummy buffer that causes the linker to reserve enough space for the stack.
116#[no_mangle]
117#[link_section = ".stack_buffer"]
118pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
119
120/// A structure representing this platform that holds references to all
121/// capsules for this platform.
122struct LiteXSim {
123    gpio_driver: &'static capsules_core::gpio::GPIO<
124        'static,
125        litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
126    >,
127    button_driver: &'static capsules_core::button::Button<
128        'static,
129        litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
130    >,
131    led_driver: &'static capsules_core::led::LedDriver<
132        'static,
133        LedHigh<
134            'static,
135            litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
136        >,
137        8,
138    >,
139    console: &'static capsules_core::console::Console<'static>,
140    lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
141        'static,
142        capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
143    >,
144    alarm: &'static capsules_core::alarm::AlarmDriver<
145        'static,
146        VirtualMuxAlarm<
147            'static,
148            litex_vexriscv::timer::LiteXAlarm<
149                'static,
150                'static,
151                socc::SoCRegisterFmt,
152                socc::ClockFrequency,
153            >,
154        >,
155    >,
156    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
157    scheduler: &'static MLFQSched<
158        'static,
159        VirtualMuxAlarm<
160            'static,
161            litex_vexriscv::timer::LiteXAlarm<
162                'static,
163                'static,
164                socc::SoCRegisterFmt,
165                socc::ClockFrequency,
166            >,
167        >,
168    >,
169    scheduler_timer: &'static VirtualSchedulerTimer<
170        VirtualMuxAlarm<
171            'static,
172            litex_vexriscv::timer::LiteXAlarm<
173                'static,
174                'static,
175                socc::SoCRegisterFmt,
176                socc::ClockFrequency,
177            >,
178        >,
179    >,
180}
181
182/// Mapping of integer syscalls to objects that implement syscalls.
183impl SyscallDriverLookup for LiteXSim {
184    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
185    where
186        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
187    {
188        match driver_num {
189            capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
190            capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
191            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
192            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
193            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
194            capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
195            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
196            _ => f(None),
197        }
198    }
199}
200
201impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
202    for LiteXSim
203{
204    type SyscallDriverLookup = Self;
205    type SyscallFilter = ();
206    type ProcessFault = ();
207    type Scheduler = MLFQSched<
208        'static,
209        VirtualMuxAlarm<
210            'static,
211            litex_vexriscv::timer::LiteXAlarm<
212                'static,
213                'static,
214                socc::SoCRegisterFmt,
215                socc::ClockFrequency,
216            >,
217        >,
218    >;
219    type SchedulerTimer = VirtualSchedulerTimer<
220        VirtualMuxAlarm<
221            'static,
222            litex_vexriscv::timer::LiteXAlarm<
223                'static,
224                'static,
225                socc::SoCRegisterFmt,
226                socc::ClockFrequency,
227            >,
228        >,
229    >;
230    type WatchDog = ();
231    type ContextSwitchCallback = ();
232
233    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
234        self
235    }
236    fn syscall_filter(&self) -> &Self::SyscallFilter {
237        &()
238    }
239    fn process_fault(&self) -> &Self::ProcessFault {
240        &()
241    }
242    fn scheduler(&self) -> &Self::Scheduler {
243        self.scheduler
244    }
245    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
246        self.scheduler_timer
247    }
248    fn watchdog(&self) -> &Self::WatchDog {
249        &()
250    }
251    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
252        &()
253    }
254}
255
256/// This is in a separate, inline(never) function so that its stack frame is
257/// removed when this function returns. Otherwise, the stack space used for
258/// these static_inits is wasted.
259#[inline(never)]
260unsafe fn start() -> (
261    &'static kernel::Kernel,
262    LiteXSim,
263    &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
264) {
265    // These symbols are defined in the linker script.
266    extern "C" {
267        /// Beginning of the ROM region containing app images.
268        static _sapps: u8;
269        /// End of the ROM region containing app images.
270        static _eapps: u8;
271        /// Beginning of the RAM region for app memory.
272        static mut _sappmem: u8;
273        /// End of the RAM region for app memory.
274        static _eappmem: u8;
275        /// The start of the kernel text (Included only for kernel PMP)
276        static _stext: u8;
277        /// The end of the kernel text (Included only for kernel PMP)
278        static _etext: u8;
279        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
280        static _sflash: u8;
281        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
282        static _eflash: u8;
283        /// The start of the kernel / app RAM (Included only for kernel PMP)
284        static _ssram: u8;
285        /// The end of the kernel / app RAM (Included only for kernel PMP)
286        static _esram: u8;
287    }
288
289    // ---------- BASIC INITIALIZATION ----------
290
291    // Basic setup of the riscv platform.
292    rv32i::configure_trap_handler();
293
294    // Set up memory protection immediately after setting the trap handler, to
295    // ensure that much of the board initialization routine runs with PMP kernel
296    // memory protection.
297    let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
298        rv32i::pmp::kernel_protection::FlashRegion(
299            rv32i::pmp::NAPOTRegionSpec::from_start_end(
300                core::ptr::addr_of!(_sflash),
301                core::ptr::addr_of!(_eflash),
302            )
303            .unwrap(),
304        ),
305        rv32i::pmp::kernel_protection::RAMRegion(
306            rv32i::pmp::NAPOTRegionSpec::from_start_end(
307                core::ptr::addr_of!(_ssram),
308                core::ptr::addr_of!(_esram),
309            )
310            .unwrap(),
311        ),
312        rv32i::pmp::kernel_protection::MMIORegion(
313            rv32i::pmp::NAPOTRegionSpec::from_start_size(
314                0xf0000000 as *const u8, // start
315                0x10000000,              // size
316            )
317            .unwrap(),
318        ),
319        rv32i::pmp::kernel_protection::KernelTextRegion(
320            rv32i::pmp::TORRegionSpec::from_start_end(
321                core::ptr::addr_of!(_stext),
322                core::ptr::addr_of!(_etext),
323            )
324            .unwrap(),
325        ),
326    )
327    .unwrap();
328
329    // initialize capabilities
330    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
331    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
332
333    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
334
335    // --------- TIMER & UPTIME CORE; ALARM INITIALIZATION ----------
336
337    // Initialize the hardware timer
338    let timer0 = static_init!(
339        litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
340        litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
341            socc::CSR_TIMER0_BASE
342                as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
343        ),)
344    );
345
346    // The SoC is expected to feature the 64-bit uptime extension to the timer hardware
347    let timer0_uptime = static_init!(
348        litex_vexriscv::timer::LiteXTimerUptime<
349            'static,
350            socc::SoCRegisterFmt,
351            socc::ClockFrequency,
352        >,
353        litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
354    );
355
356    // Create the LiteXAlarm based on the hardware LiteXTimer core and
357    // the uptime peripheral
358    let litex_alarm = static_init!(
359        litex_vexriscv::timer::LiteXAlarm<
360            'static,
361            'static,
362            socc::SoCRegisterFmt,
363            socc::ClockFrequency,
364        >,
365        litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
366    );
367    timer0.set_timer_client(litex_alarm);
368    litex_alarm.initialize();
369
370    // Create a shared virtualization mux layer on top of a single hardware
371    // alarm.
372    let mux_alarm = static_init!(
373        MuxAlarm<
374            'static,
375            litex_vexriscv::timer::LiteXAlarm<
376                'static,
377                'static,
378                socc::SoCRegisterFmt,
379                socc::ClockFrequency,
380            >,
381        >,
382        MuxAlarm::new(litex_alarm)
383    );
384    litex_alarm.set_alarm_client(mux_alarm);
385
386    // Userspace alarm driver
387    let virtual_alarm_user = static_init!(
388        VirtualMuxAlarm<
389            'static,
390            litex_vexriscv::timer::LiteXAlarm<
391                'static,
392                'static,
393                socc::SoCRegisterFmt,
394                socc::ClockFrequency,
395            >,
396        >,
397        VirtualMuxAlarm::new(mux_alarm)
398    );
399    virtual_alarm_user.setup();
400
401    let alarm = static_init!(
402        capsules_core::alarm::AlarmDriver<
403            'static,
404            VirtualMuxAlarm<
405                'static,
406                litex_vexriscv::timer::LiteXAlarm<
407                    'static,
408                    'static,
409                    socc::SoCRegisterFmt,
410                    socc::ClockFrequency,
411                >,
412            >,
413        >,
414        capsules_core::alarm::AlarmDriver::new(
415            virtual_alarm_user,
416            board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
417        )
418    );
419    virtual_alarm_user.set_alarm_client(alarm);
420
421    // Systick virtual alarm for scheduling
422    let systick_virtual_alarm = static_init!(
423        VirtualMuxAlarm<
424            'static,
425            litex_vexriscv::timer::LiteXAlarm<
426                'static,
427                'static,
428                socc::SoCRegisterFmt,
429                socc::ClockFrequency,
430            >,
431        >,
432        VirtualMuxAlarm::new(mux_alarm)
433    );
434    systick_virtual_alarm.setup();
435
436    let scheduler_timer = static_init!(
437        VirtualSchedulerTimer<
438            VirtualMuxAlarm<
439                'static,
440                litex_vexriscv::timer::LiteXAlarm<
441                    'static,
442                    'static,
443                    socc::SoCRegisterFmt,
444                    socc::ClockFrequency,
445                >,
446            >,
447        >,
448        VirtualSchedulerTimer::new(systick_virtual_alarm)
449    );
450
451    // ---------- UART ----------
452
453    // Initialize the HW UART
454    let uart0 = static_init!(
455        litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
456        litex_vexriscv::uart::LiteXUart::new(
457            StaticRef::new(
458                socc::CSR_UART_BASE
459                    as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
460            ),
461            None, // LiteX simulator has no UART phy
462        )
463    );
464    uart0.initialize();
465
466    PANIC_REFERENCES.uart = Some(uart0);
467
468    // Create a shared UART channel for the console and for kernel debug.
469    //
470    // The baudrate is ingnored, as no UART phy is present in the
471    // verilated simulation.
472    let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
473        .finalize(components::uart_mux_component_static!());
474
475    // ---------- ETHERNET ----------
476
477    // ETHMAC peripheral
478    let ethmac0 = static_init!(
479        litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
480        litex_vexriscv::liteeth::LiteEth::new(
481            StaticRef::new(
482                socc::CSR_ETHMAC_BASE
483                    as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
484            ),
485            socc::MEM_ETHMAC_BASE,
486            socc::MEM_ETHMAC_SIZE,
487            socc::ETHMAC_SLOT_SIZE,
488            socc::ETHMAC_RX_SLOTS,
489            socc::ETHMAC_TX_SLOTS,
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}