/ firmware / src / bin / microvisor.rs
microvisor.rs
  1  #![no_std]
  2  #![no_main]
  3  #![feature(impl_trait_in_assoc_type)]
  4  #![deny(
  5      clippy::mem_forget,
  6      reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
  7      holding buffers for the duration of a data transfer."
  8  )]
  9  #![deny(clippy::large_stack_frames)]
 10  
 11  extern crate alloc;
 12  
 13  use defmt::info;
 14  use embassy_executor::Spawner;
 15  use embassy_time::{Duration, Timer};
 16  use esp_hal::{
 17      clock::CpuClock,
 18      delay::Delay,
 19      gpio::{Level, Output, OutputConfig},
 20      interrupt::software::SoftwareInterruptControl,
 21      timer::timg::TimerGroup,
 22  };
 23  use esp_storage::FlashStorage;
 24  use panic_rtt_target as _;
 25  
 26  use firmware::{
 27      boot,
 28      config::{app, board},
 29      networking::wifi,
 30  };
 31  
 32  esp_bootloader_esp_idf::esp_app_desc!();
 33  
 34  #[allow(
 35      clippy::large_stack_frames,
 36      reason = "it's not unusual to allocate larger buffers etc. in main"
 37  )]
 38  #[esp_rtos::main]
 39  async fn main(spawner: Spawner) -> ! {
 40      rtt_target::rtt_init_defmt!();
 41  
 42      let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
 43      let peripherals = esp_hal::init(config);
 44  
 45      esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 73744);
 46      // 32 KB — shares SRAM with main thread stack. Was 64 KB but
 47      // smoltcp::Interface::new() overflows the stack during embassy_net init.
 48      // PSRAM handles bulk allocations; keep this small.
 49      esp_alloc::heap_allocator!(size: 32 * 1024);
 50      esp_alloc::psram_allocator!(peripherals.PSRAM, esp_hal::psram);
 51  
 52      let timg0 = TimerGroup::new(peripherals.TIMG0);
 53      let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
 54      esp_rtos::start(timg0.timer0, sw_ints.software_interrupt0);
 55  
 56      info!("Embassy initialized!");
 57      info!("host_platform={}", board::PLATFORM);
 58      info!("active_user_key={}", app::ACTIVE_USER_KEY);
 59      info!("time_zone={}", app::time::ZONE);
 60      info!(
 61          "filesystem.sd_card: device={} fs_type={} data_log_path={}",
 62          app::sd_card::DEVICE,
 63          app::sd_card::FS_TYPE,
 64          app::sd_card::DATA_LOG_PATH
 65      );
 66      info!(
 67          "networking.ap_fallback={} ap_ssid={} ap_channel={} ap_max_connections={} ap_auth_mode={}",
 68          app::wifi::FALLBACK_TO_AP,
 69          app::wifi::ap::SSID,
 70          app::wifi::ap::CHANNEL,
 71          app::wifi::ap::MAX_CONNECTIONS,
 72          app::wifi::ap::AUTH_MODE,
 73      );
 74  
 75      let mut flash = FlashStorage::new(peripherals.FLASH).multicore_auto_park();
 76      boot::validate_ota_slot(&mut flash);
 77  
 78      let _sensor_power_relay = match board::i2c::LEGACY_POWER_GPIO {
 79          5 => Output::new(peripherals.GPIO5, Level::High, OutputConfig::default()),
 80          unsupported_gpio => {
 81              panic!("unsupported sensor_power_enable_gpio={}", unsupported_gpio)
 82          }
 83      };
 84      Delay::new().delay_millis(1_000);
 85  
 86      boot::initialize_sd_and_filesystem(
 87          peripherals.SPI2,
 88          peripherals.GPIO10,
 89          peripherals.GPIO11,
 90          peripherals.GPIO12,
 91          peripherals.GPIO13,
 92      );
 93  
 94      let (mut i2c0_bus, mut i2c1_bus) = boot::initialize_i2c_buses(
 95          peripherals.I2C0,
 96          peripherals.I2C1,
 97          peripherals.GPIO8,
 98          peripherals.GPIO9,
 99          peripherals.GPIO17,
100          peripherals.GPIO18,
101      );
102      boot::discover_i2c_devices(&mut i2c0_bus, &mut i2c1_bus).await;
103  
104      let credentials = wifi::load_credentials_or_default(&mut flash);
105  
106      let network = boot::initialize_networking(
107          spawner,
108          peripherals.WIFI,
109          peripherals.BT,
110          &credentials,
111      )
112      .await;
113  
114      boot::spawn_sensor_tasks(&spawner, &mut i2c0_bus, &mut i2c1_bus);
115      boot::start_services(&spawner, network.stack, flash);
116  
117      let _ble_controller = network.ble_controller;
118      loop {
119          Timer::after(Duration::from_secs(60)).await;
120      }
121  }