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::debug::PanicResources;
19use kernel::hil;
20use kernel::hil::led::LedLow;
21use kernel::platform::{KernelResources, SyscallDriverLookup};
22use kernel::scheduler::cooperative::CooperativeSched;
23use kernel::utilities::registers::interfaces::ReadWriteable;
24use kernel::utilities::single_thread_value::SingleThreadValue;
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>>;
34type AlarmHw = e310_g002::chip::E310xClint<'static>;
35type SchedulerTimerHw =
36 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
37type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
38
39static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
41 SingleThreadValue::new(PanicResources::new());
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 SchedulerTimerHw,
68}
69
70impl SyscallDriverLookup for HiFive1 {
72 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
73 where
74 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
75 {
76 match driver_num {
77 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
78 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
79 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
80 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
81 _ => f(None),
82 }
83 }
84}
85
86impl KernelResources<e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>>
87 for HiFive1
88{
89 type SyscallDriverLookup = Self;
90 type SyscallFilter = ();
91 type ProcessFault = ();
92 type Scheduler = CooperativeSched<'static>;
93 type SchedulerTimer = SchedulerTimerHw;
94 type WatchDog = ();
95 type ContextSwitchCallback = ();
96
97 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
98 self
99 }
100 fn syscall_filter(&self) -> &Self::SyscallFilter {
101 &()
102 }
103 fn process_fault(&self) -> &Self::ProcessFault {
104 &()
105 }
106 fn scheduler(&self) -> &Self::Scheduler {
107 self.scheduler
108 }
109 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
110 self.scheduler_timer
111 }
112 fn watchdog(&self) -> &Self::WatchDog {
113 &()
114 }
115 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
116 &()
117 }
118}
119
120#[inline(never)]
124fn load_processes_not_inlined<C: kernel::platform::chip::Chip>(
125 board_kernel: &'static Kernel,
126 chip: &'static C,
127) {
128 extern "C" {
130 static _sapps: u8;
132 static _eapps: u8;
134 static mut _sappmem: u8;
136 static _eappmem: u8;
138 }
139
140 let app_flash = unsafe {
141 core::slice::from_raw_parts(
142 core::ptr::addr_of!(_sapps),
143 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
144 )
145 };
146
147 let app_memory = unsafe {
148 core::slice::from_raw_parts_mut(
149 core::ptr::addr_of_mut!(_sappmem),
150 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
151 )
152 };
153
154 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
155 kernel::process::load_processes(
156 board_kernel,
157 chip,
158 app_flash,
159 app_memory,
160 &FAULT_RESPONSE,
161 &process_mgmt_cap,
162 )
163 .unwrap_or_else(|err| {
164 debug!("Error loading processes!");
165 debug!("{:?}", err);
166 });
167}
168
169#[inline(never)]
173unsafe fn start() -> (
174 &'static kernel::Kernel,
175 HiFive1,
176 &'static e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>,
177) {
178 rv32i::configure_trap_handler();
180
181 kernel::deferred_call::initialize_deferred_call_state::<
183 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
184 >();
185
186 PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
188
189 let peripherals = static_init!(
190 E310G002DefaultPeripherals,
191 E310G002DefaultPeripherals::new(344_000_000)
192 );
193
194 peripherals.init();
195
196 peripherals.e310x.watchdog.disable();
197 peripherals.e310x.rtc.disable();
198 peripherals.e310x.pwm0.disable();
199 peripherals.e310x.pwm1.disable();
200 peripherals.e310x.pwm2.disable();
201 peripherals.e310x.uart1.disable();
202
203 peripherals
204 .e310x
205 .prci
206 .set_clock_frequency(sifive::prci::ClockFrequency::Freq344Mhz);
207
208 let processes = components::process_array::ProcessArrayComponent::new()
210 .finalize(components::process_array_component_static!(NUM_PROCS));
211 PANIC_RESOURCES.get().map(|resources| {
212 resources.processes.put(processes.as_slice());
213 });
214
215 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
217
218 let debug_gpios = static_init!(
220 [&'static dyn kernel::hil::gpio::Pin; 1],
221 [
222 &peripherals.e310x.gpio_port[22]
224 ]
225 );
226 kernel::debug::initialize_debug_gpio::<
227 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
228 >();
229 kernel::debug::assign_gpios(debug_gpios);
230
231 let uart_mux = components::console::UartMuxComponent::new(&peripherals.e310x.uart0, 115200)
233 .finalize(components::uart_mux_component_static!());
234
235 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
237 LedLow<'static, sifive::gpio::GpioPin>,
238 LedLow::new(&peripherals.e310x.gpio_port[22]), LedLow::new(&peripherals.e310x.gpio_port[19]), LedLow::new(&peripherals.e310x.gpio_port[21]), ));
242
243 peripherals.e310x.uart0.initialize_gpio_pins(
244 &peripherals.e310x.gpio_port[17],
245 &peripherals.e310x.gpio_port[16],
246 );
247
248 let hardware_timer = static_init!(
249 e310_g002::chip::E310xClint,
250 e310_g002::chip::E310xClint::new(&e310_g002::clint::CLINT_BASE)
251 );
252
253 let mux_alarm = static_init!(
256 MuxAlarm<'static, e310_g002::chip::E310xClint>,
257 MuxAlarm::new(hardware_timer)
258 );
259 hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
260
261 let virtual_alarm_user = static_init!(
263 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
264 VirtualMuxAlarm::new(mux_alarm)
265 );
266 virtual_alarm_user.setup();
267
268 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
269 let alarm = static_init!(
270 capsules_core::alarm::AlarmDriver<
271 'static,
272 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
273 >,
274 capsules_core::alarm::AlarmDriver::new(
275 virtual_alarm_user,
276 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
277 )
278 );
279 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
280
281 let chip = static_init!(
282 e310_g002::chip::E310x<E310G002DefaultPeripherals>,
283 e310_g002::chip::E310x::new(peripherals, hardware_timer)
284 );
285 PANIC_RESOURCES.get().map(|resources| {
286 resources.chip.put(chip);
287 });
288
289 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
290 .finalize(components::process_printer_text_component_static!());
291 PANIC_RESOURCES.get().map(|resources| {
292 resources.printer.put(process_printer);
293 });
294
295 let process_console = components::process_console::ProcessConsoleComponent::new(
296 board_kernel,
297 uart_mux,
298 mux_alarm,
299 process_printer,
300 None,
301 )
302 .finalize(components::process_console_component_static!(
303 e310_g002::chip::E310xClint
304 ));
305 let _ = process_console.start();
306
307 chip.enable_plic_interrupts();
309
310 csr::CSR
312 .mie
313 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
314 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
315
316 let console = components::console::ConsoleComponent::new(
318 board_kernel,
319 capsules_core::console::DRIVER_NUM,
320 uart_mux,
321 )
322 .finalize(components::console_component_static!());
323 const DEBUG_BUFFER_KB: usize = 1;
325 components::debug_writer::DebugWriterComponent::new::<
326 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
327 >(
328 uart_mux,
329 create_capability!(capabilities::SetDebugWriterCapability),
330 )
331 .finalize(components::debug_writer_component_static!(DEBUG_BUFFER_KB));
332
333 let lldb = components::lldb::LowLevelDebugComponent::new(
334 board_kernel,
335 capsules_core::low_level_debug::DRIVER_NUM,
336 uart_mux,
337 )
338 .finalize(components::low_level_debug_component_static!());
339
340 debug!("HiFive1 initialization complete.");
344 debug!("Entering main loop.");
345
346 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
347 .finalize(components::cooperative_component_static!(NUM_PROCS));
348
349 let scheduler_timer =
350 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
351 .finalize(components::virtual_scheduler_timer_component_static!(
352 AlarmHw
353 ));
354
355 let hifive1 = HiFive1 {
356 led,
357 console,
358 lldb,
359 alarm,
360 scheduler,
361 scheduler_timer,
362 };
363
364 load_processes_not_inlined(board_kernel, chip);
365
366 (board_kernel, hifive1, chip)
367}
368
369#[no_mangle]
371pub unsafe fn main() {
372 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
373
374 let (board_kernel, board, chip) = start();
375 board_kernel.kernel_loop(
376 &board,
377 chip,
378 None::<&kernel::ipc::IPC<0>>,
379 &main_loop_capability,
380 );
381}