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