1#![no_std]
34#![no_main]
35#![deny(missing_docs)]
36#![feature(custom_test_frameworks)]
37#![test_runner(test_runner)]
38#![reexport_test_harness_main = "test_main"]
39
40use apollo3::chip::Apollo3DefaultPeripherals;
41use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
42use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
43use components::bme280::Bme280Component;
44use components::ccs811::Ccs811Component;
45use kernel::capabilities;
46use kernel::component::Component;
47use kernel::hil::flash::HasClient;
48use kernel::hil::hasher::Hasher;
49use kernel::hil::i2c::I2CMaster;
50use kernel::hil::led::LedHigh;
51use kernel::hil::spi::SpiMaster;
52use kernel::hil::time::Counter;
53use kernel::platform::{KernelResources, SyscallDriverLookup};
54use kernel::process::ProcessArray;
55use kernel::scheduler::round_robin::RoundRobinSched;
56use kernel::{create_capability, debug, static_init};
57
58#[cfg(feature = "atecc508a")]
59use {
60 capsules_core::virtualizers::virtual_i2c::MuxI2C,
61 components::atecc508a::Atecc508aComponent,
62 kernel::hil::entropy::Entropy32,
63 kernel::hil::gpio::{Configure, Output},
64 kernel::hil::rng::Rng,
65};
66
67#[cfg(any(feature = "chirp_i2c_moisture", feature = "dfrobot_i2c_rainfall"))]
68use capsules_core::virtualizers::virtual_i2c::MuxI2C;
69
70pub mod io;
72
73#[cfg(test)]
74mod tests;
75
76const NUM_PROCS: usize = 4;
78
79static mut PROCESSES: Option<&'static ProcessArray<NUM_PROCS>> = None;
81
82static mut CHIP: Option<&'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> = None;
84static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
86 None;
87
88const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
90 capsules_system::process_policies::PanicFaultPolicy {};
91
92static mut PERIPHERALS: Option<&'static Apollo3DefaultPeripherals> = None;
94#[cfg(test)]
96static mut BOARD: Option<&'static kernel::Kernel> = None;
97#[cfg(test)]
99static mut PLATFORM: Option<&'static LoRaThingsPlus> = None;
100#[cfg(test)]
102static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
103static mut ALARM: Option<&'static MuxAlarm<'static, apollo3::stimer::STimer<'static>>> = None;
105static mut BME280: Option<
107 &'static capsules_extra::bme280::Bme280<
108 'static,
109 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
110 >,
111> = None;
112static mut CCS811: Option<&'static capsules_extra::ccs811::Ccs811<'static>> = None;
113#[cfg(feature = "atecc508a")]
114static mut ATECC508A: Option<&'static capsules_extra::atecc508a::Atecc508a<'static>> = None;
115
116kernel::stack_size! {0x1000}
117
118const LORA_SPI_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhySPI as usize;
119const LORA_GPIO_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhyGPIO as usize;
120
121type ChirpI2cMoistureType = components::chirp_i2c_moisture::ChirpI2cMoistureComponentType<
122 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
123>;
124type DFRobotRainFallType = components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponentType<
125 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
126 'static,
127 apollo3::stimer::STimer<'static>,
128 >,
129 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
130>;
131type BME280Sensor = components::bme280::Bme280ComponentType<
132 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
133>;
134
135type TemperatureDriver = components::temperature::TemperatureComponentType<BME280Sensor>;
136type HumidityDriver = components::humidity::HumidityComponentType<BME280Sensor>;
137
138#[cfg(feature = "atecc508a")]
139type Verifier = capsules_extra::atecc508a::Atecc508a<'static>;
140#[cfg(feature = "atecc508a")]
141type SignatureVerifyInMemoryKeys =
142 components::signature_verify_in_memory_keys::SignatureVerifyInMemoryKeysComponentType<
143 Verifier,
144 1,
145 64,
146 32,
147 64,
148 >;
149
150struct LoRaThingsPlus {
153 alarm: &'static capsules_core::alarm::AlarmDriver<
154 'static,
155 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
156 >,
157 led: &'static capsules_core::led::LedDriver<
158 'static,
159 LedHigh<'static, apollo3::gpio::GpioPin<'static>>,
160 1,
161 >,
162 gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
163 console: &'static capsules_core::console::Console<'static>,
164 i2c_master:
165 &'static capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
166 external_spi_controller: &'static capsules_core::spi_controller::Spi<
167 'static,
168 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
169 'static,
170 apollo3::iom::Iom<'static>,
171 >,
172 >,
173 sx1262_spi_controller: &'static capsules_core::spi_controller::Spi<
174 'static,
175 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
176 'static,
177 apollo3::iom::Iom<'static>,
178 >,
179 >,
180 sx1262_gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
181 temperature: &'static TemperatureDriver,
182 humidity: &'static HumidityDriver,
183 air_quality: &'static capsules_extra::air_quality::AirQualitySensor<'static>,
184 moisture: Option<&'static components::moisture::MoistureComponentType<ChirpI2cMoistureType>>,
185 rainfall: Option<&'static components::rainfall::RainFallComponentType<DFRobotRainFallType>>,
186 rng: Option<
187 &'static capsules_core::rng::RngDriver<
188 'static,
189 capsules_core::rng::Entropy32ToRandom<
190 'static,
191 capsules_extra::atecc508a::Atecc508a<'static>,
192 >,
193 >,
194 >,
195 scheduler: &'static RoundRobinSched<'static>,
196 systick: cortexm4::systick::SysTick,
197 kv_driver: &'static capsules_extra::kv_driver::KVStoreDriver<
198 'static,
199 capsules_extra::virtualizers::virtual_kv::VirtualKVPermissions<
200 'static,
201 capsules_extra::kv_store_permissions::KVStorePermissions<
202 'static,
203 capsules_extra::tickv_kv_store::TicKVKVStore<
204 'static,
205 capsules_extra::tickv::TicKVSystem<
206 'static,
207 capsules_core::virtualizers::virtual_flash::FlashUser<
208 'static,
209 apollo3::flashctrl::FlashCtrl<'static>,
210 >,
211 capsules_extra::sip_hash::SipHasher24<'static>,
212 { apollo3::flashctrl::PAGE_SIZE },
213 >,
214 [u8; 8],
215 >,
216 >,
217 >,
218 >,
219}
220
221#[cfg(feature = "atecc508a")]
222fn atecc508a_wakeup() {
223 let peripherals = (unsafe { PERIPHERALS }).unwrap();
224
225 peripherals.gpio_port[6].make_output();
226 peripherals.gpio_port[6].clear();
227
228 for _i in 0..700 {
231 cortexm4::support::nop();
232 }
233
234 let _ = &peripherals
236 .gpio_port
237 .enable_i2c(&peripherals.gpio_port[6], &peripherals.gpio_port[5]);
238}
239
240#[cfg(feature = "atecc508a")]
241unsafe fn setup_atecc508a(
242 board_kernel: &'static kernel::Kernel,
243 memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
244 mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
245) -> &'static capsules_core::rng::RngDriver<
246 'static,
247 capsules_core::rng::Entropy32ToRandom<'static, capsules_extra::atecc508a::Atecc508a<'static>>,
248> {
249 let atecc508a = Atecc508aComponent::new(mux_i2c, 0x60, atecc508a_wakeup).finalize(
250 components::atecc508a_component_static!(apollo3::iom::Iom<'static>),
251 );
252 ATECC508A = Some(atecc508a);
253
254 let entropy_to_random = static_init!(
256 capsules_core::rng::Entropy32ToRandom<
257 'static,
258 capsules_extra::atecc508a::Atecc508a<'static>,
259 >,
260 capsules_core::rng::Entropy32ToRandom::new(atecc508a)
261 );
262 atecc508a.set_client(entropy_to_random);
263 let rng_local = static_init!(
265 capsules_core::rng::RngDriver<
266 'static,
267 capsules_core::rng::Entropy32ToRandom<
268 'static,
269 capsules_extra::atecc508a::Atecc508a<'static>,
270 >,
271 >,
272 capsules_core::rng::RngDriver::new(
273 entropy_to_random,
274 board_kernel.create_grant(capsules_core::rng::DRIVER_NUM, memory_allocation_cap)
275 )
276 );
277 entropy_to_random.set_client(rng_local);
278
279 rng_local
280}
281
282#[cfg(feature = "chirp_i2c_moisture")]
283unsafe fn setup_chirp_i2c_moisture(
284 board_kernel: &'static kernel::Kernel,
285 _memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
286 mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
287) -> &'static components::moisture::MoistureComponentType<ChirpI2cMoistureType> {
288 let chirp_moisture =
289 components::chirp_i2c_moisture::ChirpI2cMoistureComponent::new(mux_i2c, 0x20).finalize(
290 components::chirp_i2c_moisture_component_static!(apollo3::iom::Iom<'static>),
291 );
292
293 let moisture = components::moisture::MoistureComponent::new(
294 board_kernel,
295 capsules_extra::moisture::DRIVER_NUM,
296 chirp_moisture,
297 )
298 .finalize(components::moisture_component_static!(ChirpI2cMoistureType));
299
300 moisture
301}
302
303#[cfg(feature = "dfrobot_i2c_rainfall")]
304unsafe fn setup_dfrobot_i2c_rainfall(
305 board_kernel: &'static kernel::Kernel,
306 _memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
307 mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
308 mux_alarm: &'static MuxAlarm<'static, apollo3::stimer::STimer<'static>>,
309) -> &'static components::rainfall::RainFallComponentType<DFRobotRainFallType> {
310 let dfrobot_rainfall =
311 components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponent::new(
312 mux_i2c, 0x1D, mux_alarm,
313 )
314 .finalize(components::dfrobot_rainfall_sensor_component_static!(
315 apollo3::stimer::STimer<'static>,
316 apollo3::iom::Iom<'static>
317 ));
318
319 let rainfall = components::rainfall::RainFallComponent::new(
320 board_kernel,
321 capsules_extra::rainfall::DRIVER_NUM,
322 dfrobot_rainfall,
323 )
324 .finalize(components::rainfall_component_static!(DFRobotRainFallType));
325
326 rainfall
327}
328
329impl SyscallDriverLookup for LoRaThingsPlus {
331 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
332 where
333 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
334 {
335 match driver_num {
336 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
337 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
338 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
339 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
340 capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c_master)),
341 capsules_core::spi_controller::DRIVER_NUM => f(Some(self.external_spi_controller)),
342 LORA_SPI_DRIVER_NUM => f(Some(self.sx1262_spi_controller)),
343 LORA_GPIO_DRIVER_NUM => f(Some(self.sx1262_gpio)),
344 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
345 capsules_extra::humidity::DRIVER_NUM => f(Some(self.humidity)),
346 capsules_extra::air_quality::DRIVER_NUM => f(Some(self.air_quality)),
347 capsules_extra::kv_driver::DRIVER_NUM => f(Some(self.kv_driver)),
348 capsules_core::rng::DRIVER_NUM => {
349 if let Some(rng) = self.rng {
350 f(Some(rng))
351 } else {
352 f(None)
353 }
354 }
355 capsules_extra::moisture::DRIVER_NUM => {
356 if let Some(moisture) = self.moisture {
357 f(Some(moisture))
358 } else {
359 f(None)
360 }
361 }
362 capsules_extra::rainfall::DRIVER_NUM => {
363 if let Some(rainfall) = self.rainfall {
364 f(Some(rainfall))
365 } else {
366 f(None)
367 }
368 }
369 _ => f(None),
370 }
371 }
372}
373
374impl KernelResources<apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> for LoRaThingsPlus {
375 type SyscallDriverLookup = Self;
376 type SyscallFilter = ();
377 type ProcessFault = ();
378 type Scheduler = RoundRobinSched<'static>;
379 type SchedulerTimer = cortexm4::systick::SysTick;
380 type WatchDog = ();
381 type ContextSwitchCallback = ();
382
383 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
384 self
385 }
386 fn syscall_filter(&self) -> &Self::SyscallFilter {
387 &()
388 }
389 fn process_fault(&self) -> &Self::ProcessFault {
390 &()
391 }
392 fn scheduler(&self) -> &Self::Scheduler {
393 self.scheduler
394 }
395 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
396 &self.systick
397 }
398 fn watchdog(&self) -> &Self::WatchDog {
399 &()
400 }
401 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
402 &()
403 }
404}
405
406#[inline(never)]
409unsafe fn setup() -> (
410 &'static kernel::Kernel,
411 &'static LoRaThingsPlus,
412 &'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
413) {
414 let peripherals = static_init!(Apollo3DefaultPeripherals, Apollo3DefaultPeripherals::new());
415 PERIPHERALS = Some(peripherals);
416
417 let mcu_ctrl = apollo3::mcuctrl::McuCtrl::new();
419 let pwr_ctrl = apollo3::pwrctrl::PwrCtrl::new();
420 let clkgen = apollo3::clkgen::ClkGen::new();
421
422 clkgen.set_clock_frequency(apollo3::clkgen::ClockFrequency::Freq48MHz);
423
424 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
426
427 let processes = components::process_array::ProcessArrayComponent::new()
429 .finalize(components::process_array_component_static!(NUM_PROCS));
430 PROCESSES = Some(processes);
431
432 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(processes.as_slice()));
433
434 pwr_ctrl.enable_uart0();
436 pwr_ctrl.enable_iom0();
437 pwr_ctrl.enable_iom2();
438 pwr_ctrl.enable_iom3();
439
440 peripherals.init();
441
442 peripherals
444 .gpio_port
445 .enable_uart(&peripherals.gpio_port[48], &peripherals.gpio_port[49]);
446 peripherals.gpio_port.enable_spi(
448 &peripherals.gpio_port[27],
449 &peripherals.gpio_port[28],
450 &peripherals.gpio_port[25],
451 );
452 peripherals.gpio_port.enable_spi(
454 &peripherals.gpio_port[42],
455 &peripherals.gpio_port[38],
456 &peripherals.gpio_port[43],
457 );
458 peripherals.gpio_port.enable_sx1262_radio_pins();
460
461 kernel::debug::assign_gpios(Some(&peripherals.gpio_port[26]), None, None);
463
464 let uart_mux = components::console::UartMuxComponent::new(&peripherals.uart0, 115200)
466 .finalize(components::uart_mux_component_static!());
467
468 let console = components::console::ConsoleComponent::new(
470 board_kernel,
471 capsules_core::console::DRIVER_NUM,
472 uart_mux,
473 )
474 .finalize(components::console_component_static!());
475 components::debug_writer::DebugWriterComponent::new(
477 uart_mux,
478 create_capability!(capabilities::SetDebugWriterCapability),
479 )
480 .finalize(components::debug_writer_component_static!());
481
482 let led = components::led::LedsComponent::new().finalize(components::led_component_static!(
484 LedHigh<'static, apollo3::gpio::GpioPin>,
485 LedHigh::new(&peripherals.gpio_port[19]),
486 ));
487
488 let gpio = components::gpio::GpioComponent::new(
491 board_kernel,
492 capsules_core::gpio::DRIVER_NUM,
493 components::gpio_component_helper!(
494 apollo3::gpio::GpioPin,
495 0 => &peripherals.gpio_port[13], 1 => &peripherals.gpio_port[12], 2 => &peripherals.gpio_port[32], 3 => &peripherals.gpio_port[35], 4 => &peripherals.gpio_port[34], ),
501 )
502 .finalize(components::gpio_component_static!(apollo3::gpio::GpioPin));
503
504 let _ = peripherals.stimer.start();
507 let mux_alarm = components::alarm::AlarmMuxComponent::new(&peripherals.stimer).finalize(
508 components::alarm_mux_component_static!(apollo3::stimer::STimer),
509 );
510 let alarm = components::alarm::AlarmDriverComponent::new(
511 board_kernel,
512 capsules_core::alarm::DRIVER_NUM,
513 mux_alarm,
514 )
515 .finalize(components::alarm_component_static!(apollo3::stimer::STimer));
516 ALARM = Some(mux_alarm);
517
518 let process_printer = components::process_printer::ProcessPrinterTextComponent::new()
520 .finalize(components::process_printer_text_component_static!());
521 PROCESS_PRINTER = Some(process_printer);
522
523 peripherals
525 .gpio_port
526 .enable_i2c(&peripherals.gpio_port[6], &peripherals.gpio_port[5]);
527
528 let i2c_master_buffer = static_init!(
530 [u8; capsules_core::i2c_master::BUFFER_LENGTH],
531 [0; capsules_core::i2c_master::BUFFER_LENGTH]
532 );
533 let i2c_master = static_init!(
534 capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
535 capsules_core::i2c_master::I2CMasterDriver::new(
536 &peripherals.iom0,
537 i2c_master_buffer,
538 board_kernel.create_grant(
539 capsules_core::i2c_master::DRIVER_NUM,
540 &memory_allocation_cap
541 )
542 )
543 );
544
545 peripherals.iom0.set_master_client(i2c_master);
546 peripherals.iom0.enable();
547
548 let mux_i2c = components::i2c::I2CMuxComponent::new(&peripherals.iom0, None).finalize(
549 components::i2c_mux_component_static!(apollo3::iom::Iom<'static>),
550 );
551
552 let bme280 = Bme280Component::new(mux_i2c, 0x77).finalize(
553 components::bme280_component_static!(apollo3::iom::Iom<'static>),
554 );
555 let temperature = components::temperature::TemperatureComponent::new(
556 board_kernel,
557 capsules_extra::temperature::DRIVER_NUM,
558 bme280,
559 )
560 .finalize(components::temperature_component_static!(BME280Sensor));
561 let humidity = components::humidity::HumidityComponent::new(
562 board_kernel,
563 capsules_extra::humidity::DRIVER_NUM,
564 bme280,
565 )
566 .finalize(components::humidity_component_static!(BME280Sensor));
567 BME280 = Some(bme280);
568
569 let ccs811 = Ccs811Component::new(mux_i2c, 0x5B).finalize(
570 components::ccs811_component_static!(apollo3::iom::Iom<'static>),
571 );
572 let air_quality = components::air_quality::AirQualityComponent::new(
573 board_kernel,
574 capsules_extra::temperature::DRIVER_NUM,
575 ccs811,
576 )
577 .finalize(components::air_quality_component_static!());
578 CCS811 = Some(ccs811);
579
580 #[cfg(feature = "chirp_i2c_moisture")]
581 let moisture = Some(setup_chirp_i2c_moisture(
582 board_kernel,
583 &memory_allocation_cap,
584 mux_i2c,
585 ));
586 #[cfg(not(feature = "chirp_i2c_moisture"))]
587 let moisture = None;
588
589 #[cfg(feature = "dfrobot_i2c_rainfall")]
590 let rainfall = Some(setup_dfrobot_i2c_rainfall(
591 board_kernel,
592 &memory_allocation_cap,
593 mux_i2c,
594 mux_alarm,
595 ));
596 #[cfg(not(feature = "dfrobot_i2c_rainfall"))]
597 let rainfall = None;
598
599 #[cfg(feature = "atecc508a")]
600 let rng = Some(setup_atecc508a(
601 board_kernel,
602 &memory_allocation_cap,
603 mux_i2c,
604 ));
605 #[cfg(not(feature = "atecc508a"))]
606 let rng = None;
607
608 let external_mux_spi = components::spi::SpiMuxComponent::new(&peripherals.iom2).finalize(
610 components::spi_mux_component_static!(apollo3::iom::Iom<'static>),
611 );
612
613 let external_spi_controller = components::spi::SpiSyscallComponent::new(
614 board_kernel,
615 external_mux_spi,
616 kernel::hil::spi::cs::IntoChipSelect::<_, kernel::hil::spi::cs::ActiveLow>::into_cs(
617 &peripherals.gpio_port[11], ),
619 capsules_core::spi_controller::DRIVER_NUM,
620 )
621 .finalize(components::spi_syscall_component_static!(
622 apollo3::iom::Iom<'static>
623 ));
624
625 let sx1262_mux_spi = components::spi::SpiMuxComponent::new(&peripherals.iom3).finalize(
627 components::spi_mux_component_static!(apollo3::iom::Iom<'static>),
628 );
629
630 let sx1262_spi_controller = components::spi::SpiSyscallComponent::new(
631 board_kernel,
632 sx1262_mux_spi,
633 kernel::hil::spi::cs::IntoChipSelect::<_, kernel::hil::spi::cs::ActiveLow>::into_cs(
634 &peripherals.gpio_port[36], ),
636 LORA_SPI_DRIVER_NUM,
637 )
638 .finalize(components::spi_syscall_component_static!(
639 apollo3::iom::Iom<'static>
640 ));
641 peripherals
642 .iom3
643 .specify_chip_select(kernel::hil::spi::cs::IntoChipSelect::<
644 _,
645 kernel::hil::spi::cs::ActiveLow,
646 >::into_cs(
647 &peripherals.gpio_port[36], ))
649 .unwrap();
650
651 let sx1262_gpio = components::gpio::GpioComponent::new(
652 board_kernel,
653 LORA_GPIO_DRIVER_NUM,
654 components::gpio_component_helper!(
655 apollo3::gpio::GpioPin,
656 0 => &peripherals.gpio_port[36], 1 => &peripherals.gpio_port[39], 2 => &peripherals.gpio_port[40], 3 => &peripherals.gpio_port[47], 4 => &peripherals.gpio_port[44], ),
662 )
663 .finalize(components::gpio_component_static!(apollo3::gpio::GpioPin));
664
665 mcu_ctrl.disable_ble();
667
668 let flash_ctrl_read_buf = static_init!(
670 [u8; apollo3::flashctrl::PAGE_SIZE],
671 [0; apollo3::flashctrl::PAGE_SIZE]
672 );
673 let page_buffer = static_init!(
674 apollo3::flashctrl::Apollo3Page,
675 apollo3::flashctrl::Apollo3Page::default()
676 );
677
678 let mux_flash = components::flash::FlashMuxComponent::new(&peripherals.flash_ctrl).finalize(
679 components::flash_mux_component_static!(apollo3::flashctrl::FlashCtrl),
680 );
681
682 let sip_hash = static_init!(
684 capsules_extra::sip_hash::SipHasher24,
685 capsules_extra::sip_hash::SipHasher24::new()
686 );
687 kernel::deferred_call::DeferredCallClient::register(sip_hash);
688
689 let tickv = components::tickv::TicKVComponent::new(
691 sip_hash,
692 mux_flash, core::ptr::addr_of!(_skv_data) as usize / apollo3::flashctrl::PAGE_SIZE, core::ptr::addr_of!(_lkv_data) as usize - apollo3::flashctrl::PAGE_SIZE,
696 flash_ctrl_read_buf, page_buffer, )
699 .finalize(components::tickv_component_static!(
700 apollo3::flashctrl::FlashCtrl,
701 capsules_extra::sip_hash::SipHasher24,
702 { apollo3::flashctrl::PAGE_SIZE }
703 ));
704 HasClient::set_client(&peripherals.flash_ctrl, mux_flash);
705 sip_hash.set_client(tickv);
706
707 let kv_store = components::kv::TicKVKVStoreComponent::new(tickv).finalize(
708 components::tickv_kv_store_component_static!(
709 capsules_extra::tickv::TicKVSystem<
710 capsules_core::virtualizers::virtual_flash::FlashUser<
711 apollo3::flashctrl::FlashCtrl,
712 >,
713 capsules_extra::sip_hash::SipHasher24<'static>,
714 { apollo3::flashctrl::PAGE_SIZE },
715 >,
716 capsules_extra::tickv::TicKVKeyType,
717 ),
718 );
719
720 let kv_store_permissions = components::kv::KVStorePermissionsComponent::new(kv_store).finalize(
721 components::kv_store_permissions_component_static!(
722 capsules_extra::tickv_kv_store::TicKVKVStore<
723 capsules_extra::tickv::TicKVSystem<
724 capsules_core::virtualizers::virtual_flash::FlashUser<
725 apollo3::flashctrl::FlashCtrl,
726 >,
727 capsules_extra::sip_hash::SipHasher24<'static>,
728 { apollo3::flashctrl::PAGE_SIZE },
729 >,
730 capsules_extra::tickv::TicKVKeyType,
731 >
732 ),
733 );
734
735 let mux_kv = components::kv::KVPermissionsMuxComponent::new(kv_store_permissions).finalize(
736 components::kv_permissions_mux_component_static!(
737 capsules_extra::kv_store_permissions::KVStorePermissions<
738 capsules_extra::tickv_kv_store::TicKVKVStore<
739 capsules_extra::tickv::TicKVSystem<
740 capsules_core::virtualizers::virtual_flash::FlashUser<
741 apollo3::flashctrl::FlashCtrl,
742 >,
743 capsules_extra::sip_hash::SipHasher24<'static>,
744 { apollo3::flashctrl::PAGE_SIZE },
745 >,
746 capsules_extra::tickv::TicKVKeyType,
747 >,
748 >
749 ),
750 );
751
752 let virtual_kv_driver = components::kv::VirtualKVPermissionsComponent::new(mux_kv).finalize(
753 components::virtual_kv_permissions_component_static!(
754 capsules_extra::kv_store_permissions::KVStorePermissions<
755 capsules_extra::tickv_kv_store::TicKVKVStore<
756 capsules_extra::tickv::TicKVSystem<
757 capsules_core::virtualizers::virtual_flash::FlashUser<
758 apollo3::flashctrl::FlashCtrl,
759 >,
760 capsules_extra::sip_hash::SipHasher24<'static>,
761 { apollo3::flashctrl::PAGE_SIZE },
762 >,
763 capsules_extra::tickv::TicKVKeyType,
764 >,
765 >
766 ),
767 );
768
769 let kv_driver = components::kv::KVDriverComponent::new(
770 virtual_kv_driver,
771 board_kernel,
772 capsules_extra::kv_driver::DRIVER_NUM,
773 )
774 .finalize(components::kv_driver_component_static!(
775 capsules_extra::virtualizers::virtual_kv::VirtualKVPermissions<
776 capsules_extra::kv_store_permissions::KVStorePermissions<
777 capsules_extra::tickv_kv_store::TicKVKVStore<
778 capsules_extra::tickv::TicKVSystem<
779 capsules_core::virtualizers::virtual_flash::FlashUser<
780 apollo3::flashctrl::FlashCtrl,
781 >,
782 capsules_extra::sip_hash::SipHasher24<'static>,
783 { apollo3::flashctrl::PAGE_SIZE },
784 >,
785 capsules_extra::tickv::TicKVKeyType,
786 >,
787 >,
788 >
789 ));
790
791 mcu_ctrl.print_chip_revision();
792
793 debug!("Initialization complete. Entering main loop");
794
795 extern "C" {
797 static _sapps: u8;
799 static _eapps: u8;
801 static mut _sappmem: u8;
803 static _eappmem: u8;
805 static _skv_data: u8;
807 static _lkv_data: u8;
809 }
810
811 let scheduler = components::sched::round_robin::RoundRobinComponent::new(processes)
812 .finalize(components::round_robin_component_static!(NUM_PROCS));
813
814 let systick = cortexm4::systick::SysTick::new_with_calibration(48_000_000);
815
816 let artemis_nano = static_init!(
817 LoRaThingsPlus,
818 LoRaThingsPlus {
819 alarm,
820 led,
821 gpio,
822 console,
823 i2c_master,
824 external_spi_controller,
825 sx1262_spi_controller,
826 sx1262_gpio,
827 temperature,
828 humidity,
829 air_quality,
830 moisture,
831 rainfall,
832 rng,
833 scheduler,
834 systick,
835 kv_driver,
836 }
837 );
838
839 let chip = static_init!(
840 apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
841 apollo3::chip::Apollo3::new(peripherals)
842 );
843 CHIP = Some(chip);
844
845 let checking_policy;
846 #[cfg(feature = "atecc508a")]
847 {
848 let sha = components::sha::ShaSoftware256Component::new()
853 .finalize(components::sha_software_256_component_static!());
854
855 let public_key = static_init!(
871 [u8; 64],
872 [
873 0x14, 0x14, 0xc4, 0xc5, 0xa0, 0xd2, 0xfd, 0xa0, 0x5a, 0x46, 0x9a, 0x0e, 0x82, 0xa7,
874 0x7e, 0x75, 0x85, 0x03, 0x2a, 0xf6, 0x1a, 0x25, 0x2a, 0x91, 0x1d, 0x41, 0xf8, 0xcf,
875 0xd6, 0x76, 0x05, 0xd6, 0x3c, 0x6a, 0xcf, 0x9d, 0x98, 0x8c, 0xfa, 0x45, 0x1e, 0xfb,
876 0x9d, 0x90, 0xaf, 0xdf, 0x16, 0xc8, 0xa4, 0xe5, 0x17, 0x74, 0x01, 0xeb, 0xcd, 0x91,
877 0x0a, 0xa3, 0x05, 0xd5, 0x84, 0xaa, 0x6a, 0x56
878 ]
879 );
880 let verifying_keys = kernel::static_init!([&'static mut [u8; 64]; 1], [public_key]);
881
882 let verifier_multiple_keys =
884 components::signature_verify_in_memory_keys::SignatureVerifyInMemoryKeysComponent::new(
885 ATECC508A.unwrap(),
886 verifying_keys,
887 )
888 .finalize(
889 components::signature_verify_in_memory_keys_component_static!(
890 Verifier, 1, 64, 32, 64,
891 ),
892 );
893
894 checking_policy = components::appid::checker_signature::AppCheckerSignatureComponent::new(
895 sha,
896 verifier_multiple_keys,
897 tock_tbf::types::TbfFooterV2CredentialsType::EcdsaNistP256,
898 )
899 .finalize(components::app_checker_signature_component_static!(
900 SignatureVerifyInMemoryKeys,
901 capsules_extra::sha256::Sha256Software<'static>,
902 32,
903 64,
904 ));
905 };
906 #[cfg(not(feature = "atecc508a"))]
907 {
908 checking_policy = components::appid::checker_null::AppCheckerNullComponent::new()
909 .finalize(components::app_checker_null_component_static!());
910 }
911
912 let assigner = components::appid::assigner_name::AppIdAssignerNamesComponent::new()
914 .finalize(components::appid_assigner_names_component_static!());
915
916 let checker = components::appid::checker::ProcessCheckerMachineComponent::new(checking_policy)
918 .finalize(components::process_checker_machine_component_static!());
919
920 let storage_permissions_policy =
921 components::storage_permissions::tbf_header::StoragePermissionsTbfHeaderComponent::new()
922 .finalize(
923 components::storage_permissions_tbf_header_component_static!(
924 apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
925 kernel::process::ProcessStandardDebugFull,
926 ),
927 );
928
929 let app_flash = core::slice::from_raw_parts(
930 core::ptr::addr_of!(_sapps),
931 core::ptr::addr_of!(_eapps) as usize - core::ptr::addr_of!(_sapps) as usize,
932 );
933 let app_memory = core::slice::from_raw_parts_mut(
934 core::ptr::addr_of_mut!(_sappmem),
935 core::ptr::addr_of!(_eappmem) as usize - core::ptr::addr_of!(_sappmem) as usize,
936 );
937
938 let _loader = components::loader::sequential::ProcessLoaderSequentialComponent::new(
940 checker,
941 board_kernel,
942 chip,
943 &FAULT_RESPONSE,
944 assigner,
945 storage_permissions_policy,
946 app_flash,
947 app_memory,
948 )
949 .finalize(components::process_loader_sequential_component_static!(
950 apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
951 kernel::process::ProcessStandardDebugFull,
952 NUM_PROCS,
953 ));
954
955 (board_kernel, artemis_nano, chip)
956}
957
958#[no_mangle]
963pub unsafe fn main() {
964 apollo3::init();
965
966 #[cfg(test)]
967 test_main();
968
969 #[cfg(not(test))]
970 {
971 let (board_kernel, sf_lora_thing_plus_board, chip) = setup();
972
973 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
974
975 board_kernel.kernel_loop(
976 sf_lora_thing_plus_board,
977 chip,
978 None::<&kernel::ipc::IPC<{ NUM_PROCS as u8 }>>,
979 &main_loop_cap,
980 );
981 }
982}
983
984#[cfg(test)]
985use kernel::platform::watchdog::WatchDog;
986
987#[cfg(test)]
988fn test_runner(tests: &[&dyn Fn()]) {
989 unsafe {
990 let (board_kernel, sf_lora_thing_plus_board, _chip) = setup();
991
992 BOARD = Some(board_kernel);
993 PLATFORM = Some(&sf_lora_thing_plus_board);
994 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
995
996 PLATFORM.map(|p| {
997 p.watchdog().setup();
998 });
999
1000 for test in tests {
1001 test();
1002 }
1003 }
1004
1005 loop {}
1006}