This commit is contained in:
Pascal Engélibert 2023-10-07 13:33:14 +02:00
commit 865599e059
64 changed files with 6448 additions and 1221 deletions

View file

@ -0,0 +1,27 @@
[build]
target = "xtensa-esp32-none-elf"
[target.'cfg(target_arch = "xtensa")']
#runner = "espflash flash --monitor --flash-size 4mb --chip esp32 --partition-table partition.csv --flash-freq 40mhz --flash-mode qio"
runner = "espflash flash --monitor --flash-size 4mb --chip esp32"
rustflags = [
# Optimization
"-Z", "location-detail=none",
"-C", "link-args=-Wl,--sort-section=alignment",
"-C", "inline-threshold=7",
# GNU LD
"-C", "link-arg=-Wl,-Tlinkall.x",
"-C", "link-arg=-nostartfiles",
# LLD
# "-C", "link-arg=-Tlinkall.x",
# "-C", "linker=rust-lld",
]
[env]
ESP_LOGLEVEL = "info"
[unstable]
build-std = ["core", "panic_abort"]
#build-std = ["core"]

17
esp/.cargo/config.toml Normal file
View file

@ -0,0 +1,17 @@
[target.xtensa-esp32-none-elf]
runner = "espflash flash --monitor"
[env]
ESP_LOG="info"
[build]
rustflags = [
"-C", "link-arg=-Wl,-Tlinkall.x",
"-C", "link-arg=-Trom_functions.x",
"-C", "link-arg=-nostartfiles",
]
target = "xtensa-esp32-none-elf"
[unstable]
build-std = ["alloc", "core"]

3
esp/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
wifi-ssid.txt
wifi-psw.txt
target

4
esp/.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,4 @@
{
"rust-analyzer.cargo.allTargets": false,
"rust-analyzer.cargo.target": "xtensa-esp32-none-elf",
}

1552
esp/Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

53
esp/Cargo.toml Normal file
View file

@ -0,0 +1,53 @@
[package]
name = "rustphone"
version = "0.1.0"
edition = "2021"
[dependencies]
cfg-if = "1.0.0"
critical-section = "1.2.0"
embassy-embedded-hal = "0.2.0"
embassy-executor = { version = "0.6.3", features = ["task-arena-size-20480"] }
embassy-net = { version = "0.4.0", features = [ "tcp", "udp", "dhcpv4", "medium-ethernet"] }
embassy-sync = "0.6.1"
embassy-time = { version = "0.3.2", features = ["generic-queue-8"] }
embedded-graphics = "0.8.1"
embedded-hal = "1.0.0"
embedded-hal-02 = { version = "0.2.7", package = "embedded-hal", features = ["unproven"] }
embedded-io = "0.6.1"
embedded-io-async = "0.6.1"
embedded-layout = "0.4.1"
embedded-text = "0.7.2"
#embedded-tls = { version = "0.17.0", default-features = false }
epd-waveshare = { path = "../../epd-waveshare", optional = true }
esp-alloc = "0.5.0"
esp-backtrace = { version = "0.14.2", features = ["esp32", "exception-handler", "panic-handler", "println"] }
esp-hal = { version = "0.22.0", features = ["esp32"] }
esp-hal-embassy = { version = "0.5.0", features = ["esp32"] }
esp-println = { version = "0.12.0", features = ["esp32", "log"] }
esp-wifi = { version = "0.11.0", default-features = false, features = ["esp32", "utils", "wifi", "esp-alloc", "log"] }
log = "0.4.21"
#oled_async = { path = "../../oled_async", features = ["spi"] }
nb = "1.1.0"
#panic-halt = "0.2.0"
rand_core = "0.6.4"
#sh1106 = { version = "0.5.0", optional = true }
sh1106 = { git = "https://github.com/techmccat/sh1106", branch = "hal-1", optional = true }
static_cell = { version = "2.1.0", features = ["nightly"] }
[features]
default = ["display_sh1106"]
display_epd = ["dep:epd-waveshare"]
display_sh1106 = ["dep:sh1106"]
[profile.release]
codegen-units = 1
debug = 2
debug-assertions = false
incremental = false
opt-level = 's'
lto = 'fat'
overflow-checks = false
#panic = "abort"
strip = true

11
esp/README.md Normal file
View file

@ -0,0 +1,11 @@
## Build
```bash
cargo +esp run --release --target xtensa-esp32-none-elf
```
## Links
https://github.com/ivmarkov/rust-esp32-std-demo/blob/main/src/main.rs#L1505
OLED SPI/I2C V2 1.3in SH1106 5/3.3V

5
esp/build.rs Normal file
View file

@ -0,0 +1,5 @@
fn main() {
//println!("cargo:rustc-link-arg-bins=-Tlinkall.x");
//println!("cargo:rustc-link-arg-bins=-Tesp32_rom_functions.x");
//println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
}

4
esp/partition.csv Normal file
View file

@ -0,0 +1,4 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x7000,
factory, app, factory, 0x10000, 2M,
spiffs, data, spiffs, , 2M,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x9000 0x7000
3 factory app factory 0x10000 2M
4 spiffs data spiffs 2M

1982
esp/rom_functions.x Normal file

File diff suppressed because it is too large Load diff

2
esp/rust-toolchain.toml Normal file
View file

@ -0,0 +1,2 @@
[toolchain]
channel = "esp"

9
esp/rustfmt.toml Normal file
View file

@ -0,0 +1,9 @@
hard_tabs = true
newline_style = "Unix"
imports_granularity = "Crate"
unstable_features = true
format_code_in_doc_comments = true
format_macro_bodies = true
format_macro_matchers = true
format_strings = true

9
esp/src/display.rs Normal file
View file

@ -0,0 +1,9 @@
cfg_if::cfg_if! {
if #[cfg(feature = "display_sh1106")] {
mod sh1106;
pub use sh1106::*;
} else if #[cfg(feature = "display_epd")] {
mod epd;
pub use epd::*;
}
}

96
esp/src/display/epd.rs Normal file
View file

@ -0,0 +1,96 @@
use core::cell::RefCell;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_sync::blocking_mutex::{raw::NoopRawMutex, NoopMutex};
use embedded_graphics::prelude::*;
use epd_waveshare::{
epd1in54::{Display1in54, Epd1in54},
prelude::*,
};
use esp_hal::{
delay::Delay,
gpio::{GpioPin, Input, InputPin, Level, Output, Pull},
peripherals::SPI2,
spi::{master::Spi, FullDuplexMode},
};
use esp_println::println;
use static_cell::StaticCell;
type EpdSpi<'a> =
SpiDevice<'a, NoopRawMutex, Spi<'a, SPI2, FullDuplexMode>, Output<'a, GpioPin<15>>>;
type Epd = Epd1in54<
EpdSpi<'static>,
Input<'static, GpioPin<18>>,
Output<'static, GpioPin<19>>,
Output<'static, GpioPin<21>>,
Delay,
>;
pub type Color = epd_waveshare::color::Color;
pub const BLACK: Color = epd_waveshare::color::Color::Black;
pub const WHITE: Color = epd_waveshare::color::Color::White;
//static DISPLAY: StaticCell<Display> = StaticCell::new();
pub fn init(
spi: &mut EpdSpi<'static>,
busy: GpioPin<18>,
dc: GpioPin<19>,
rst: GpioPin<21>,
delay: &mut Delay,
) -> Epd {
Epd::new(
spi,
Input::new(busy, Pull::Down),
Output::new(dc, Level::High),
Output::new(rst, Level::High),
delay,
Some(5),
)
.unwrap()
}
#[embassy_executor::task]
pub async fn run(mut spi: EpdSpi<'static>, mut epd: Epd, mut delay: Delay) {
println!("EPD start");
epd.clear_frame(&mut spi, &mut delay).unwrap();
epd.display_frame(&mut spi, &mut delay).unwrap();
let small_buffer = [Color::Black.get_byte_value(); 8]; //8x8
epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 96, 96, 8, 8)
.unwrap();
// Display updated frame
epd.display_frame(&mut spi, &mut delay).unwrap();
delay.delay_millis(5000);
// Set the EPD to sleep
epd.sleep(&mut spi, &mut delay).unwrap();
println!("EPD done");
}
/*pub struct Display {
epd: Epd,
display: Display1in54,
}
impl Display {
pub fn new(spi: &mut Spi<_, _>) -> Self {
Self {
epd: Epd1in54::new(&mut spi, cs, busy, dc, rst, &mut delay),
display: Display1in54::default(),
}
}
pub fn update(&self) {
//self.epd.update_and_display_frame( & mut spi, & self.display.buffer());
}
pub fn inner(&self) -> &Display1in54 {
&self.display
}
pub fn inner_mut(&mut self) -> &mut Display1in54 {
&mut self.display
}
}*/

98
esp/src/display/sh1106.rs Normal file
View file

@ -0,0 +1,98 @@
use crate::string::String;
use core::cell::RefCell;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_sync::{
blocking_mutex::{
raw::{CriticalSectionRawMutex, NoopRawMutex},
NoopMutex,
},
channel::Channel,
};
use embedded_graphics::{
mono_font::{ascii::FONT_5X8, MonoTextStyle},
pixelcolor::BinaryColor,
prelude::*,
primitives::{PrimitiveStyle, Rectangle},
text::renderer::CharacterStyle,
};
use embedded_text::{
alignment::HorizontalAlignment,
style::{HeightMode, TextBoxStyleBuilder},
TextBox,
};
use esp_hal::{
delay::Delay,
gpio::{AnyPin, GpioPin, Input, InputPin, Level, Output, Pull},
peripherals::SPI2,
spi::master::Spi,
};
use esp_println::println;
use sh1106::{prelude::*, Builder};
use static_cell::StaticCell;
type OledSpi<'a> =
SpiDevice<'a, NoopRawMutex, Spi<'a, esp_hal::Blocking, SPI2>, Output<'a, GpioPin<15>>>;
pub static CHANNEL: Channel<CriticalSectionRawMutex, String<1024>, 2> = Channel::new();
/*pub fn init(
spi: OledSpi<'static>,
dc: GpioPin<19>,
) -> GraphicsMode<SpiInterface<OledSpi<'static>, Output<'static, GpioPin<19>>>> {
Builder::new()
.connect_spi(spi, Output::new(dc, Level::High))
.into()
}*/
pub fn init(
spi: OledSpi<'static>,
dc: AnyPin,
) -> GraphicsMode<SpiInterface<OledSpi<'static>, Output<'static, AnyPin>>> {
Builder::new()
.connect_spi(spi, Output::new(dc, Level::High))
.into()
}
#[embassy_executor::task]
pub async fn run(
mut display: GraphicsMode<SpiInterface<OledSpi<'static>, Output<'static, GpioPin<19>>>>,
delay: Delay,
) {
display.init().unwrap();
display.flush().unwrap();
let mut character_style = MonoTextStyle::new(&FONT_5X8, BinaryColor::On);
character_style.set_background_color(Some(BinaryColor::Off));
let textbox_style = TextBoxStyleBuilder::new()
.height_mode(HeightMode::FitToText)
.alignment(HorizontalAlignment::Left)
.paragraph_spacing(3)
.build();
let bounds = Rectangle::new(Point::zero(), Size::new(128, 0));
loop {
let buf = CHANNEL.receive().await;
let text = buf.as_ref();
display.clear();
let text_box = TextBox::with_textbox_style(
&text[0..text.len().min(100)],
bounds,
character_style,
textbox_style,
);
text_box.draw(&mut display).ok();
/*Rectangle::with_center(Point::new(20, 20), Size::new(8, 8))
.into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
.draw(&mut display)
.ok();
Rectangle::with_center(Point::new(25, 25), Size::new(8, 8))
.into_styled(PrimitiveStyle::with_fill(BinaryColor::Off))
.draw(&mut display)
.ok();*/
display.flush().ok();
}
}

225
esp/src/main.rs Normal file
View file

@ -0,0 +1,225 @@
#![no_std]
#![no_main]
#![feature(array_windows)]
#![feature(impl_trait_in_assoc_type)]
#![feature(type_alias_impl_trait)]
mod display;
mod modem;
//mod rng;
mod string;
#[macro_use]
mod util;
mod wifi;
use string::String;
use util::*;
use core::cell::RefCell;
use embassy_embedded_hal::shared_bus::blocking::spi::SpiDevice;
use embassy_sync::blocking_mutex::NoopMutex;
//use embedded_tls::{Aes256GcmSha384, TlsConfig, TlsConnection, TlsContext};
use embassy_executor::Spawner;
use embassy_net::{tcp::TcpSocket, Ipv4Address};
use embassy_time::{Duration, Timer};
use embedded_io_async::Write;
use esp_backtrace as _;
use esp_hal::{
delay::Delay,
gpio::{self, Level},
prelude::*,
spi::{self, master::Spi},
timer::{timg::TimerGroup, AnyTimer, OneShotTimer},
Blocking,
};
use esp_println::println;
use log::info;
#[main]
async fn main(spawner: Spawner) {
let mut peripherals = esp_hal::init({
let mut config = esp_hal::Config::default();
config.cpu_clock = CpuClock::max();
config
});
esp_alloc::heap_allocator!(72 * 1024);
esp_println::logger::init_logger_from_env();
let timer0 = esp_hal::timer::timg::TimerGroup::new(&mut peripherals.TIMG1);
esp_hal_embassy::init(timer0.timer0);
info!("Embassy ok");
//let timer1 = esp_hal::timer::timg::TimerGroup::new(&mut peripherals.TIMG0);
/*let _init = esp_wifi::init(
timer1.timer0,
esp_hal::rng::Rng::new(&mut peripherals.RNG),
peripherals.RADIO_CLK,
)
.unwrap();*/
//let system = SystemControl::new(peripherals.SYSTEM);
//let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
//let io = Io::new(peripherals.IO_MUX);
//rng::init(peripherals.RNG, peripherals.ADC1);
let mut trng = esp_hal::rng::Trng::new(peripherals.RNG, &mut peripherals.ADC1);
let seed = {
let mut buf = [0; 8];
trng.read(&mut buf);
u64::from_be_bytes(buf)
};
let rng = trng.downgrade();
let sclk = peripherals.GPIO14;
let miso = peripherals.GPIO12;
let mosi = peripherals.GPIO13;
let cs = peripherals.GPIO15;
let spi = Spi::<Blocking, esp_hal::peripherals::SPI2>::new_typed_with_config(
mk_static!(esp_hal::peripherals::SPI2, peripherals.SPI2),
spi::master::Config {
frequency: 400.kHz(),
..Default::default()
},
)
.with_sck(sclk)
.with_mosi(mosi)
.with_miso(miso);
let spi = NoopMutex::new(RefCell::new(spi));
let spi_dev = SpiDevice::new(
mk_static!(
NoopMutex<RefCell<Spi<'static, esp_hal::Blocking, esp_hal::peripherals::SPI2>>>,
spi
),
gpio::Output::new_typed(cs, Level::High),
);
info!("SPI ok");
let delay = Delay::new();
#[cfg(feature = "display_epd")]
let mut display = display::init(
&mut spi_dev,
io.pins.gpio18,
io.pins.gpio19,
io.pins.gpio21,
&mut delay,
);
#[cfg(feature = "display_sh1106")]
//let mut display = display::init(spi_dev, io.pins.gpio19);
let display = sh1106::Builder::new()
.connect_spi(
spi_dev,
gpio::Output::new_typed(peripherals.GPIO19, Level::High),
)
.into();
info!("Display ok");
let timg0 = TimerGroup::new(peripherals.TIMG0);
let (wifi_interface, wifi_controller) =
wifi::pre_init(timg0.timer0, rng, peripherals.RADIO_CLK, peripherals.WIFI);
info!("Wifi pre-init ok");
/*let timg1 = esp_hal::timer::timg::TimerGroup::new(peripherals.TIMG1);
esp_hal_embassy::init(
mk_static!(
[OneShotTimer<AnyTimer>; 1],
[OneShotTimer::new(AnyTimer::from(timg1.timer0))]
),
);*/
#[cfg(feature = "display_sh1106")]
let _gpio21 = gpio::Output::new(peripherals.GPIO21, Level::High);
#[cfg(feature = "display_sh1106")]
spawner.spawn(display::run(display, delay)).ok();
#[cfg(feature = "display_epd")]
spawner.spawn(display::run(spi_dev, display, delay)).ok();
let net_stack = wifi::post_init(&spawner, wifi_interface, wifi_controller, seed);
info!("Wifi post-init ok");
let mut rx_buffer = [0; 4096];
let mut tx_buffer = [0; 4096];
'get: loop {
Timer::after(Duration::from_millis(1_000)).await;
let mut socket = TcpSocket::new(&net_stack, &mut rx_buffer, &mut tx_buffer);
socket.set_timeout(Some(embassy_time::Duration::from_millis(10_000)));
let remote_endpoint = (Ipv4Address::new(192, 168, 1, 14), 80);
println!("conn...");
let r = socket.connect(remote_endpoint).await;
if let Err(e) = r {
println!("conn err: {:?}", e);
continue;
}
println!("conn!");
/*let mut read_record_buffer = [0; 16384];
let mut write_record_buffer = [0; 16384];
let tls_config = TlsConfig::new().with_server_name("txmn.tk").with_psk(&[], &[]);
let mut tls = TlsConnection::new(socket, &mut read_record_buffer, &mut write_record_buffer);
if let Err(e) = tls.open(TlsContext::new(
&tls_config,
&mut prng,
))
.await {
println!("TLS err: {:?}", e);
continue;
}*/
let mut buf = [0; 1024];
loop {
/*let r = socket
.write_all(b"GET /fortune.php?raw HTTP/1.0\r\nHost: txmn.tk\r\n\r\n")
.await;
if let Err(e) = r {
println!("w err: {:?}", e);
break;
}
let n = match socket.read(&mut buf).await {
Ok(0) => {
println!("EOF");
break;
}
Ok(n) => n,
Err(e) => {
println!("r err: {:?}", e);
break;
}
};*/
socket
.write_all(b"GET /fortune.php?raw HTTP/1.0\r\nHost: txmn.tk\r\n\r\n")
.await
.unwrap();
socket.flush().await.unwrap();
let n = match socket.read(&mut buf).await {
Ok(0) => {
println!("EOF");
break;
}
Ok(n) => n,
Err(e) => {
println!("r err: {:?}", e);
break;
}
};
println!("{}", core::str::from_utf8(&buf[..n]).unwrap());
#[cfg(feature = "display_sh1106")]
if let Some(content_start) = buf.array_windows().position(|o| o == b"\r\n\r\n") {
if let Some(text) = String::from_ascii(&buf[content_start + 4..n]) {
display::CHANNEL.send(text).await;
}
}
//break 'get;
}
Timer::after(Duration::from_millis(5_000)).await;
}
}

1
esp/src/modem.rs Normal file
View file

@ -0,0 +1 @@

13
esp/src/rng.rs Normal file
View file

@ -0,0 +1,13 @@
use core::cell::OnceCell;
use embassy_sync::{mutex::Mutex, blocking_mutex::NoopMutex};
use esp_hal::{peripherals::Peripherals, rng::Trng};
static TRNG: OnceCell<Mutex<NoopMutex<Trng>, Trng>> = OnceCell::new();
pub fn init(rng: Peripherals::RNG, adc1: Peripherals::ADC1) {
TRNG.set(Mutex::new(Trng::new(peripherals.RNG, &mut peripherals.ADC1))).unwrap();
}
pub async fn randomize(buf: &mut [u8]) {
TRNG.get().expect("no RNG").lock().await.read(buf)
}

45
esp/src/string.rs Normal file
View file

@ -0,0 +1,45 @@
use core::{mem::MaybeUninit, str::from_utf8_unchecked};
#[derive(Clone)]
pub struct String<const N: usize> {
buf: [u8; N],
len: usize,
}
impl<const N: usize> String<N> {
pub fn from_str(s: &str) -> Self {
let mut buf = [0; N];
buf[0..s.as_bytes().len()].copy_from_slice(s.as_bytes());
Self { len: s.len(), buf }
}
pub fn from_ascii(s: &[u8]) -> Option<Self> {
if s.len() < N && s.is_ascii() {
let mut buf = [0; N];
buf[0..s.len()].copy_from_slice(s);
Some(Self { len: s.len(), buf })
} else {
None
}
}
pub fn from_buf_ascii(buf: [u8; N], len: usize) -> Option<Self> {
if len < N && buf[0..len].is_ascii() {
Some(Self { buf, len })
} else {
None
}
}
}
impl<const N: usize> AsRef<str> for String<N> {
fn as_ref(&self) -> &str {
unsafe { core::str::from_utf8_unchecked(&self.buf[0..self.len]) }
}
}
impl<const N: usize> AsMut<str> for String<N> {
fn as_mut(&mut self) -> &mut str {
unsafe { core::str::from_utf8_unchecked_mut(&mut self.buf[0..self.len]) }
}
}

8
esp/src/util.rs Normal file
View file

@ -0,0 +1,8 @@
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
}};
}

112
esp/src/wifi.rs Normal file
View file

@ -0,0 +1,112 @@
//use crate::rng::randomize;
use embassy_executor::Spawner;
use embassy_time::{Duration, Timer};
use esp_hal::{peripheral::Peripheral, rng::Rng};
use esp_println::println;
use esp_wifi::{
wifi::{WifiController, WifiDevice, WifiEvent, WifiStaDevice, WifiState},
EspWifiController, EspWifiTimerSource,
};
use static_cell::StaticCell;
const SSID: &str = include_str!("../wifi-ssid.txt");
const PASSWORD: &str = include_str!("../wifi-psw.txt");
static WIFI_CONTROLLER: StaticCell<WifiController> = StaticCell::new();
pub fn pre_init<'d, T: EspWifiTimerSource>(
timer: impl Peripheral<P = T> + 'static,
rng: Rng,
radio_clk: esp_hal::peripherals::RADIO_CLK,
wifi: esp_hal::peripherals::WIFI,
) -> (
WifiDevice<'static, WifiStaDevice>,
&'static mut WifiController<'static>,
) {
let wifi_init = esp_wifi::init(timer, rng, radio_clk).unwrap();
let wifi_init = mk_static!(EspWifiController, wifi_init);
let (wifi_interface, wifi_controller) =
esp_wifi::wifi::new_with_mode(wifi_init, wifi, WifiStaDevice).unwrap();
(wifi_interface, WIFI_CONTROLLER.init(wifi_controller))
}
pub fn post_init(
spawner: &Spawner,
interface: WifiDevice<'static, WifiStaDevice>,
controller: &'static mut WifiController,
seed: u64,
) -> &'static embassy_net::Stack<WifiDevice<'static, WifiStaDevice>> {
let net_stack = &*mk_static!(
embassy_net::Stack<WifiDevice<'_, WifiStaDevice>>,
embassy_net::Stack::new(
interface,
embassy_net::Config::dhcpv4(Default::default()),
mk_static!(
embassy_net::StackResources<3>,
embassy_net::StackResources::<3>::new()
),
seed
)
);
spawner.spawn(connection(controller, &net_stack)).ok();
spawner.spawn(net_task(&net_stack)).ok();
net_stack
}
/// Connection task
///
/// Reconnects automatically when needed.
#[embassy_executor::task]
pub async fn connection(
controller: &'static mut WifiController<'static>,
stack: &'static embassy_net::Stack<WifiDevice<'static, WifiStaDevice>>,
) {
loop {
match esp_wifi::wifi::wifi_state() {
WifiState::StaConnected => {
controller.wait_for_event(WifiEvent::StaDisconnected).await;
Timer::after(Duration::from_millis(5000)).await
}
_ => {}
}
if !matches!(controller.is_started(), Ok(true)) {
let client_config =
esp_wifi::wifi::Configuration::Client(esp_wifi::wifi::ClientConfiguration {
ssid: SSID.try_into().unwrap(),
password: PASSWORD.try_into().unwrap(),
auth_method: esp_wifi::wifi::AuthMethod::WPA2Personal,
..Default::default()
});
controller.set_configuration(&client_config).unwrap();
controller.start_async().await.unwrap();
}
match controller.connect_async().await {
Ok(_) => {
while !stack.is_link_up() {
Timer::after(Duration::from_millis(500)).await;
}
loop {
if let Some(config) = stack.config_v4() {
println!("IP {}", config.address);
break;
}
Timer::after(Duration::from_millis(500)).await;
}
}
Err(e) => {
println!("Wifi err: {e:?}");
Timer::after(Duration::from_millis(5000)).await
}
}
}
}
#[embassy_executor::task]
pub async fn net_task(stack: &'static embassy_net::Stack<WifiDevice<'static, WifiStaDevice>>) {
stack.run().await
}