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