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
91type ChipHw = litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>;
92
93/// Static variables used by io.rs.
94static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
95
96// Reference to the chip and UART hardware for panic dumps
97struct LiteXSimPanicReferences {
98    chip: Option<&'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>,
99    uart: Option<&'static litex_vexriscv::uart::LiteXUart<'static, socc::SoCRegisterFmt>>,
100    process_printer: Option<&'static capsules_system::process_printer::ProcessPrinterText>,
101}
102static mut PANIC_REFERENCES: LiteXSimPanicReferences = LiteXSimPanicReferences {
103    chip: None,
104    uart: None,
105    process_printer: None,
106};
107
108// How should the kernel respond when a process faults.
109const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
110    capsules_system::process_policies::PanicFaultPolicy {};
111
112kernel::stack_size! {0x2000}
113
114/// A structure representing this platform that holds references to all
115/// capsules for this platform.
116struct LiteXSim {
117    gpio_driver: &'static capsules_core::gpio::GPIO<
118        'static,
119        litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
120    >,
121    button_driver: &'static capsules_core::button::Button<
122        'static,
123        litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
124    >,
125    led_driver: &'static capsules_core::led::LedDriver<
126        'static,
127        LedHigh<
128            'static,
129            litex_vexriscv::gpio::LiteXGPIOPin<'static, 'static, socc::SoCRegisterFmt>,
130        >,
131        8,
132    >,
133    console: &'static capsules_core::console::Console<'static>,
134    lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
135        'static,
136        capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
137    >,
138    alarm: &'static capsules_core::alarm::AlarmDriver<
139        'static,
140        VirtualMuxAlarm<
141            'static,
142            litex_vexriscv::timer::LiteXAlarm<
143                'static,
144                'static,
145                socc::SoCRegisterFmt,
146                socc::ClockFrequency,
147            >,
148        >,
149    >,
150    ipc: kernel::ipc::IPC<{ NUM_PROCS as u8 }>,
151    scheduler: &'static MLFQSched<
152        'static,
153        VirtualMuxAlarm<
154            'static,
155            litex_vexriscv::timer::LiteXAlarm<
156                'static,
157                'static,
158                socc::SoCRegisterFmt,
159                socc::ClockFrequency,
160            >,
161        >,
162    >,
163    scheduler_timer: &'static VirtualSchedulerTimer<
164        VirtualMuxAlarm<
165            'static,
166            litex_vexriscv::timer::LiteXAlarm<
167                'static,
168                'static,
169                socc::SoCRegisterFmt,
170                socc::ClockFrequency,
171            >,
172        >,
173    >,
174}
175
176/// Mapping of integer syscalls to objects that implement syscalls.
177impl SyscallDriverLookup for LiteXSim {
178    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
179    where
180        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
181    {
182        match driver_num {
183            capsules_core::button::DRIVER_NUM => f(Some(self.button_driver)),
184            capsules_core::led::DRIVER_NUM => f(Some(self.led_driver)),
185            capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio_driver)),
186            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
187            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
188            capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
189            kernel::ipc::DRIVER_NUM => f(Some(&self.ipc)),
190            _ => f(None),
191        }
192    }
193}
194
195impl KernelResources<litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>>
196    for LiteXSim
197{
198    type SyscallDriverLookup = Self;
199    type SyscallFilter = ();
200    type ProcessFault = ();
201    type Scheduler = MLFQSched<
202        'static,
203        VirtualMuxAlarm<
204            'static,
205            litex_vexriscv::timer::LiteXAlarm<
206                'static,
207                'static,
208                socc::SoCRegisterFmt,
209                socc::ClockFrequency,
210            >,
211        >,
212    >;
213    type SchedulerTimer = VirtualSchedulerTimer<
214        VirtualMuxAlarm<
215            'static,
216            litex_vexriscv::timer::LiteXAlarm<
217                'static,
218                'static,
219                socc::SoCRegisterFmt,
220                socc::ClockFrequency,
221            >,
222        >,
223    >;
224    type WatchDog = ();
225    type ContextSwitchCallback = ();
226
227    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
228        self
229    }
230    fn syscall_filter(&self) -> &Self::SyscallFilter {
231        &()
232    }
233    fn process_fault(&self) -> &Self::ProcessFault {
234        &()
235    }
236    fn scheduler(&self) -> &Self::Scheduler {
237        self.scheduler
238    }
239    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
240        self.scheduler_timer
241    }
242    fn watchdog(&self) -> &Self::WatchDog {
243        &()
244    }
245    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
246        &()
247    }
248}
249
250/// This is in a separate, inline(never) function so that its stack frame is
251/// removed when this function returns. Otherwise, the stack space used for
252/// these static_inits is wasted.
253#[inline(never)]
254unsafe fn start() -> (
255    &'static kernel::Kernel,
256    LiteXSim,
257    &'static litex_vexriscv::chip::LiteXVexRiscv<LiteXSimInterruptablePeripherals>,
258) {
259    // These symbols are defined in the linker script.
260    extern "C" {
261        /// Beginning of the ROM region containing app images.
262        static _sapps: u8;
263        /// End of the ROM region containing app images.
264        static _eapps: u8;
265        /// Beginning of the RAM region for app memory.
266        static mut _sappmem: u8;
267        /// End of the RAM region for app memory.
268        static _eappmem: u8;
269        /// The start of the kernel text (Included only for kernel PMP)
270        static _stext: u8;
271        /// The end of the kernel text (Included only for kernel PMP)
272        static _etext: u8;
273        /// The start of the kernel / app / storage flash (Included only for kernel PMP)
274        static _sflash: u8;
275        /// The end of the kernel / app / storage flash (Included only for kernel PMP)
276        static _eflash: u8;
277        /// The start of the kernel / app RAM (Included only for kernel PMP)
278        static _ssram: u8;
279        /// The end of the kernel / app RAM (Included only for kernel PMP)
280        static _esram: u8;
281    }
282
283    // ---------- BASIC INITIALIZATION ----------
284
285    // Basic setup of the riscv platform.
286    rv32i::configure_trap_handler();
287
288    // Set up memory protection immediately after setting the trap handler, to
289    // ensure that much of the board initialization routine runs with PMP kernel
290    // memory protection.
291    let pmp = rv32i::pmp::kernel_protection::KernelProtectionPMP::new(
292        rv32i::pmp::kernel_protection::FlashRegion(
293            rv32i::pmp::NAPOTRegionSpec::from_start_end(
294                core::ptr::addr_of!(_sflash),
295                core::ptr::addr_of!(_eflash),
296            )
297            .unwrap(),
298        ),
299        rv32i::pmp::kernel_protection::RAMRegion(
300            rv32i::pmp::NAPOTRegionSpec::from_start_end(
301                core::ptr::addr_of!(_ssram),
302                core::ptr::addr_of!(_esram),
303            )
304            .unwrap(),
305        ),
306        rv32i::pmp::kernel_protection::MMIORegion(
307            rv32i::pmp::NAPOTRegionSpec::from_start_size(
308                0xf0000000 as *const u8, // start
309                0x10000000,              // size
310            )
311            .unwrap(),
312        ),
313        rv32i::pmp::kernel_protection::KernelTextRegion(
314            rv32i::pmp::TORRegionSpec::from_start_end(
315                core::ptr::addr_of!(_stext),
316                core::ptr::addr_of!(_etext),
317            )
318            .unwrap(),
319        ),
320    )
321    .unwrap();
322
323    // initialize capabilities
324    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
325    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
326
327    // Create an array to hold process references.
328    let processes = components::process_array::ProcessArrayComponent::new()
329        .finalize(components::process_array_component_static!(NUM_PROCS));
330    PROCESSES = Some(processes);
331
332    // Setup space to store the core kernel data structure.
333    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
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_unsafe(
668        uart_mux,
669        create_capability!(capabilities::SetDebugWriterCapability),
670        || unsafe {
671            kernel::debug::initialize_debug_writer_wrapper_unsafe::<
672                <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
673            >();
674        },
675    )
676    .finalize(components::debug_writer_component_static!());
677
678    let lldb = components::lldb::LowLevelDebugComponent::new(
679        board_kernel,
680        capsules_core::low_level_debug::DRIVER_NUM,
681        uart_mux,
682    )
683    .finalize(components::low_level_debug_component_static!());
684
685    let scheduler = components::sched::mlfq::MLFQComponent::new(mux_alarm, processes).finalize(
686        components::mlfq_component_static!(
687            litex_vexriscv::timer::LiteXAlarm<
688                'static,
689                'static,
690                socc::SoCRegisterFmt,
691                socc::ClockFrequency,
692            >,
693            NUM_PROCS
694        ),
695    );
696
697    let litex_sim = LiteXSim {
698        gpio_driver,
699        button_driver,
700        led_driver,
701        console,
702        alarm,
703        lldb,
704        ipc: kernel::ipc::IPC::new(
705            board_kernel,
706            kernel::ipc::DRIVER_NUM,
707            &memory_allocation_cap,
708        ),
709        scheduler,
710        scheduler_timer,
711    };
712
713    debug!("Verilated LiteX+VexRiscv: initialization complete, entering main loop.");
714
715    kernel::process::load_processes(
716        board_kernel,
717        chip,
718        core::slice::from_raw_parts(
719            core::ptr::addr_of!(_sapps),
720            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
721        ),
722        core::slice::from_raw_parts_mut(
723            core::ptr::addr_of_mut!(_sappmem),
724            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
725        ),
726        &FAULT_RESPONSE,
727        &process_mgmt_cap,
728    )
729    .unwrap_or_else(|err| {
730        debug!("Error loading processes!");
731        debug!("{:?}", err);
732    });
733
734    (board_kernel, litex_sim, chip)
735}
736
737/// Main function called after RAM initialized.
738#[no_mangle]
739pub unsafe fn main() {
740    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
741
742    let (board_kernel, board, chip) = start();
743    board_kernel.kernel_loop(&board, chip, Some(&board.ipc), &main_loop_capability);
744}