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 core::ptr::addr_of;
41use core::ptr::addr_of_mut;
42
43use apollo3::chip::Apollo3DefaultPeripherals;
44use capsules_core::virtualizers::virtual_alarm::MuxAlarm;
45use capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm;
46use components::bme280::Bme280Component;
47use components::ccs811::Ccs811Component;
48use kernel::capabilities;
49use kernel::component::Component;
50use kernel::hil::flash::HasClient;
51use kernel::hil::hasher::Hasher;
52use kernel::hil::i2c::I2CMaster;
53use kernel::hil::led::LedHigh;
54use kernel::hil::spi::SpiMaster;
55use kernel::hil::time::Counter;
56use kernel::platform::{KernelResources, SyscallDriverLookup};
57use kernel::scheduler::round_robin::RoundRobinSched;
58use kernel::{create_capability, debug, static_init};
59
60#[cfg(feature = "atecc508a")]
61use {
62 capsules_core::virtualizers::virtual_i2c::MuxI2C,
63 components::atecc508a::Atecc508aComponent,
64 kernel::hil::entropy::Entropy32,
65 kernel::hil::gpio::{Configure, Output},
66 kernel::hil::rng::Rng,
67};
68
69#[cfg(any(feature = "chirp_i2c_moisture", feature = "dfrobot_i2c_rainfall"))]
70use capsules_core::virtualizers::virtual_i2c::MuxI2C;
71
72pub mod io;
74
75#[cfg(test)]
76mod tests;
77
78const NUM_PROCS: usize = 4;
80
81static mut PROCESSES: [Option<&'static dyn kernel::process::Process>; NUM_PROCS] = [None; 4];
83
84static mut CHIP: Option<&'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> = None;
86static mut PROCESS_PRINTER: Option<&'static capsules_system::process_printer::ProcessPrinterText> =
88 None;
89
90const FAULT_RESPONSE: capsules_system::process_policies::PanicFaultPolicy =
92 capsules_system::process_policies::PanicFaultPolicy {};
93
94static mut PERIPHERALS: Option<&'static Apollo3DefaultPeripherals> = None;
96#[cfg(test)]
98static mut BOARD: Option<&'static kernel::Kernel> = None;
99#[cfg(test)]
101static mut PLATFORM: Option<&'static LoRaThingsPlus> = None;
102#[cfg(test)]
104static mut MAIN_CAP: Option<&dyn kernel::capabilities::MainLoopCapability> = None;
105static mut ALARM: Option<&'static MuxAlarm<'static, apollo3::stimer::STimer<'static>>> = None;
107static mut BME280: Option<
109 &'static capsules_extra::bme280::Bme280<
110 'static,
111 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
112 >,
113> = None;
114static mut CCS811: Option<&'static capsules_extra::ccs811::Ccs811<'static>> = None;
115#[cfg(feature = "atecc508a")]
116static mut ATECC508A: Option<&'static capsules_extra::atecc508a::Atecc508a<'static>> = None;
117
118#[no_mangle]
120#[link_section = ".stack_buffer"]
121pub static mut STACK_MEMORY: [u8; 0x1000] = [0; 0x1000];
122
123const LORA_SPI_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhySPI as usize;
124const LORA_GPIO_DRIVER_NUM: usize = capsules_core::driver::NUM::LoRaPhyGPIO as usize;
125
126type ChirpI2cMoistureType = components::chirp_i2c_moisture::ChirpI2cMoistureComponentType<
127 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
128>;
129type DFRobotRainFallType = components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponentType<
130 capsules_core::virtualizers::virtual_alarm::VirtualMuxAlarm<
131 'static,
132 apollo3::stimer::STimer<'static>,
133 >,
134 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
135>;
136type BME280Sensor = components::bme280::Bme280ComponentType<
137 capsules_core::virtualizers::virtual_i2c::I2CDevice<'static, apollo3::iom::Iom<'static>>,
138>;
139
140type TemperatureDriver = components::temperature::TemperatureComponentType<BME280Sensor>;
141type HumidityDriver = components::humidity::HumidityComponentType<BME280Sensor>;
142
143#[cfg(feature = "atecc508a")]
144type Verifier = capsules_extra::atecc508a::Atecc508a<'static>;
145#[cfg(feature = "atecc508a")]
146type SignatureVerifyInMemoryKeys =
147 components::signature_verify_in_memory_keys::SignatureVerifyInMemoryKeysComponentType<
148 Verifier,
149 1,
150 64,
151 32,
152 64,
153 >;
154
155struct LoRaThingsPlus {
158 alarm: &'static capsules_core::alarm::AlarmDriver<
159 'static,
160 VirtualMuxAlarm<'static, apollo3::stimer::STimer<'static>>,
161 >,
162 led: &'static capsules_core::led::LedDriver<
163 'static,
164 LedHigh<'static, apollo3::gpio::GpioPin<'static>>,
165 1,
166 >,
167 gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
168 console: &'static capsules_core::console::Console<'static>,
169 i2c_master:
170 &'static capsules_core::i2c_master::I2CMasterDriver<'static, apollo3::iom::Iom<'static>>,
171 external_spi_controller: &'static capsules_core::spi_controller::Spi<
172 'static,
173 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
174 'static,
175 apollo3::iom::Iom<'static>,
176 >,
177 >,
178 sx1262_spi_controller: &'static capsules_core::spi_controller::Spi<
179 'static,
180 capsules_core::virtualizers::virtual_spi::VirtualSpiMasterDevice<
181 'static,
182 apollo3::iom::Iom<'static>,
183 >,
184 >,
185 sx1262_gpio: &'static capsules_core::gpio::GPIO<'static, apollo3::gpio::GpioPin<'static>>,
186 temperature: &'static TemperatureDriver,
187 humidity: &'static HumidityDriver,
188 air_quality: &'static capsules_extra::air_quality::AirQualitySensor<'static>,
189 moisture: Option<&'static components::moisture::MoistureComponentType<ChirpI2cMoistureType>>,
190 rainfall: Option<&'static components::rainfall::RainFallComponentType<DFRobotRainFallType>>,
191 rng: Option<
192 &'static capsules_core::rng::RngDriver<
193 'static,
194 capsules_core::rng::Entropy32ToRandom<
195 'static,
196 capsules_extra::atecc508a::Atecc508a<'static>,
197 >,
198 >,
199 >,
200 scheduler: &'static RoundRobinSched<'static>,
201 systick: cortexm4::systick::SysTick,
202 kv_driver: &'static capsules_extra::kv_driver::KVStoreDriver<
203 'static,
204 capsules_extra::virtual_kv::VirtualKVPermissions<
205 'static,
206 capsules_extra::kv_store_permissions::KVStorePermissions<
207 'static,
208 capsules_extra::tickv_kv_store::TicKVKVStore<
209 'static,
210 capsules_extra::tickv::TicKVSystem<
211 'static,
212 capsules_core::virtualizers::virtual_flash::FlashUser<
213 'static,
214 apollo3::flashctrl::FlashCtrl<'static>,
215 >,
216 capsules_extra::sip_hash::SipHasher24<'static>,
217 { apollo3::flashctrl::PAGE_SIZE },
218 >,
219 [u8; 8],
220 >,
221 >,
222 >,
223 >,
224}
225
226#[cfg(feature = "atecc508a")]
227fn atecc508a_wakeup() {
228 let peripherals = (unsafe { PERIPHERALS }).unwrap();
229
230 peripherals.gpio_port[6].make_output();
231 peripherals.gpio_port[6].clear();
232
233 for _i in 0..700 {
236 cortexm4::support::nop();
237 }
238
239 let _ = &peripherals
241 .gpio_port
242 .enable_i2c(&peripherals.gpio_port[6], &peripherals.gpio_port[5]);
243}
244
245#[cfg(feature = "atecc508a")]
246unsafe fn setup_atecc508a(
247 board_kernel: &'static kernel::Kernel,
248 memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
249 mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
250) -> &'static capsules_core::rng::RngDriver<
251 'static,
252 capsules_core::rng::Entropy32ToRandom<'static, capsules_extra::atecc508a::Atecc508a<'static>>,
253> {
254 let atecc508a = Atecc508aComponent::new(mux_i2c, 0x60, atecc508a_wakeup).finalize(
255 components::atecc508a_component_static!(apollo3::iom::Iom<'static>),
256 );
257 ATECC508A = Some(atecc508a);
258
259 let entropy_to_random = static_init!(
261 capsules_core::rng::Entropy32ToRandom<
262 'static,
263 capsules_extra::atecc508a::Atecc508a<'static>,
264 >,
265 capsules_core::rng::Entropy32ToRandom::new(atecc508a)
266 );
267 atecc508a.set_client(entropy_to_random);
268 let rng_local = static_init!(
270 capsules_core::rng::RngDriver<
271 'static,
272 capsules_core::rng::Entropy32ToRandom<
273 'static,
274 capsules_extra::atecc508a::Atecc508a<'static>,
275 >,
276 >,
277 capsules_core::rng::RngDriver::new(
278 entropy_to_random,
279 board_kernel.create_grant(capsules_core::rng::DRIVER_NUM, memory_allocation_cap)
280 )
281 );
282 entropy_to_random.set_client(rng_local);
283
284 rng_local
285}
286
287#[cfg(feature = "chirp_i2c_moisture")]
288unsafe fn setup_chirp_i2c_moisture(
289 board_kernel: &'static kernel::Kernel,
290 _memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
291 mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
292) -> &'static components::moisture::MoistureComponentType<ChirpI2cMoistureType> {
293 let chirp_moisture =
294 components::chirp_i2c_moisture::ChirpI2cMoistureComponent::new(mux_i2c, 0x20).finalize(
295 components::chirp_i2c_moisture_component_static!(apollo3::iom::Iom<'static>),
296 );
297
298 let moisture = components::moisture::MoistureComponent::new(
299 board_kernel,
300 capsules_extra::moisture::DRIVER_NUM,
301 chirp_moisture,
302 )
303 .finalize(components::moisture_component_static!(ChirpI2cMoistureType));
304
305 moisture
306}
307
308#[cfg(feature = "dfrobot_i2c_rainfall")]
309unsafe fn setup_dfrobot_i2c_rainfall(
310 board_kernel: &'static kernel::Kernel,
311 _memory_allocation_cap: &dyn capabilities::MemoryAllocationCapability,
312 mux_i2c: &'static MuxI2C<'static, apollo3::iom::Iom<'static>>,
313 mux_alarm: &'static MuxAlarm<'static, apollo3::stimer::STimer<'static>>,
314) -> &'static components::rainfall::RainFallComponentType<DFRobotRainFallType> {
315 let dfrobot_rainfall =
316 components::dfrobot_rainfall_sensor::DFRobotRainFallSensorComponent::new(
317 mux_i2c, 0x1D, mux_alarm,
318 )
319 .finalize(components::dfrobot_rainfall_sensor_component_static!(
320 apollo3::stimer::STimer<'static>,
321 apollo3::iom::Iom<'static>
322 ));
323
324 let rainfall = components::rainfall::RainFallComponent::new(
325 board_kernel,
326 capsules_extra::rainfall::DRIVER_NUM,
327 dfrobot_rainfall,
328 )
329 .finalize(components::rainfall_component_static!(DFRobotRainFallType));
330
331 rainfall
332}
333
334impl SyscallDriverLookup for LoRaThingsPlus {
336 fn with_driver<F, R>(&self, driver_num: usize, f: F) -> R
337 where
338 F: FnOnce(Option<&dyn kernel::syscall::SyscallDriver>) -> R,
339 {
340 match driver_num {
341 capsules_core::alarm::DRIVER_NUM => f(Some(self.alarm)),
342 capsules_core::led::DRIVER_NUM => f(Some(self.led)),
343 capsules_core::gpio::DRIVER_NUM => f(Some(self.gpio)),
344 capsules_core::console::DRIVER_NUM => f(Some(self.console)),
345 capsules_core::i2c_master::DRIVER_NUM => f(Some(self.i2c_master)),
346 capsules_core::spi_controller::DRIVER_NUM => f(Some(self.external_spi_controller)),
347 LORA_SPI_DRIVER_NUM => f(Some(self.sx1262_spi_controller)),
348 LORA_GPIO_DRIVER_NUM => f(Some(self.sx1262_gpio)),
349 capsules_extra::temperature::DRIVER_NUM => f(Some(self.temperature)),
350 capsules_extra::humidity::DRIVER_NUM => f(Some(self.humidity)),
351 capsules_extra::air_quality::DRIVER_NUM => f(Some(self.air_quality)),
352 capsules_extra::kv_driver::DRIVER_NUM => f(Some(self.kv_driver)),
353 capsules_core::rng::DRIVER_NUM => {
354 if let Some(rng) = self.rng {
355 f(Some(rng))
356 } else {
357 f(None)
358 }
359 }
360 capsules_extra::moisture::DRIVER_NUM => {
361 if let Some(moisture) = self.moisture {
362 f(Some(moisture))
363 } else {
364 f(None)
365 }
366 }
367 capsules_extra::rainfall::DRIVER_NUM => {
368 if let Some(rainfall) = self.rainfall {
369 f(Some(rainfall))
370 } else {
371 f(None)
372 }
373 }
374 _ => f(None),
375 }
376 }
377}
378
379impl KernelResources<apollo3::chip::Apollo3<Apollo3DefaultPeripherals>> for LoRaThingsPlus {
380 type SyscallDriverLookup = Self;
381 type SyscallFilter = ();
382 type ProcessFault = ();
383 type Scheduler = RoundRobinSched<'static>;
384 type SchedulerTimer = cortexm4::systick::SysTick;
385 type WatchDog = ();
386 type ContextSwitchCallback = ();
387
388 fn syscall_driver_lookup(&self) -> &Self::SyscallDriverLookup {
389 self
390 }
391 fn syscall_filter(&self) -> &Self::SyscallFilter {
392 &()
393 }
394 fn process_fault(&self) -> &Self::ProcessFault {
395 &()
396 }
397 fn scheduler(&self) -> &Self::Scheduler {
398 self.scheduler
399 }
400 fn scheduler_timer(&self) -> &Self::SchedulerTimer {
401 &self.systick
402 }
403 fn watchdog(&self) -> &Self::WatchDog {
404 &()
405 }
406 fn context_switch_callback(&self) -> &Self::ContextSwitchCallback {
407 &()
408 }
409}
410
411#[inline(never)]
414unsafe fn setup() -> (
415 &'static kernel::Kernel,
416 &'static LoRaThingsPlus,
417 &'static apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
418) {
419 let peripherals = static_init!(Apollo3DefaultPeripherals, Apollo3DefaultPeripherals::new());
420 PERIPHERALS = Some(peripherals);
421
422 let mcu_ctrl = apollo3::mcuctrl::McuCtrl::new();
424 let pwr_ctrl = apollo3::pwrctrl::PwrCtrl::new();
425 let clkgen = apollo3::clkgen::ClkGen::new();
426
427 clkgen.set_clock_frequency(apollo3::clkgen::ClockFrequency::Freq48MHz);
428
429 let memory_allocation_cap = create_capability!(capabilities::MemoryAllocationCapability);
431
432 let board_kernel = static_init!(kernel::Kernel, kernel::Kernel::new(&*addr_of!(PROCESSES)));
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::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(&*addr_of!(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 &mut *addr_of_mut!(PROCESSES),
942 board_kernel,
943 chip,
944 &FAULT_RESPONSE,
945 assigner,
946 storage_permissions_policy,
947 app_flash,
948 app_memory,
949 )
950 .finalize(components::process_loader_sequential_component_static!(
951 apollo3::chip::Apollo3<Apollo3DefaultPeripherals>,
952 kernel::process::ProcessStandardDebugFull,
953 NUM_PROCS,
954 ));
955
956 (board_kernel, artemis_nano, chip)
957}
958
959#[no_mangle]
964pub unsafe fn main() {
965 apollo3::init();
966
967 #[cfg(test)]
968 test_main();
969
970 #[cfg(not(test))]
971 {
972 let (board_kernel, sf_lora_thing_plus_board, chip) = setup();
973
974 let main_loop_cap = create_capability!(capabilities::MainLoopCapability);
975
976 board_kernel.kernel_loop(
977 sf_lora_thing_plus_board,
978 chip,
979 None::<&kernel::ipc::IPC<{ NUM_PROCS as u8 }>>,
980 &main_loop_cap,
981 );
982 }
983}
984
985#[cfg(test)]
986use kernel::platform::watchdog::WatchDog;
987
988#[cfg(test)]
989fn test_runner(tests: &[&dyn Fn()]) {
990 unsafe {
991 let (board_kernel, sf_lora_thing_plus_board, _chip) = setup();
992
993 BOARD = Some(board_kernel);
994 PLATFORM = Some(&sf_lora_thing_plus_board);
995 MAIN_CAP = Some(&create_capability!(capabilities::MainLoopCapability));
996
997 PLATFORM.map(|p| {
998 p.watchdog().setup();
999 });
1000
1001 for test in tests {
1002 test();
1003 }
1004 }
1005
1006 loop {}
1007}