1#![no_std]
12#![cfg_attr(not(doc), no_main)]
15
16use core::ptr::{addr_of, addr_of_mut};
17
18use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
19use e310_g002::interrupt_service::E310G002DefaultPeripherals;
20use kernel::capabilities;
21use kernel::component::Component;
22use kernel::hil;
23use kernel::hil::led::LedLow;
24use kernel::platform::chip::Chip;
25use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
26use kernel::platform::{KernelResources, SyscallDriverLookup};
27use kernel::scheduler::cooperative::CooperativeSched;
28use kernel::utilities::registers::interfaces::ReadWriteable;
29use kernel::Kernel;
30use kernel::{create_capability, debug, static_init};
31use rv32i::csr;
32
33pub mod io;
34
35pub const NUM_PROCS: usize = 4;
36static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
40 [None; NUM_PROCS];
41
42static mut CHIP: Option<&'static e310_g002::chip::E310x<E310G002DefaultPeripherals>> = None;
44static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
46 None;
47
48const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
50 capsules_system::process_policies::PanicFaultPolicy {};
51
52#[no_mangle]
54#[link_section = ".stack_buffer"]
55pub static mut STACK_MEMORY: [u8; 0x900] = [0; 0x900];
56
57struct HiFive1 {
60 led: &'static capsules_core::led::LedDriver<
61 'static,
62 LedLow<'static, sifive::gpio::GpioPin<'static>>,
63 3,
64 >,
65 console: &'static capsules_core::console::Console<'static>,
66 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
67 'static,
68 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
69 >,
70 alarm: &'static capsules_core::alarm::AlarmDriver<
71 'static,
72 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
73 >,
74 scheduler: &'static CooperativeSched<'static>,
75 scheduler_timer: &'static VirtualSchedulerTimer<
76 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
77 >,
78}
79
80impl SyscallDriverLookup for HiFive1 {
82 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
83 where
84 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
85 {
86 match driver_num {
87 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
88 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
89 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
90 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
91 _ => f(None),
92 }
93 }
94}
95
96impl KernelResources<e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>>
97 for HiFive1
98{
99 type SyscallDriverLookup = Self;
100 type SyscallFilter = ();
101 type ProcessFault = ();
102 type Scheduler = CooperativeSched<'static>;
103 type SchedulerTimer =
104 VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>;
105 type WatchDog = ();
106 type ContextSwitchCallback = ();
107
108 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
109 self
110 }
111 fn syscall_filter(&self) -> &Self::SyscallFilter {
112 &()
113 }
114 fn process_fault(&self) -> &Self::ProcessFault {
115 &()
116 }
117 fn scheduler(&self) -> &Self::Scheduler {
118 self.scheduler
119 }
120 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
121 self.scheduler_timer
122 }
123 fn watchdog(&self) -> &Self::WatchDog {
124 &()
125 }
126 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
127 &()
128 }
129}
130
131#[inline(never)]
135fn load_processes_not_inlined<C: Chip>(board_kernel: &'static Kernel, chip: &'static C) {
136 extern "C" {
138 static _sapps: u8;
140 static _eapps: u8;
142 static mut _sappmem: u8;
144 static _eappmem: u8;
146 }
147
148 let app_flash = unsafe {
149 core::slice::from_raw_parts(
150 core::ptr::addr_of!(_sapps),
151 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
152 )
153 };
154
155 let app_memory = unsafe {
156 core::slice::from_raw_parts_mut(
157 core::ptr::addr_of_mut!(_sappmem),
158 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
159 )
160 };
161
162 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
163 kernel::process::load_processes(
164 board_kernel,
165 chip,
166 app_flash,
167 app_memory,
168 unsafe { &mut *addr_of_mut!(PROCESSES) },
169 &FAULT_RESPONSE,
170 &process_mgmt_cap,
171 )
172 .unwrap_or_else(|err| {
173 debug!("Error loading processes!");
174 debug!("{:?}", err);
175 });
176}
177
178#[inline(never)]
182unsafe fn start() -> (
183 &'static kernel::Kernel,
184 HiFive1,
185 &'static e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>,
186) {
187 rv32i::configure_trap_handler();
189
190 let peripherals = static_init!(
191 E310G002DefaultPeripherals,
192 E310G002DefaultPeripherals::new(344_000_000)
193 );
194
195 peripherals.init();
196
197 peripherals.e310x.watchdog.disable();
198 peripherals.e310x.rtc.disable();
199 peripherals.e310x.pwm0.disable();
200 peripherals.e310x.pwm1.disable();
201 peripherals.e310x.pwm2.disable();
202 peripherals.e310x.uart1.disable();
203
204 peripherals
205 .e310x
206 .prci
207 .set_clock_frequency(sifive::prci::ClockFrequency::Freq344Mhz);
208
209 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
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(uart_mux)
315 .finalize(components::debug_writer_component_static!(DEBUG_BUFFER_KB));
316
317 let lldb = components::lldb::LowLevelDebugComponent::new(
318 board_kernel,
319 capsules_core::low_level_debug::DRIVER_NUM,
320 uart_mux,
321 )
322 .finalize(components::low_level_debug_component_static!());
323
324 debug!("HiFive1 initialization complete.");
328 debug!("Entering main loop.");
329
330 let scheduler =
331 components::sched::cooperative::CooperativeComponent::new(&*addr_of!(PROCESSES))
332 .finalize(components::cooperative_component_static!(NUM_PROCS));
333
334 let scheduler_timer = static_init!(
335 VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>,
336 VirtualSchedulerTimer::new(systick_virtual_alarm)
337 );
338
339 let hifive1 = HiFive1 {
340 led,
341 console,
342 lldb,
343 alarm,
344 scheduler,
345 scheduler_timer,
346 };
347
348 load_processes_not_inlined(board_kernel, chip);
349
350 (board_kernel, hifive1, chip)
351}
352
353#[no_mangle]
355pub unsafe fn main() {
356 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
357
358 let (board_kernel, board, chip) = start();
359 board_kernel.kernel_loop(
360 &board,
361 chip,
362 None::<&kernel::ipc::IPC<0>>,
363 &main_loop_capability,
364 );
365}