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