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