1#![no_std]
12#![no_main]
13
14use core::ptr::addr_of;
15use core::ptr::addr_of_mut;
16
17use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
18use e310_g002::interrupt_service::E310G002DefaultPeripherals;
19use kernel::capabilities;
20use kernel::component::Component;
21use kernel::hil;
22use kernel::hil::led::LedLow;
23use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
24use kernel::platform::{KernelResources, SyscallDriverLookup};
25use kernel::process::ProcessArray;
26use kernel::scheduler::cooperative::CooperativeSched;
27use kernel::utilities::registers::interfaces::ReadWriteable;
28use kernel::{create_capability, debug, static_init};
29use rv32i::csr;
30
31pub mod io;
32
33pub const NUM_PROCS: usize = 4;
34
35static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
37
38static mut CHIP: Option<&'static e310_g002::chip::E310x<E310G002DefaultPeripherals>> = None;
40static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
42 None;
43
44const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
46 capsules_system::process_policies::PanicFaultPolicy {};
47
48kernel::stack_size! {0x900}
49
50struct RedV {
53 led: &'static capsules_core::led::LedDriver<
54 'static,
55 LedLow<'static, sifive::gpio::GpioPin<'static>>,
56 1,
57 >,
58 console: &'static capsules_core::console::Console<'static>,
59 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
60 'static,
61 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
62 >,
63 alarm: &'static capsules_core::alarm::AlarmDriver<
64 'static,
65 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
66 >,
67 scheduler: &'static CooperativeSched<'static>,
68 scheduler_timer: &'static VirtualSchedulerTimer<
69 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
70 >,
71}
72
73impl SyscallDriverLookup for RedV {
75 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
76 where
77 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
78 {
79 match driver_num {
80 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
81 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
82 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
83 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
84 _ => f(None),
85 }
86 }
87}
88
89impl KernelResources<e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>>
90 for RedV
91{
92 type SyscallDriverLookup = Self;
93 type SyscallFilter = ();
94 type ProcessFault = ();
95 type Scheduler = CooperativeSched<'static>;
96 type SchedulerTimer =
97 VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>;
98 type WatchDog = ();
99 type ContextSwitchCallback = ();
100
101 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
102 self
103 }
104 fn syscall_filter(&self) -> &Self::SyscallFilter {
105 &()
106 }
107 fn process_fault(&self) -> &Self::ProcessFault {
108 &()
109 }
110 fn scheduler(&self) -> &Self::Scheduler {
111 self.scheduler
112 }
113 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
114 self.scheduler_timer
115 }
116 fn watchdog(&self) -> &Self::WatchDog {
117 &()
118 }
119 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
120 &()
121 }
122}
123
124#[inline(never)]
128unsafe fn start() -> (
129 &'static kernel::Kernel,
130 RedV,
131 &'static e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>,
132) {
133 rv32i::configure_trap_handler();
135
136 let peripherals = static_init!(
137 E310G002DefaultPeripherals,
138 E310G002DefaultPeripherals::new(16_000_000)
139 );
140
141 peripherals.init();
143
144 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
146 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
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 peripherals
156 .e310x
157 .prci
158 .set_clock_frequency(sifive::prci::ClockFrequency::Freq16Mhz);
159
160 let processes = components::process_array::ProcessArrayComponent::new()
162 .finalize(components::process_array_component_static!(NUM_PROCS));
163 PROCESSES = Some(processes);
164
165 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
167
168 kernel::debug::assign_gpios(
170 Some(&peripherals.e310x.gpio_port[5]), None,
172 None,
173 );
174
175 let uart_mux = components::console::UartMuxComponent::new(&peripherals.e310x.uart0, 115200)
177 .finalize(components::uart_mux_component_static!());
178
179 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
181 LedLow<'static, sifive::gpio::GpioPin>,
182 LedLow::new(&peripherals.e310x.gpio_port[5]), ));
184
185 peripherals.e310x.uart0.initialize_gpio_pins(
186 &peripherals.e310x.gpio_port[17],
187 &peripherals.e310x.gpio_port[16],
188 );
189
190 let hardware_timer = static_init!(
191 e310_g002::chip::E310xClint,
192 e310_g002::chip::E310xClint::new(&e310_g002::clint::CLINT_BASE)
193 );
194
195 let mux_alarm = static_init!(
198 MuxAlarm<'static, e310_g002::chip::E310xClint>,
199 MuxAlarm::new(hardware_timer)
200 );
201 hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
202
203 let virtual_alarm_user = static_init!(
205 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
206 VirtualMuxAlarm::new(mux_alarm)
207 );
208 virtual_alarm_user.setup();
209
210 let systick_virtual_alarm = static_init!(
211 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
212 VirtualMuxAlarm::new(mux_alarm)
213 );
214 systick_virtual_alarm.setup();
215
216 let alarm = static_init!(
217 capsules_core::alarm::AlarmDriver<
218 'static,
219 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
220 >,
221 capsules_core::alarm::AlarmDriver::new(
222 virtual_alarm_user,
223 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
224 )
225 );
226 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
227
228 let chip = static_init!(
229 e310_g002::chip::E310x<E310G002DefaultPeripherals>,
230 e310_g002::chip::E310x::new(peripherals, hardware_timer)
231 );
232 CHIP = Some(chip);
233
234 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
235 .finalize(components::process_printer_text_component_static!());
236 PROCESS_PRINTER = Some(process_printer);
237
238 let process_console = components::process_console::ProcessConsoleComponent::new(
239 board_kernel,
240 uart_mux,
241 mux_alarm,
242 process_printer,
243 None,
244 )
245 .finalize(components::process_console_component_static!(
246 e310_g002::chip::E310xClint
247 ));
248 let _ = process_console.start();
249
250 chip.enable_plic_interrupts();
252
253 csr::CSR
255 .mie
256 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
257 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
258
259 let console = components::console::ConsoleComponent::new(
261 board_kernel,
262 capsules_core::console::DRIVER_NUM,
263 uart_mux,
264 )
265 .finalize(components::console_component_static!());
266 components::debug_writer::DebugWriterComponent::new(
268 uart_mux,
269 create_capability!(capabilities::SetDebugWriterCapability),
270 )
271 .finalize(components::debug_writer_component_static!());
272
273 let lldb = components::lldb::LowLevelDebugComponent::new(
274 board_kernel,
275 capsules_core::low_level_debug::DRIVER_NUM,
276 uart_mux,
277 )
278 .finalize(components::low_level_debug_component_static!());
279
280 debug!("Red-V initialization complete.");
284 debug!("Entering main loop.");
285
286 extern "C" {
288 static _sapps: u8;
290 static _eapps: u8;
292 static mut _sappmem: u8;
294 static _eappmem: u8;
296 }
297
298 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
299 .finalize(components::cooperative_component_static!(NUM_PROCS));
300
301 let scheduler_timer = static_init!(
302 VirtualSchedulerTimer<VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>>,
303 VirtualSchedulerTimer::new(systick_virtual_alarm)
304 );
305
306 let redv = RedV {
307 led,
308 console,
309 lldb,
310 alarm,
311 scheduler,
312 scheduler_timer,
313 };
314
315 kernel::process::load_processes(
316 board_kernel,
317 chip,
318 core::slice::from_raw_parts(
319 addr_of!(_sapps),
320 addr_of!(_eapps) as usize - addr_of!(_sapps) as usize,
321 ),
322 core::slice::from_raw_parts_mut(
323 addr_of_mut!(_sappmem),
324 addr_of!(_eappmem) as usize - addr_of!(_sappmem) as usize,
325 ),
326 &FAULT_RESPONSE,
327 &process_mgmt_cap,
328 )
329 .unwrap_or_else(|err| {
330 debug!("Error loading processes!");
331 debug!("{:?}", err);
332 });
333
334 (board_kernel, redv, chip)
335}
336
337#[no_mangle]
339pub unsafe fn main() {
340 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
341
342 let (board_kernel, platform, chip) = start();
343 board_kernel.kernel_loop(
344 &platform,
345 chip,
346 None::<&kernel::ipc::IPC<{ NUM_PROCS as u8 }>>,
347 &main_loop_capability,
348 );
349}