aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
Diffstat (limited to 'examples')
-rw-r--r--examples/nrf54l15/Cargo.toml2
-rw-r--r--examples/nrf54l15/src/bin/nvmc.rs44
-rw-r--r--examples/rp235x/Cargo.toml2
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_icmp.rs143
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs134
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_multisocket.rs139
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs127
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs136
-rw-r--r--examples/rp235x/src/bin/ethernet_w5500_udp.rs116
9 files changed, 842 insertions, 1 deletions
diff --git a/examples/nrf54l15/Cargo.toml b/examples/nrf54l15/Cargo.toml
index faa3a4abe..5f1ee50a0 100644
--- a/examples/nrf54l15/Cargo.toml
+++ b/examples/nrf54l15/Cargo.toml
@@ -16,5 +16,7 @@ panic-probe = { version = "1.0.0", features = ["print-defmt"] }
16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] } 16cortex-m = { version = "0.7.6", features = ["inline-asm", "critical-section-single-core"] }
17cortex-m-rt = "0.7.0" 17cortex-m-rt = "0.7.0"
18 18
19embedded-storage = "0.3.1"
20
19[profile.release] 21[profile.release]
20debug = 2 22debug = 2
diff --git a/examples/nrf54l15/src/bin/nvmc.rs b/examples/nrf54l15/src/bin/nvmc.rs
new file mode 100644
index 000000000..f990604cd
--- /dev/null
+++ b/examples/nrf54l15/src/bin/nvmc.rs
@@ -0,0 +1,44 @@
1#![no_std]
2#![no_main]
3
4use defmt::{info, unwrap};
5use embassy_executor::Spawner;
6use embassy_nrf::nvmc::{Nvmc, PAGE_SIZE};
7use embedded_storage::nor_flash::{NorFlash, ReadNorFlash};
8use {defmt_rtt as _, panic_probe as _};
9
10#[embassy_executor::main]
11async fn main(_spawner: Spawner) {
12 let p = embassy_nrf::init(Default::default());
13 info!("Hello RRAMC NVMC!");
14
15 let mut f = Nvmc::new(p.RRAMC);
16
17 const ADDR: u32 = 0x80000;
18 let mut buf = [0u8; 4];
19
20 info!("Reading...");
21 unwrap!(f.read(ADDR, &mut buf));
22 info!("Read: {=[u8]:x}", buf);
23
24 info!("Erasing...");
25 unwrap!(f.erase(ADDR, ADDR + PAGE_SIZE as u32));
26
27 info!("Reading...");
28 unwrap!(f.read(ADDR, &mut buf));
29 info!("Read: {=[u8]:x}", buf);
30
31 info!("Writing...");
32 // 16 B (128-bit) write minimum
33 let out: [u8; 16] = [
34 0xaa, 0xaa, 0xaa, 0xaa, 0xbb, 0xbb, 0xbb, 0xbb, 0xcc, 0xcc, 0xcc, 0xcc, 0xdd, 0xdd, 0xdd, 0xdd,
35 ];
36 unwrap!(f.write(ADDR, &out));
37
38 info!("Reading...");
39 // Can read arbitrary sizes
40 for addr in (ADDR..ADDR + 16).step_by(4) {
41 unwrap!(f.read(addr, &mut buf));
42 info!("Read: {=[u8]:x}", buf);
43 }
44}
diff --git a/examples/rp235x/Cargo.toml b/examples/rp235x/Cargo.toml
index eecd98894..2a4e888d9 100644
--- a/examples/rp235x/Cargo.toml
+++ b/examples/rp235x/Cargo.toml
@@ -12,7 +12,7 @@ embassy-executor = { version = "0.8.0", path = "../../embassy-executor", feature
12embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.4.0", path = "../../embassy-time", features = ["defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] } 13embassy-rp = { version = "0.7.0", path = "../../embassy-rp", features = ["defmt", "unstable-pac", "time-driver", "critical-section-impl", "rp235xa", "binary-info"] }
14embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.5.0", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] } 15embassy-net = { version = "0.7.0", path = "../../embassy-net", features = ["defmt", "icmp", "tcp", "udp", "raw", "dhcpv4", "medium-ethernet", "dns"] }
16embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] } 16embassy-net-wiznet = { version = "0.2.0", path = "../../embassy-net-wiznet", features = ["defmt"] }
17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
18embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" } 18embassy-usb-logger = { version = "0.5.0", path = "../../embassy-usb-logger" }
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs
new file mode 100644
index 000000000..f1abd311c
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_icmp.rs
@@ -0,0 +1,143 @@
1//! This example implements an echo (ping) with an ICMP Socket and using defmt to report the results.
2//!
3//! Although there is a better way to execute pings using the child module ping of the icmp module,
4//! this example allows for other icmp messages like `Destination unreachable` to be sent aswell.
5//!
6//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
7
8#![no_std]
9#![no_main]
10
11use defmt::*;
12use embassy_executor::Spawner;
13use embassy_futures::yield_now;
14use embassy_net::icmp::{ChecksumCapabilities, IcmpEndpoint, IcmpSocket, Icmpv4Packet, Icmpv4Repr, PacketMetadata};
15use embassy_net::{Stack, StackResources};
16use embassy_net_wiznet::chip::W5500;
17use embassy_net_wiznet::*;
18use embassy_rp::clocks::RoscRng;
19use embassy_rp::gpio::{Input, Level, Output, Pull};
20use embassy_rp::peripherals::SPI0;
21use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
22use embassy_time::{Delay, Instant, Timer};
23use embedded_hal_bus::spi::ExclusiveDevice;
24use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _};
26
27type ExclusiveSpiDevice = ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>;
28
29#[embassy_executor::task]
30async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! {
31 runner.run().await
32}
33
34#[embassy_executor::task]
35async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
36 runner.run().await
37}
38
39#[embassy_executor::main]
40async fn main(spawner: Spawner) {
41 let p = embassy_rp::init(Default::default());
42 let mut rng = RoscRng;
43
44 let mut spi_cfg = SpiConfig::default();
45 spi_cfg.frequency = 50_000_000;
46 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
47 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
48 let cs = Output::new(p.PIN_17, Level::High);
49 let w5500_int = Input::new(p.PIN_21, Pull::Up);
50 let w5500_reset = Output::new(p.PIN_20, Level::High);
51
52 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
53 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
54 let state = STATE.init(State::<8, 8>::new());
55 let (device, runner) = embassy_net_wiznet::new(
56 mac_addr,
57 state,
58 ExclusiveDevice::new(spi, cs, Delay),
59 w5500_int,
60 w5500_reset,
61 )
62 .await
63 .unwrap();
64 unwrap!(spawner.spawn(ethernet_task(runner)));
65
66 // Generate random seed
67 let seed = rng.next_u64();
68
69 // Init network stack
70 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
71 let (stack, runner) = embassy_net::new(
72 device,
73 embassy_net::Config::dhcpv4(Default::default()),
74 RESOURCES.init(StackResources::new()),
75 seed,
76 );
77
78 // Launch network task
79 unwrap!(spawner.spawn(net_task(runner)));
80
81 info!("Waiting for DHCP...");
82 let cfg = wait_for_config(stack).await;
83 let local_addr = cfg.address.address();
84 info!("IP address: {:?}", local_addr);
85
86 // Then we can use it!
87 let mut rx_buffer = [0; 256];
88 let mut tx_buffer = [0; 256];
89 let mut rx_meta = [PacketMetadata::EMPTY];
90 let mut tx_meta = [PacketMetadata::EMPTY];
91
92 // Identifier used for the ICMP socket
93 let ident = 42;
94
95 // Create and bind the socket
96 let mut socket = IcmpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
97 socket.bind(IcmpEndpoint::Ident(ident)).unwrap();
98
99 // Create the repr for the packet
100 let icmp_repr = Icmpv4Repr::EchoRequest {
101 ident,
102 seq_no: 0,
103 data: b"Hello, icmp!",
104 };
105
106 // Send the packet and store the starting instant to mesure latency later
107 let start = socket
108 .send_to_with(icmp_repr.buffer_len(), cfg.gateway.unwrap(), |buf| {
109 // Create and populate the packet buffer allocated by `send_to_with`
110 let mut icmp_packet = Icmpv4Packet::new_unchecked(buf);
111 icmp_repr.emit(&mut icmp_packet, &ChecksumCapabilities::default());
112 Instant::now() // Return the instant where the packet was sent
113 })
114 .await
115 .unwrap();
116
117 // Recieve and log the data of the reply
118 socket
119 .recv_from_with(|(buf, addr)| {
120 let packet = Icmpv4Packet::new_checked(buf).unwrap();
121 info!(
122 "Recieved {:?} from {} in {}ms",
123 packet.data(),
124 addr,
125 start.elapsed().as_millis()
126 );
127 })
128 .await
129 .unwrap();
130
131 loop {
132 Timer::after_secs(10).await;
133 }
134}
135
136async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
137 loop {
138 if let Some(config) = stack.config_v4() {
139 return config.clone();
140 }
141 yield_now().await;
142 }
143}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
new file mode 100644
index 000000000..1f799a6b0
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_icmp_ping.rs
@@ -0,0 +1,134 @@
1//! This example implements a LAN ping scan with the ping utilities in the icmp module of embassy-net.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use core::net::Ipv4Addr;
9use core::ops::Not;
10use core::str::FromStr;
11
12use defmt::*;
13use embassy_executor::Spawner;
14use embassy_futures::yield_now;
15use embassy_net::icmp::ping::{PingManager, PingParams};
16use embassy_net::icmp::PacketMetadata;
17use embassy_net::{Ipv4Cidr, Stack, StackResources};
18use embassy_net_wiznet::chip::W5500;
19use embassy_net_wiznet::*;
20use embassy_rp::clocks::RoscRng;
21use embassy_rp::gpio::{Input, Level, Output, Pull};
22use embassy_rp::peripherals::SPI0;
23use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
24use embassy_time::{Delay, Duration};
25use embedded_hal_bus::spi::ExclusiveDevice;
26use static_cell::StaticCell;
27use {defmt_rtt as _, panic_probe as _};
28
29type ExclusiveSpiDevice = ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>;
30
31#[embassy_executor::task]
32async fn ethernet_task(runner: Runner<'static, W5500, ExclusiveSpiDevice, Input<'static>, Output<'static>>) -> ! {
33 runner.run().await
34}
35
36#[embassy_executor::task]
37async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
38 runner.run().await
39}
40
41#[embassy_executor::main]
42async fn main(spawner: Spawner) {
43 let p = embassy_rp::init(Default::default());
44 let mut rng = RoscRng;
45
46 let mut spi_cfg = SpiConfig::default();
47 spi_cfg.frequency = 50_000_000;
48 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
49 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
50 let cs = Output::new(p.PIN_17, Level::High);
51 let w5500_int = Input::new(p.PIN_21, Pull::Up);
52 let w5500_reset = Output::new(p.PIN_20, Level::High);
53
54 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
55 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
56 let state = STATE.init(State::<8, 8>::new());
57 let (device, runner) = embassy_net_wiznet::new(
58 mac_addr,
59 state,
60 ExclusiveDevice::new(spi, cs, Delay),
61 w5500_int,
62 w5500_reset,
63 )
64 .await
65 .unwrap();
66 unwrap!(spawner.spawn(ethernet_task(runner)));
67
68 // Generate random seed
69 let seed = rng.next_u64();
70
71 // Init network stack
72 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
73 let (stack, runner) = embassy_net::new(
74 device,
75 embassy_net::Config::dhcpv4(Default::default()),
76 RESOURCES.init(StackResources::new()),
77 seed,
78 );
79
80 // Launch network task
81 unwrap!(spawner.spawn(net_task(runner)));
82
83 info!("Waiting for DHCP...");
84 let cfg = wait_for_config(stack).await;
85 let local_addr = cfg.address.address();
86 info!("IP address: {:?}", local_addr);
87 let gateway = cfg.gateway.unwrap();
88 let mask = cfg.address.netmask();
89 let lower_bound = (gateway.to_bits() & mask.to_bits()) + 1;
90 let upper_bound = gateway.to_bits() | mask.to_bits().not();
91 let addr_range = lower_bound..=upper_bound;
92
93 // Then we can use it!
94 let mut rx_buffer = [0; 256];
95 let mut tx_buffer = [0; 256];
96 let mut rx_meta = [PacketMetadata::EMPTY];
97 let mut tx_meta = [PacketMetadata::EMPTY];
98
99 // Create the ping manager instance
100 let mut ping_manager = PingManager::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
101 let addr = "192.168.8.1"; // Address to ping to
102 // Create the PingParams with the target address
103 let mut ping_params = PingParams::new(Ipv4Addr::from_str(addr).unwrap());
104 // (optional) Set custom properties of the ping
105 ping_params.set_payload(b"Hello, Ping!"); // custom payload
106 ping_params.set_count(1); // ping 1 times per ping call
107 ping_params.set_timeout(Duration::from_millis(500)); // wait .5 seconds instead of 4
108
109 info!("Online hosts in {}:", Ipv4Cidr::from_netmask(gateway, mask).unwrap());
110 let mut total_online_hosts = 0u32;
111 for addr in addr_range {
112 let ip_addr = Ipv4Addr::from_bits(addr);
113 // Set the target address in the ping params
114 ping_params.set_target(ip_addr);
115 // Execute the ping with the given parameters and wait for the reply
116 match ping_manager.ping(&ping_params).await {
117 Ok(time) => {
118 info!("{} is online\n- latency: {}ms\n", ip_addr, time.as_millis());
119 total_online_hosts += 1;
120 }
121 _ => continue,
122 }
123 }
124 info!("Ping scan complete, total online hosts: {}", total_online_hosts);
125}
126
127async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
128 loop {
129 if let Some(config) = stack.config_v4() {
130 return config.clone();
131 }
132 yield_now().await;
133 }
134}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs
new file mode 100644
index 000000000..fd8bc5c7a
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_multisocket.rs
@@ -0,0 +1,139 @@
1//! This example shows how you can allow multiple simultaneous TCP connections, by having multiple sockets listening on the same port.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_futures::yield_now;
11use embassy_net::{Stack, StackResources};
12use embassy_net_wiznet::chip::W5500;
13use embassy_net_wiznet::*;
14use embassy_rp::clocks::RoscRng;
15use embassy_rp::gpio::{Input, Level, Output, Pull};
16use embassy_rp::peripherals::SPI0;
17use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
18use embassy_time::{Delay, Duration};
19use embedded_hal_bus::spi::ExclusiveDevice;
20use embedded_io_async::Write;
21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _};
23
24#[embassy_executor::task]
25async fn ethernet_task(
26 runner: Runner<
27 'static,
28 W5500,
29 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
30 Input<'static>,
31 Output<'static>,
32 >,
33) -> ! {
34 runner.run().await
35}
36
37#[embassy_executor::task]
38async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
39 runner.run().await
40}
41
42#[embassy_executor::main]
43async fn main(spawner: Spawner) {
44 let p = embassy_rp::init(Default::default());
45 let mut rng = RoscRng;
46
47 let mut spi_cfg = SpiConfig::default();
48 spi_cfg.frequency = 50_000_000;
49 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
50 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
51 let cs = Output::new(p.PIN_17, Level::High);
52 let w5500_int = Input::new(p.PIN_21, Pull::Up);
53 let w5500_reset = Output::new(p.PIN_20, Level::High);
54
55 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
56 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
57 let state = STATE.init(State::<8, 8>::new());
58 let (device, runner) = embassy_net_wiznet::new(
59 mac_addr,
60 state,
61 ExclusiveDevice::new(spi, cs, Delay),
62 w5500_int,
63 w5500_reset,
64 )
65 .await
66 .unwrap();
67 unwrap!(spawner.spawn(ethernet_task(runner)));
68
69 // Generate random seed
70 let seed = rng.next_u64();
71
72 // Init network stack
73 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
74 let (stack, runner) = embassy_net::new(
75 device,
76 embassy_net::Config::dhcpv4(Default::default()),
77 RESOURCES.init(StackResources::new()),
78 seed,
79 );
80
81 // Launch network task
82 unwrap!(spawner.spawn(net_task(runner)));
83
84 info!("Waiting for DHCP...");
85 let cfg = wait_for_config(stack).await;
86 let local_addr = cfg.address.address();
87 info!("IP address: {:?}", local_addr);
88
89 // Create two sockets listening to the same port, to handle simultaneous connections
90 unwrap!(spawner.spawn(listen_task(stack, 0, 1234)));
91 unwrap!(spawner.spawn(listen_task(stack, 1, 1234)));
92}
93
94#[embassy_executor::task(pool_size = 2)]
95async fn listen_task(stack: Stack<'static>, id: u8, port: u16) {
96 let mut rx_buffer = [0; 4096];
97 let mut tx_buffer = [0; 4096];
98 let mut buf = [0; 4096];
99 loop {
100 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
101 socket.set_timeout(Some(Duration::from_secs(10)));
102
103 info!("SOCKET {}: Listening on TCP:{}...", id, port);
104 if let Err(e) = socket.accept(port).await {
105 warn!("accept error: {:?}", e);
106 continue;
107 }
108 info!("SOCKET {}: Received connection from {:?}", id, socket.remote_endpoint());
109
110 loop {
111 let n = match socket.read(&mut buf).await {
112 Ok(0) => {
113 warn!("read EOF");
114 break;
115 }
116 Ok(n) => n,
117 Err(e) => {
118 warn!("SOCKET {}: {:?}", id, e);
119 break;
120 }
121 };
122 info!("SOCKET {}: rxd {}", id, core::str::from_utf8(&buf[..n]).unwrap());
123
124 if let Err(e) = socket.write_all(&buf[..n]).await {
125 warn!("write error: {:?}", e);
126 break;
127 }
128 }
129 }
130}
131
132async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
133 loop {
134 if let Some(config) = stack.config_v4() {
135 return config.clone();
136 }
137 yield_now().await;
138 }
139}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs
new file mode 100644
index 000000000..b726b9cc6
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_client.rs
@@ -0,0 +1,127 @@
1//! This example implements a TCP client that attempts to connect to a host on port 1234 and send it some data once per second.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use core::str::FromStr;
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_futures::yield_now;
13use embassy_net::{Stack, StackResources};
14use embassy_net_wiznet::chip::W5500;
15use embassy_net_wiznet::*;
16use embassy_rp::clocks::RoscRng;
17use embassy_rp::gpio::{Input, Level, Output, Pull};
18use embassy_rp::peripherals::SPI0;
19use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::{Delay, Duration, Timer};
21use embedded_hal_bus::spi::ExclusiveDevice;
22use embedded_io_async::Write;
23use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _};
25
26#[embassy_executor::task]
27async fn ethernet_task(
28 runner: Runner<
29 'static,
30 W5500,
31 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
32 Input<'static>,
33 Output<'static>,
34 >,
35) -> ! {
36 runner.run().await
37}
38
39#[embassy_executor::task]
40async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
41 runner.run().await
42}
43
44#[embassy_executor::main]
45async fn main(spawner: Spawner) {
46 let p = embassy_rp::init(Default::default());
47 let mut rng = RoscRng;
48 let mut led = Output::new(p.PIN_25, Level::Low);
49
50 let mut spi_cfg = SpiConfig::default();
51 spi_cfg.frequency = 50_000_000;
52 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
53 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
54 let cs = Output::new(p.PIN_17, Level::High);
55 let w5500_int = Input::new(p.PIN_21, Pull::Up);
56 let w5500_reset = Output::new(p.PIN_20, Level::High);
57
58 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
59 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
60 let state = STATE.init(State::<8, 8>::new());
61 let (device, runner) = embassy_net_wiznet::new(
62 mac_addr,
63 state,
64 ExclusiveDevice::new(spi, cs, Delay),
65 w5500_int,
66 w5500_reset,
67 )
68 .await
69 .unwrap();
70 unwrap!(spawner.spawn(ethernet_task(runner)));
71
72 // Generate random seed
73 let seed = rng.next_u64();
74
75 // Init network stack
76 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
77 let (stack, runner) = embassy_net::new(
78 device,
79 embassy_net::Config::dhcpv4(Default::default()),
80 RESOURCES.init(StackResources::new()),
81 seed,
82 );
83
84 // Launch network task
85 unwrap!(spawner.spawn(net_task(runner)));
86
87 info!("Waiting for DHCP...");
88 let cfg = wait_for_config(stack).await;
89 let local_addr = cfg.address.address();
90 info!("IP address: {:?}", local_addr);
91
92 let mut rx_buffer = [0; 4096];
93 let mut tx_buffer = [0; 4096];
94 loop {
95 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
96 socket.set_timeout(Some(Duration::from_secs(10)));
97
98 led.set_low();
99 info!("Connecting...");
100 let host_addr = embassy_net::Ipv4Address::from_str("192.168.0.118").unwrap();
101 if let Err(e) = socket.connect((host_addr, 1234)).await {
102 warn!("connect error: {:?}", e);
103 continue;
104 }
105 info!("Connected to {:?}", socket.remote_endpoint());
106 led.set_high();
107
108 let msg = b"Hello world!\n";
109 loop {
110 if let Err(e) = socket.write_all(msg).await {
111 warn!("write error: {:?}", e);
112 break;
113 }
114 info!("txd: {}", core::str::from_utf8(msg).unwrap());
115 Timer::after_secs(1).await;
116 }
117 }
118}
119
120async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
121 loop {
122 if let Some(config) = stack.config_v4() {
123 return config.clone();
124 }
125 yield_now().await;
126 }
127}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs
new file mode 100644
index 000000000..32b3880f6
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_tcp_server.rs
@@ -0,0 +1,136 @@
1//! This example implements a TCP echo server on port 1234 and using DHCP.
2//! Send it some data, you should see it echoed back and printed in the console.
3//!
4//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
5
6#![no_std]
7#![no_main]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_futures::yield_now;
12use embassy_net::{Stack, StackResources};
13use embassy_net_wiznet::chip::W5500;
14use embassy_net_wiznet::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::SPI0;
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::{Delay, Duration};
20use embedded_hal_bus::spi::ExclusiveDevice;
21use embedded_io_async::Write;
22use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _};
24
25#[embassy_executor::task]
26async fn ethernet_task(
27 runner: Runner<
28 'static,
29 W5500,
30 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
31 Input<'static>,
32 Output<'static>,
33 >,
34) -> ! {
35 runner.run().await
36}
37
38#[embassy_executor::task]
39async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
40 runner.run().await
41}
42
43#[embassy_executor::main]
44async fn main(spawner: Spawner) {
45 let p = embassy_rp::init(Default::default());
46 let mut rng = RoscRng;
47 let mut led = Output::new(p.PIN_25, Level::Low);
48
49 let mut spi_cfg = SpiConfig::default();
50 spi_cfg.frequency = 50_000_000;
51 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
52 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
53 let cs = Output::new(p.PIN_17, Level::High);
54 let w5500_int = Input::new(p.PIN_21, Pull::Up);
55 let w5500_reset = Output::new(p.PIN_20, Level::High);
56
57 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
58 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
59 let state = STATE.init(State::<8, 8>::new());
60 let (device, runner) = embassy_net_wiznet::new(
61 mac_addr,
62 state,
63 ExclusiveDevice::new(spi, cs, Delay),
64 w5500_int,
65 w5500_reset,
66 )
67 .await
68 .unwrap();
69 unwrap!(spawner.spawn(ethernet_task(runner)));
70
71 // Generate random seed
72 let seed = rng.next_u64();
73
74 // Init network stack
75 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
76 let (stack, runner) = embassy_net::new(
77 device,
78 embassy_net::Config::dhcpv4(Default::default()),
79 RESOURCES.init(StackResources::new()),
80 seed,
81 );
82
83 // Launch network task
84 unwrap!(spawner.spawn(net_task(runner)));
85
86 info!("Waiting for DHCP...");
87 let cfg = wait_for_config(stack).await;
88 let local_addr = cfg.address.address();
89 info!("IP address: {:?}", local_addr);
90
91 let mut rx_buffer = [0; 4096];
92 let mut tx_buffer = [0; 4096];
93 let mut buf = [0; 4096];
94 loop {
95 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
96 socket.set_timeout(Some(Duration::from_secs(10)));
97
98 led.set_low();
99 info!("Listening on TCP:1234...");
100 if let Err(e) = socket.accept(1234).await {
101 warn!("accept error: {:?}", e);
102 continue;
103 }
104 info!("Received connection from {:?}", socket.remote_endpoint());
105 led.set_high();
106
107 loop {
108 let n = match socket.read(&mut buf).await {
109 Ok(0) => {
110 warn!("read EOF");
111 break;
112 }
113 Ok(n) => n,
114 Err(e) => {
115 warn!("{:?}", e);
116 break;
117 }
118 };
119 info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap());
120
121 if let Err(e) = socket.write_all(&buf[..n]).await {
122 warn!("write error: {:?}", e);
123 break;
124 }
125 }
126 }
127}
128
129async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
130 loop {
131 if let Some(config) = stack.config_v4() {
132 return config.clone();
133 }
134 yield_now().await;
135 }
136}
diff --git a/examples/rp235x/src/bin/ethernet_w5500_udp.rs b/examples/rp235x/src/bin/ethernet_w5500_udp.rs
new file mode 100644
index 000000000..cd0824df1
--- /dev/null
+++ b/examples/rp235x/src/bin/ethernet_w5500_udp.rs
@@ -0,0 +1,116 @@
1//! This example implements a UDP server listening on port 1234 and echoing back the data.
2//!
3//! Example written for the [`WIZnet W5500-EVB-Pico2`](https://docs.wiznet.io/Product/iEthernet/W5500/w5500-evb-pico2) board.
4
5#![no_std]
6#![no_main]
7
8use defmt::*;
9use embassy_executor::Spawner;
10use embassy_futures::yield_now;
11use embassy_net::udp::{PacketMetadata, UdpSocket};
12use embassy_net::{Stack, StackResources};
13use embassy_net_wiznet::chip::W5500;
14use embassy_net_wiznet::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::SPI0;
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::Delay;
20use embedded_hal_bus::spi::ExclusiveDevice;
21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _};
23
24#[embassy_executor::task]
25async fn ethernet_task(
26 runner: Runner<
27 'static,
28 W5500,
29 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static>, Delay>,
30 Input<'static>,
31 Output<'static>,
32 >,
33) -> ! {
34 runner.run().await
35}
36
37#[embassy_executor::task]
38async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
39 runner.run().await
40}
41
42#[embassy_executor::main]
43async fn main(spawner: Spawner) {
44 let p = embassy_rp::init(Default::default());
45 let mut rng = RoscRng;
46
47 let mut spi_cfg = SpiConfig::default();
48 spi_cfg.frequency = 50_000_000;
49 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
50 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
51 let cs = Output::new(p.PIN_17, Level::High);
52 let w5500_int = Input::new(p.PIN_21, Pull::Up);
53 let w5500_reset = Output::new(p.PIN_20, Level::High);
54
55 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
56 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
57 let state = STATE.init(State::<8, 8>::new());
58 let (device, runner) = embassy_net_wiznet::new(
59 mac_addr,
60 state,
61 ExclusiveDevice::new(spi, cs, Delay),
62 w5500_int,
63 w5500_reset,
64 )
65 .await
66 .unwrap();
67 unwrap!(spawner.spawn(ethernet_task(runner)));
68
69 // Generate random seed
70 let seed = rng.next_u64();
71
72 // Init network stack
73 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
74 let (stack, runner) = embassy_net::new(
75 device,
76 embassy_net::Config::dhcpv4(Default::default()),
77 RESOURCES.init(StackResources::new()),
78 seed,
79 );
80
81 // Launch network task
82 unwrap!(spawner.spawn(net_task(runner)));
83
84 info!("Waiting for DHCP...");
85 let cfg = wait_for_config(stack).await;
86 let local_addr = cfg.address.address();
87 info!("IP address: {:?}", local_addr);
88
89 // Then we can use it!
90 let mut rx_buffer = [0; 4096];
91 let mut tx_buffer = [0; 4096];
92 let mut rx_meta = [PacketMetadata::EMPTY; 16];
93 let mut tx_meta = [PacketMetadata::EMPTY; 16];
94 let mut buf = [0; 4096];
95 loop {
96 let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
97 socket.bind(1234).unwrap();
98
99 loop {
100 let (n, ep) = socket.recv_from(&mut buf).await.unwrap();
101 if let Ok(s) = core::str::from_utf8(&buf[..n]) {
102 info!("rxd from {}: {}", ep, s);
103 }
104 socket.send_to(&buf[..n], ep).await.unwrap();
105 }
106 }
107}
108
109async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
110 loop {
111 if let Some(config) = stack.config_v4() {
112 return config.clone();
113 }
114 yield_now().await;
115 }
116}