/ firmware / examples / esp32s3 / http_hello.rs
http_hello.rs
  1  #![no_std]
  2  #![no_main]
  3  #![feature(impl_trait_in_assoc_type)]
  4  
  5  extern crate alloc;
  6  
  7  use defmt::info;
  8  use embassy_executor::Spawner;
  9  use embassy_net::{Runner, StackResources};
 10  use embassy_time::{Duration, Timer, with_timeout};
 11  use esp_hal::{
 12      clock::CpuClock,
 13      interrupt::software::SoftwareInterruptControl,
 14      rng::Rng,
 15      timer::timg::TimerGroup,
 16  };
 17  use esp_radio::wifi::{Config, ControllerConfig, Interface, WifiController, sta::StationConfig};
 18  use panic_rtt_target as _;
 19  use picoserve::AppBuilder;
 20  use static_cell::StaticCell;
 21  
 22  use firmware::{config::app, services::http::HttpAppProps};
 23  
 24  const WIFI_SSID: &str = env!("WIFI_SSID");
 25  const WIFI_PASSWORD: &str = env!("WIFI_PSK");
 26  
 27  macro_rules! mk_static {
 28      ($type:ty, $value:expr) => {{
 29          static STATIC_CELL: StaticCell<$type> = StaticCell::new();
 30          STATIC_CELL.uninit().write($value)
 31      }};
 32  }
 33  
 34  esp_bootloader_esp_idf::esp_app_desc!();
 35  
 36  fn random_seed(rng: &mut Rng) -> u64 {
 37      (u64::from(rng.random()) << 32) | u64::from(rng.random())
 38  }
 39  
 40  #[embassy_executor::task]
 41  async fn wifi_connection_task(mut ctrl: WifiController<'static>) {
 42      loop {
 43          info!("attempting Wi-Fi connection");
 44          match ctrl.connect_async().await {
 45              Ok(_connected_info) => {
 46                  info!("Wi-Fi connected");
 47                  let _ = ctrl.wait_for_disconnect_async().await;
 48              }
 49              Err(e) => {
 50                  info!("Wi-Fi connect failed: {:?}", e);
 51                  Timer::after(Duration::from_secs(2)).await;
 52              }
 53          }
 54      }
 55  }
 56  
 57  #[embassy_executor::task]
 58  async fn network_task(mut runner: Runner<'static, Interface<'static>>) {
 59      runner.run().await;
 60  }
 61  
 62  #[esp_rtos::main]
 63  async fn main(spawner: Spawner) -> ! {
 64      rtt_target::rtt_init_defmt!();
 65  
 66      let config = esp_hal::Config::default().with_cpu_clock(CpuClock::max());
 67      let peripherals = esp_hal::init(config);
 68  
 69      esp_alloc::heap_allocator!(#[esp_hal::ram(reclaimed)] size: 64 * 1024);
 70      esp_alloc::heap_allocator!(size: 64 * 1024);
 71  
 72      let timg0 = TimerGroup::new(peripherals.TIMG0);
 73      let sw_ints = SoftwareInterruptControl::new(peripherals.SW_INTERRUPT);
 74      esp_rtos::start(timg0.timer0, sw_ints.software_interrupt0);
 75  
 76      let station_config = Config::Station(
 77          StationConfig::default()
 78              .with_ssid(WIFI_SSID)
 79              .with_password(WIFI_PASSWORD.into()),
 80      );
 81  
 82      let (wifi_ctrl, interfaces) = esp_radio::wifi::new(
 83          peripherals.WIFI,
 84          ControllerConfig::default().with_initial_config(station_config),
 85      )
 86      .unwrap();
 87  
 88      let mut rng = Rng::new();
 89      let (stack, runner) = embassy_net::new(
 90          interfaces.station,
 91          embassy_net::Config::dhcpv4(Default::default()),
 92          mk_static!(StackResources<3>, StackResources::<3>::new()),
 93          random_seed(&mut rng),
 94      );
 95  
 96      spawner.spawn(wifi_connection_task(wifi_ctrl).unwrap());
 97      spawner.spawn(network_task(runner).unwrap());
 98  
 99      with_timeout(Duration::from_secs(30), stack.wait_config_up())
100          .await
101          .unwrap();
102  
103      info!("DHCP: {}", stack.config_v4().unwrap().address);
104  
105      let app = mk_static!(
106          picoserve::AppRouter<HttpAppProps>,
107          HttpAppProps { stack }.build_app()
108      );
109  
110      spawner.spawn(firmware::services::http::task(0, stack, app).unwrap());
111  
112      info!("HTTP server on port {}", app::http::PORT);
113  
114      loop {
115          Timer::after(Duration::from_secs(60)).await;
116      }
117  }