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