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