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::virtualizers::virtual_alarm::MuxAlarm;
18use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
19use components::bme280::Bme280Component;
20use components::ccs811::Ccs811Component;
21use kernel::capabilities;
22use kernel::component::Component;
23use kernel::hil::i2c::I2CMaster;
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 RedboardArtemisNano> = 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;
67static mut BME280: Option<
69 &'static capsules_extra::bme280::Bme280<
70 'static,
71 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
72 >,
73> = None;
74static mut CCS811: Option<&'static capsules_extra::ccs811::Ccs811<'static>> = None;
75
76#[no_mangle]
78#[link_section = ".stack_buffer"]
79static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
80
81type BME280Sensor = components::bme280::Bme280ComponentType<
82 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
83>;
84type TemperatureDriver = components::temperature::TemperatureComponentType<BME280Sensor>;
85type HumidityDriver = components::humidity::HumidityComponentType<BME280Sensor>;
86
87struct RedboardArtemisNano {
90 alarm: &'static capsules_core::alarm::AlarmDriver<
91 'static,
92 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
93 >,
94 led: &'static capsules_core::led::LedDriver<
95 'static,
96 LedHigh<'static, apollo3::gpio::GpioPin<'static>>,
97 1,
98 >,
99 gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
100 console: &'static capsules_core::console::Console<'static>,
101 i2c_master:
102 &'static capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
103 spi_controller: &'static capsules_core::spi_controller::Spi<
104 'static,
105 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
106 'static,
107 apollo3::iom::Iom<'static>,
108 >,
109 >,
110 ble_radio: &'static capsules_extra::ble_advertising_driver::BLE<
111 'static,
112 apollo3::ble::Ble<'static>,
113 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
114 >,
115 temperature: &'static TemperatureDriver,
116 humidity: &'static HumidityDriver,
117 air_quality: &'static capsules_extra::air_quality::AirQualitySensor<'static>,
118 scheduler: &'static RoundRobinSched<'static>,
119 systick: cortexm4::systick::SysTick,
120}
121
122impl SyscallDriverLookup for RedboardArtemisNano {
124 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
125 where
126 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
127 {
128 match driver_num {
129 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
130 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
131 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
132 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
133 capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c_master)),
134 capsules_core::spi_controller::DRIVER_NUM => f(Some(self.spi_controller)),
135 capsules_extra::ble_advertising_driver::DRIVER_NUM => f(Some(self.ble_radio)),
136 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
137 capsules_extra::humidity::DRIVER_NUM => f(Some(self.humidity)),
138 capsules_extra::air_quality::DRIVER_NUM => f(Some(self.air_quality)),
139 _ => f(None),
140 }
141 }
142}
143
144impl KernelResources<apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> for RedboardArtemisNano {
145 type SyscallDriverLookup = Self;
146 type SyscallFilter = ();
147 type ProcessFault = ();
148 type Scheduler = RoundRobinSched<'static>;
149 type SchedulerTimer = cortexm4::systick::SysTick;
150 type WatchDog = ();
151 type ContextSwitchCallback = ();
152
153 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
154 self
155 }
156 fn syscall_filter(&self) -> &Self::SyscallFilter {
157 &()
158 }
159 fn process_fault(&self) -> &Self::ProcessFault {
160 &()
161 }
162 fn scheduler(&self) -> &Self::Scheduler {
163 self.scheduler
164 }
165 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
166 &self.systick
167 }
168 fn watchdog(&self) -> &Self::WatchDog {
169 &()
170 }
171 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
172 &()
173 }
174}
175
176#[inline(never)]
179unsafe fn setup() -> (
180 &'static kernel::Kernel,
181 &'static RedboardArtemisNano,
182 &'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
183 &'static Apollo3DefaultPeripherals,
184) {
185 let peripherals = static_init!(Apollo3DefaultPeripherals, Apollo3DefaultPeripherals::new());
186
187 let mcu_ctrl = apollo3::mcuctrl::McuCtrl::new();
189 let pwr_ctrl = apollo3::pwrctrl::PwrCtrl::new();
190 let clkgen = apollo3::clkgen::ClkGen::new();
191
192 clkgen.set_clock_frequency(apollo3::clkgen::ClockFrequency::Freq48MHz);
193
194 let process_mgmt_cap = create_capability!(capabilities::ProcessManagementCapability);
196 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
197
198 let processes = components::process_array::ProcessArrayComponent::new()
200 .finalize(components::process_array_component_static!(NUM_PROCS));
201 PROCESSES = Some(processes);
202
203 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
204
205 pwr_ctrl.enable_uart0();
207 pwr_ctrl.enable_iom0();
208 pwr_ctrl.enable_iom2();
209 pwr_ctrl.enable_ios();
210
211 peripherals.init();
212
213 peripherals
215 .gpio_port
216 .enable_uart(&peripherals.gpio_port[48], &peripherals.gpio_port[49]);
217 peripherals
219 .gpio_port
220 .enable_i2c(&peripherals.gpio_port[25], &peripherals.gpio_port[27]);
221 peripherals.gpio_port.enable_spi(
223 &peripherals.gpio_port[5],
224 &peripherals.gpio_port[7],
225 &peripherals.gpio_port[6],
226 );
227 peripherals
229 .gpio_port
230 .enable_i2c_slave(&peripherals.gpio_port[1], &peripherals.gpio_port[0]);
231
232 kernel::debug::assign_gpios(
234 Some(&peripherals.gpio_port[19]), None,
236 None,
237 );
238
239 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
241 .finalize(components::uart_mux_component_static!());
242
243 let console = components::console::ConsoleComponent::new(
245 board_kernel,
246 capsules_core::console::DRIVER_NUM,
247 uart_mux,
248 )
249 .finalize(components::console_component_static!());
250 components::debug_writer::DebugWriterComponent::new(
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[13], 1 => &peripherals.gpio_port[33], 2 => &peripherals.gpio_port[11], 3 => &peripherals.gpio_port[29], 5 => &peripherals.gpio_port[31] ),
276 )
277 .finalize(components::gpio_component_static!(apollo3::gpio::GpioPin));
278
279 let _ = peripherals.stimer.start();
282 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.stimer).finalize(
283 components::alarm_mux_component_static!(apollo3::stimer::STimer),
284 );
285 let alarm = components::alarm::AlarmDriverComponent::new(
286 board_kernel,
287 capsules_core::alarm::DRIVER_NUM,
288 mux_alarm,
289 )
290 .finalize(components::alarm_component_static!(apollo3::stimer::STimer));
291 ALARM = Some(mux_alarm);
292
293 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
295 .finalize(components::process_printer_text_component_static!());
296 PROCESS_PRINTER = Some(process_printer);
297
298 let i2c_master_buffer = static_init!(
300 [u8; capsules_core::i2c_master::BUFFER_LENGTH],
301 [0; capsules_core::i2c_master::BUFFER_LENGTH]
302 );
303 let i2c_master = static_init!(
304 capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
305 capsules_core::i2c_master::I2CMasterDriver::new(
306 &peripherals.iom2,
307 i2c_master_buffer,
308 board_kernel.create_grant(
309 capsules_core::i2c_master::DRIVER_NUM,
310 &memory_allocation_cap
311 )
312 )
313 );
314
315 peripherals.iom2.set_master_client(i2c_master);
316 peripherals.iom2.enable();
317
318 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.iom2, None)
319 .finalize(components::i2c_mux_component_static!(apollo3::iom::Iom));
320
321 let bme280 = Bme280Component::new(mux_i2c, 0x77)
322 .finalize(components::bme280_component_static!(apollo3::iom::Iom));
323 let temperature = components::temperature::TemperatureComponent::new(
324 board_kernel,
325 capsules_extra::temperature::DRIVER_NUM,
326 bme280,
327 )
328 .finalize(components::temperature_component_static!(BME280Sensor));
329 let humidity = components::humidity::HumidityComponent::new(
330 board_kernel,
331 capsules_extra::humidity::DRIVER_NUM,
332 bme280,
333 )
334 .finalize(components::humidity_component_static!(BME280Sensor));
335 BME280 = Some(bme280);
336
337 let ccs811 = Ccs811Component::new(mux_i2c, 0x5B)
338 .finalize(components::ccs811_component_static!(apollo3::iom::Iom));
339 let air_quality = components::air_quality::AirQualityComponent::new(
340 board_kernel,
341 capsules_extra::temperature::DRIVER_NUM,
342 ccs811,
343 )
344 .finalize(components::air_quality_component_static!());
345 CCS811 = Some(ccs811);
346
347 let mux_spi = components::spi::SpiMuxComponent::new(&peripherals.iom0).finalize(
349 components::spi_mux_component_static!(apollo3::iom::Iom<'static>),
350 );
351
352 let spi_controller = components::spi::SpiSyscallComponent::new(
355 board_kernel,
356 mux_spi,
357 kernel::hil::spi::cs::IntoChipSelect::<_, kernel::hil::spi::cs::ActiveLow>::into_cs(
358 &peripherals.gpio_port[35], ),
360 capsules_core::spi_controller::DRIVER_NUM,
361 )
362 .finalize(components::spi_syscall_component_static!(
363 apollo3::iom::Iom<'static>
364 ));
365
366 mcu_ctrl.enable_ble();
368 clkgen.enable_ble();
369 pwr_ctrl.enable_ble();
370 peripherals.ble.setup_clocks();
371 mcu_ctrl.reset_ble();
372 peripherals.ble.power_up();
373 peripherals.ble.ble_initialise();
374
375 let ble_radio = components::ble::BLEComponent::new(
376 board_kernel,
377 capsules_extra::ble_advertising_driver::DRIVER_NUM,
378 &peripherals.ble,
379 mux_alarm,
380 )
381 .finalize(components::ble_component_static!(
382 apollo3::stimer::STimer,
383 apollo3::ble::Ble,
384 ));
385
386 mcu_ctrl.print_chip_revision();
387
388 debug!("Initialization complete. Entering main loop");
389
390 extern "C" {
392 static _sapps: u8;
394 static _eapps: u8;
396 static mut _sappmem: u8;
398 static _eappmem: u8;
400 }
401
402 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
403 .finalize(components::round_robin_component_static!(NUM_PROCS));
404
405 let systick = cortexm4::systick::SysTick::new_with_calibration(48_000_000);
406
407 let artemis_nano = static_init!(
408 RedboardArtemisNano,
409 RedboardArtemisNano {
410 alarm,
411 led,
412 gpio,
413 console,
414 i2c_master,
415 spi_controller,
416 ble_radio,
417 temperature,
418 humidity,
419 air_quality,
420 scheduler,
421 systick,
422 }
423 );
424
425 let chip = static_init!(
426 apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
427 apollo3::chip::Apollo3::new(peripherals)
428 );
429 CHIP = Some(chip);
430
431 kernel::process::load_processes(
432 board_kernel,
433 chip,
434 core::slice::from_raw_parts(
435 core::ptr::addr_of!(_sapps),
436 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
437 ),
438 core::slice::from_raw_parts_mut(
439 core::ptr::addr_of_mut!(_sappmem),
440 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
441 ),
442 &FAULT_RESPONSE,
443 &process_mgmt_cap,
444 )
445 .unwrap_or_else(|err| {
446 debug!("Error loading processes!");
447 debug!("{:?}", err);
448 });
449
450 (board_kernel, artemis_nano, chip, peripherals)
451}
452
453#[no_mangle]
458pub unsafe fn main() {
459 apollo3::init();
460
461 #[cfg(test)]
462 test_main();
463
464 #[cfg(not(test))]
465 {
466 let (board_kernel, esp32_c3_board, chip, _peripherals) = setup();
467
468 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
469
470 board_kernel.kernel_loop(
471 esp32_c3_board,
472 chip,
473 None::<&kernel::ipc::IPC<{ NUM_PROCS as u8 }>>,
474 &main_loop_cap,
475 );
476 }
477}
478
479#[cfg(test)]
480use kernel::platform::watchdog::WatchDog;
481
482#[cfg(test)]
483fn test_runner(tests: &[&dyn Fn()]) {
484 unsafe {
485 let (board_kernel, esp32_c3_board, _chip, peripherals) = setup();
486
487 BOARD = Some(board_kernel);
488 PLATFORM = Some(&esp32_c3_board);
489 PERIPHERALS = Some(peripherals);
490 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
491
492 PLATFORM.map(|p| {
493 p.watchdog().setup();
494 });
495
496 for test in tests {
497 test();
498 }
499 }
500
501 loop {}
502}