162 lines
4.6 KiB
Rust
162 lines
4.6 KiB
Rust
#![no_std]
|
|
#![no_main]
|
|
#![deny(
|
|
clippy::mem_forget,
|
|
reason = "mem::forget is generally not safe to do with esp_hal types, especially those \
|
|
holding buffers for the duration of a data transfer."
|
|
)]
|
|
|
|
use esp_backtrace as _;
|
|
use esp_println as _;
|
|
use esp_alloc as _;
|
|
|
|
use alloc::vec::Vec;
|
|
use alloc::string::String;
|
|
|
|
pub mod ecu;
|
|
pub mod wifi;
|
|
pub mod mdns;
|
|
pub mod streamer;
|
|
pub mod ota;
|
|
pub mod wibble;
|
|
|
|
use getrandom::Error;
|
|
|
|
pub fn getrandom_custom(dest: &mut [u8]) -> Result<(), Error> {
|
|
unsafe {
|
|
esp_hal::rng::Rng::new().read_into_raw(dest.as_mut_ptr(), dest.len())
|
|
};
|
|
Ok(())
|
|
}
|
|
use getrandom::register_custom_getrandom;
|
|
register_custom_getrandom!(getrandom_custom);
|
|
|
|
use esp_hal::{
|
|
timer::timg::TimerGroup,
|
|
clock::CpuClock,
|
|
};
|
|
|
|
use embassy_executor::Spawner;
|
|
|
|
use esp_radio::{
|
|
Controller,
|
|
wifi::{
|
|
ClientConfig,
|
|
ModeConfig,
|
|
}
|
|
};
|
|
|
|
use log::{info};
|
|
|
|
use crate::ecu::Ecu;
|
|
use crate::ota::Flasher;
|
|
|
|
extern crate alloc;
|
|
|
|
// This creates a default app-descriptor required by the esp-idf bootloader.
|
|
// For more information see: <https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/app_image_format.html#application-description>
|
|
esp_bootloader_esp_idf::esp_app_desc!();
|
|
|
|
const BUILD_ID: &str = env!("BUILD_ID");
|
|
|
|
// If the device has valid wifi credentials but you need to change them,
|
|
// build with FORCE_WIFI_CHOOSER.
|
|
// We should figure out some way to let the end-user do this (add a button?)
|
|
|
|
const FORCE_WIFI_CHOOSER : bool = option_env!("FORCE_WIFI_CHOOSER").is_some();
|
|
|
|
|
|
macro_rules! mk_static {
|
|
($t:ty,$val:expr) => {{
|
|
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
|
|
#[deny(unused_attributes)]
|
|
let x = STATIC_CELL.uninit().write(($val));
|
|
x
|
|
}};
|
|
}
|
|
|
|
fn wifi_creds_from_nvs(flasher: &mut Flasher) -> Option<(String, String)> {
|
|
let ssid = flasher.var("ssid");
|
|
let secret = flasher.var("secret");
|
|
if let (Some(ssid), Some(secret)) = (ssid, secret) {
|
|
Some((ssid, secret))
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
// #[main]
|
|
#[esp_rtos::main]
|
|
async fn main(s : Spawner) {
|
|
esp_println::logger::init_logger_from_env();
|
|
|
|
let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
|
|
let peripherals = esp_hal::init(config);
|
|
|
|
esp_alloc::heap_allocator!(size: 92 * 1024);
|
|
|
|
// handwaving: we need the timer to schedule tasks for the rtos,
|
|
// and we need the rtos so that the ble works (assumption:
|
|
// it needs to receive packets)
|
|
let timg0 = TimerGroup::new(peripherals.TIMG0);
|
|
let sw_interrupt =
|
|
esp_hal::interrupt::software::SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
|
|
esp_rtos::start(timg0.timer0, sw_interrupt.software_interrupt0);
|
|
|
|
|
|
info!("let's go! {}", BUILD_ID);
|
|
|
|
let mut ecu = Ecu::new(
|
|
peripherals.GPIO21,
|
|
peripherals.GPIO20,
|
|
peripherals.UART0
|
|
);
|
|
|
|
|
|
let mut flasher = Flasher::new(peripherals.FLASH, peripherals.SHA);
|
|
|
|
let esp_radio_ctrl = // esp_radio::init().expect("esp_radio init failed");
|
|
&*mk_static!(Controller<'static>, esp_radio::init().unwrap());
|
|
|
|
let (mut wifi_controller, interfaces) =
|
|
esp_radio::wifi::new(esp_radio_ctrl, peripherals.WIFI, Default::default()).unwrap();
|
|
let wifi_interface = interfaces.sta;
|
|
|
|
let wifi_creds = wifi_creds_from_nvs(&mut flasher);
|
|
info!("stored wifi creds {:?}", wifi_creds);
|
|
|
|
if !FORCE_WIFI_CHOOSER && let Some((wifi_ssid, wifi_secret)) = wifi_creds {
|
|
info!("using stored wifi creds");
|
|
let station_config = ModeConfig::Client(ClientConfig::default()
|
|
.with_ssid(wifi_ssid)
|
|
.with_password(wifi_secret));
|
|
|
|
wifi_controller.set_config(&station_config).expect("can't config wifi");
|
|
wifi_controller.start_async().await.expect("wifi failed to start");
|
|
|
|
crate::wifi::start_wifi(&s,
|
|
wifi_controller, wifi_interface,
|
|
flasher,
|
|
&mut ecu).await;
|
|
} else {
|
|
info!("no stored wifi creds");
|
|
|
|
let station_config = ModeConfig::Client(ClientConfig::default());
|
|
wifi_controller.set_config(&station_config).expect("can't config wifi");
|
|
wifi_controller.start_async().await.expect("wifi failed to start");
|
|
|
|
let wifi_networks : Vec<[u8;40]> =
|
|
crate::wifi::scan_networks(&mut wifi_controller).await.into_iter().map(
|
|
|ap| {
|
|
let mut s : [u8; 40] = [0u8; 40];
|
|
s[0] = (ap.signal_strength & 0x7f) as u8;
|
|
s[1..7].copy_from_slice(&ap.bssid);
|
|
let name = ap.ssid.as_bytes();
|
|
s[8..(8+name.len())].copy_from_slice(name);
|
|
s
|
|
}
|
|
).collect();
|
|
wibble::run_ble(&esp_radio_ctrl, peripherals.BT, wifi_networks, flasher).await;
|
|
}
|
|
}
|