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