1#![no_std]
8#![no_main]
9
10use arty_e21_chip::chip::ArtyExxDefaultPeripherals;
11use capsules_core::virtualizers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};
12
13use kernel::capabilities;
14use kernel::component::Component;
15use kernel::hil;
16use kernel::platform::{KernelResources, SyscallDriverLookup};
17use kernel::process::ProcessArray;
18use kernel::scheduler::priority::PrioritySched;
19use kernel::{create_capability, debug, static_init};
20
21#[allow(dead_code)]
22mod timer_test;
23
24pub mod io;
25
26const NUM_PROCS: usize = 4;
30
31type ChipHw = arty_e21_chip::chip::ArtyExx<'static, ArtyExxDefaultPeripherals<'static>>;
32
33const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
35 capsules_system::process_policies::PanicFaultPolicy {};
36
37static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
39
40static mut CHIP: Option<&'static arty_e21_chip::chip::ArtyExx<ArtyExxDefaultPeripherals>> = None;
42static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
43 None;
44
45kernel::stack_size! {0x1000}
46
47struct ArtyE21 {
50 console: &'static capsules_core::console::Console<'static>,
51 gpio: &'static capsules_core::gpio::GPIO<'static, arty_e21_chip::gpio::GpioPin<'static>>,
52 alarm: &'static capsules_core::alarm::AlarmDriver<
53 'static,
54 VirtualMuxAlarm<'static, arty_e21_chip::chip::ArtyExxClint<'static>>,
55 >,
56 led: &'static capsules_core::led::LedDriver<
57 'static,
58 hil::led::LedHigh<'static, arty_e21_chip::gpio::GpioPin<'static>>,
59 3,
60 >,
61 button: &'static capsules_core::button::Button<'static, arty_e21_chip::gpio::GpioPin<'static>>,
62 scheduler: &'static PrioritySched,
64}
65
66impl SyscallDriverLookup for ArtyE21 {
68 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
69 where
70 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
71 {
72 match driver_num {
73 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
74 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
75
76 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
77 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
78 capsules_core::button::DRIVER_NUM => f(Some(self.button)),
79
80 _ => f(None),
82 }
83 }
84}
85
86impl KernelResources<arty_e21_chip::chip::ArtyExx<'static, ArtyExxDefaultPeripherals<'static>>>
87 for ArtyE21
88{
89 type SyscallDriverLookup = Self;
90 type SyscallFilter = ();
91 type ProcessFault = ();
92 type Scheduler = PrioritySched;
93 type SchedulerTimer = ();
94 type WatchDog = ();
95 type ContextSwitchCallback = ();
96
97 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
98 self
99 }
100 fn syscall_filter(&self) -> &Self::SyscallFilter {
101 &()
102 }
103 fn process_fault(&self) -> &Self::ProcessFault {
104 &()
105 }
106 fn scheduler(&self) -> &Self::Scheduler {
107 self.scheduler
108 }
109 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
110 &()
111 }
112 fn watchdog(&self) -> &Self::WatchDog {
113 &()
114 }
115 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
116 &()
117 }
118}
119
120#[inline(never)]
124unsafe fn start() -> (
125 &'static kernel::Kernel,
126 ArtyE21,
127 &'static arty_e21_chip::chip::ArtyExx<'static, ArtyExxDefaultPeripherals<'static>>,
128) {
129 kernel::deferred_call::initialize_deferred_call_state::<
131 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
132 >();
133
134 let peripherals = static_init!(ArtyExxDefaultPeripherals, ArtyExxDefaultPeripherals::new());
135 peripherals.init();
136
137 let chip = static_init!(
138 arty_e21_chip::chip::ArtyExx<ArtyExxDefaultPeripherals>,
139 arty_e21_chip::chip::ArtyExx::new(&peripherals.machinetimer, peripherals)
140 );
141 CHIP = Some(chip);
142 chip.initialize();
143
144 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
145
146 let processes = components::process_array::ProcessArrayComponent::new()
148 .finalize(components::process_array_component_static!(NUM_PROCS));
149 PROCESSES = Some(processes);
150
151 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
152
153 let debug_gpios = static_init!(
155 [&'static dyn kernel::hil::gpio::Pin; 3],
156 [
157 &peripherals.gpio_port[0],
159 &peripherals.gpio_port[1],
161 &peripherals.gpio_port[8],
162 ]
163 );
164 kernel::debug::initialize_debug_gpio::<
165 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
166 >();
167 kernel::debug::assign_gpios(debug_gpios);
168
169 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 uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
175 .finalize(components::uart_mux_component_static!());
176
177 let console = components::console::ConsoleComponent::new(
178 board_kernel,
179 capsules_core::console::DRIVER_NUM,
180 uart_mux,
181 )
182 .finalize(components::console_component_static!());
183
184 let mux_alarm = static_init!(
187 MuxAlarm<'static, arty_e21_chip::chip::ArtyExxClint>,
188 MuxAlarm::new(&peripherals.machinetimer)
189 );
190 hil::time::Alarm::set_alarm_client(&peripherals.machinetimer, mux_alarm);
191
192 let alarm = components::alarm::AlarmDriverComponent::new(
194 board_kernel,
195 capsules_core::alarm::DRIVER_NUM,
196 mux_alarm,
197 )
198 .finalize(components::alarm_component_static!(
199 arty_e21_chip::chip::ArtyExxClint
200 ));
201
202 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
216 hil::led::LedHigh<'static, arty_e21_chip::gpio::GpioPin>,
217 hil::led::LedHigh::new(&peripherals.gpio_port[2]), hil::led::LedHigh::new(&peripherals.gpio_port[1]), hil::led::LedHigh::new(&peripherals.gpio_port[0]), ));
221
222 let button = components::button::ButtonComponent::new(
224 board_kernel,
225 capsules_core::button::DRIVER_NUM,
226 components::button_component_helper!(
227 arty_e21_chip::gpio::GpioPin,
228 (
229 &peripherals.gpio_port[4],
230 kernel::hil::gpio::ActivationMode::ActiveHigh,
231 kernel::hil::gpio::FloatingState::PullNone
232 )
233 ),
234 )
235 .finalize(components::button_component_static!(
236 arty_e21_chip::gpio::GpioPin
237 ));
238
239 let gpio = components::gpio::GpioComponent::new(
241 board_kernel,
242 capsules_core::gpio::DRIVER_NUM,
243 components::gpio_component_helper!(
244 arty_e21_chip::gpio::GpioPin,
245 0 => &peripherals.gpio_port[7],
246 1 => &peripherals.gpio_port[5],
247 2 => &peripherals.gpio_port[6]
248 ),
249 )
250 .finalize(components::gpio_component_static!(
251 arty_e21_chip::gpio::GpioPin
252 ));
253
254 chip.enable_all_interrupts();
255
256 let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
257 .finalize(components::priority_component_static!());
258
259 let artye21 = ArtyE21 {
260 console,
261 gpio,
262 alarm,
263 led,
264 button,
265 scheduler,
267 };
268
269 components::debug_writer::DebugWriterComponent::new::<
271 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
272 >(
273 uart_mux,
274 create_capability!(capabilities::SetDebugWriterCapability),
275 )
276 .finalize(components::debug_writer_component_static!());
277
278 debug!("Initialization complete. Entering main loop.");
281
282 extern "C" {
290 static _sapps: u8;
292 static _eapps: u8;
294 static mut _sappmem: u8;
296 static _eappmem: u8;
298 }
299
300 kernel::process::load_processes(
301 board_kernel,
302 chip,
303 core::slice::from_raw_parts(
304 core::ptr::addr_of!(_sapps),
305 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
306 ),
307 core::slice::from_raw_parts_mut(
308 core::ptr::addr_of_mut!(_sappmem),
309 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
310 ),
311 &FAULT_RESPONSE,
312 &process_mgmt_cap,
313 )
314 .unwrap_or_else(|err| {
315 debug!("Error loading processes!");
316 debug!("{:?}", err);
317 });
318
319 (board_kernel, artye21, chip)
320}
321
322#[no_mangle]
324pub unsafe fn main() {
325 let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
326
327 let (board_kernel, board, chip) = start();
328 board_kernel.kernel_loop(
329 &board,
330 chip,
331 None::<&kernel::ipc::IPC<0>>,
332 &main_loop_capability,
333 );
334}