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