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