1#![no_std]
10#![cfg_attr(not(doc), no_main)]
13
14use core::ptr::{addr_of, addr_of_mut};
15
16use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
17use e310_g003::interrupt_service::E310G003DefaultPeripherals;
18use kernel::capabilities;
19use kernel::component::Component;
20use kernel::hil;
21use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
22use kernel::platform::{KernelResources, SyscallDriverLookup};
23use kernel::scheduler::cooperative::CooperativeSched;
24use kernel::utilities::registers::interfaces::ReadWriteable;
25use kernel::{create_capability, debug, static_init};
26use rv32i::csr;
27
28pub mod io;
29
30pub const NUM_PROCS: usize = 4;
31static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
35 [None; NUM_PROCS];
36
37static mut CHIP: Option<&'static e310_g003::chip::E310x<E310G003DefaultPeripherals>> = None;
39static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
41 None;
42
43const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
45 capsules_system::process_policies::PanicFaultPolicy {};
46
47#[no_mangle]
49#[link_section = ".stack_buffer"]
50pub static mut STACK_MEMORY: [u8; 0x1500] = [0; 0x1500];
51
52struct HiFiveInventor {
55 console: &'static capsules_core::console::Console<'static>,
56 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
57 'static,
58 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
59 >,
60 alarm: &'static capsules_core::alarm::AlarmDriver<
61 'static,
62 VirtualMuxAlarm<'static, e310_g003::chip::E310xClint<'static>>,
63 >,
64 scheduler: &'static CooperativeSched<'static>,
65 scheduler_timer: &'static VirtualSchedulerTimer<
66 VirtualMuxAlarm<'static, e310_g003::chip::E310xClint<'static>>,
67 >,
68}
69
70impl SyscallDriverLookup for HiFiveInventor {
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::console::DRIVER_NUM => f(Some(self.console)),
78 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
79 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
80 _ => f(None),
81 }
82 }
83}
84
85impl KernelResources<e310_g003::chip::E310x<'static, E310G003DefaultPeripherals<'static>>>
86 for HiFiveInventor
87{
88 type SyscallDriverLookup = Self;
89 type SyscallFilter = ();
90 type ProcessFault = ();
91 type Scheduler = CooperativeSched<'static>;
92 type SchedulerTimer =
93 VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g003::chip::E310xClint<'static>>>;
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)]
124unsafe fn start() -> (
125 &'static kernel::Kernel,
126 HiFiveInventor,
127 &'static e310_g003::chip::E310x<'static, E310G003DefaultPeripherals<'static>>,
128) {
129 rv32i::configure_trap_handler();
131
132 let peripherals = static_init!(
133 E310G003DefaultPeripherals,
134 E310G003DefaultPeripherals::new(16_000_000)
135 );
136
137 peripherals.init();
139
140 peripherals
141 .e310x
142 .prci
143 .set_clock_frequency(sifive::prci::ClockFrequency::Freq16Mhz);
144
145 peripherals.e310x.uart0.initialize_gpio_pins(
146 &peripherals.e310x.gpio_port[17],
147 &peripherals.e310x.gpio_port[16],
148 );
149 peripherals.e310x.uart1.initialize_gpio_pins(
150 &peripherals.e310x.gpio_port[18],
151 &peripherals.e310x.gpio_port[23],
152 );
153
154 peripherals.e310x.watchdog.disable();
155 peripherals.e310x.rtc.disable();
156 peripherals.e310x.pwm0.disable();
157 peripherals.e310x.pwm1.disable();
158 peripherals.e310x.pwm2.disable();
159 peripherals.e310x.uart1.disable();
160
161 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
163 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
164
165 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
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(uart_mux)
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 =
276 components::sched::cooperative::CooperativeComponent::new(&*addr_of!(PROCESSES))
277 .finalize(components::cooperative_component_static!(NUM_PROCS));
278
279 let scheduler_timer = static_init!(
280 VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g003::chip::E310xClint<'static>>>,
281 VirtualSchedulerTimer::new(systick_virtual_alarm)
282 );
283 let hifive1 = HiFiveInventor {
284 console,
285 lldb,
286 alarm,
287 scheduler,
288 scheduler_timer,
289 };
290 kernel::process::load_processes(
291 board_kernel,
292 chip,
293 core::slice::from_raw_parts(
294 core::ptr::addr_of!(_sapps),
295 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
296 ),
297 core::slice::from_raw_parts_mut(
298 core::ptr::addr_of_mut!(_sappmem),
299 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
300 ),
301 &mut *addr_of_mut!(PROCESSES),
302 &FAULT_RESPONSE,
303 &process_mgmt_cap,
304 )
305 .unwrap_or_else(|err| {
306 debug!("Error loading processes!");
307 debug!("{:?}", err);
308 });
309
310 (board_kernel, hifive1, chip)
311}
312
313#[no_mangle]
315pub unsafe fn main() {
316 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
317
318 let (board_kernel, board, chip) = start();
319 board_kernel.kernel_loop(
320 &board,
321 chip,
322 None::<&kernel::ipc::IPC<0>>,
323 &main_loop_capability,
324 );
325}