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::debug::PanicResources;
17use kernel::hil;
18use kernel::platform::{KernelResources, SyscallDriverLookup};
19use kernel::scheduler::cooperative::CooperativeSched;
20use kernel::utilities::registers::interfaces::ReadWriteable;
21use kernel::utilities::single_thread_value::SingleThreadValue;
22use kernel::{create_capability, debug, static_init};
23use rv32i::csr;
24
25pub mod io;
26
27pub const NUM_PROCS: usize = 4;
28
29type ChipHw = e310_g003::chip::E310x<'static, E310G003DefaultPeripherals<'static>>;
30type AlarmHw = e310_g003::chip::E310xClint<'static>;
31type SchedulerTimerHw =
32 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
33type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
34
35static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
37 SingleThreadValue::new(PanicResources::new());
38
39const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
41 capsules_system::process_policies::PanicFaultPolicy {};
42
43kernel::stack_size! {0x1500}
44
45struct HiFiveInventor {
48 console: &'static capsules_core::console::Console<'static>,
49 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
50 'static,
51 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
52 >,
53 alarm: &'static capsules_core::alarm::AlarmDriver<
54 'static,
55 VirtualMuxAlarm<'static, e310_g003::chip::E310xClint<'static>>,
56 >,
57 scheduler: &'static CooperativeSched<'static>,
58 scheduler_timer: &'static SchedulerTimerHw,
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 = SchedulerTimerHw;
84 type WatchDog = ();
85 type ContextSwitchCallback = ();
86
87 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
88 self
89 }
90 fn syscall_filter(&self) -> &Self::SyscallFilter {
91 &()
92 }
93 fn process_fault(&self) -> &Self::ProcessFault {
94 &()
95 }
96 fn scheduler(&self) -> &Self::Scheduler {
97 self.scheduler
98 }
99 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
100 self.scheduler_timer
101 }
102 fn watchdog(&self) -> &Self::WatchDog {
103 &()
104 }
105 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
106 &()
107 }
108}
109
110#[inline(never)]
114unsafe fn start() -> (
115 &'static kernel::Kernel,
116 HiFiveInventor,
117 &'static e310_g003::chip::E310x<'static, E310G003DefaultPeripherals<'static>>,
118) {
119 rv32i::configure_trap_handler();
121
122 kernel::deferred_call::initialize_deferred_call_state::<
124 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
125 >();
126
127 PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
129
130 let peripherals = static_init!(
131 E310G003DefaultPeripherals,
132 E310G003DefaultPeripherals::new(16_000_000)
133 );
134
135 peripherals.init();
137
138 peripherals
139 .e310x
140 .prci
141 .set_clock_frequency(sifive::prci::ClockFrequency::Freq16Mhz);
142
143 peripherals.e310x.uart0.initialize_gpio_pins(
144 &peripherals.e310x.gpio_port[17],
145 &peripherals.e310x.gpio_port[16],
146 );
147 peripherals.e310x.uart1.initialize_gpio_pins(
148 &peripherals.e310x.gpio_port[18],
149 &peripherals.e310x.gpio_port[23],
150 );
151
152 peripherals.e310x.watchdog.disable();
153 peripherals.e310x.rtc.disable();
154 peripherals.e310x.pwm0.disable();
155 peripherals.e310x.pwm1.disable();
156 peripherals.e310x.pwm2.disable();
157 peripherals.e310x.uart1.disable();
158
159 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
161 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
162
163 let processes = components::process_array::ProcessArrayComponent::new()
165 .finalize(components::process_array_component_static!(NUM_PROCS));
166 PANIC_RESOURCES.get().map(|resources| {
167 resources.processes.put(processes.as_slice());
168 });
169
170 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
172
173 let uart_mux = components::console::UartMuxComponent::new(&peripherals.e310x.uart0, 115200)
175 .finalize(components::uart_mux_component_static!());
176
177 let hardware_timer = static_init!(
178 e310_g003::chip::E310xClint,
179 e310_g003::chip::E310xClint::new(&e310_g003::clint::CLINT_BASE)
180 );
181
182 let mux_alarm = static_init!(
185 MuxAlarm<'static, e310_g003::chip::E310xClint>,
186 MuxAlarm::new(hardware_timer)
187 );
188 hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
189
190 let virtual_alarm_user = static_init!(
192 VirtualMuxAlarm<'static, e310_g003::chip::E310xClint>,
193 VirtualMuxAlarm::new(mux_alarm)
194 );
195 virtual_alarm_user.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 PANIC_RESOURCES.get().map(|resources| {
214 resources.chip.put(chip);
215 });
216
217 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
218 .finalize(components::process_printer_text_component_static!());
219 PANIC_RESOURCES.get().map(|resources| {
220 resources.printer.put(process_printer);
221 });
222
223 let process_console = components::process_console::ProcessConsoleComponent::new(
224 board_kernel,
225 uart_mux,
226 mux_alarm,
227 process_printer,
228 None,
229 )
230 .finalize(components::process_console_component_static!(
231 e310_g003::chip::E310xClint
232 ));
233 let _ = process_console.start();
234
235 chip.enable_plic_interrupts();
237
238 csr::CSR
240 .mie
241 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
242 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
243
244 let console = components::console::ConsoleComponent::new(
246 board_kernel,
247 capsules_core::console::DRIVER_NUM,
248 uart_mux,
249 )
250 .finalize(components::console_component_static!());
251 components::debug_writer::DebugWriterComponent::new::<
253 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
254 >(
255 uart_mux,
256 create_capability!(capabilities::SetDebugWriterCapability),
257 )
258 .finalize(components::debug_writer_component_static!());
259
260 let lldb = components::lldb::LowLevelDebugComponent::new(
261 board_kernel,
262 capsules_core::low_level_debug::DRIVER_NUM,
263 uart_mux,
264 )
265 .finalize(components::low_level_debug_component_static!());
266
267 debug!("HiFive1 initialization complete. Entering main loop.");
268
269 extern "C" {
271 static _sapps: u8;
273 static _eapps: u8;
275 static mut _sappmem: u8;
277 static _eappmem: u8;
279 }
280
281 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
282 .finalize(components::cooperative_component_static!(NUM_PROCS));
283
284 let scheduler_timer =
285 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
286 .finalize(components::virtual_scheduler_timer_component_static!(
287 AlarmHw
288 ));
289
290 let hifive1 = HiFiveInventor {
291 console,
292 lldb,
293 alarm,
294 scheduler,
295 scheduler_timer,
296 };
297 kernel::process::load_processes(
298 board_kernel,
299 chip,
300 core::slice::from_raw_parts(
301 core::ptr::addr_of!(_sapps),
302 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
303 ),
304 core::slice::from_raw_parts_mut(
305 core::ptr::addr_of_mut!(_sappmem),
306 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
307 ),
308 &FAULT_RESPONSE,
309 &process_mgmt_cap,
310 )
311 .unwrap_or_else(|err| {
312 debug!("Error loading processes!");
313 debug!("{:?}", err);
314 });
315
316 (board_kernel, hifive1, chip)
317}
318
319#[no_mangle]
321pub unsafe fn main() {
322 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
323
324 let (board_kernel, board, chip) = start();
325 board_kernel.kernel_loop(
326 &board,
327 chip,
328 None::<&kernel::ipc::IPC<0>>,
329 &main_loop_capability,
330 );
331}