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