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    let peripherals = static_init!(ArtyExxDefaultPeripherals, ArtyExxDefaultPeripherals::new());
130    peripherals.init();
131
132    let chip = static_init!(
133        arty_e21_chip::chip::ArtyExx<ArtyExxDefaultPeripherals>,
134        arty_e21_chip::chip::ArtyExx::new(&peripherals.machinetimer, peripherals)
135    );
136    CHIP = Some(chip);
137    chip.initialize();
138
139    let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
140
141    let processes = components::process_array::ProcessArrayComponent::new()
143        .finalize(components::process_array_component_static!(NUM_PROCS));
144    PROCESSES = Some(processes);
145
146    let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
147
148    kernel::debug::assign_gpios(
150        Some(&peripherals.gpio_port[0]), Some(&peripherals.gpio_port[1]), Some(&peripherals.gpio_port[8]),
153    );
154
155    let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
156        .finalize(components::process_printer_text_component_static!());
157    PROCESS_PRINTER = Some(process_printer);
158
159    let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
161        .finalize(components::uart_mux_component_static!());
162
163    let console = components::console::ConsoleComponent::new(
164        board_kernel,
165        capsules_core::console::DRIVER_NUM,
166        uart_mux,
167    )
168    .finalize(components::console_component_static!());
169
170    let mux_alarm = static_init!(
173        MuxAlarm<'static, arty_e21_chip::chip::ArtyExxClint>,
174        MuxAlarm::new(&peripherals.machinetimer)
175    );
176    hil::time::Alarm::set_alarm_client(&peripherals.machinetimer, mux_alarm);
177
178    let alarm = components::alarm::AlarmDriverComponent::new(
180        board_kernel,
181        capsules_core::alarm::DRIVER_NUM,
182        mux_alarm,
183    )
184    .finalize(components::alarm_component_static!(
185        arty_e21_chip::chip::ArtyExxClint
186    ));
187
188    let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
202        hil::led::LedHigh<'static, arty_e21_chip::gpio::GpioPin>,
203        hil::led::LedHigh::new(&peripherals.gpio_port[2]), hil::led::LedHigh::new(&peripherals.gpio_port[1]), hil::led::LedHigh::new(&peripherals.gpio_port[0]), ));
207
208    let button = components::button::ButtonComponent::new(
210        board_kernel,
211        capsules_core::button::DRIVER_NUM,
212        components::button_component_helper!(
213            arty_e21_chip::gpio::GpioPin,
214            (
215                &peripherals.gpio_port[4],
216                kernel::hil::gpio::ActivationMode::ActiveHigh,
217                kernel::hil::gpio::FloatingState::PullNone
218            )
219        ),
220    )
221    .finalize(components::button_component_static!(
222        arty_e21_chip::gpio::GpioPin
223    ));
224
225    let gpio = components::gpio::GpioComponent::new(
227        board_kernel,
228        capsules_core::gpio::DRIVER_NUM,
229        components::gpio_component_helper!(
230            arty_e21_chip::gpio::GpioPin,
231            0 => &peripherals.gpio_port[7],
232            1 => &peripherals.gpio_port[5],
233            2 => &peripherals.gpio_port[6]
234        ),
235    )
236    .finalize(components::gpio_component_static!(
237        arty_e21_chip::gpio::GpioPin
238    ));
239
240    chip.enable_all_interrupts();
241
242    let scheduler = components::sched::priority::PriorityComponent::new(board_kernel)
243        .finalize(components::priority_component_static!());
244
245    let artye21 = ArtyE21 {
246        console,
247        gpio,
248        alarm,
249        led,
250        button,
251        scheduler,
253    };
254
255    components::debug_writer::DebugWriterComponent::new::<
257        <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
258    >(
259        uart_mux,
260        create_capability!(capabilities::SetDebugWriterCapability),
261    )
262    .finalize(components::debug_writer_component_static!());
263
264    debug!("Initialization complete. Entering main loop.");
267
268    extern "C" {
276        static _sapps: u8;
278        static _eapps: u8;
280        static mut _sappmem: u8;
282        static _eappmem: u8;
284    }
285
286    kernel::process::load_processes(
287        board_kernel,
288        chip,
289        core::slice::from_raw_parts(
290            core::ptr::addr_of!(_sapps),
291            core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
292        ),
293        core::slice::from_raw_parts_mut(
294            core::ptr::addr_of_mut!(_sappmem),
295            core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
296        ),
297        &FAULT_RESPONSE,
298        &process_mgmt_cap,
299    )
300    .unwrap_or_else(|err| {
301        debug!("Error loading processes!");
302        debug!("{:?}", err);
303    });
304
305    (board_kernel, artye21, chip)
306}
307
308#[no_mangle]
310pub unsafe fn main() {
311    let main_loop_capability = create_capability!(capabilities::MainLoopCapability);
312
313    let (board_kernel, board, chip) = start();
314    board_kernel.kernel_loop(
315        &board,
316        chip,
317        None::<&kernel::ipc::IPC<0>>,
318        &main_loop_capability,
319    );
320}