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::debug::PanicResources;
22use kernel::hil;
23use kernel::hil::led::LedLow;
24use kernel::platform::{KernelResources, SyscallDriverLookup};
25use kernel::scheduler::cooperative::CooperativeSched;
26use kernel::utilities::registers::interfaces::ReadWriteable;
27use kernel::utilities::single_thread_value::SingleThreadValue;
28use kernel::{create_capability, debug, static_init};
29use rv32i::csr;
30
31pub mod io;
32
33pub const NUM_PROCS: usize = 4;
34
35type ChipHw = e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>;
36type AlarmHw = e310_g002::chip::E310xClint<'static>;
37type SchedulerTimerHw =
38 components::virtual_scheduler_timer::VirtualSchedulerTimerComponentType<AlarmHw>;
39type ProcessPrinterInUse = capsules_system::process_printer::ProcessPrinterText;
40
41static PANIC_RESOURCES: SingleThreadValue<PanicResources<ChipHw, ProcessPrinterInUse>> =
43 SingleThreadValue::new(PanicResources::new());
44
45const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
47 capsules_system::process_policies::PanicFaultPolicy {};
48
49kernel::stack_size! {0x900}
50
51struct RedV {
54 led: &'static capsules_core::led::LedDriver<
55 'static,
56 LedLow<'static, sifive::gpio::GpioPin<'static>>,
57 1,
58 >,
59 console: &'static capsules_core::console::Console<'static>,
60 lldb: &'static capsules_core::low_level_debug::LowLevelDebug<
61 'static,
62 capsules_core::virtualizers::virtual_uart::UartDevice<'static>,
63 >,
64 alarm: &'static capsules_core::alarm::AlarmDriver<
65 'static,
66 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint<'static>>,
67 >,
68 scheduler: &'static CooperativeSched<'static>,
69 scheduler_timer: &'static SchedulerTimerHw,
70}
71
72impl SyscallDriverLookup for RedV {
74 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
75 where
76 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
77 {
78 match driver_num {
79 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
80 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
81 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
82 capsules_core::low_level_debug::DRIVER_NUM => f(Some(self.lldb)),
83 _ => f(None),
84 }
85 }
86}
87
88impl KernelResources<e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>>
89 for RedV
90{
91 type SyscallDriverLookup = Self;
92 type SyscallFilter = ();
93 type ProcessFault = ();
94 type Scheduler = CooperativeSched<'static>;
95 type SchedulerTimer = SchedulerTimerHw;
96 type WatchDog = ();
97 type ContextSwitchCallback = ();
98
99 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
100 self
101 }
102 fn syscall_filter(&self) -> &Self::SyscallFilter {
103 &()
104 }
105 fn process_fault(&self) -> &Self::ProcessFault {
106 &()
107 }
108 fn scheduler(&self) -> &Self::Scheduler {
109 self.scheduler
110 }
111 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
112 self.scheduler_timer
113 }
114 fn watchdog(&self) -> &Self::WatchDog {
115 &()
116 }
117 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
118 &()
119 }
120}
121
122#[inline(never)]
126unsafe fn start() -> (
127 &'static kernel::Kernel,
128 RedV,
129 &'static e310_g002::chip::E310x<'static, E310G002DefaultPeripherals<'static>>,
130) {
131 rv32i::configure_trap_handler();
133
134 kernel::deferred_call::initialize_deferred_call_state::<
136 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
137 >();
138
139 PANIC_RESOURCES.bind_to_thread::<<ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider>();
141
142 let peripherals = static_init!(
143 E310G002DefaultPeripherals,
144 E310G002DefaultPeripherals::new(16_000_000)
145 );
146
147 peripherals.init();
149
150 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
152 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
153
154 peripherals.e310x.watchdog.disable();
155 peripherals.e310x.rtc.disable();
156 peripherals.e310x.pwm0.disable();
157 peripherals.e310x.pwm1.disable();
158 peripherals.e310x.pwm2.disable();
159 peripherals.e310x.uart1.disable();
160
161 peripherals
162 .e310x
163 .prci
164 .set_clock_frequency(sifive::prci::ClockFrequency::Freq16Mhz);
165
166 let processes = components::process_array::ProcessArrayComponent::new()
168 .finalize(components::process_array_component_static!(NUM_PROCS));
169 PANIC_RESOURCES.get().map(|resources| {
170 resources.processes.put(processes.as_slice());
171 });
172
173 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
175
176 let debug_gpios = static_init!(
178 [&'static dyn kernel::hil::gpio::Pin; 1],
179 [
180 &peripherals.e310x.gpio_port[5]
182 ]
183 );
184 kernel::debug::initialize_debug_gpio::<
185 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
186 >();
187 kernel::debug::assign_gpios(debug_gpios);
188
189 let uart_mux = components::console::UartMuxComponent::new(&peripherals.e310x.uart0, 115200)
191 .finalize(components::uart_mux_component_static!());
192
193 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
195 LedLow<'static, sifive::gpio::GpioPin>,
196 LedLow::new(&peripherals.e310x.gpio_port[5]), ));
198
199 peripherals.e310x.uart0.initialize_gpio_pins(
200 &peripherals.e310x.gpio_port[17],
201 &peripherals.e310x.gpio_port[16],
202 );
203
204 let hardware_timer = static_init!(
205 e310_g002::chip::E310xClint,
206 e310_g002::chip::E310xClint::new(&e310_g002::clint::CLINT_BASE)
207 );
208
209 let mux_alarm = static_init!(
212 MuxAlarm<'static, e310_g002::chip::E310xClint>,
213 MuxAlarm::new(hardware_timer)
214 );
215 hil::time::Alarm::set_alarm_client(hardware_timer, mux_alarm);
216
217 let virtual_alarm_user = static_init!(
219 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
220 VirtualMuxAlarm::new(mux_alarm)
221 );
222 virtual_alarm_user.setup();
223
224 let systick_virtual_alarm = static_init!(
225 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
226 VirtualMuxAlarm::new(mux_alarm)
227 );
228 systick_virtual_alarm.setup();
229
230 let alarm = static_init!(
231 capsules_core::alarm::AlarmDriver<
232 'static,
233 VirtualMuxAlarm<'static, e310_g002::chip::E310xClint>,
234 >,
235 capsules_core::alarm::AlarmDriver::new(
236 virtual_alarm_user,
237 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
238 )
239 );
240 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
241
242 let chip = static_init!(
243 e310_g002::chip::E310x<E310G002DefaultPeripherals>,
244 e310_g002::chip::E310x::new(peripherals, hardware_timer)
245 );
246 PANIC_RESOURCES.get().map(|resources| {
247 resources.chip.put(chip);
248 });
249
250 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
251 .finalize(components::process_printer_text_component_static!());
252 PANIC_RESOURCES.get().map(|resources| {
253 resources.printer.put(process_printer);
254 });
255
256 let process_console = components::process_console::ProcessConsoleComponent::new(
257 board_kernel,
258 uart_mux,
259 mux_alarm,
260 process_printer,
261 None,
262 )
263 .finalize(components::process_console_component_static!(
264 e310_g002::chip::E310xClint
265 ));
266 let _ = process_console.start();
267
268 chip.enable_plic_interrupts();
270
271 csr::CSR
273 .mie
274 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
275 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
276
277 let console = components::console::ConsoleComponent::new(
279 board_kernel,
280 capsules_core::console::DRIVER_NUM,
281 uart_mux,
282 )
283 .finalize(components::console_component_static!());
284 components::debug_writer::DebugWriterComponent::new::<
286 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
287 >(
288 uart_mux,
289 create_capability!(capabilities::SetDebugWriterCapability),
290 )
291 .finalize(components::debug_writer_component_static!());
292
293 let lldb = components::lldb::LowLevelDebugComponent::new(
294 board_kernel,
295 capsules_core::low_level_debug::DRIVER_NUM,
296 uart_mux,
297 )
298 .finalize(components::low_level_debug_component_static!());
299
300 debug!("Red-V initialization complete.");
304 debug!("Entering main loop.");
305
306 extern "C" {
308 static _sapps: u8;
310 static _eapps: u8;
312 static mut _sappmem: u8;
314 static _eappmem: u8;
316 }
317
318 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
319 .finalize(components::cooperative_component_static!(NUM_PROCS));
320
321 let scheduler_timer =
322 components::virtual_scheduler_timer::VirtualSchedulerTimerComponent::new(mux_alarm)
323 .finalize(components::virtual_scheduler_timer_component_static!(
324 AlarmHw
325 ));
326
327 let redv = RedV {
328 led,
329 console,
330 lldb,
331 alarm,
332 scheduler,
333 scheduler_timer,
334 };
335
336 kernel::process::load_processes(
337 board_kernel,
338 chip,
339 core::slice::from_raw_parts(
340 addr_of!(_sapps),
341 addr_of!(_eapps) as usize - addr_of!(_sapps) as usize,
342 ),
343 core::slice::from_raw_parts_mut(
344 addr_of_mut!(_sappmem),
345 addr_of!(_eappmem) as usize - addr_of!(_sappmem) as usize,
346 ),
347 &FAULT_RESPONSE,
348 &process_mgmt_cap,
349 )
350 .unwrap_or_else(|err| {
351 debug!("Error loading processes!");
352 debug!("{:?}", err);
353 });
354
355 (board_kernel, redv, chip)
356}
357
358#[no_mangle]
360pub unsafe fn main() {
361 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
362
363 let (board_kernel, platform, chip) = start();
364 board_kernel.kernel_loop(
365 &platform,
366 chip,
367 None::<&kernel::ipc::IPC<{ NUM_PROCS as u8 }>>,
368 &main_loop_capability,
369 );
370}