From 72b0379125b87bcd274bdb81127dd5f0ab29d661 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Tue, 9 May 2023 01:51:08 +0200 Subject: :rainbow: --- examples/.cargo/config.toml | 8 +++ examples/Cargo.toml | 70 +++++++++++++++++++ examples/README.md | 33 +++++++++ examples/build.rs | 36 ++++++++++ examples/memory.x | 5 ++ examples/src/bin/multisocket.rs | 148 ++++++++++++++++++++++++++++++++++++++++ examples/src/bin/tcp-client.rs | 128 ++++++++++++++++++++++++++++++++++ examples/src/bin/tcp-server.rs | 136 ++++++++++++++++++++++++++++++++++++ examples/src/bin/udp.rs | 123 +++++++++++++++++++++++++++++++++ 9 files changed, 687 insertions(+) create mode 100644 examples/.cargo/config.toml create mode 100644 examples/Cargo.toml create mode 100644 examples/README.md create mode 100644 examples/build.rs create mode 100644 examples/memory.x create mode 100644 examples/src/bin/multisocket.rs create mode 100644 examples/src/bin/tcp-client.rs create mode 100644 examples/src/bin/tcp-server.rs create mode 100644 examples/src/bin/udp.rs (limited to 'examples') diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml new file mode 100644 index 000000000..e6b6b4a41 --- /dev/null +++ b/examples/.cargo/config.toml @@ -0,0 +1,8 @@ +[target.'cfg(all(target_arch = "arm", target_os = "none"))'] +runner = "probe-rs-cli run --chip RP2040" + +[build] +target = "thumbv6m-none-eabi" + +[env] +DEFMT_LOG = "info" diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 000000000..013a2755f --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,70 @@ +[package] +name = "embassy-net-w5500-examples" +version = "0.1.0" +edition = "2021" + +[dependencies] +embassy-executor = { version = "0.1.0", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } +embassy-time = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] } +embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } +embassy-net = { version = "0.1.0", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet", "unstable-traits", "nightly"] } +embassy-sync = { version = "0.1.0" } +embassy-futures = { version = "0.1.0" } +embassy-net-driver = { version = "0.1.0" } +embassy-net-driver-channel = { version = "0.1.0" } +atomic-polyfill = "0.1.5" +static_cell = "1.0" + +defmt = "=0.3.2" +defmt-rtt = "0.3" +panic-probe = { version = "0.3", features = ["print-defmt"] } +cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } +cortex-m-rt = "0.7.0" + +embedded-io = { version = "0.4.0", features = ["async", "defmt"] } +heapless = "0.7.15" +embedded-hal = { version = "1.0.0-alpha.10" } +embedded-hal-async = { version = "=0.2.0-alpha.1" } +rand = { version = "0.8.5", default-features = false } + +embassy-net-w5500 = { path = "../" } + +[patch.crates-io] +embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } + +[profile.dev] +debug = 2 +debug-assertions = true +opt-level = 1 +overflow-checks = true + +[profile.release] +codegen-units = 1 +debug = 1 +debug-assertions = false +incremental = false +lto = 'fat' +opt-level = 'z' +overflow-checks = false + +# do not optimize proc-macro crates = faster builds from scratch +[profile.dev.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false + +[profile.release.build-override] +codegen-units = 8 +debug = false +debug-assertions = false +opt-level = 0 +overflow-checks = false diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 000000000..d818c4a89 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,33 @@ +# Examples for the rp2040 `WIZnet W5500-EVB-Pico` board + +Examples are written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +## Prerequisites +```bash +cargo install probe-rs-cli +``` + +## TCP server example +```bash +cargo run --bin tcp-server --release +``` +This example implements a TCP echo server on port 1234 and using DHCP. +Send it some data, you should see it echoed back and printed in the console. + +## Multi-socket example +```bash +cargo run --bin multisocket --release +``` +This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port. + +## TCP client example +```bash +cargo run --bin tcp-client --release +``` +This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. + +## UDP server example +```bash +cargo run --bin udp --release +``` +This example implements a UDP server listening on port 1234 and echoing back the data. diff --git a/examples/build.rs b/examples/build.rs new file mode 100644 index 000000000..3f915f931 --- /dev/null +++ b/examples/build.rs @@ -0,0 +1,36 @@ +//! This build script copies the `memory.x` file from the crate root into +//! a directory where the linker can always find it at build time. +//! For many projects this is optional, as the linker always searches the +//! project root directory -- wherever `Cargo.toml` is. However, if you +//! are using a workspace or have a more complicated build setup, this +//! build script becomes required. Additionally, by requesting that +//! Cargo re-run the build script whenever `memory.x` is changed, +//! updating `memory.x` ensures a rebuild of the application with the +//! new memory settings. + +use std::env; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; + +fn main() { + // Put `memory.x` in our output directory and ensure it's + // on the linker search path. + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("memory.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); + + // By default, Cargo will re-run a build script whenever + // any file in the project changes. By specifying `memory.x` + // here, we ensure the build script is only re-run when + // `memory.x` is changed. + println!("cargo:rerun-if-changed=memory.x"); + + println!("cargo:rustc-link-arg-bins=--nmagic"); + println!("cargo:rustc-link-arg-bins=-Tlink.x"); + println!("cargo:rustc-link-arg-bins=-Tlink-rp.x"); + println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); +} diff --git a/examples/memory.x b/examples/memory.x new file mode 100644 index 000000000..eb8c1731d --- /dev/null +++ b/examples/memory.x @@ -0,0 +1,5 @@ +MEMORY { + BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 + FLASH : ORIGIN = 0x10000100, LENGTH = 1024K - 0x100 + RAM : ORIGIN = 0x20000000, LENGTH = 256K +} \ No newline at end of file diff --git a/examples/src/bin/multisocket.rs b/examples/src/bin/multisocket.rs new file mode 100644 index 000000000..49bcbdbb0 --- /dev/null +++ b/examples/src/bin/multisocket.rs @@ -0,0 +1,148 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<3>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Create two sockets listening to the same port, to handle simultaneous connections + unwrap!(spawner.spawn(listen_task(&stack, 0, 1234))); + unwrap!(spawner.spawn(listen_task(&stack, 1, 1234))); +} + +#[embassy_executor::task(pool_size = 2)] +async fn listen_task(stack: &'static Stack>, id: u8, port: u16) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + info!("SOCKET {}: Listening on TCP:{}...", id, port); + if let Err(e) = socket.accept(port).await { + warn!("accept error: {:?}", e); + continue; + } + info!( + "SOCKET {}: Received connection from {:?}", + id, + socket.remote_endpoint() + ); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("SOCKET {}: {:?}", id, e); + break; + } + }; + info!( + "SOCKET {}: rxd {}", + id, + core::str::from_utf8(&buf[..n]).unwrap() + ); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/src/bin/tcp-client.rs b/examples/src/bin/tcp-client.rs new file mode 100644 index 000000000..32dfb6a68 --- /dev/null +++ b/examples/src/bin/tcp-client.rs @@ -0,0 +1,128 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::str::FromStr; +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Duration, Timer}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + led.set_low(); + info!("Connecting..."); + let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap(); + if let Err(e) = socket.connect((host_addr, 1234)).await { + warn!("connect error: {:?}", e); + continue; + } + info!("Connected to {:?}", socket.remote_endpoint()); + led.set_high(); + + let msg = b"Hello world!\n"; + loop { + if let Err(e) = socket.write_all(msg).await { + warn!("write error: {:?}", e); + break; + } + info!("txd: {}", core::str::from_utf8(msg).unwrap()); + Timer::after(Duration::from_secs(1)).await; + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/src/bin/tcp-server.rs b/examples/src/bin/tcp-server.rs new file mode 100644 index 000000000..04b220146 --- /dev/null +++ b/examples/src/bin/tcp-server.rs @@ -0,0 +1,136 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + led.set_low(); + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + info!("Received connection from {:?}", socket.remote_endpoint()); + led.set_high(); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("{:?}", e); + break; + } + }; + info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/src/bin/udp.rs b/examples/src/bin/udp.rs new file mode 100644 index 000000000..4dc5e1f2f --- /dev/null +++ b/examples/src/bin/udp.rs @@ -0,0 +1,123 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::udp::UdpSocket; +use embassy_net::{PacketMetadata, Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut buf = [0; 4096]; + loop { + let mut socket = UdpSocket::new( + stack, + &mut rx_meta, + &mut rx_buffer, + &mut tx_meta, + &mut tx_buffer, + ); + socket.bind(1234).unwrap(); + + loop { + let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); + if let Ok(s) = core::str::from_utf8(&buf[..n]) { + info!("rxd from {}: {}", ep, s); + } + socket.send_to(&buf[..n], ep).await.unwrap(); + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} -- cgit From bbd687fcb0e63a1bb8eb4d31c8f5ed2f403603f6 Mon Sep 17 00:00:00 2001 From: kalkyl Date: Wed, 10 May 2023 02:40:41 +0200 Subject: Update embassy --- examples/Cargo.toml | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'examples') diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 013a2755f..46659c2bc 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -embassy-executor = { version = "0.1.0", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } +embassy-executor = { version = "0.2.0", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } embassy-time = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] } embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } embassy-net = { version = "0.1.0", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet", "unstable-traits", "nightly"] } @@ -30,14 +30,14 @@ rand = { version = "0.8.5", default-features = false } embassy-net-w5500 = { path = "../" } [patch.crates-io] -embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } -embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "03d6363d5af5dcaf21b52734994a466ca593d2b6" } +embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } +embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } [profile.dev] debug = 2 -- cgit From 7f0e778145e7a0f7281d9b37e59473fddf232097 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 31 May 2023 00:54:20 +0200 Subject: move embassy-net-w5500 to subdir. --- examples/.cargo/config.toml | 8 -- examples/Cargo.toml | 70 ---------- examples/README.md | 33 ----- examples/build.rs | 36 ----- examples/memory.x | 5 - examples/rp/src/bin/ethernet_w5500_multisocket.rs | 152 ++++++++++++++++++++++ examples/rp/src/bin/ethernet_w5500_tcp_client.rs | 132 +++++++++++++++++++ examples/rp/src/bin/ethernet_w5500_tcp_server.rs | 141 ++++++++++++++++++++ examples/rp/src/bin/ethernet_w5500_udp.rs | 127 ++++++++++++++++++ examples/src/bin/multisocket.rs | 148 --------------------- examples/src/bin/tcp-client.rs | 128 ------------------ examples/src/bin/tcp-server.rs | 136 ------------------- examples/src/bin/udp.rs | 123 ----------------- 13 files changed, 552 insertions(+), 687 deletions(-) delete mode 100644 examples/.cargo/config.toml delete mode 100644 examples/Cargo.toml delete mode 100644 examples/README.md delete mode 100644 examples/build.rs delete mode 100644 examples/memory.x create mode 100644 examples/rp/src/bin/ethernet_w5500_multisocket.rs create mode 100644 examples/rp/src/bin/ethernet_w5500_tcp_client.rs create mode 100644 examples/rp/src/bin/ethernet_w5500_tcp_server.rs create mode 100644 examples/rp/src/bin/ethernet_w5500_udp.rs delete mode 100644 examples/src/bin/multisocket.rs delete mode 100644 examples/src/bin/tcp-client.rs delete mode 100644 examples/src/bin/tcp-server.rs delete mode 100644 examples/src/bin/udp.rs (limited to 'examples') diff --git a/examples/.cargo/config.toml b/examples/.cargo/config.toml deleted file mode 100644 index e6b6b4a41..000000000 --- a/examples/.cargo/config.toml +++ /dev/null @@ -1,8 +0,0 @@ -[target.'cfg(all(target_arch = "arm", target_os = "none"))'] -runner = "probe-rs-cli run --chip RP2040" - -[build] -target = "thumbv6m-none-eabi" - -[env] -DEFMT_LOG = "info" diff --git a/examples/Cargo.toml b/examples/Cargo.toml deleted file mode 100644 index 46659c2bc..000000000 --- a/examples/Cargo.toml +++ /dev/null @@ -1,70 +0,0 @@ -[package] -name = "embassy-net-w5500-examples" -version = "0.1.0" -edition = "2021" - -[dependencies] -embassy-executor = { version = "0.2.0", features = ["defmt", "integrated-timers", "executor-thread", "arch-cortex-m"] } -embassy-time = { version = "0.1.0", features = ["defmt", "defmt-timestamp-uptime"] } -embassy-rp = { version = "0.1.0", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver"] } -embassy-net = { version = "0.1.0", features = ["defmt", "tcp", "udp", "dhcpv4", "medium-ethernet", "unstable-traits", "nightly"] } -embassy-sync = { version = "0.1.0" } -embassy-futures = { version = "0.1.0" } -embassy-net-driver = { version = "0.1.0" } -embassy-net-driver-channel = { version = "0.1.0" } -atomic-polyfill = "0.1.5" -static_cell = "1.0" - -defmt = "=0.3.2" -defmt-rtt = "0.3" -panic-probe = { version = "0.3", features = ["print-defmt"] } -cortex-m = { version = "0.7.6", features = ["critical-section-single-core"] } -cortex-m-rt = "0.7.0" - -embedded-io = { version = "0.4.0", features = ["async", "defmt"] } -heapless = "0.7.15" -embedded-hal = { version = "1.0.0-alpha.10" } -embedded-hal-async = { version = "=0.2.0-alpha.1" } -rand = { version = "0.8.5", default-features = false } - -embassy-net-w5500 = { path = "../" } - -[patch.crates-io] -embassy-executor = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-time = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-futures = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-sync = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-rp = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-net = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-net-driver = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } -embassy-net-driver-channel = { git = "https://github.com/embassy-rs/embassy", rev = "e179e7cf85810f0aa7ef8027d8d48f6d21f64dac" } - -[profile.dev] -debug = 2 -debug-assertions = true -opt-level = 1 -overflow-checks = true - -[profile.release] -codegen-units = 1 -debug = 1 -debug-assertions = false -incremental = false -lto = 'fat' -opt-level = 'z' -overflow-checks = false - -# do not optimize proc-macro crates = faster builds from scratch -[profile.dev.build-override] -codegen-units = 8 -debug = false -debug-assertions = false -opt-level = 0 -overflow-checks = false - -[profile.release.build-override] -codegen-units = 8 -debug = false -debug-assertions = false -opt-level = 0 -overflow-checks = false diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index d818c4a89..000000000 --- a/examples/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Examples for the rp2040 `WIZnet W5500-EVB-Pico` board - -Examples are written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. - -## Prerequisites -```bash -cargo install probe-rs-cli -``` - -## TCP server example -```bash -cargo run --bin tcp-server --release -``` -This example implements a TCP echo server on port 1234 and using DHCP. -Send it some data, you should see it echoed back and printed in the console. - -## Multi-socket example -```bash -cargo run --bin multisocket --release -``` -This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port. - -## TCP client example -```bash -cargo run --bin tcp-client --release -``` -This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. - -## UDP server example -```bash -cargo run --bin udp --release -``` -This example implements a UDP server listening on port 1234 and echoing back the data. diff --git a/examples/build.rs b/examples/build.rs deleted file mode 100644 index 3f915f931..000000000 --- a/examples/build.rs +++ /dev/null @@ -1,36 +0,0 @@ -//! This build script copies the `memory.x` file from the crate root into -//! a directory where the linker can always find it at build time. -//! For many projects this is optional, as the linker always searches the -//! project root directory -- wherever `Cargo.toml` is. However, if you -//! are using a workspace or have a more complicated build setup, this -//! build script becomes required. Additionally, by requesting that -//! Cargo re-run the build script whenever `memory.x` is changed, -//! updating `memory.x` ensures a rebuild of the application with the -//! new memory settings. - -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; - -fn main() { - // Put `memory.x` in our output directory and ensure it's - // on the linker search path. - let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); - File::create(out.join("memory.x")) - .unwrap() - .write_all(include_bytes!("memory.x")) - .unwrap(); - println!("cargo:rustc-link-search={}", out.display()); - - // By default, Cargo will re-run a build script whenever - // any file in the project changes. By specifying `memory.x` - // here, we ensure the build script is only re-run when - // `memory.x` is changed. - println!("cargo:rerun-if-changed=memory.x"); - - println!("cargo:rustc-link-arg-bins=--nmagic"); - println!("cargo:rustc-link-arg-bins=-Tlink.x"); - println!("cargo:rustc-link-arg-bins=-Tlink-rp.x"); - println!("cargo:rustc-link-arg-bins=-Tdefmt.x"); -} diff --git a/examples/memory.x b/examples/memory.x deleted file mode 100644 index eb8c1731d..000000000 --- a/examples/memory.x +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY { - BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100 - FLASH : ORIGIN = 0x10000100, LENGTH = 1024K - 0x100 - RAM : ORIGIN = 0x20000000, LENGTH = 256K -} \ No newline at end of file diff --git a/examples/rp/src/bin/ethernet_w5500_multisocket.rs b/examples/rp/src/bin/ethernet_w5500_multisocket.rs new file mode 100644 index 000000000..eb3b8de81 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_multisocket.rs @@ -0,0 +1,152 @@ +//! This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<3>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Create two sockets listening to the same port, to handle simultaneous connections + unwrap!(spawner.spawn(listen_task(&stack, 0, 1234))); + unwrap!(spawner.spawn(listen_task(&stack, 1, 1234))); +} + +#[embassy_executor::task(pool_size = 2)] +async fn listen_task(stack: &'static Stack>, id: u8, port: u16) { + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + info!("SOCKET {}: Listening on TCP:{}...", id, port); + if let Err(e) = socket.accept(port).await { + warn!("accept error: {:?}", e); + continue; + } + info!( + "SOCKET {}: Received connection from {:?}", + id, + socket.remote_endpoint() + ); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("SOCKET {}: {:?}", id, e); + break; + } + }; + info!( + "SOCKET {}: rxd {}", + id, + core::str::from_utf8(&buf[..n]).unwrap() + ); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs new file mode 100644 index 000000000..e166e0f35 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_tcp_client.rs @@ -0,0 +1,132 @@ +//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use core::str::FromStr; +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embassy_time::{Duration, Timer}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + led.set_low(); + info!("Connecting..."); + let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap(); + if let Err(e) = socket.connect((host_addr, 1234)).await { + warn!("connect error: {:?}", e); + continue; + } + info!("Connected to {:?}", socket.remote_endpoint()); + led.set_high(); + + let msg = b"Hello world!\n"; + loop { + if let Err(e) = socket.write_all(msg).await { + warn!("write error: {:?}", e); + break; + } + info!("txd: {}", core::str::from_utf8(msg).unwrap()); + Timer::after(Duration::from_secs(1)).await; + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs new file mode 100644 index 000000000..ffd664d15 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_tcp_server.rs @@ -0,0 +1,141 @@ +//! This example implements a TCP echo server on port 1234 and using DHCP. +//! Send it some data, you should see it echoed back and printed in the console. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::{Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use embedded_io::asynch::Write; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + let mut led = Output::new(p.PIN_25, Level::Low); + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut buf = [0; 4096]; + loop { + let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); + socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); + + led.set_low(); + info!("Listening on TCP:1234..."); + if let Err(e) = socket.accept(1234).await { + warn!("accept error: {:?}", e); + continue; + } + info!("Received connection from {:?}", socket.remote_endpoint()); + led.set_high(); + + loop { + let n = match socket.read(&mut buf).await { + Ok(0) => { + warn!("read EOF"); + break; + } + Ok(n) => n, + Err(e) => { + warn!("{:?}", e); + break; + } + }; + info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); + + if let Err(e) = socket.write_all(&buf[..n]).await { + warn!("write error: {:?}", e); + break; + } + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/rp/src/bin/ethernet_w5500_udp.rs b/examples/rp/src/bin/ethernet_w5500_udp.rs new file mode 100644 index 000000000..08ffeb244 --- /dev/null +++ b/examples/rp/src/bin/ethernet_w5500_udp.rs @@ -0,0 +1,127 @@ +//! This example implements a UDP server listening on port 1234 and echoing back the data. +//! +//! Example written for the [`WIZnet W5500-EVB-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_futures::yield_now; +use embassy_net::udp::UdpSocket; +use embassy_net::{PacketMetadata, Stack, StackResources}; +use embassy_net_w5500::*; +use embassy_rp::clocks::RoscRng; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; +use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; +use embedded_hal_async::spi::ExclusiveDevice; +use rand::RngCore; +use static_cell::StaticCell; +use {defmt_rtt as _, panic_probe as _}; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +#[embassy_executor::task] +async fn ethernet_task( + runner: Runner< + 'static, + ExclusiveDevice, Output<'static, PIN_17>>, + Input<'static, PIN_21>, + Output<'static, PIN_20>, + >, +) -> ! { + runner.run().await +} + +#[embassy_executor::task] +async fn net_task(stack: &'static Stack>) -> ! { + stack.run().await +} + +#[embassy_executor::main] +async fn main(spawner: Spawner) { + let p = embassy_rp::init(Default::default()); + let mut rng = RoscRng; + + let mut spi_cfg = SpiConfig::default(); + spi_cfg.frequency = 50_000_000; + let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); + let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); + let cs = Output::new(p.PIN_17, Level::High); + let w5500_int = Input::new(p.PIN_21, Pull::Up); + let w5500_reset = Output::new(p.PIN_20, Level::High); + + let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; + let state = singleton!(State::<8, 8>::new()); + let (device, runner) = embassy_net_w5500::new( + mac_addr, + state, + ExclusiveDevice::new(spi, cs), + w5500_int, + w5500_reset, + ) + .await; + unwrap!(spawner.spawn(ethernet_task(runner))); + + // Generate random seed + let seed = rng.next_u64(); + + // Init network stack + let stack = &*singleton!(Stack::new( + device, + embassy_net::Config::Dhcp(Default::default()), + singleton!(StackResources::<2>::new()), + seed + )); + + // Launch network task + unwrap!(spawner.spawn(net_task(&stack))); + + info!("Waiting for DHCP..."); + let cfg = wait_for_config(stack).await; + let local_addr = cfg.address.address(); + info!("IP address: {:?}", local_addr); + + // Then we can use it! + let mut rx_buffer = [0; 4096]; + let mut tx_buffer = [0; 4096]; + let mut rx_meta = [PacketMetadata::EMPTY; 16]; + let mut tx_meta = [PacketMetadata::EMPTY; 16]; + let mut buf = [0; 4096]; + loop { + let mut socket = UdpSocket::new( + stack, + &mut rx_meta, + &mut rx_buffer, + &mut tx_meta, + &mut tx_buffer, + ); + socket.bind(1234).unwrap(); + + loop { + let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); + if let Ok(s) = core::str::from_utf8(&buf[..n]) { + info!("rxd from {}: {}", ep, s); + } + socket.send_to(&buf[..n], ep).await.unwrap(); + } + } +} + +async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { + loop { + if let Some(config) = stack.config() { + return config.clone(); + } + yield_now().await; + } +} diff --git a/examples/src/bin/multisocket.rs b/examples/src/bin/multisocket.rs deleted file mode 100644 index 49bcbdbb0..000000000 --- a/examples/src/bin/multisocket.rs +++ /dev/null @@ -1,148 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use defmt::*; -use embassy_executor::Spawner; -use embassy_futures::yield_now; -use embassy_net::{Stack, StackResources}; -use embassy_net_w5500::*; -use embassy_rp::clocks::RoscRng; -use embassy_rp::gpio::{Input, Level, Output, Pull}; -use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; -use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embedded_hal_async::spi::ExclusiveDevice; -use embedded_io::asynch::Write; -use rand::RngCore; -use static_cell::StaticCell; -use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - -#[embassy_executor::task] -async fn ethernet_task( - runner: Runner< - 'static, - ExclusiveDevice, Output<'static, PIN_17>>, - Input<'static, PIN_21>, - Output<'static, PIN_20>, - >, -) -> ! { - runner.run().await -} - -#[embassy_executor::task] -async fn net_task(stack: &'static Stack>) -> ! { - stack.run().await -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_rp::init(Default::default()); - let mut rng = RoscRng; - - let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = 50_000_000; - let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); - let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); - let cs = Output::new(p.PIN_17, Level::High); - let w5500_int = Input::new(p.PIN_21, Pull::Up); - let w5500_reset = Output::new(p.PIN_20, Level::High); - - let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; - unwrap!(spawner.spawn(ethernet_task(runner))); - - // Generate random seed - let seed = rng.next_u64(); - - // Init network stack - let stack = &*singleton!(Stack::new( - device, - embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<3>::new()), - seed - )); - - // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); - - info!("Waiting for DHCP..."); - let cfg = wait_for_config(stack).await; - let local_addr = cfg.address.address(); - info!("IP address: {:?}", local_addr); - - // Create two sockets listening to the same port, to handle simultaneous connections - unwrap!(spawner.spawn(listen_task(&stack, 0, 1234))); - unwrap!(spawner.spawn(listen_task(&stack, 1, 1234))); -} - -#[embassy_executor::task(pool_size = 2)] -async fn listen_task(stack: &'static Stack>, id: u8, port: u16) { - let mut rx_buffer = [0; 4096]; - let mut tx_buffer = [0; 4096]; - let mut buf = [0; 4096]; - loop { - let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); - - info!("SOCKET {}: Listening on TCP:{}...", id, port); - if let Err(e) = socket.accept(port).await { - warn!("accept error: {:?}", e); - continue; - } - info!( - "SOCKET {}: Received connection from {:?}", - id, - socket.remote_endpoint() - ); - - loop { - let n = match socket.read(&mut buf).await { - Ok(0) => { - warn!("read EOF"); - break; - } - Ok(n) => n, - Err(e) => { - warn!("SOCKET {}: {:?}", id, e); - break; - } - }; - info!( - "SOCKET {}: rxd {}", - id, - core::str::from_utf8(&buf[..n]).unwrap() - ); - - if let Err(e) = socket.write_all(&buf[..n]).await { - warn!("write error: {:?}", e); - break; - } - } - } -} - -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { - loop { - if let Some(config) = stack.config() { - return config.clone(); - } - yield_now().await; - } -} diff --git a/examples/src/bin/tcp-client.rs b/examples/src/bin/tcp-client.rs deleted file mode 100644 index 32dfb6a68..000000000 --- a/examples/src/bin/tcp-client.rs +++ /dev/null @@ -1,128 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use core::str::FromStr; -use defmt::*; -use embassy_executor::Spawner; -use embassy_futures::yield_now; -use embassy_net::{Stack, StackResources}; -use embassy_net_w5500::*; -use embassy_rp::clocks::RoscRng; -use embassy_rp::gpio::{Input, Level, Output, Pull}; -use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; -use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embassy_time::{Duration, Timer}; -use embedded_hal_async::spi::ExclusiveDevice; -use embedded_io::asynch::Write; -use rand::RngCore; -use static_cell::StaticCell; -use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - -#[embassy_executor::task] -async fn ethernet_task( - runner: Runner< - 'static, - ExclusiveDevice, Output<'static, PIN_17>>, - Input<'static, PIN_21>, - Output<'static, PIN_20>, - >, -) -> ! { - runner.run().await -} - -#[embassy_executor::task] -async fn net_task(stack: &'static Stack>) -> ! { - stack.run().await -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_rp::init(Default::default()); - let mut rng = RoscRng; - let mut led = Output::new(p.PIN_25, Level::Low); - - let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = 50_000_000; - let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); - let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); - let cs = Output::new(p.PIN_17, Level::High); - let w5500_int = Input::new(p.PIN_21, Pull::Up); - let w5500_reset = Output::new(p.PIN_20, Level::High); - - let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; - unwrap!(spawner.spawn(ethernet_task(runner))); - - // Generate random seed - let seed = rng.next_u64(); - - // Init network stack - let stack = &*singleton!(Stack::new( - device, - embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), - seed - )); - - // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); - - info!("Waiting for DHCP..."); - let cfg = wait_for_config(stack).await; - let local_addr = cfg.address.address(); - info!("IP address: {:?}", local_addr); - - let mut rx_buffer = [0; 4096]; - let mut tx_buffer = [0; 4096]; - loop { - let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); - - led.set_low(); - info!("Connecting..."); - let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap(); - if let Err(e) = socket.connect((host_addr, 1234)).await { - warn!("connect error: {:?}", e); - continue; - } - info!("Connected to {:?}", socket.remote_endpoint()); - led.set_high(); - - let msg = b"Hello world!\n"; - loop { - if let Err(e) = socket.write_all(msg).await { - warn!("write error: {:?}", e); - break; - } - info!("txd: {}", core::str::from_utf8(msg).unwrap()); - Timer::after(Duration::from_secs(1)).await; - } - } -} - -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { - loop { - if let Some(config) = stack.config() { - return config.clone(); - } - yield_now().await; - } -} diff --git a/examples/src/bin/tcp-server.rs b/examples/src/bin/tcp-server.rs deleted file mode 100644 index 04b220146..000000000 --- a/examples/src/bin/tcp-server.rs +++ /dev/null @@ -1,136 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use defmt::*; -use embassy_executor::Spawner; -use embassy_futures::yield_now; -use embassy_net::{Stack, StackResources}; -use embassy_net_w5500::*; -use embassy_rp::clocks::RoscRng; -use embassy_rp::gpio::{Input, Level, Output, Pull}; -use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; -use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embedded_hal_async::spi::ExclusiveDevice; -use embedded_io::asynch::Write; -use rand::RngCore; -use static_cell::StaticCell; -use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - -#[embassy_executor::task] -async fn ethernet_task( - runner: Runner< - 'static, - ExclusiveDevice, Output<'static, PIN_17>>, - Input<'static, PIN_21>, - Output<'static, PIN_20>, - >, -) -> ! { - runner.run().await -} - -#[embassy_executor::task] -async fn net_task(stack: &'static Stack>) -> ! { - stack.run().await -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_rp::init(Default::default()); - let mut rng = RoscRng; - let mut led = Output::new(p.PIN_25, Level::Low); - - let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = 50_000_000; - let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); - let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); - let cs = Output::new(p.PIN_17, Level::High); - let w5500_int = Input::new(p.PIN_21, Pull::Up); - let w5500_reset = Output::new(p.PIN_20, Level::High); - - let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; - unwrap!(spawner.spawn(ethernet_task(runner))); - - // Generate random seed - let seed = rng.next_u64(); - - // Init network stack - let stack = &*singleton!(Stack::new( - device, - embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), - seed - )); - - // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); - - info!("Waiting for DHCP..."); - let cfg = wait_for_config(stack).await; - let local_addr = cfg.address.address(); - info!("IP address: {:?}", local_addr); - - let mut rx_buffer = [0; 4096]; - let mut tx_buffer = [0; 4096]; - let mut buf = [0; 4096]; - loop { - let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer); - socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10))); - - led.set_low(); - info!("Listening on TCP:1234..."); - if let Err(e) = socket.accept(1234).await { - warn!("accept error: {:?}", e); - continue; - } - info!("Received connection from {:?}", socket.remote_endpoint()); - led.set_high(); - - loop { - let n = match socket.read(&mut buf).await { - Ok(0) => { - warn!("read EOF"); - break; - } - Ok(n) => n, - Err(e) => { - warn!("{:?}", e); - break; - } - }; - info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap()); - - if let Err(e) = socket.write_all(&buf[..n]).await { - warn!("write error: {:?}", e); - break; - } - } - } -} - -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { - loop { - if let Some(config) = stack.config() { - return config.clone(); - } - yield_now().await; - } -} diff --git a/examples/src/bin/udp.rs b/examples/src/bin/udp.rs deleted file mode 100644 index 4dc5e1f2f..000000000 --- a/examples/src/bin/udp.rs +++ /dev/null @@ -1,123 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] - -use defmt::*; -use embassy_executor::Spawner; -use embassy_futures::yield_now; -use embassy_net::udp::UdpSocket; -use embassy_net::{PacketMetadata, Stack, StackResources}; -use embassy_net_w5500::*; -use embassy_rp::clocks::RoscRng; -use embassy_rp::gpio::{Input, Level, Output, Pull}; -use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0}; -use embassy_rp::spi::{Async, Config as SpiConfig, Spi}; -use embedded_hal_async::spi::ExclusiveDevice; -use rand::RngCore; -use static_cell::StaticCell; -use {defmt_rtt as _, panic_probe as _}; - -macro_rules! singleton { - ($val:expr) => {{ - type T = impl Sized; - static STATIC_CELL: StaticCell = StaticCell::new(); - let (x,) = STATIC_CELL.init(($val,)); - x - }}; -} - -#[embassy_executor::task] -async fn ethernet_task( - runner: Runner< - 'static, - ExclusiveDevice, Output<'static, PIN_17>>, - Input<'static, PIN_21>, - Output<'static, PIN_20>, - >, -) -> ! { - runner.run().await -} - -#[embassy_executor::task] -async fn net_task(stack: &'static Stack>) -> ! { - stack.run().await -} - -#[embassy_executor::main] -async fn main(spawner: Spawner) { - let p = embassy_rp::init(Default::default()); - let mut rng = RoscRng; - - let mut spi_cfg = SpiConfig::default(); - spi_cfg.frequency = 50_000_000; - let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18); - let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg); - let cs = Output::new(p.PIN_17, Level::High); - let w5500_int = Input::new(p.PIN_21, Pull::Up); - let w5500_reset = Output::new(p.PIN_20, Level::High); - - let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00]; - let state = singleton!(State::<8, 8>::new()); - let (device, runner) = embassy_net_w5500::new( - mac_addr, - state, - ExclusiveDevice::new(spi, cs), - w5500_int, - w5500_reset, - ) - .await; - unwrap!(spawner.spawn(ethernet_task(runner))); - - // Generate random seed - let seed = rng.next_u64(); - - // Init network stack - let stack = &*singleton!(Stack::new( - device, - embassy_net::Config::Dhcp(Default::default()), - singleton!(StackResources::<2>::new()), - seed - )); - - // Launch network task - unwrap!(spawner.spawn(net_task(&stack))); - - info!("Waiting for DHCP..."); - let cfg = wait_for_config(stack).await; - let local_addr = cfg.address.address(); - info!("IP address: {:?}", local_addr); - - // Then we can use it! - let mut rx_buffer = [0; 4096]; - let mut tx_buffer = [0; 4096]; - let mut rx_meta = [PacketMetadata::EMPTY; 16]; - let mut tx_meta = [PacketMetadata::EMPTY; 16]; - let mut buf = [0; 4096]; - loop { - let mut socket = UdpSocket::new( - stack, - &mut rx_meta, - &mut rx_buffer, - &mut tx_meta, - &mut tx_buffer, - ); - socket.bind(1234).unwrap(); - - loop { - let (n, ep) = socket.recv_from(&mut buf).await.unwrap(); - if let Ok(s) = core::str::from_utf8(&buf[..n]) { - info!("rxd from {}: {}", ep, s); - } - socket.send_to(&buf[..n], ep).await.unwrap(); - } - } -} - -async fn wait_for_config(stack: &'static Stack>) -> embassy_net::StaticConfig { - loop { - if let Some(config) = stack.config() { - return config.clone(); - } - yield_now().await; - } -} -- cgit