1#![no_std]
9#![no_main]
10
11use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
12use kernel::capabilities;
13use kernel::component::Component;
14use kernel::hil;
15use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
16use kernel::platform::{KernelResources, SyscallDriverLookup};
17use kernel::process::ProcessArray;
18use kernel::scheduler::cooperative::CooperativeSched;
19use kernel::utilities::registers::interfaces::ReadWriteable;
20use kernel::{create_capability, debug, static_init};
21use rv32i::csr;
22use veer_el2::chip::VeeRDefaultPeripherals;
23
24use veer_el2::machine_timer::Clint;
25use veer_el2::machine_timer::CLINT_BASE;
26
27pub mod io;
28
29pub const NUM_PROCS: usize = 4;
30
31pub type VeeRChip = veer_el2::chip::VeeR<'static, VeeRDefaultPeripherals>;
32pub type ChipHw = VeeRChip;
33
34static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
36static mut CHIP: Option<&'static VeeRChip> = None;
38static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
40 None;
41
42const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
44 capsules_system::process_policies::PanicFaultPolicy {};
45
46kernel::stack_size! {0x900}
47
48struct VeeR {
51 console: &'static capsules_core::console::Console<'static>,
52 alarm: &'static capsules_core::alarm::AlarmDriver<
53 'static,
54 VirtualMuxAlarm<'static, Clint<'static>>,
55 >,
56 scheduler: &'static CooperativeSched<'static>,
57 scheduler_timer: &'static VirtualSchedulerTimer<VirtualMuxAlarm<'static, Clint<'static>>>,
58}
59
60impl SyscallDriverLookup for VeeR {
62 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
63 where
64 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
65 {
66 match driver_num {
67 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
68 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
69 _ => f(None),
70 }
71 }
72}
73
74impl KernelResources<VeeRChip> for VeeR {
75 type SyscallDriverLookup = Self;
76 type SyscallFilter = ();
77 type ProcessFault = ();
78 type Scheduler = CooperativeSched<'static>;
79 type SchedulerTimer = VirtualSchedulerTimer<VirtualMuxAlarm<'static, Clint<'static>>>;
80 type WatchDog = ();
81 type ContextSwitchCallback = ();
82
83 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
84 self
85 }
86 fn syscall_filter(&self) -> &Self::SyscallFilter {
87 &()
88 }
89 fn process_fault(&self) -> &Self::ProcessFault {
90 &()
91 }
92 fn scheduler(&self) -> &Self::Scheduler {
93 self.scheduler
94 }
95 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
96 self.scheduler_timer
97 }
98 fn watchdog(&self) -> &Self::WatchDog {
99 &()
100 }
101 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
102 &()
103 }
104}
105
106#[inline(never)]
110unsafe fn start() -> (&'static kernel::Kernel, VeeR, &'static VeeRChip) {
111 rv32i::configure_trap_handler();
113
114 let peripherals = static_init!(VeeRDefaultPeripherals, VeeRDefaultPeripherals::new());
115 peripherals.init();
116
117 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
119 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
120
121 let processes = components::process_array::ProcessArrayComponent::new()
123 .finalize(components::process_array_component_static!(NUM_PROCS));
124 PROCESSES = Some(processes);
125
126 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
128
129 kernel::debug::assign_gpios(None, None, None);
131
132 let uart_mux = components::console::UartMuxComponent::new(&peripherals.sim_uart, 115200)
134 .finalize(components::uart_mux_component_static!());
135
136 let mtimer = static_init!(Clint, Clint::new(&CLINT_BASE));
137
138 let mux_alarm = static_init!(MuxAlarm<'static, Clint>, MuxAlarm::new(mtimer));
141 hil::time::Alarm::set_alarm_client(mtimer, mux_alarm);
142
143 let virtual_alarm_user = static_init!(
145 VirtualMuxAlarm<'static, Clint>,
146 VirtualMuxAlarm::new(mux_alarm)
147 );
148 virtual_alarm_user.setup();
149
150 let systick_virtual_alarm = static_init!(
151 VirtualMuxAlarm<'static, Clint>,
152 VirtualMuxAlarm::new(mux_alarm)
153 );
154 systick_virtual_alarm.setup();
155
156 let alarm = static_init!(
157 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, Clint>>,
158 capsules_core::alarm::AlarmDriver::new(
159 virtual_alarm_user,
160 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
161 )
162 );
163 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
164
165 let chip = static_init!(VeeRChip, veer_el2::chip::VeeR::new(peripherals, mtimer));
166 CHIP = Some(chip);
167
168 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
170 .finalize(components::process_printer_text_component_static!());
171 PROCESS_PRINTER = Some(process_printer);
172
173 let process_console = components::process_console::ProcessConsoleComponent::new(
174 board_kernel,
175 uart_mux,
176 mux_alarm,
177 process_printer,
178 None,
179 )
180 .finalize(components::process_console_component_static!(Clint));
181 let _ = process_console.start();
182
183 chip.enable_pic_interrupts();
185
186 csr::CSR
188 .mie
189 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
190 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
191
192 let console = components::console::ConsoleComponent::new(
194 board_kernel,
195 capsules_core::console::DRIVER_NUM,
196 uart_mux,
197 )
198 .finalize(components::console_component_static!());
199 components::debug_writer::DebugWriterComponent::new_unsafe(
201 uart_mux,
202 create_capability!(capabilities::SetDebugWriterCapability),
203 || unsafe {
204 kernel::debug::initialize_debug_writer_wrapper_unsafe::<
205 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
206 >();
207 },
208 )
209 .finalize(components::debug_writer_component_static!());
210
211 debug!("VeeR EL2 initialisation complete.");
212 debug!("Entering main loop.");
213
214 extern "C" {
216 static _sapps: u8;
218 static _eapps: u8;
220 static mut _sappmem: u8;
222 static _eappmem: u8;
224 }
225
226 let scheduler = components::sched::cooperative::CooperativeComponent::new(processes)
227 .finalize(components::cooperative_component_static!(NUM_PROCS));
228
229 let scheduler_timer = static_init!(
230 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Clint<'static>>>,
231 VirtualSchedulerTimer::new(systick_virtual_alarm)
232 );
233
234 let veer = VeeR {
235 console,
236 alarm,
237 scheduler,
238 scheduler_timer,
239 };
240
241 kernel::process::load_processes(
242 board_kernel,
243 chip,
244 core::slice::from_raw_parts(
245 core::ptr::addr_of!(_sapps),
246 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
247 ),
248 core::slice::from_raw_parts_mut(
249 core::ptr::addr_of_mut!(_sappmem),
250 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
251 ),
252 &FAULT_RESPONSE,
253 &process_mgmt_cap,
254 )
255 .unwrap_or_else(|err| {
256 debug!("Error loading processes!");
257 debug!("{:?}", err);
258 });
259
260 (board_kernel, veer, chip)
261}
262
263#[no_mangle]
268pub unsafe fn main() {
269 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
270 let (board_kernel, veer, chip) = start();
271 board_kernel.kernel_loop(&veer, chip, None::<&kernel::ipc::IPC<0>>, &main_loop_cap);
272}