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