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