1#![no_std]
10#![no_main]
11#![deny(missing_docs)]
12#![feature(custom_test_frameworks)]
13#![test_runner(test_runner)]
14#![reexport_test_harness_main = "test_main"]
15
16use apollo3::chip::Apollo3DefaultPeripherals;
17use capsules_core::i2c_master_slave_driver::I2CMasterSlaveDriver;
18use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
19use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
20use kernel::capabilities;
21use kernel::component::Component;
22use kernel::hil::i2c::I2CMaster;
23use kernel::hil::i2c::I2CSlave;
24use kernel::hil::led::LedHigh;
25use kernel::hil::time::Counter;
26use kernel::platform::{KernelResources, SyscallDriverLookup};
27use kernel::process::ProcessArray;
28use kernel::scheduler::round_robin::RoundRobinSched;
29use kernel::{create_capability, debug, static_init};
30
31pub mod io;
33
34#[cfg(test)]
35mod tests;
36
37const NUM_PROCS: usize = 4;
39
40static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
42
43type ChipHw = apollo3::chip::Apollo3<Apollo3DefaultPeripherals>;
44
45static mut CHIP: Option<&'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> = None;
47static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
49 None;
50
51const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
53 capsules_system::process_policies::PanicFaultPolicy {};
54
55#[cfg(test)]
57static mut PERIPHERALS: Option<&'static Apollo3DefaultPeripherals> = None;
58#[cfg(test)]
60static mut BOARD: Option<&'static kernel::Kernel> = None;
61#[cfg(test)]
63static mut PLATFORM: Option<&'static RedboardArtemisAtp> = None;
64#[cfg(test)]
66static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
67static mut ALARM: Option<&'static MuxAlarm<'static, apollo3::stimer::STimer<'static>>> = None;
69
70kernel::stack_size! {0x1000}
71
72struct RedboardArtemisAtp {
75 alarm: &'static capsules_core::alarm::AlarmDriver<
76 'static,
77 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
78 >,
79 led: &'static capsules_core::led::LedDriver<
80 'static,
81 LedHigh<'static, apollo3::gpio::GpioPin<'static>>,
82 1,
83 >,
84 gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
85 console: &'static capsules_core::console::Console<'static>,
86 i2c_master_slave: &'static capsules_core::i2c_master_slave_driver::I2CMasterSlaveDriver<
87 'static,
88 capsules_core::i2c_master_slave_combo::I2CMasterSlaveCombo<
89 'static,
90 apollo3::iom::Iom<'static>,
91 apollo3::ios::Ios<'static>,
92 >,
93 >,
94 spi_controller: &'static capsules_core::spi_controller::Spi<
95 'static,
96 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
97 'static,
98 apollo3::iom::Iom<'static>,
99 >,
100 >,
101 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
102 'static,
103 apollo3::ble::Ble<'static>,
104 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
105 >,
106 scheduler: &'static RoundRobinSched<'static>,
107 systick: cortexm4::systick::SysTick,
108}
109
110impl SyscallDriverLookup for RedboardArtemisAtp {
112 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
113 where
114 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
115 {
116 match driver_num {
117 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
118 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
119 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
120 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
121 capsules_core::i2c_master_slave_driver::DRIVER_NUM => f(Some(self.i2c_master_slave)),
122 capsules_core::spi_controller::DRIVER_NUM => f(Some(self.spi_controller)),
123 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
124 _ => f(None),
125 }
126 }
127}
128
129impl KernelResources<apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> for RedboardArtemisAtp {
130 type SyscallDriverLookup = Self;
131 type SyscallFilter = ();
132 type ProcessFault = ();
133 type Scheduler = RoundRobinSched<'static>;
134 type SchedulerTimer = cortexm4::systick::SysTick;
135 type WatchDog = ();
136 type ContextSwitchCallback = ();
137
138 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
139 self
140 }
141 fn syscall_filter(&self) -> &Self::SyscallFilter {
142 &()
143 }
144 fn process_fault(&self) -> &Self::ProcessFault {
145 &()
146 }
147 fn scheduler(&self) -> &Self::Scheduler {
148 self.scheduler
149 }
150 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
151 &self.systick
152 }
153 fn watchdog(&self) -> &Self::WatchDog {
154 &()
155 }
156 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
157 &()
158 }
159}
160
161#[inline(never)]
164unsafe fn setup() -> (
165 &'static kernel::Kernel,
166 &'static RedboardArtemisAtp,
167 &'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
168 &'static Apollo3DefaultPeripherals,
169) {
170 kernel::deferred_call::initialize_deferred_call_state::<
172 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
173 >();
174
175 let peripherals = static_init!(Apollo3DefaultPeripherals, Apollo3DefaultPeripherals::new());
176
177 let mcu_ctrl = apollo3::mcuctrl::McuCtrl::new();
179 let pwr_ctrl = apollo3::pwrctrl::PwrCtrl::new();
180 let clkgen = apollo3::clkgen::ClkGen::new();
181
182 clkgen.set_clock_frequency(apollo3::clkgen::ClockFrequency::Freq48MHz);
183
184 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
186 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
187
188 let processes = components::process_array::ProcessArrayComponent::new()
190 .finalize(components::process_array_component_static!(NUM_PROCS));
191 PROCESSES = Some(processes);
192
193 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
194
195 pwr_ctrl.enable_uart0();
197 pwr_ctrl.enable_iom0();
198 pwr_ctrl.enable_iom4();
199 pwr_ctrl.enable_ios();
200
201 peripherals.init();
202
203 peripherals
205 .gpio_port
206 .enable_uart(&peripherals.gpio_port[48], &peripherals.gpio_port[49]);
207 peripherals
209 .gpio_port
210 .enable_i2c(&peripherals.gpio_port[40], &peripherals.gpio_port[39]);
211 peripherals
213 .gpio_port
214 .enable_i2c_slave(&peripherals.gpio_port[1], &peripherals.gpio_port[0]);
215 peripherals.gpio_port.enable_spi(
217 &peripherals.gpio_port[5],
218 &peripherals.gpio_port[7],
219 &peripherals.gpio_port[6],
220 );
221
222 let debug_gpios = static_init!(
224 [&'static dyn kernel::hil::gpio::Pin; 1],
225 [
226 &peripherals.gpio_port[19]
228 ]
229 );
230 kernel::debug::initialize_debug_gpio::<
231 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
232 >();
233 kernel::debug::assign_gpios(debug_gpios);
234
235 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
237 .finalize(components::uart_mux_component_static!());
238
239 let console = components::console::ConsoleComponent::new(
241 board_kernel,
242 capsules_core::console::DRIVER_NUM,
243 uart_mux,
244 )
245 .finalize(components::console_component_static!());
246 components::debug_writer::DebugWriterComponent::new::<
248 <ChipHw as kernel::platform::chip::Chip>::ThreadIdProvider,
249 >(
250 uart_mux,
251 create_capability!(capabilities::SetDebugWriterCapability),
252 )
253 .finalize(components::debug_writer_component_static!());
254
255 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
257 LedHigh<'static, apollo3::gpio::GpioPin>,
258 LedHigh::new(&peripherals.gpio_port[19]),
259 ));
260
261 let gpio = components::gpio::GpioComponent::new(
264 board_kernel,
265 capsules_core::gpio::DRIVER_NUM,
266 components::gpio_component_helper!(
267 apollo3::gpio::GpioPin,
268 0 => &peripherals.gpio_port[2], 1 => &peripherals.gpio_port[8], ),
271 )
272 .finalize(components::gpio_component_static!(apollo3::gpio::GpioPin));
273
274 let _ = peripherals.stimer.start();
277 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.stimer).finalize(
278 components::alarm_mux_component_static!(apollo3::stimer::STimer),
279 );
280 let alarm = components::alarm::AlarmDriverComponent::new(
281 board_kernel,
282 capsules_core::alarm::DRIVER_NUM,
283 mux_alarm,
284 )
285 .finalize(components::alarm_component_static!(apollo3::stimer::STimer));
286 ALARM = Some(mux_alarm);
287
288 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
290 .finalize(components::process_printer_text_component_static!());
291 PROCESS_PRINTER = Some(process_printer);
292
293 let i2c_master_slave_combo = static_init!(
294 capsules_core::i2c_master_slave_combo::I2CMasterSlaveCombo<
295 'static,
296 apollo3::iom::Iom<'static>,
297 apollo3::ios::Ios<'static>,
298 >,
299 capsules_core::i2c_master_slave_combo::I2CMasterSlaveCombo::new(
300 &peripherals.iom4,
301 &peripherals.ios
302 )
303 );
304
305 let i2c_master_buffer = static_init!([u8; 32], [0; 32]);
306 let i2c_slave_buffer1 = static_init!([u8; 32], [0; 32]);
307 let i2c_slave_buffer2 = static_init!([u8; 32], [0; 32]);
308
309 let i2c_master_slave = static_init!(
310 I2CMasterSlaveDriver<
311 capsules_core::i2c_master_slave_combo::I2CMasterSlaveCombo<
312 'static,
313 apollo3::iom::Iom<'static>,
314 apollo3::ios::Ios<'static>,
315 >,
316 >,
317 I2CMasterSlaveDriver::new(
318 i2c_master_slave_combo,
319 i2c_master_buffer,
320 i2c_slave_buffer1,
321 i2c_slave_buffer2,
322 board_kernel.create_grant(
323 capsules_core::i2c_master_slave_driver::DRIVER_NUM,
324 &memory_allocation_cap
325 ),
326 )
327 );
328
329 i2c_master_slave_combo.set_master_client(i2c_master_slave);
330 i2c_master_slave_combo.set_slave_client(i2c_master_slave);
331
332 peripherals.iom4.enable();
333
334 let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.iom0).finalize(
336 components::spi_mux_component_static!(apollo3::iom::Iom<'static>),
337 );
338
339 let spi_controller = components::spi::SpiSyscallComponent::new(
343 board_kernel,
344 mux_spi,
345 kernel::hil::spi::cs::IntoChipSelect::<_, kernel::hil::spi::cs::ActiveLow>::into_cs(
346 &peripherals.gpio_port[13], ),
348 capsules_core::spi_controller::DRIVER_NUM,
349 )
350 .finalize(components::spi_syscall_component_static!(
351 apollo3::iom::Iom<'static>
352 ));
353
354 mcu_ctrl.enable_ble();
356 clkgen.enable_ble();
357 pwr_ctrl.enable_ble();
358 peripherals.ble.setup_clocks();
359 mcu_ctrl.reset_ble();
360 peripherals.ble.power_up();
361 peripherals.ble.ble_initialise();
362
363 let ble_radio = components::ble::BLEComponent::new(
364 board_kernel,
365 capsules_extra::ble_advertising_driver::DRIVER_NUM,
366 &peripherals.ble,
367 mux_alarm,
368 )
369 .finalize(components::ble_component_static!(
370 apollo3::stimer::STimer,
371 apollo3::ble::Ble,
372 ));
373
374 mcu_ctrl.print_chip_revision();
375
376 debug!("Initialization complete. Entering main loop");
377
378 extern "C" {
380 static _sapps: u8;
382 static _eapps: u8;
384 static mut _sappmem: u8;
386 static _eappmem: u8;
388 }
389
390 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
391 .finalize(components::round_robin_component_static!(NUM_PROCS));
392
393 let systick = cortexm4::systick::SysTick::new_with_calibration(48_000_000);
394
395 let artemis_atp = static_init!(
396 RedboardArtemisAtp,
397 RedboardArtemisAtp {
398 alarm,
399 led,
400 gpio,
401 console,
402 i2c_master_slave,
403 spi_controller,
404 ble_radio,
405 scheduler,
406 systick,
407 }
408 );
409
410 let chip = static_init!(
411 apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
412 apollo3::chip::Apollo3::new(peripherals)
413 );
414 CHIP = Some(chip);
415
416 kernel::process::load_processes(
417 board_kernel,
418 chip,
419 core::slice::from_raw_parts(
420 core::ptr::addr_of!(_sapps),
421 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
422 ),
423 core::slice::from_raw_parts_mut(
424 core::ptr::addr_of_mut!(_sappmem),
425 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
426 ),
427 &FAULT_RESPONSE,
428 &process_mgmt_cap,
429 )
430 .unwrap_or_else(|err| {
431 debug!("Error loading processes!");
432 debug!("{:?}", err);
433 });
434
435 (board_kernel, artemis_atp, chip, peripherals)
436}
437
438#[no_mangle]
443pub unsafe fn main() {
444 apollo3::init();
445
446 #[cfg(test)]
447 test_main();
448
449 #[cfg(not(test))]
450 {
451 let (board_kernel, esp32_c3_board, chip, _peripherals) = setup();
452
453 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
454
455 board_kernel.kernel_loop(
456 esp32_c3_board,
457 chip,
458 None::<&kernel::ipc::IPC<{ NUM_PROCS as u8 }>>,
459 &main_loop_cap,
460 );
461 }
462}
463
464#[cfg(test)]
465use kernel::platform::watchdog::WatchDog;
466
467#[cfg(test)]
468fn test_runner(tests: &[&dyn Fn()]) {
469 unsafe {
470 let (board_kernel, esp32_c3_board, _chip, peripherals) = setup();
471
472 BOARD = Some(board_kernel);
473 PLATFORM = Some(&esp32_c3_board);
474 PERIPHERALS = Some(peripherals);
475 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
476
477 PLATFORM.map(|p| {
478 p.watchdog().setup();
479 });
480
481 for test in tests {
482 test();
483 }
484 }
485
486 loop {}
487}