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