1#![no_std]
9#![cfg_attr(not(doc), no_main)]
12
13use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
14use core::ptr::{addr_of, addr_of_mut};
15use kernel::capabilities;
16use kernel::component::Component;
17use kernel::hil;
18use kernel::platform::scheduler_timer::VirtualSchedulerTimer;
19use kernel::platform::{KernelResources, SyscallDriverLookup};
20use kernel::scheduler::cooperative::CooperativeSched;
21use kernel::utilities::registers::interfaces::ReadWriteable;
22use kernel::{create_capability, debug, static_init};
23use rv32i::csr;
24use veer_el2::chip::VeeRDefaultPeripherals;
25
26use veer_el2::machine_timer::Clint;
27use veer_el2::machine_timer::CLINT_BASE;
28
29pub mod io;
30
31pub const NUM_PROCS: usize = 4;
32
33static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] =
36 [None; NUM_PROCS];
37
38pub type VeeRChip = veer_el2::chip::VeeR<'static, VeeRDefaultPeripherals>;
39
40static mut CHIP: Option<&'static VeeRChip> = 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 VeeR {
58 console: &'static capsules_core::console::Console<'static>,
59 alarm: &'static capsules_core::alarm::AlarmDriver<
60 'static,
61 VirtualMuxAlarm<'static, Clint<'static>>,
62 >,
63 scheduler: &'static CooperativeSched<'static>,
64 scheduler_timer: &'static VirtualSchedulerTimer<VirtualMuxAlarm<'static, Clint<'static>>>,
65}
66
67impl SyscallDriverLookup for VeeR {
69 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
70 where
71 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
72 {
73 match driver_num {
74 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
75 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
76 _ => f(None),
77 }
78 }
79}
80
81impl KernelResources<VeeRChip> for VeeR {
82 type SyscallDriverLookup = Self;
83 type SyscallFilter = ();
84 type ProcessFault = ();
85 type Scheduler = CooperativeSched<'static>;
86 type SchedulerTimer = VirtualSchedulerTimer<VirtualMuxAlarm<'static, Clint<'static>>>;
87 type WatchDog = ();
88 type ContextSwitchCallback = ();
89
90 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
91 self
92 }
93 fn syscall_filter(&self) -> &Self::SyscallFilter {
94 &()
95 }
96 fn process_fault(&self) -> &Self::ProcessFault {
97 &()
98 }
99 fn scheduler(&self) -> &Self::Scheduler {
100 self.scheduler
101 }
102 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
103 self.scheduler_timer
104 }
105 fn watchdog(&self) -> &Self::WatchDog {
106 &()
107 }
108 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
109 &()
110 }
111}
112
113#[inline(never)]
117unsafe fn start() -> (&'static kernel::Kernel, VeeR, &'static VeeRChip) {
118 rv32i::configure_trap_handler();
120
121 let peripherals = static_init!(VeeRDefaultPeripherals, VeeRDefaultPeripherals::new());
122 peripherals.init();
123
124 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
126 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
127
128 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
129
130 kernel::debug::assign_gpios(None, None, None);
132
133 let uart_mux = components::console::UartMuxComponent::new(&peripherals.sim_uart, 115200)
135 .finalize(components::uart_mux_component_static!());
136
137 let mtimer = static_init!(Clint, Clint::new(&CLINT_BASE));
138
139 let mux_alarm = static_init!(MuxAlarm<'static, Clint>, MuxAlarm::new(mtimer));
142 hil::time::Alarm::set_alarm_client(mtimer, mux_alarm);
143
144 let virtual_alarm_user = static_init!(
146 VirtualMuxAlarm<'static, Clint>,
147 VirtualMuxAlarm::new(mux_alarm)
148 );
149 virtual_alarm_user.setup();
150
151 let systick_virtual_alarm = static_init!(
152 VirtualMuxAlarm<'static, Clint>,
153 VirtualMuxAlarm::new(mux_alarm)
154 );
155 systick_virtual_alarm.setup();
156
157 let alarm = static_init!(
158 capsules_core::alarm::AlarmDriver<'static, VirtualMuxAlarm<'static, Clint>>,
159 capsules_core::alarm::AlarmDriver::new(
160 virtual_alarm_user,
161 board_kernel.create_grant(capsules_core::alarm::DRIVER_NUM, &memory_allocation_cap)
162 )
163 );
164 hil::time::Alarm::set_alarm_client(virtual_alarm_user, alarm);
165
166 let chip = static_init!(VeeRChip, veer_el2::chip::VeeR::new(peripherals, mtimer));
167 CHIP = Some(chip);
168
169 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
171 .finalize(components::process_printer_text_component_static!());
172 PROCESS_PRINTER = Some(process_printer);
173
174 let process_console = components::process_console::ProcessConsoleComponent::new(
175 board_kernel,
176 uart_mux,
177 mux_alarm,
178 process_printer,
179 None,
180 )
181 .finalize(components::process_console_component_static!(Clint));
182 let _ = process_console.start();
183
184 chip.enable_pic_interrupts();
186
187 csr::CSR
189 .mie
190 .modify(csr::mie::mie::mext::SET + csr::mie::mie::msoft::SET + csr::mie::mie::mtimer::SET);
191 csr::CSR.mstatus.modify(csr::mstatus::mstatus::mie::SET);
192
193 let console = components::console::ConsoleComponent::new(
195 board_kernel,
196 capsules_core::console::DRIVER_NUM,
197 uart_mux,
198 )
199 .finalize(components::console_component_static!());
200 components::debug_writer::DebugWriterComponent::new(uart_mux)
202 .finalize(components::debug_writer_component_static!());
203
204 debug!("VeeR EL2 initialisation complete.");
205 debug!("Entering main loop.");
206
207 extern "C" {
209 static _sapps: u8;
211 static _eapps: u8;
213 static mut _sappmem: u8;
215 static _eappmem: u8;
217 }
218
219 let scheduler =
220 components::sched::cooperative::CooperativeComponent::new(&*addr_of!(PROCESSES))
221 .finalize(components::cooperative_component_static!(NUM_PROCS));
222
223 let scheduler_timer = static_init!(
224 VirtualSchedulerTimer<VirtualMuxAlarm<'static, Clint<'static>>>,
225 VirtualSchedulerTimer::new(systick_virtual_alarm)
226 );
227
228 let veer = VeeR {
229 console,
230 alarm,
231 scheduler,
232 scheduler_timer,
233 };
234
235 kernel::process::load_processes(
236 board_kernel,
237 chip,
238 core::slice::from_raw_parts(
239 core::ptr::addr_of!(_sapps),
240 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
241 ),
242 core::slice::from_raw_parts_mut(
243 core::ptr::addr_of_mut!(_sappmem),
244 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
245 ),
246 &mut *addr_of_mut!(PROCESSES),
247 &FAULT_RESPONSE,
248 &process_mgmt_cap,
249 )
250 .unwrap_or_else(|err| {
251 debug!("Error loading processes!");
252 debug!("{:?}", err);
253 });
254
255 (board_kernel, veer, chip)
256}
257
258#[no_mangle]
263pub unsafe fn main() {
264 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
265 let (board_kernel, veer, chip) = start();
266 board_kernel.kernel_loop(&veer, chip, None::<&kernel::ipc::IPC<0>>, &main_loop_cap);
267}