From d6396944f72e3f1e9b81fd5402833e241ba56726 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 9 Feb 2023 00:14:27 +0000 Subject: [PATCH 1/6] Async WiFi with embassy - Add embassy_net::Driver impl for WifiDevice - Add embassy_dhcp example - Update README with embassy_dhcp running instruction Notes: TCP connection may fail a few times until the esp gets an IP address, it seems there is no way to await dhcp completion in embassy_net yet. --- README.md | 10 +- esp-wifi/Cargo.toml | 10 +- esp-wifi/examples/embassy_dhcp.rs | 208 ++++++++++++++++++++++++++++++ esp-wifi/src/wifi/mod.rs | 114 ++++++++++++++++ 4 files changed, 337 insertions(+), 5 deletions(-) create mode 100644 esp-wifi/examples/embassy_dhcp.rs diff --git a/README.md b/README.md index 460f87f4..4f220e35 100644 --- a/README.md +++ b/README.md @@ -111,7 +111,15 @@ If a cell contains am em dash (—) this means that the particular feature i | ESP32-C2 | `CARGO_PROFILE_RELEASE_LTO=false cargo +nightly run --example embassy_esp_now --release --target riscv32imc-unknown-none-elf --features "esp32c2,esp32c2-async,esp-now"` | | ESP32-C3 | `cargo +nightly run --example embassy_esp_now --release --target riscv32imc-unknown-none-elf --features "esp32c3,esp32c3-async,esp-now"` | | ESP32-S2 | `cargo +esp run --example embassy_esp_now --release --target xtensa-esp32s2-none-elf --features "esp32s2,esp32s2-async,esp-now"` | -| ESP32-S3 | `cargo +esp run --example embassy_esp_now --release --target xtensa-esp32s3-none-elf --features "esp32s3,esp32s3-async,esp-now"` | +| ESP32-S3 | `cargo +esp run --example embassy_esp_now --release --target xtensa-esp32s3-none-elf --features "esp32s3,esp32s3-async,esp-now"` + +| Chip | Command | +| :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| ESP32 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32-none-elf --features "esp32,esp32-async,embedded-svc,wifi"` | +| ESP32-C2 | `CARGO_PROFILE_RELEASE_LTO=false cargo +nightly run --example embassy_dhcp --release --target riscv32imc-unknown-none-elf --features "esp32c2,esp32c2-async,embedded-svc,wifi"` | +| ESP32-C3 | `cargo +nightly run --example embassy_dhcp --release --target riscv32imc-unknown-none-elf --features "esp32c3,esp32c3-async,embedded-svc,wifi"` | +| ESP32-S2 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32s2-none-elf --features "esp32s2,esp32s2-async,embedded-svc,wifi"` | +| ESP32-S3 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32s3-none-elf --features "esp32s3,esp32s3-async,embedded-svc,wifi"` | ## Features diff --git a/esp-wifi/Cargo.toml b/esp-wifi/Cargo.toml index d8298561..e4808dba 100644 --- a/esp-wifi/Cargo.toml +++ b/esp-wifi/Cargo.toml @@ -26,20 +26,22 @@ log = "0.4.17" embedded-svc = { version = "0.23.1", default-features = false, features = [], optional = true } enumset = { version = "1", default-features = false, optional = true } linked_list_allocator = { version = "0.10.3", default-features = false, features = ["const_mut_refs"] } -embedded-io = "0.3.1" +embedded-io = { version = "0.4.0" } fugit = "0.3.6" heapless = { version = "0.7.14", default-features = false } num-derive = { version = "0.3", features = ["full-syntax"] } num-traits = { version = "0.2", default-features = false } esp-wifi-sys = { version = "0.1.0", path = "../esp-wifi-sys" } embassy-sync = { version = "0.1.0", optional = true } +embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a", features = ["nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } +embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a" } [build-dependencies] riscv-target = { version = "0.1.2", optional = true } [dev-dependencies] -bleps = { git = "https://github.com/bjoernQ/bleps", package = "bleps", rev = "5ce5ca139fe85c0120e9c2f9607d165d1c32d725" } -bleps-macros = { git = "https://github.com/bjoernQ/bleps", package = "bleps-macros", rev = "5ce5ca139fe85c0120e9c2f9607d165d1c32d725" } +bleps = { git = "https://github.com/mabezdev/bleps", package = "bleps", branch = "patch-1" } +bleps-macros = { git = "https://github.com/mabezdev/bleps", package = "bleps-macros", branch = "patch-1" } embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", features = ["nightly"] } embassy-futures = "0.1.0" @@ -85,4 +87,4 @@ ble = [ "esp32-hal?/bluetooth" ] phy-enable-usb = [] ps-min-modem = [] esp-now = [ "wifi", "embedded-svc" ] -async = [ "dep:embassy-sync"] +async = [ "dep:embassy-sync", "embedded-io/async"] \ No newline at end of file diff --git a/esp-wifi/examples/embassy_dhcp.rs b/esp-wifi/examples/embassy_dhcp.rs new file mode 100644 index 00000000..aee81e73 --- /dev/null +++ b/esp-wifi/examples/embassy_dhcp.rs @@ -0,0 +1,208 @@ +#![no_std] +#![no_main] +#![feature(c_variadic)] +#![feature(const_mut_refs)] +#![feature(type_alias_impl_trait)] + +use embassy_executor::_export::StaticCell; +use embassy_net::tcp::TcpSocket; +use embassy_net::{StackResources, Stack, Config, Ipv4Address}; +#[cfg(feature = "esp32")] +use esp32_hal as hal; +#[cfg(feature = "esp32c2")] +use esp32c2_hal as hal; +#[cfg(feature = "esp32c3")] +use esp32c3_hal as hal; +#[cfg(feature = "esp32s2")] +use esp32s2_hal as hal; +#[cfg(feature = "esp32s3")] +use esp32s3_hal as hal; + +use embassy_executor::Executor; +use embassy_time::{Duration, Timer}; +use esp_backtrace as _; +use esp_println::logger::init_logger; +use esp_println::println; +use esp_wifi::initialize; +use esp_wifi::wifi::{WifiDevice, WifiError}; +use hal::clock::{ClockControl, CpuClock}; +use hal::Rng; +use hal::{embassy, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc}; +use embedded_svc::wifi::{Wifi, ClientConfiguration, Configuration, AccessPointInfo}; + +#[cfg(any(feature = "esp32c3", feature = "esp32c2"))] +use hal::system::SystemExt; + +#[cfg(any(feature = "esp32c3", feature = "esp32c2"))] +use riscv_rt::entry; +#[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] +use xtensa_lx_rt::entry; + +const SSID: &str = env!("SSID"); +const PASSWORD: &str = env!("PASSWORD"); + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +static EXECUTOR: StaticCell = StaticCell::new(); + +#[entry] +fn main() -> ! { + init_logger(log::LevelFilter::Info); + esp_wifi::init_heap(); + + let peripherals = Peripherals::take(); + + #[cfg(not(feature = "esp32"))] + let system = peripherals.SYSTEM.split(); + #[cfg(feature = "esp32")] + let system = peripherals.DPORT.split(); + + #[cfg(feature = "esp32c3")] + let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock160MHz).freeze(); + #[cfg(feature = "esp32c2")] + let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock120MHz).freeze(); + #[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] + let clocks = ClockControl::configure(system.clock_control, CpuClock::Clock240MHz).freeze(); + + let mut rtc = Rtc::new(peripherals.RTC_CNTL); + + // Disable watchdog timers + #[cfg(not(any(feature = "esp32", feature = "esp32s2")))] + rtc.swd.disable(); + + rtc.rwdt.disable(); + + #[cfg(any(feature = "esp32c3", feature = "esp32c2"))] + { + use hal::systimer::SystemTimer; + let syst = SystemTimer::new(peripherals.SYSTIMER); + initialize(syst.alarm0, Rng::new(peripherals.RNG), &clocks).unwrap(); + } + #[cfg(any(feature = "esp32", feature = "esp32s3", feature = "esp32s2"))] + { + use hal::timer::TimerGroup; + let timg1 = TimerGroup::new(peripherals.TIMG1, &clocks); + initialize(timg1.timer0, Rng::new(peripherals.RNG), &clocks).unwrap(); + } + + let mut wifi_interface = WifiDevice::new(); + + println!("is wifi started: {:?}", wifi_interface.is_started()); + + println!("Start Wifi Scan"); + let res: Result<(heapless::Vec, usize), WifiError> = + wifi_interface.scan_n(); + if let Ok((res, _count)) = res { + for ap in res { + println!("{:?}", ap); + } + } + + println!("Call wifi_connect"); + let client_config = Configuration::Client(ClientConfiguration { + ssid: SSID.into(), + password: PASSWORD.into(), + ..Default::default() + }); + let res = wifi_interface.set_configuration(&client_config); + println!("wifi_set_configuration returned {:?}", res); + + println!("{:?}", wifi_interface.get_capabilities()); + println!("wifi_connect {:?}", wifi_interface.connect()); + + // wait to get connected + println!("Wait to get connected"); + loop { + let res = wifi_interface.is_connected(); + match res { + Ok(connected) => { + if connected { + break; + } + } + Err(err) => { + println!("{:?}", err); + loop {} + } + } + } + println!("{:?}", wifi_interface.is_connected()); + + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + embassy::init(&clocks, timer_group0.timer0); + + let config = Config::Dhcp(Default::default()); + + let seed = 1234; // very random, very secure seed + + // Init network stack + let stack = &*singleton!(Stack::new( + wifi_interface, + config, + singleton!(StackResources::<3>::new()), + seed + )); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(net_task(&stack)).ok(); + spawner.spawn(task(&stack)).ok(); + }); +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack) { + stack.run().await +} + +#[embassy_executor::task] +async fn task(stack: &'static Stack) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + + loop { + Timer::after(Duration::from_millis(1_000)).await; + + let mut socket = TcpSocket::new(&stack, &mut rx_buffer, &mut tx_buffer); + + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + let remote_endpoint = (Ipv4Address::new(142, 250, 185, 115), 80); + println!("connecting..."); + let r = socket.connect(remote_endpoint).await; + if let Err(e) = r { + println!("connect error: {:?}", e); + continue; + } + println!("connected!"); + let mut buf = [0; 1024]; + loop { + use embedded_io::asynch::Write; + let r = socket.write_all(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n").await; + if let Err(e) = r { + println!("write error: {:?}", e); + break; + } + let n = match socket.read(&mut buf).await { + Ok(0) => { + println!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + println!("read error: {:?}", e); + break; + } + }; + println!("{}", core::str::from_utf8(&buf[..n]).unwrap()); + } + Timer::after(Duration::from_millis(1000)).await; + } +} diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index c44caf58..30f7b3f1 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -567,6 +567,10 @@ unsafe extern "C" fn recv_cb( let packet = DataFrame::from_bytes(src); queue.enqueue(packet).unwrap(); esp_wifi_internal_free_rx_buffer(eb); + + #[cfg(feature = "async")] + embassy::RECEIVE_WAKER.wake(); + 0 } else { 1 @@ -805,6 +809,9 @@ pub fn send_data_if_needed() { log::trace!("esp_wifi_internal_tx {}", _res); } } + + #[cfg(feature = "async")] + embassy::TRANSMIT_WAKER.wake(); }); } @@ -1059,3 +1066,110 @@ macro_rules! esp_wifi_result { } }; } + +#[cfg(all(feature = "wifi", feature = "async"))] +pub(crate) mod embassy { + use super::*; + use embassy_net_driver::{Driver, RxToken, TxToken, Capabilities}; + use embassy_sync::waitqueue::AtomicWaker; + + pub(crate) static TRANSMIT_WAKER: AtomicWaker = AtomicWaker::new(); + pub(crate) static RECEIVE_WAKER: AtomicWaker = AtomicWaker::new(); + + impl RxToken for WifiRxToken { + fn consume(self, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + critical_section::with(|cs| { + let mut queue = DATA_QUEUE_RX.borrow_ref_mut(cs); + + let mut data = queue + .dequeue() + .expect("unreachable: transmit()/receive() ensures there is a packet to process"); + let buffer = unsafe { core::slice::from_raw_parts(&data.data as *const u8, data.len) }; + dump_packet_info(&buffer); + f(&mut data.data[..]) + }) + } + } + + impl TxToken for WifiTxToken { + fn consume(self, len: usize, f: F) -> R + where + F: FnOnce(&mut [u8]) -> R, + { + let res = critical_section::with(|cs| { + let mut queue = DATA_QUEUE_TX.borrow_ref_mut(cs); + + let mut packet = DataFrame::new(); + packet.len = len; + let res = f(&mut packet.data[..len]); + queue + .enqueue(packet) + .expect("unreachable: transmit()/receive() ensures there is a buffer free"); + res + }); + + send_data_if_needed(); + res + } + } + + impl Driver for WifiDevice { + type RxToken<'a> = WifiRxToken + where + Self: 'a; + + type TxToken<'a> = WifiTxToken + where + Self: 'a; + + fn receive( + &mut self, + cx: &mut core::task::Context, + ) -> Option<(Self::RxToken<'_>, Self::TxToken<'_>)> { + RECEIVE_WAKER.register(cx.waker()); + critical_section::with(|cs| { + let rx = DATA_QUEUE_RX.borrow_ref_mut(cs); + let tx = DATA_QUEUE_TX.borrow_ref_mut(cs); + if !rx.is_empty() && !tx.is_full() { + Some((WifiRxToken::default(), WifiTxToken::default())) + } else { + None + } + }) + } + + fn transmit(&mut self, cx: &mut core::task::Context) -> Option> { + TRANSMIT_WAKER.register(cx.waker()); + critical_section::with(|cs| { + let tx = DATA_QUEUE_TX.borrow_ref_mut(cs); + if !tx.is_full() { + Some(WifiTxToken::default()) + } else { + None + } + }) + } + + fn link_state(&mut self, _cx: &mut core::task::Context) -> embassy_net_driver::LinkState { + // TODO once we have an async way of connecting to wifi, use here + // for now just assume the link is up + embassy_net_driver::LinkState::Up + } + + fn capabilities(&self) -> Capabilities { + let mut caps = Capabilities::default(); + caps.max_transmission_unit = 1514; + caps.max_burst_size = Some(1); + caps + } + + fn ethernet_address(&self) -> [u8; 6] { + let mut mac = [0; 6]; + get_sta_mac(&mut mac); + mac + } + } +} From 638aaf035a36684e6e1c3305e5fb46ba2cf73c21 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 9 Feb 2023 00:33:13 +0000 Subject: [PATCH 2/6] Put embassy-net behind feature - Whilst other embassy crates can be used behind the async feature, embassy-net should be put behind its own feature --- README.md | 10 +++++----- esp-wifi/Cargo.toml | 15 +++++++++++---- esp-wifi/src/wifi/mod.rs | 6 +++--- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 4f220e35..4e5a132d 100644 --- a/README.md +++ b/README.md @@ -115,11 +115,11 @@ If a cell contains am em dash (—) this means that the particular feature i | Chip | Command | | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| ESP32 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32-none-elf --features "esp32,esp32-async,embedded-svc,wifi"` | -| ESP32-C2 | `CARGO_PROFILE_RELEASE_LTO=false cargo +nightly run --example embassy_dhcp --release --target riscv32imc-unknown-none-elf --features "esp32c2,esp32c2-async,embedded-svc,wifi"` | -| ESP32-C3 | `cargo +nightly run --example embassy_dhcp --release --target riscv32imc-unknown-none-elf --features "esp32c3,esp32c3-async,embedded-svc,wifi"` | -| ESP32-S2 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32s2-none-elf --features "esp32s2,esp32s2-async,embedded-svc,wifi"` | -| ESP32-S3 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32s3-none-elf --features "esp32s3,esp32s3-async,embedded-svc,wifi"` | +| ESP32 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32-none-elf --features "esp32,esp32-async,embedded-svc,wifi,embassy-net"` | +| ESP32-C2 | `CARGO_PROFILE_RELEASE_LTO=false cargo +nightly run --example embassy_dhcp --release --target riscv32imc-unknown-none-elf --features "esp32c2,esp32c2-async,embedded-svc,wifi,embassy-net"` | +| ESP32-C3 | `cargo +nightly run --example embassy_dhcp --release --target riscv32imc-unknown-none-elf --features "esp32c3,esp32c3-async,embedded-svc,wifi,embassy-net"` | +| ESP32-S2 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32s2-none-elf --features "esp32s2,esp32s2-async,embedded-svc,wifi,embassy-net"` | +| ESP32-S3 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32s3-none-elf --features "esp32s3,esp32s3-async,embedded-svc,wifi,embassy-net"` | ## Features diff --git a/esp-wifi/Cargo.toml b/esp-wifi/Cargo.toml index e4808dba..44a0b105 100644 --- a/esp-wifi/Cargo.toml +++ b/esp-wifi/Cargo.toml @@ -33,8 +33,8 @@ num-derive = { version = "0.3", features = ["full-syntax"] } num-traits = { version = "0.2", default-features = false } esp-wifi-sys = { version = "0.1.0", path = "../esp-wifi-sys" } embassy-sync = { version = "0.1.0", optional = true } -embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a", features = ["nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] } -embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a" } +embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a", features = ["nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"], optional = true } +embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "26474ce6eb759e5add1c137f3417845e0797df3a", optional = true } [build-dependencies] riscv-target = { version = "0.1.2", optional = true } @@ -67,16 +67,24 @@ xtensa-atomic-emulation-trap = "0.3.0" [features] default = [ "utils" ] + +# chip features esp32c3 = [ "riscv-target", "riscv", "riscv-rt", "esp32c3-hal", "dep:esp32c3", "esp-wifi-sys/esp32c3" ] esp32c2 = [ "riscv-target", "riscv", "riscv-rt", "esp32c2-hal", "dep:esp32c2", "esp-wifi-sys/esp32c2" ] esp32 = [ "esp32-hal", "xtensa-lx-rt/esp32", "xtensa-lx/esp32", "esp-wifi-sys/esp32" ] esp32s3 = [ "esp32s3-hal", "xtensa-lx-rt/esp32s3", "xtensa-lx/esp32s3", "esp-wifi-sys/esp32s3" ] esp32s2 = [ "esp32s2-hal", "xtensa-lx-rt/esp32s2", "xtensa-lx/esp32s2", "esp-wifi-sys/esp32s2" ] + +# async features esp32c3-async = [ "esp32c3-hal/embassy", "esp32c3-hal/embassy-time-timg0", "async" ] esp32c2-async = [ "esp32c2-hal/embassy", "esp32c2-hal/embassy-time-timg0", "async" ] esp32-async = [ "esp32-hal/embassy", "esp32-hal/embassy-time-timg0", "async" ] esp32s2-async = [ "esp32s2-hal/embassy", "esp32s2-hal/embassy-time-timg0", "async" ] esp32s3-async = [ "esp32s3-hal/embassy", "esp32s3-hal/embassy-time-timg0", "async" ] +async = [ "dep:embassy-sync", "embedded-io/async"] +embassy-net = ["dep:embassy-net", "dep:embassy-net-driver", "async"] + +# misc features wifi-logs = [] dump-packets = [] utils = [] @@ -86,5 +94,4 @@ wifi = [] ble = [ "esp32-hal?/bluetooth" ] phy-enable-usb = [] ps-min-modem = [] -esp-now = [ "wifi", "embedded-svc" ] -async = [ "dep:embassy-sync", "embedded-io/async"] \ No newline at end of file +esp-now = [ "wifi", "embedded-svc" ] \ No newline at end of file diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 30f7b3f1..5dba09e8 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -568,7 +568,7 @@ unsafe extern "C" fn recv_cb( queue.enqueue(packet).unwrap(); esp_wifi_internal_free_rx_buffer(eb); - #[cfg(feature = "async")] + #[cfg(feature = "embassy-net")] embassy::RECEIVE_WAKER.wake(); 0 @@ -810,7 +810,7 @@ pub fn send_data_if_needed() { } } - #[cfg(feature = "async")] + #[cfg(feature = "embassy-net")] embassy::TRANSMIT_WAKER.wake(); }); } @@ -1067,7 +1067,7 @@ macro_rules! esp_wifi_result { }; } -#[cfg(all(feature = "wifi", feature = "async"))] +#[cfg(feature = "embassy-net")] pub(crate) mod embassy { use super::*; use embassy_net_driver::{Driver, RxToken, TxToken, Capabilities}; From ef77cb252c8cf0fff93b54f3b38f47e74e7b830c Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 9 Feb 2023 13:23:47 +0000 Subject: [PATCH 3/6] wait for dhcp to complete in example --- esp-wifi/examples/embassy_dhcp.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/esp-wifi/examples/embassy_dhcp.rs b/esp-wifi/examples/embassy_dhcp.rs index aee81e73..639b996f 100644 --- a/esp-wifi/examples/embassy_dhcp.rs +++ b/esp-wifi/examples/embassy_dhcp.rs @@ -167,6 +167,15 @@ async fn task(stack: &'static Stack) { let mut rx_buffer = [0; 4096]; let mut tx_buffer = [0; 4096]; + println!("Waiting to get IP address..."); + loop { + if let Some(config) = stack.config() { + println!("Got IP: {}", config.address); + break; + } + Timer::after(Duration::from_millis(500)).await; + } + loop { Timer::after(Duration::from_millis(1_000)).await; From 8a81b6e07d8d14623dc92b982efa3afdbde61277 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 9 Feb 2023 14:09:05 +0000 Subject: [PATCH 4/6] fmt --- esp-wifi/examples/embassy_dhcp.rs | 8 ++++-- esp-wifi/src/wifi/mod.rs | 47 ++++++++++++++++--------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/esp-wifi/examples/embassy_dhcp.rs b/esp-wifi/examples/embassy_dhcp.rs index 639b996f..94fb94fc 100644 --- a/esp-wifi/examples/embassy_dhcp.rs +++ b/esp-wifi/examples/embassy_dhcp.rs @@ -6,7 +6,7 @@ use embassy_executor::_export::StaticCell; use embassy_net::tcp::TcpSocket; -use embassy_net::{StackResources, Stack, Config, Ipv4Address}; +use embassy_net::{Config, Ipv4Address, Stack, StackResources}; #[cfg(feature = "esp32")] use esp32_hal as hal; #[cfg(feature = "esp32c2")] @@ -20,6 +20,7 @@ use esp32s3_hal as hal; use embassy_executor::Executor; use embassy_time::{Duration, Timer}; +use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wifi}; use esp_backtrace as _; use esp_println::logger::init_logger; use esp_println::println; @@ -28,7 +29,6 @@ use esp_wifi::wifi::{WifiDevice, WifiError}; use hal::clock::{ClockControl, CpuClock}; use hal::Rng; use hal::{embassy, peripherals::Peripherals, prelude::*, timer::TimerGroup, Rtc}; -use embedded_svc::wifi::{Wifi, ClientConfiguration, Configuration, AccessPointInfo}; #[cfg(any(feature = "esp32c3", feature = "esp32c2"))] use hal::system::SystemExt; @@ -194,7 +194,9 @@ async fn task(stack: &'static Stack) { let mut buf = [0; 1024]; loop { use embedded_io::asynch::Write; - let r = socket.write_all(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n").await; + let r = socket + .write_all(b"GET / HTTP/1.0\r\nHost: www.mobile-j.de\r\n\r\n") + .await; if let Err(e) = r { println!("write error: {:?}", e); break; diff --git a/esp-wifi/src/wifi/mod.rs b/esp-wifi/src/wifi/mod.rs index 5dba09e8..1633424e 100644 --- a/esp-wifi/src/wifi/mod.rs +++ b/esp-wifi/src/wifi/mod.rs @@ -1070,7 +1070,7 @@ macro_rules! esp_wifi_result { #[cfg(feature = "embassy-net")] pub(crate) mod embassy { use super::*; - use embassy_net_driver::{Driver, RxToken, TxToken, Capabilities}; + use embassy_net_driver::{Capabilities, Driver, RxToken, TxToken}; use embassy_sync::waitqueue::AtomicWaker; pub(crate) static TRANSMIT_WAKER: AtomicWaker = AtomicWaker::new(); @@ -1084,10 +1084,11 @@ pub(crate) mod embassy { critical_section::with(|cs| { let mut queue = DATA_QUEUE_RX.borrow_ref_mut(cs); - let mut data = queue - .dequeue() - .expect("unreachable: transmit()/receive() ensures there is a packet to process"); - let buffer = unsafe { core::slice::from_raw_parts(&data.data as *const u8, data.len) }; + let mut data = queue.dequeue().expect( + "unreachable: transmit()/receive() ensures there is a packet to process", + ); + let buffer = + unsafe { core::slice::from_raw_parts(&data.data as *const u8, data.len) }; dump_packet_info(&buffer); f(&mut data.data[..]) }) @@ -1096,24 +1097,24 @@ pub(crate) mod embassy { impl TxToken for WifiTxToken { fn consume(self, len: usize, f: F) -> R - where - F: FnOnce(&mut [u8]) -> R, - { - let res = critical_section::with(|cs| { - let mut queue = DATA_QUEUE_TX.borrow_ref_mut(cs); - - let mut packet = DataFrame::new(); - packet.len = len; - let res = f(&mut packet.data[..len]); - queue - .enqueue(packet) - .expect("unreachable: transmit()/receive() ensures there is a buffer free"); + where + F: FnOnce(&mut [u8]) -> R, + { + let res = critical_section::with(|cs| { + let mut queue = DATA_QUEUE_TX.borrow_ref_mut(cs); + + let mut packet = DataFrame::new(); + packet.len = len; + let res = f(&mut packet.data[..len]); + queue + .enqueue(packet) + .expect("unreachable: transmit()/receive() ensures there is a buffer free"); + res + }); + + send_data_if_needed(); res - }); - - send_data_if_needed(); - res - } + } } impl Driver for WifiDevice { @@ -1156,7 +1157,7 @@ pub(crate) mod embassy { fn link_state(&mut self, _cx: &mut core::task::Context) -> embassy_net_driver::LinkState { // TODO once we have an async way of connecting to wifi, use here // for now just assume the link is up - embassy_net_driver::LinkState::Up + embassy_net_driver::LinkState::Up } fn capabilities(&self) -> Capabilities { From c5ab62562769b0c0dd915cd9b9c8f959d09c76e4 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 9 Feb 2023 14:12:25 +0000 Subject: [PATCH 5/6] Simplify embedded-io import --- esp-wifi/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-wifi/Cargo.toml b/esp-wifi/Cargo.toml index 44a0b105..c4988595 100644 --- a/esp-wifi/Cargo.toml +++ b/esp-wifi/Cargo.toml @@ -26,7 +26,7 @@ log = "0.4.17" embedded-svc = { version = "0.23.1", default-features = false, features = [], optional = true } enumset = { version = "1", default-features = false, optional = true } linked_list_allocator = { version = "0.10.3", default-features = false, features = ["const_mut_refs"] } -embedded-io = { version = "0.4.0" } +embedded-io = "0.4.0" fugit = "0.3.6" heapless = { version = "0.7.14", default-features = false } num-derive = { version = "0.3", features = ["full-syntax"] } From ada7a20329b079ef0c4bb9e59aaed273c2ee7a57 Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Thu, 9 Feb 2023 15:30:50 +0000 Subject: [PATCH 6/6] Update README, use new bleps --- README.md | 4 ++++ esp-wifi/Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4e5a132d..f2118ba2 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,10 @@ If a cell contains am em dash (—) this means that the particular feature i | ESP32-S2 | `cargo +esp run --example embassy_esp_now --release --target xtensa-esp32s2-none-elf --features "esp32s2,esp32s2-async,esp-now"` | | ESP32-S3 | `cargo +esp run --example embassy_esp_now --release --target xtensa-esp32s3-none-elf --features "esp32s3,esp32s3-async,esp-now"` +### embassy_dhcp + +- Read and Write to sockets over WiFi asyncronously using embassy-executor. + | Chip | Command | | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ESP32 | `cargo +esp run --example embassy_dhcp --release --target xtensa-esp32-none-elf --features "esp32,esp32-async,embedded-svc,wifi,embassy-net"` | diff --git a/esp-wifi/Cargo.toml b/esp-wifi/Cargo.toml index c4988595..a1b50729 100644 --- a/esp-wifi/Cargo.toml +++ b/esp-wifi/Cargo.toml @@ -40,8 +40,8 @@ embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "264 riscv-target = { version = "0.1.2", optional = true } [dev-dependencies] -bleps = { git = "https://github.com/mabezdev/bleps", package = "bleps", branch = "patch-1" } -bleps-macros = { git = "https://github.com/mabezdev/bleps", package = "bleps-macros", branch = "patch-1" } +bleps = { git = "https://github.com/bjoernQ/bleps", package = "bleps", rev = "33fde67257bfbc6c0aebf7649fd302c82ed94c64" } +bleps-macros = { git = "https://github.com/bjoernQ/bleps", package = "bleps-macros", rev = "33fde67257bfbc6c0aebf7649fd302c82ed94c64" } embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] } embassy-time = { version = "0.1.0", features = ["nightly"] } embassy-futures = "0.1.0"