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