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