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 core::ptr::{addr_of, addr_of_mut};
11
12use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
13use kernel::capabilities;
14use kernel::component::Component;
15use kernel::hil::led::LedHigh;
16use kernel::hil::time::{Alarm, Timer};
17use kernel::platform::chip::InterruptService;
18use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
19use kernel::platform::{KernelResources, SyscallDriverLookup};
20use kernel::scheduler::mlfq::MLFQSched;
21use kernel::utilities::registers::interfaces::ReadWriteable;
22use kernel::utilities::StaticRef;
23use kernel::{create_capability, debug, static_init};
24use rv32i::csr;
25
26mod io;
27mod litex_generated_constants;
28
29// This module contains the LiteX SoC configuration options, register
30// positions, interrupt mappings and other implementation details of
31// the generated bitstream.
32//
33// Its values are used throughout the file, hence import it under a
34// short name.
35use litex_generated_constants as socc;
36
37/// Structure for dynamic interrupt mapping, depending on the SoC
38/// configuration
39///
40/// This struct is deliberately kept in the board crate. Because of
41/// the configurable nature of LiteX, it does not make sense to define
42/// a default interrupt mapping, as the interrupt numbers are
43/// generated sequentially for all softcores.
44struct LiteXSimInterruptablePeripherals {
45    gpio0: &'static litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
46    uart0: &'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>,
47    timer0: &'static litex_vexriscv::timer::LiteXTimer<
48        'static,
49        socc::SoCRegisterFmt,
50        socc::ClockFrequency,
51    >,
52    ethmac0: &'static litex_vexriscv::liteeth::LiteEth<
53        'static,
54        { socc::ETHMAC_TX_SLOTS },
55        socc::SoCRegisterFmt,
56    >,
57}
58
59impl LiteXSimInterruptablePeripherals {
60    // Resolve any recursive dependencies and set up deferred calls:
61    pub fn init(&'static self) {
62        kernel::deferred_call::DeferredCallClient::register(self.uart0);
63    }
64}
65
66impl InterruptService for LiteXSimInterruptablePeripherals {
67    unsafe fn service_interrupt(&self, interrupt: u32) -> bool {
68        match interrupt as usize {
69            socc::UART_INTERRUPT => {
70                self.uart0.service_interrupt();
71                true
72            }
73            socc::TIMER0_INTERRUPT => {
74                self.timer0.service_interrupt();
75                true
76            }
77            socc::ETHMAC_INTERRUPT => {
78                self.ethmac0.service_interrupt();
79                true
80            }
81            socc::GPIO_INTERRUPT => {
82                self.gpio0.service_interrupt();
83                true
84            }
85            _ => false,
86        }
87    }
88}
89
90const NUM_PROCS: usize = 4;
91
92// Actual memory for holding the active process structures. Need an
93// empty list at least.
94static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
95    [None; NUM_PROCS];
96
97// Reference to the chip and UART hardware for panic dumps
98struct LiteXSimPanicReferences {
99    chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
100    uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
101    process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
102}
103static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
104    chip: None,
105    uart: None,
106    process_printer: None,
107};
108
109// How should the kernel respond when a process faults.
110const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
111    capsules_system::process_policies::PanicFaultPolicy {};
112
113/// Dummy buffer that causes the linker to reserve enough space for the stack.
114#[no_mangle]
115#[link_section = ".stack_buffer"]
116pub static mut STACK_MEMORY: [u8; 0x2000] = [0; 0x2000];
117
118/// A structure representing this platform that holds references to all
119/// capsules for this platform.
120struct LiteXSim {
121    gpio_driver: &'static capsules_core::gpio::GPIO<
122        'static,
123        litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
124    >,
125    button_driver: &'static capsules_core::button::Button<
126        'static,
127        litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
128    >,
129    led_driver: &'static capsules_core::led::LedDriver<
130        'static,
131        LedHigh<
132            'static,
133            litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
134        >,
135        8,
136    >,
137    console: &'static capsules_core::console::Console<'static>,
138    lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
139        'static,
140        capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
141    >,
142    alarm: &'static capsules_core::alarm::AlarmDriver<
143        'static,
144        VirtualMuxAlarm<
145            'static,
146            litex_vexriscv::timer::LiteXAlarm<
147                'static,
148                'static,
149                socc::SoCRegisterFmt,
150                socc::ClockFrequency,
151            >,
152        >,
153    >,
154    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
155    scheduler: &'static MLFQSched<
156        'static,
157        VirtualMuxAlarm<
158            'static,
159            litex_vexriscv::timer::LiteXAlarm<
160                'static,
161                'static,
162                socc::SoCRegisterFmt,
163                socc::ClockFrequency,
164            >,
165        >,
166    >,
167    scheduler_timer: &'static VirtualSchedulerTimer<
168        VirtualMuxAlarm<
169            'static,
170            litex_vexriscv::timer::LiteXAlarm<
171                'static,
172                'static,
173                socc::SoCRegisterFmt,
174                socc::ClockFrequency,
175            >,
176        >,
177    >,
178}
179
180/// Mapping of integer syscalls to objects that implement syscalls.
181impl SyscallDriverLookup for LiteXSim {
182    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
183    where
184        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
185    {
186        match driver_num {
187            capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
188            capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
189            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
190            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
191            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
192            capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
193            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
194            _ => f(None),
195        }
196    }
197}
198
199impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
200    for LiteXSim
201{
202    type SyscallDriverLookup = Self;
203    type SyscallFilter = ();
204    type ProcessFault = ();
205    type Scheduler = MLFQSched<
206        'static,
207        VirtualMuxAlarm<
208            'static,
209            litex_vexriscv::timer::LiteXAlarm<
210                'static,
211                'static,
212                socc::SoCRegisterFmt,
213                socc::ClockFrequency,
214            >,
215        >,
216    >;
217    type SchedulerTimer = VirtualSchedulerTimer<
218        VirtualMuxAlarm<
219            'static,
220            litex_vexriscv::timer::LiteXAlarm<
221                'static,
222                'static,
223                socc::SoCRegisterFmt,
224                socc::ClockFrequency,
225            >,
226        >,
227    >;
228    type WatchDog = ();
229    type ContextSwitchCallback = ();
230
231    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
232        self
233    }
234    fn syscall_filter(&self) -> &Self::SyscallFilter {
235        &()
236    }
237    fn process_fault(&self) -> &Self::ProcessFault {
238        &()
239    }
240    fn scheduler(&self) -> &Self::Scheduler {
241        self.scheduler
242    }
243    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
244        self.scheduler_timer
245    }
246    fn watchdog(&self) -> &Self::WatchDog {
247        &()
248    }
249    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
250        &()
251    }
252}
253
254/// This is in a separate, inline(never) function so that its stack frame is
255/// removed when this function returns. Otherwise, the stack space used for
256/// these static_inits is wasted.
257#[inline(never)]
258unsafe fn start() -> (
259    &'static kernel::Kernel,
260    LiteXSim,
261    &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
262) {
263    // These symbols are defined in the linker script.
264    extern "C" {
265        /// Beginning of the ROM region containing app images.
266        static _sapps: u8;
267        /// End of the ROM region containing app images.
268        static _eapps: u8;
269        /// Beginning of the RAM region for app memory.
270        static mut _sappmem: u8;
271        /// End of the RAM region for app memory.
272        static _eappmem: u8;
273        /// The start of the kernel text (Included only for kernel PMP)
274        static _stext: u8;
275        /// The end of the kernel text (Included only for kernel PMP)
276        static _etext: u8;
277        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
278        static _sflash: u8;
279        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
280        static _eflash: u8;
281        /// The start of the kernel / app RAM (Included only for kernel PMP)
282        static _ssram: u8;
283        /// The end of the kernel / app RAM (Included only for kernel PMP)
284        static _esram: u8;
285    }
286
287    // ---------- BASIC INITIALIZATION ----------
288
289    // Basic setup of the riscv platform.
290    rv32i::configure_trap_handler();
291
292    // Set up memory protection immediately after setting the trap handler, to
293    // ensure that much of the board initialization routine runs with PMP kernel
294    // memory protection.
295    let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
296        rv32i::pmp::kernel_protection::FlashRegion(
297            rv32i::pmp::NAPOTRegionSpec::from_start_end(
298                core::ptr::addr_of!(_sflash),
299                core::ptr::addr_of!(_eflash),
300            )
301            .unwrap(),
302        ),
303        rv32i::pmp::kernel_protection::RAMRegion(
304            rv32i::pmp::NAPOTRegionSpec::from_start_end(
305                core::ptr::addr_of!(_ssram),
306                core::ptr::addr_of!(_esram),
307            )
308            .unwrap(),
309        ),
310        rv32i::pmp::kernel_protection::MMIORegion(
311            rv32i::pmp::NAPOTRegionSpec::from_start_size(
312                0xf0000000 as *const u8, // start
313                0x10000000,              // size
314            )
315            .unwrap(),
316        ),
317        rv32i::pmp::kernel_protection::KernelTextRegion(
318            rv32i::pmp::TORRegionSpec::from_start_end(
319                core::ptr::addr_of!(_stext),
320                core::ptr::addr_of!(_etext),
321            )
322            .unwrap(),
323        ),
324    )
325    .unwrap();
326
327    // initialize capabilities
328    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
329    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
330
331    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
332
333    // --------- TIMER & UPTIME CORE; ALARM INITIALIZATION ----------
334
335    // Initialize the hardware timer
336    let timer0 = static_init!(
337        litex_vexriscv::timer::LiteXTimer<'static, socc::SoCRegisterFmt, socc::ClockFrequency>,
338        litex_vexriscv::timer::LiteXTimer::new(StaticRef::new(
339            socc::CSR_TIMER0_BASE
340                as *const litex_vexriscv::timer::LiteXTimerRegisters<socc::SoCRegisterFmt>
341        ),)
342    );
343
344    // The SoC is expected to feature the 64-bit uptime extension to the timer hardware
345    let timer0_uptime = static_init!(
346        litex_vexriscv::timer::LiteXTimerUptime<
347            'static,
348            socc::SoCRegisterFmt,
349            socc::ClockFrequency,
350        >,
351        litex_vexriscv::timer::LiteXTimerUptime::new(timer0)
352    );
353
354    // Create the LiteXAlarm based on the hardware LiteXTimer core and
355    // the uptime peripheral
356    let litex_alarm = static_init!(
357        litex_vexriscv::timer::LiteXAlarm<
358            'static,
359            'static,
360            socc::SoCRegisterFmt,
361            socc::ClockFrequency,
362        >,
363        litex_vexriscv::timer::LiteXAlarm::new(timer0_uptime, timer0)
364    );
365    timer0.set_timer_client(litex_alarm);
366    litex_alarm.initialize();
367
368    // Create a shared virtualization mux layer on top of a single hardware
369    // alarm.
370    let mux_alarm = static_init!(
371        MuxAlarm<
372            'static,
373            litex_vexriscv::timer::LiteXAlarm<
374                'static,
375                'static,
376                socc::SoCRegisterFmt,
377                socc::ClockFrequency,
378            >,
379        >,
380        MuxAlarm::new(litex_alarm)
381    );
382    litex_alarm.set_alarm_client(mux_alarm);
383
384    // Userspace alarm driver
385    let virtual_alarm_user = static_init!(
386        VirtualMuxAlarm<
387            'static,
388            litex_vexriscv::timer::LiteXAlarm<
389                'static,
390                'static,
391                socc::SoCRegisterFmt,
392                socc::ClockFrequency,
393            >,
394        >,
395        VirtualMuxAlarm::new(mux_alarm)
396    );
397    virtual_alarm_user.setup();
398
399    let alarm = static_init!(
400        capsules_core::alarm::AlarmDriver<
401            'static,
402            VirtualMuxAlarm<
403                'static,
404                litex_vexriscv::timer::LiteXAlarm<
405                    'static,
406                    'static,
407                    socc::SoCRegisterFmt,
408                    socc::ClockFrequency,
409                >,
410            >,
411        >,
412        capsules_core::alarm::AlarmDriver::new(
413            virtual_alarm_user,
414            board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
415        )
416    );
417    virtual_alarm_user.set_alarm_client(alarm);
418
419    // Systick virtual alarm for scheduling
420    let systick_virtual_alarm = static_init!(
421        VirtualMuxAlarm<
422            'static,
423            litex_vexriscv::timer::LiteXAlarm<
424                'static,
425                'static,
426                socc::SoCRegisterFmt,
427                socc::ClockFrequency,
428            >,
429        >,
430        VirtualMuxAlarm::new(mux_alarm)
431    );
432    systick_virtual_alarm.setup();
433
434    let scheduler_timer = static_init!(
435        VirtualSchedulerTimer<
436            VirtualMuxAlarm<
437                'static,
438                litex_vexriscv::timer::LiteXAlarm<
439                    'static,
440                    'static,
441                    socc::SoCRegisterFmt,
442                    socc::ClockFrequency,
443                >,
444            >,
445        >,
446        VirtualSchedulerTimer::new(systick_virtual_alarm)
447    );
448
449    // ---------- UART ----------
450
451    // Initialize the HW UART
452    let uart0 = static_init!(
453        litex_vexriscv::uart::LiteXUart<socc::SoCRegisterFmt>,
454        litex_vexriscv::uart::LiteXUart::new(
455            StaticRef::new(
456                socc::CSR_UART_BASE
457                    as *const litex_vexriscv::uart::LiteXUartRegisters<socc::SoCRegisterFmt>,
458            ),
459            None, // LiteX simulator has no UART phy
460        )
461    );
462    uart0.initialize();
463
464    PANIC_REFERENCES.uart = Some(uart0);
465
466    // Create a shared UART channel for the console and for kernel debug.
467    //
468    // The baudrate is ingnored, as no UART phy is present in the
469    // verilated simulation.
470    let uart_mux = components::console::UartMuxComponent::new(uart0, 115200)
471        .finalize(components::uart_mux_component_static!());
472
473    // ---------- ETHERNET ----------
474
475    // ETHMAC peripheral
476    let ethmac0 = static_init!(
477        litex_vexriscv::liteeth::LiteEth<{socc::ETHMAC_TX_SLOTS}, socc::SoCRegisterFmt>,
478        litex_vexriscv::liteeth::LiteEth::new(
479            StaticRef::new(
480                socc::CSR_ETHMAC_BASE
481                    as *const litex_vexriscv::liteeth::LiteEthMacRegisters<socc::SoCRegisterFmt>,
482            ),
483            socc::MEM_ETHMAC_BASE,
484            socc::MEM_ETHMAC_SIZE,
485            socc::ETHMAC_SLOT_SIZE,
486            socc::ETHMAC_RX_SLOTS,
487            socc::ETHMAC_TX_SLOTS,
488        )
489    );
490
491    // Initialize the ETHMAC controller
492    ethmac0.initialize();
493
494    // --------- GPIO CONTROLLER ----------
495    type GPIOPin = litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>;
496
497    // GPIO hardware controller
498    let gpio0 = static_init!(
499        litex_vexriscv::gpio::LiteXGPIOController<'static, socc::SoCRegisterFmt>,
500        litex_vexriscv::gpio::LiteXGPIOController::new(
501            StaticRef::new(
502                socc::CSR_GPIO_BASE
503                    as *const litex_vexriscv::gpio::LiteXGPIORegisters<socc::SoCRegisterFmt>
504            ),
505            32, // 32 GPIOs in the simulation
506        ),
507    );
508    gpio0.initialize();
509
510    // --------- GPIO DRIVER ----------
511
512    let gpio_driver = components::gpio::GpioComponent::new(
513        board_kernel,
514        capsules_core::gpio::DRIVER_NUM,
515        components::gpio_component_helper_owned!(
516            GPIOPin,
517            16 => gpio0.get_gpio_pin(16).unwrap(),
518            17 => gpio0.get_gpio_pin(17).unwrap(),
519            18 => gpio0.get_gpio_pin(18).unwrap(),
520            19 => gpio0.get_gpio_pin(19).unwrap(),
521            20 => gpio0.get_gpio_pin(20).unwrap(),
522            21 => gpio0.get_gpio_pin(21).unwrap(),
523            22 => gpio0.get_gpio_pin(22).unwrap(),
524            23 => gpio0.get_gpio_pin(23).unwrap(),
525            24 => gpio0.get_gpio_pin(24).unwrap(),
526            25 => gpio0.get_gpio_pin(25).unwrap(),
527            26 => gpio0.get_gpio_pin(26).unwrap(),
528            27 => gpio0.get_gpio_pin(27).unwrap(),
529            28 => gpio0.get_gpio_pin(28).unwrap(),
530            29 => gpio0.get_gpio_pin(29).unwrap(),
531            30 => gpio0.get_gpio_pin(30).unwrap(),
532            31 => gpio0.get_gpio_pin(31).unwrap(),
533        ),
534    )
535    .finalize(components::gpio_component_static!(GPIOPin));
536
537    // ---------- LED DRIVER ----------
538
539    let led_gpios = static_init!(
540        [GPIOPin; 8],
541        [
542            gpio0.get_gpio_pin(0).unwrap(),
543            gpio0.get_gpio_pin(1).unwrap(),
544            gpio0.get_gpio_pin(2).unwrap(),
545            gpio0.get_gpio_pin(3).unwrap(),
546            gpio0.get_gpio_pin(4).unwrap(),
547            gpio0.get_gpio_pin(5).unwrap(),
548            gpio0.get_gpio_pin(6).unwrap(),
549            gpio0.get_gpio_pin(7).unwrap(),
550        ]
551    );
552
553    let led_driver =
554        components::led::LedsComponent::new().finalize(components::led_component_static!(
555            kernel::hil::led::LedHigh<GPIOPin>,
556            LedHigh::new(&led_gpios[0]),
557            LedHigh::new(&led_gpios[1]),
558            LedHigh::new(&led_gpios[2]),
559            LedHigh::new(&led_gpios[3]),
560            LedHigh::new(&led_gpios[4]),
561            LedHigh::new(&led_gpios[5]),
562            LedHigh::new(&led_gpios[6]),
563            LedHigh::new(&led_gpios[7]),
564        ));
565
566    // ---------- BUTTON ----------
567
568    let button_driver = components::button::ButtonComponent::new(
569        board_kernel,
570        capsules_core::button::DRIVER_NUM,
571        components::button_component_helper_owned!(
572            GPIOPin,
573            (
574                gpio0.get_gpio_pin(8).unwrap(),
575                kernel::hil::gpio::ActivationMode::ActiveHigh,
576                kernel::hil::gpio::FloatingState::PullNone
577            ),
578            (
579                gpio0.get_gpio_pin(9).unwrap(),
580                kernel::hil::gpio::ActivationMode::ActiveHigh,
581                kernel::hil::gpio::FloatingState::PullNone
582            ),
583            (
584                gpio0.get_gpio_pin(10).unwrap(),
585                kernel::hil::gpio::ActivationMode::ActiveHigh,
586                kernel::hil::gpio::FloatingState::PullNone
587            ),
588            (
589                gpio0.get_gpio_pin(11).unwrap(),
590                kernel::hil::gpio::ActivationMode::ActiveHigh,
591                kernel::hil::gpio::FloatingState::PullNone
592            ),
593            (
594                gpio0.get_gpio_pin(12).unwrap(),
595                kernel::hil::gpio::ActivationMode::ActiveHigh,
596                kernel::hil::gpio::FloatingState::PullNone
597            ),
598            (
599                gpio0.get_gpio_pin(13).unwrap(),
600                kernel::hil::gpio::ActivationMode::ActiveHigh,
601                kernel::hil::gpio::FloatingState::PullNone
602            ),
603            (
604                gpio0.get_gpio_pin(14).unwrap(),
605                kernel::hil::gpio::ActivationMode::ActiveHigh,
606                kernel::hil::gpio::FloatingState::PullNone
607            ),
608            (
609                gpio0.get_gpio_pin(15).unwrap(),
610                kernel::hil::gpio::ActivationMode::ActiveHigh,
611                kernel::hil::gpio::FloatingState::PullNone
612            ),
613        ),
614    )
615    .finalize(components::button_component_static!(GPIOPin));
616
617    // ---------- INITIALIZE CHIP, ENABLE INTERRUPTS ----------
618
619    let interrupt_service = static_init!(
620        LiteXSimInterruptablePeripherals,
621        LiteXSimInterruptablePeripherals {
622            gpio0,
623            uart0,
624            timer0,
625            ethmac0,
626        }
627    );
628    interrupt_service.init();
629
630    let chip = static_init!(
631        litex_vexriscv::chip::LiteXVexRiscv<
632            LiteXSimInterruptablePeripherals,
633        >,
634        litex_vexriscv::chip::LiteXVexRiscv::new(
635            "Verilated LiteX on VexRiscv",
636            interrupt_service,
637            pmp,
638        )
639    );
640
641    PANIC_REFERENCES.chip = Some(chip);
642
643    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
644        .finalize(components::process_printer_text_component_static!());
645
646    PANIC_REFERENCES.process_printer = Some(process_printer);
647
648    // Enable RISC-V interrupts globally
649    csr::CSR
650        .mie
651        .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET);
652    csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
653
654    // Unmask all interrupt sources in the interrupt controller
655    chip.unmask_interrupts();
656
657    // Setup the console.
658    let console = components::console::ConsoleComponent::new(
659        board_kernel,
660        capsules_core::console::DRIVER_NUM,
661        uart_mux,
662    )
663    .finalize(components::console_component_static!());
664    // Create the debugger object that handles calls to `debug!()`.
665    components::debug_writer::DebugWriterComponent::new(
666        uart_mux,
667        create_capability!(capabilities::SetDebugWriterCapability),
668    )
669    .finalize(components::debug_writer_component_static!());
670
671    let lldb = components::lldb::LowLevelDebugComponent::new(
672        board_kernel,
673        capsules_core::low_level_debug::DRIVER_NUM,
674        uart_mux,
675    )
676    .finalize(components::low_level_debug_component_static!());
677
678    let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, &*addr_of!(PROCESSES))
679        .finalize(components::mlfq_component_static!(
680            litex_vexriscv::timer::LiteXAlarm<
681                'static,
682                'static,
683                socc::SoCRegisterFmt,
684                socc::ClockFrequency,
685            >,
686            NUM_PROCS
687        ));
688
689    let litex_sim = LiteXSim {
690        gpio_driver,
691        button_driver,
692        led_driver,
693        console,
694        alarm,
695        lldb,
696        ipc: kernel::ipc::IPC::new(
697            board_kernel,
698            kernel::ipc::DRIVER_NUM,
699            &memory_allocation_cap,
700        ),
701        scheduler,
702        scheduler_timer,
703    };
704
705    debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
706
707    kernel::process::load_processes(
708        board_kernel,
709        chip,
710        core::slice::from_raw_parts(
711            core::ptr::addr_of!(_sapps),
712            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
713        ),
714        core::slice::from_raw_parts_mut(
715            core::ptr::addr_of_mut!(_sappmem),
716            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
717        ),
718        &mut *addr_of_mut!(PROCESSES),
719        &FAULT_RESPONSE,
720        &process_mgmt_cap,
721    )
722    .unwrap_or_else(|err| {
723        debug!("Error loading processes!");
724        debug!("{:?}", err);
725    });
726
727    (board_kernel, litex_sim, chip)
728}
729
730/// Main function called after RAM initialized.
731#[no_mangle]
732pub unsafe fn main() {
733    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
734
735    let (board_kernel, board, chip) = start();
736    board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
737}