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
68kernel::stack_size! {0x1000}
69
70struct RedboardArtemisAtp {
73 alarm: &'static capsules_core::alarm::AlarmDriver<
74 'static,
75 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
76 >,
77 led: &'static capsules_core::led::LedDriver<
78 'static,
79 LedHigh<'static, apollo3::gpio::GpioPin<'static>>,
80 1,
81 >,
82 gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
83 console: &'static capsules_core::console::Console<'static>,
84 i2c_master_slave: &'static capsules_core::i2c_master_slave_driver::I2CMasterSlaveDriver<
85 'static,
86 capsules_core::i2c_master_slave_combo::I2CMasterSlaveCombo<
87 'static,
88 apollo3::iom::Iom<'static>,
89 apollo3::ios::Ios<'static>,
90 >,
91 >,
92 spi_controller: &'static capsules_core::spi_controller::Spi<
93 'static,
94 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
95 'static,
96 apollo3::iom::Iom<'static>,
97 >,
98 >,
99 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
100 'static,
101 apollo3::ble::Ble<'static>,
102 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
103 >,
104 scheduler: &'static RoundRobinSched<'static>,
105 systick: cortexm4::systick::SysTick,
106}
107
108impl SyscallDriverLookup for RedboardArtemisAtp {
110 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
111 where
112 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
113 {
114 match driver_num {
115 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
116 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
117 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
118 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
119 capsules_core::i2c_master_slave_driver::DRIVER_NUM => f(Some(self.i2c_master_slave)),
120 capsules_core::spi_controller::DRIVER_NUM => f(Some(self.spi_controller)),
121 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
122 _ => f(None),
123 }
124 }
125}
126
127impl KernelResources<apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> for RedboardArtemisAtp {
128 type SyscallDriverLookup = Self;
129 type SyscallFilter = ();
130 type ProcessFault = ();
131 type Scheduler = RoundRobinSched<'static>;
132 type SchedulerTimer = cortexm4::systick::SysTick;
133 type WatchDog = ();
134 type ContextSwitchCallback = ();
135
136 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
137 self
138 }
139 fn syscall_filter(&self) -> &Self::SyscallFilter {
140 &()
141 }
142 fn process_fault(&self) -> &Self::ProcessFault {
143 &()
144 }
145 fn scheduler(&self) -> &Self::Scheduler {
146 self.scheduler
147 }
148 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
149 &self.systick
150 }
151 fn watchdog(&self) -> &Self::WatchDog {
152 &()
153 }
154 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
155 &()
156 }
157}
158
159#[inline(never)]
162unsafe fn setup() -> (
163 &'static kernel::Kernel,
164 &'static RedboardArtemisAtp,
165 &'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
166 &'static Apollo3DefaultPeripherals,
167) {
168 let peripherals = static_init!(Apollo3DefaultPeripherals, Apollo3DefaultPeripherals::new());
169
170 let mcu_ctrl = apollo3::mcuctrl::McuCtrl::new();
172 let pwr_ctrl = apollo3::pwrctrl::PwrCtrl::new();
173 let clkgen = apollo3::clkgen::ClkGen::new();
174
175 clkgen.set_clock_frequency(apollo3::clkgen::ClockFrequency::Freq48MHz);
176
177 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
179 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
180
181 let processes = components::process_array::ProcessArrayComponent::new()
183 .finalize(components::process_array_component_static!(NUM_PROCS));
184 PROCESSES = Some(processes);
185
186 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
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(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 &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}