1#![no_std]
12#![no_main]
13
14use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
15use e310_g002::interrupt_service::E310G002DefaultPeripherals;
16use kernel::capabilities;
17use kernel::component::Component;
18use kernel::hil;
19use kernel::hil::led::LedLow;
20use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
21use kernel::platform::{KernelResources, SyscallDriverLookup};
22use kernel::process::ProcessArray;
23use kernel::scheduler::cooperative::CooperativeSched;
24use kernel::utilities::registers::interfaces::ReadWriteable;
25use kernel::Kernel;
26use kernel::{create_capability, debug, static_init};
27use rv32i::csr;
28
29pub mod io;
30
31pub const NUM_PROCS: usize = 4;
32
33type ChipHw = e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>;
34
35static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
37static mut CHIP: Option<&'static e310_g002::chip::E310x<E310G002DefaultPeripherals>> = None;
39static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
41    None;
42
43const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
45    capsules_system::process_policies::PanicFaultPolicy {};
46
47kernel::stack_size! {0x900}
48
49struct HiFive1 {
52    led: &'static capsules_core::led::LedDriver<
53        'static,
54        LedLow<'static, sifive::gpio::GpioPin<'static>>,
55        3,
56    >,
57    console: &'static capsules_core::console::Console<'static>,
58    lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
59        'static,
60        capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
61    >,
62    alarm: &'static capsules_core::alarm::AlarmDriver<
63        'static,
64        VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
65    >,
66    scheduler: &'static CooperativeSched<'static>,
67    scheduler_timer: &'static VirtualSchedulerTimer<
68        VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
69    >,
70}
71
72impl SyscallDriverLookup for HiFive1 {
74    fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
75    where
76        F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
77    {
78        match driver_num {
79            capsules_core::led::DRIVER_NUM => f(Some(self.led)),
80            capsules_core::console::DRIVER_NUM => f(Some(self.console)),
81            capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
82            capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
83            _ => f(None),
84        }
85    }
86}
87
88impl KernelResources<e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>>
89    for HiFive1
90{
91    type SyscallDriverLookup = Self;
92    type SyscallFilter = ();
93    type ProcessFault = ();
94    type Scheduler = CooperativeSched<'static>;
95    type SchedulerTimer =
96        VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>;
97    type WatchDog = ();
98    type ContextSwitchCallback = ();
99
100    fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
101        self
102    }
103    fn syscall_filter(&self) -> &Self::SyscallFilter {
104        &()
105    }
106    fn process_fault(&self) -> &Self::ProcessFault {
107        &()
108    }
109    fn scheduler(&self) -> &Self::Scheduler {
110        self.scheduler
111    }
112    fn scheduler_timer(&self) -> &Self::SchedulerTimer {
113        self.scheduler_timer
114    }
115    fn watchdog(&self) -> &Self::WatchDog {
116        &()
117    }
118    fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
119        &()
120    }
121}
122
123#[inline(never)]
127fn load_processes_not_inlined<C: kernel::platform::chip::Chip>(
128    board_kernel: &'static Kernel,
129    chip: &'static C,
130) {
131    extern "C" {
133        static _sapps: u8;
135        static _eapps: u8;
137        static mut _sappmem: u8;
139        static _eappmem: u8;
141    }
142
143    let app_flash = unsafe {
144        core::slice::from_raw_parts(
145            core::ptr::addr_of!(_sapps),
146            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
147        )
148    };
149
150    let app_memory = unsafe {
151        core::slice::from_raw_parts_mut(
152            core::ptr::addr_of_mut!(_sappmem),
153            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
154        )
155    };
156
157    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
158    kernel::process::load_processes(
159        board_kernel,
160        chip,
161        app_flash,
162        app_memory,
163        &FAULT_RESPONSE,
164        &process_mgmt_cap,
165    )
166    .unwrap_or_else(|err| {
167        debug!("Error loading processes!");
168        debug!("{:?}", err);
169    });
170}
171
172#[inline(never)]
176unsafe fn start() -> (
177    &'static kernel::Kernel,
178    HiFive1,
179    &'static e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>,
180) {
181    rv32i::configure_trap_handler();
183
184    let peripherals = static_init!(
185        E310G002DefaultPeripherals,
186        E310G002DefaultPeripherals::new(344_000_000)
187    );
188
189    peripherals.init();
190
191    peripherals.e310x.watchdog.disable();
192    peripherals.e310x.rtc.disable();
193    peripherals.e310x.pwm0.disable();
194    peripherals.e310x.pwm1.disable();
195    peripherals.e310x.pwm2.disable();
196    peripherals.e310x.uart1.disable();
197
198    peripherals
199        .e310x
200        .prci
201        .set_clock_frequency(sifive::prci::ClockFrequency::Freq344Mhz);
202
203    let processes = components::process_array::ProcessArrayComponent::new()
205        .finalize(components::process_array_component_static!(NUM_PROCS));
206    PROCESSES = Some(processes);
207
208    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
210
211    kernel::debug::assign_gpios(
213        Some(&peripherals.e310x.gpio_port[22]), None,
215        None,
216    );
217
218    let uart_mux = components::console::UartMuxComponent::new(&peripherals.e310x.uart0, 115200)
220        .finalize(components::uart_mux_component_static!());
221
222    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
224        LedLow<'static, sifive::gpio::GpioPin>,
225        LedLow::new(&peripherals.e310x.gpio_port[22]), LedLow::new(&peripherals.e310x.gpio_port[19]), LedLow::new(&peripherals.e310x.gpio_port[21]), ));
229
230    peripherals.e310x.uart0.initialize_gpio_pins(
231        &peripherals.e310x.gpio_port[17],
232        &peripherals.e310x.gpio_port[16],
233    );
234
235    let hardware_timer = static_init!(
236        e310_g002::chip::E310xClint,
237        e310_g002::chip::E310xClint::new(&e310_g002::clint::CLINT_BASE)
238    );
239
240    let mux_alarm = static_init!(
243        MuxAlarm<'static, e310_g002::chip::E310xClint>,
244        MuxAlarm::new(hardware_timer)
245    );
246    hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
247
248    let virtual_alarm_user = static_init!(
250        VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
251        VirtualMuxAlarm::new(mux_alarm)
252    );
253    virtual_alarm_user.setup();
254
255    let systick_virtual_alarm = static_init!(
256        VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
257        VirtualMuxAlarm::new(mux_alarm)
258    );
259    systick_virtual_alarm.setup();
260
261    let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
262    let alarm = static_init!(
263        capsules_core::alarm::AlarmDriver<
264            'static,
265            VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
266        >,
267        capsules_core::alarm::AlarmDriver::new(
268            virtual_alarm_user,
269            board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
270        )
271    );
272    hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
273
274    let chip = static_init!(
275        e310_g002::chip::E310x<E310G002DefaultPeripherals>,
276        e310_g002::chip::E310x::new(peripherals, hardware_timer)
277    );
278    CHIP = Some(chip);
279
280    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
281        .finalize(components::process_printer_text_component_static!());
282    PROCESS_PRINTER = Some(process_printer);
283
284    let process_console = components::process_console::ProcessConsoleComponent::new(
285        board_kernel,
286        uart_mux,
287        mux_alarm,
288        process_printer,
289        None,
290    )
291    .finalize(components::process_console_component_static!(
292        e310_g002::chip::E310xClint
293    ));
294    let _ = process_console.start();
295
296    chip.enable_plic_interrupts();
298
299    csr::CSR
301        .mie
302        .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
303    csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
304
305    let console = components::console::ConsoleComponent::new(
307        board_kernel,
308        capsules_core::console::DRIVER_NUM,
309        uart_mux,
310    )
311    .finalize(components::console_component_static!());
312    const DEBUG_BUFFER_KB: usize = 1;
314    components::debug_writer::DebugWriterComponent::new::<
315        <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
316    >(
317        uart_mux,
318        create_capability!(capabilities::SetDebugWriterCapability),
319    )
320    .finalize(components::debug_writer_component_static!(DEBUG_BUFFER_KB));
321
322    let lldb = components::lldb::LowLevelDebugComponent::new(
323        board_kernel,
324        capsules_core::low_level_debug::DRIVER_NUM,
325        uart_mux,
326    )
327    .finalize(components::low_level_debug_component_static!());
328
329    debug!("HiFive1 initialization complete.");
333    debug!("Entering main loop.");
334
335    let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
336        .finalize(components::cooperative_component_static!(NUM_PROCS));
337
338    let scheduler_timer = static_init!(
339        VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>,
340        VirtualSchedulerTimer::new(systick_virtual_alarm)
341    );
342
343    let hifive1 = HiFive1 {
344        led,
345        console,
346        lldb,
347        alarm,
348        scheduler,
349        scheduler_timer,
350    };
351
352    load_processes_not_inlined(board_kernel, chip);
353
354    (board_kernel, hifive1, chip)
355}
356
357#[no_mangle]
359pub unsafe fn main() {
360    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
361
362    let (board_kernel, board, chip) = start();
363    board_kernel.kernel_loop(
364        &board,
365        chip,
366        None::<&kernel::ipc::IPC<0>>,
367        &main_loop_capability,
368    );
369}