aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-05-31 00:55:16 +0200
committerDario Nieuwenhuis <[email protected]>2023-05-31 00:55:16 +0200
commit82d765689aa0f922d0b43e402eaa3d911b2d461d (patch)
tree62247897621cf874a4cd4f71b720366d8d102b28 /examples
parent3f90620343a5413423da8b84008cf468ea957d54 (diff)
parent7f0e778145e7a0f7281d9b37e59473fddf232097 (diff)
Merge remote-tracking branch 'w5500/main' into w5500
Diffstat (limited to 'examples')
-rw-r--r--examples/rp/src/bin/ethernet_w5500_multisocket.rs152
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_client.rs132
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_server.rs141
-rw-r--r--examples/rp/src/bin/ethernet_w5500_udp.rs127
4 files changed, 552 insertions, 0 deletions
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 @@
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-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board.
4
5#![no_std]
6#![no_main]
7#![feature(type_alias_impl_trait)]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_futures::yield_now;
12use embassy_net::{Stack, StackResources};
13use embassy_net_w5500::*;
14use embassy_rp::clocks::RoscRng;
15use embassy_rp::gpio::{Input, Level, Output, Pull};
16use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0};
17use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
18use embedded_hal_async::spi::ExclusiveDevice;
19use embedded_io::asynch::Write;
20use rand::RngCore;
21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _};
23
24macro_rules! singleton {
25 ($val:expr) => {{
26 type T = impl Sized;
27 static STATIC_CELL: StaticCell<T> = StaticCell::new();
28 let (x,) = STATIC_CELL.init(($val,));
29 x
30 }};
31}
32
33#[embassy_executor::task]
34async fn ethernet_task(
35 runner: Runner<
36 'static,
37 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>,
38 Input<'static, PIN_21>,
39 Output<'static, PIN_20>,
40 >,
41) -> ! {
42 runner.run().await
43}
44
45#[embassy_executor::task]
46async fn net_task(stack: &'static Stack<Device<'static>>) -> ! {
47 stack.run().await
48}
49
50#[embassy_executor::main]
51async fn main(spawner: Spawner) {
52 let p = embassy_rp::init(Default::default());
53 let mut rng = RoscRng;
54
55 let mut spi_cfg = SpiConfig::default();
56 spi_cfg.frequency = 50_000_000;
57 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
58 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
59 let cs = Output::new(p.PIN_17, Level::High);
60 let w5500_int = Input::new(p.PIN_21, Pull::Up);
61 let w5500_reset = Output::new(p.PIN_20, Level::High);
62
63 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
64 let state = singleton!(State::<8, 8>::new());
65 let (device, runner) = embassy_net_w5500::new(
66 mac_addr,
67 state,
68 ExclusiveDevice::new(spi, cs),
69 w5500_int,
70 w5500_reset,
71 )
72 .await;
73 unwrap!(spawner.spawn(ethernet_task(runner)));
74
75 // Generate random seed
76 let seed = rng.next_u64();
77
78 // Init network stack
79 let stack = &*singleton!(Stack::new(
80 device,
81 embassy_net::Config::Dhcp(Default::default()),
82 singleton!(StackResources::<3>::new()),
83 seed
84 ));
85
86 // Launch network task
87 unwrap!(spawner.spawn(net_task(&stack)));
88
89 info!("Waiting for DHCP...");
90 let cfg = wait_for_config(stack).await;
91 let local_addr = cfg.address.address();
92 info!("IP address: {:?}", local_addr);
93
94 // Create two sockets listening to the same port, to handle simultaneous connections
95 unwrap!(spawner.spawn(listen_task(&stack, 0, 1234)));
96 unwrap!(spawner.spawn(listen_task(&stack, 1, 1234)));
97}
98
99#[embassy_executor::task(pool_size = 2)]
100async fn listen_task(stack: &'static Stack<Device<'static>>, id: u8, port: u16) {
101 let mut rx_buffer = [0; 4096];
102 let mut tx_buffer = [0; 4096];
103 let mut buf = [0; 4096];
104 loop {
105 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
106 socket.set_timeout(Some(embassy_net::SmolDuration::from_secs(10)));
107
108 info!("SOCKET {}: Listening on TCP:{}...", id, port);
109 if let Err(e) = socket.accept(port).await {
110 warn!("accept error: {:?}", e);
111 continue;
112 }
113 info!(
114 "SOCKET {}: Received connection from {:?}",
115 id,
116 socket.remote_endpoint()
117 );
118
119 loop {
120 let n = match socket.read(&mut buf).await {
121 Ok(0) => {
122 warn!("read EOF");
123 break;
124 }
125 Ok(n) => n,
126 Err(e) => {
127 warn!("SOCKET {}: {:?}", id, e);
128 break;
129 }
130 };
131 info!(
132 "SOCKET {}: rxd {}",
133 id,
134 core::str::from_utf8(&buf[..n]).unwrap()
135 );
136
137 if let Err(e) = socket.write_all(&buf[..n]).await {
138 warn!("write error: {:?}", e);
139 break;
140 }
141 }
142 }
143}
144
145async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
146 loop {
147 if let Some(config) = stack.config() {
148 return config.clone();
149 }
150 yield_now().await;
151 }
152}
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 @@
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-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board.
4
5#![no_std]
6#![no_main]
7#![feature(type_alias_impl_trait)]
8
9use core::str::FromStr;
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_futures::yield_now;
13use embassy_net::{Stack, StackResources};
14use embassy_net_w5500::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0};
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embassy_time::{Duration, Timer};
20use embedded_hal_async::spi::ExclusiveDevice;
21use embedded_io::asynch::Write;
22use rand::RngCore;
23use static_cell::StaticCell;
24use {defmt_rtt as _, panic_probe as _};
25
26macro_rules! singleton {
27 ($val:expr) => {{
28 type T = impl Sized;
29 static STATIC_CELL: StaticCell<T> = StaticCell::new();
30 let (x,) = STATIC_CELL.init(($val,));
31 x
32 }};
33}
34
35#[embassy_executor::task]
36async fn ethernet_task(
37 runner: Runner<
38 'static,
39 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>,
40 Input<'static, PIN_21>,
41 Output<'static, PIN_20>,
42 >,
43) -> ! {
44 runner.run().await
45}
46
47#[embassy_executor::task]
48async fn net_task(stack: &'static Stack<Device<'static>>) -> ! {
49 stack.run().await
50}
51
52#[embassy_executor::main]
53async fn main(spawner: Spawner) {
54 let p = embassy_rp::init(Default::default());
55 let mut rng = RoscRng;
56 let mut led = Output::new(p.PIN_25, Level::Low);
57
58 let mut spi_cfg = SpiConfig::default();
59 spi_cfg.frequency = 50_000_000;
60 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
61 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
62 let cs = Output::new(p.PIN_17, Level::High);
63 let w5500_int = Input::new(p.PIN_21, Pull::Up);
64 let w5500_reset = Output::new(p.PIN_20, Level::High);
65
66 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
67 let state = singleton!(State::<8, 8>::new());
68 let (device, runner) = embassy_net_w5500::new(
69 mac_addr,
70 state,
71 ExclusiveDevice::new(spi, cs),
72 w5500_int,
73 w5500_reset,
74 )
75 .await;
76 unwrap!(spawner.spawn(ethernet_task(runner)));
77
78 // Generate random seed
79 let seed = rng.next_u64();
80
81 // Init network stack
82 let stack = &*singleton!(Stack::new(
83 device,
84 embassy_net::Config::Dhcp(Default::default()),
85 singleton!(StackResources::<2>::new()),
86 seed
87 ));
88
89 // Launch network task
90 unwrap!(spawner.spawn(net_task(&stack)));
91
92 info!("Waiting for DHCP...");
93 let cfg = wait_for_config(stack).await;
94 let local_addr = cfg.address.address();
95 info!("IP address: {:?}", local_addr);
96
97 let mut rx_buffer = [0; 4096];
98 let mut tx_buffer = [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(embassy_net::SmolDuration::from_secs(10)));
102
103 led.set_low();
104 info!("Connecting...");
105 let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap();
106 if let Err(e) = socket.connect((host_addr, 1234)).await {
107 warn!("connect error: {:?}", e);
108 continue;
109 }
110 info!("Connected to {:?}", socket.remote_endpoint());
111 led.set_high();
112
113 let msg = b"Hello world!\n";
114 loop {
115 if let Err(e) = socket.write_all(msg).await {
116 warn!("write error: {:?}", e);
117 break;
118 }
119 info!("txd: {}", core::str::from_utf8(msg).unwrap());
120 Timer::after(Duration::from_secs(1)).await;
121 }
122 }
123}
124
125async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
126 loop {
127 if let Some(config) = stack.config() {
128 return config.clone();
129 }
130 yield_now().await;
131 }
132}
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 @@
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-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board.
5
6#![no_std]
7#![no_main]
8#![feature(type_alias_impl_trait)]
9
10use defmt::*;
11use embassy_executor::Spawner;
12use embassy_futures::yield_now;
13use embassy_net::{Stack, StackResources};
14use embassy_net_w5500::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0};
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embedded_hal_async::spi::ExclusiveDevice;
20use embedded_io::asynch::Write;
21use rand::RngCore;
22use static_cell::StaticCell;
23use {defmt_rtt as _, panic_probe as _};
24
25macro_rules! singleton {
26 ($val:expr) => {{
27 type T = impl Sized;
28 static STATIC_CELL: StaticCell<T> = StaticCell::new();
29 let (x,) = STATIC_CELL.init(($val,));
30 x
31 }};
32}
33
34#[embassy_executor::task]
35async fn ethernet_task(
36 runner: Runner<
37 'static,
38 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>,
39 Input<'static, PIN_21>,
40 Output<'static, PIN_20>,
41 >,
42) -> ! {
43 runner.run().await
44}
45
46#[embassy_executor::task]
47async fn net_task(stack: &'static Stack<Device<'static>>) -> ! {
48 stack.run().await
49}
50
51#[embassy_executor::main]
52async fn main(spawner: Spawner) {
53 let p = embassy_rp::init(Default::default());
54 let mut rng = RoscRng;
55 let mut led = Output::new(p.PIN_25, Level::Low);
56
57 let mut spi_cfg = SpiConfig::default();
58 spi_cfg.frequency = 50_000_000;
59 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
60 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
61 let cs = Output::new(p.PIN_17, Level::High);
62 let w5500_int = Input::new(p.PIN_21, Pull::Up);
63 let w5500_reset = Output::new(p.PIN_20, Level::High);
64
65 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
66 let state = singleton!(State::<8, 8>::new());
67 let (device, runner) = embassy_net_w5500::new(
68 mac_addr,
69 state,
70 ExclusiveDevice::new(spi, cs),
71 w5500_int,
72 w5500_reset,
73 )
74 .await;
75 unwrap!(spawner.spawn(ethernet_task(runner)));
76
77 // Generate random seed
78 let seed = rng.next_u64();
79
80 // Init network stack
81 let stack = &*singleton!(Stack::new(
82 device,
83 embassy_net::Config::Dhcp(Default::default()),
84 singleton!(StackResources::<2>::new()),
85 seed
86 ));
87
88 // Launch network task
89 unwrap!(spawner.spawn(net_task(&stack)));
90
91 info!("Waiting for DHCP...");
92 let cfg = wait_for_config(stack).await;
93 let local_addr = cfg.address.address();
94 info!("IP address: {:?}", local_addr);
95
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(embassy_net::SmolDuration::from_secs(10)));
102
103 led.set_low();
104 info!("Listening on TCP:1234...");
105 if let Err(e) = socket.accept(1234).await {
106 warn!("accept error: {:?}", e);
107 continue;
108 }
109 info!("Received connection from {:?}", socket.remote_endpoint());
110 led.set_high();
111
112 loop {
113 let n = match socket.read(&mut buf).await {
114 Ok(0) => {
115 warn!("read EOF");
116 break;
117 }
118 Ok(n) => n,
119 Err(e) => {
120 warn!("{:?}", e);
121 break;
122 }
123 };
124 info!("rxd {}", core::str::from_utf8(&buf[..n]).unwrap());
125
126 if let Err(e) = socket.write_all(&buf[..n]).await {
127 warn!("write error: {:?}", e);
128 break;
129 }
130 }
131 }
132}
133
134async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
135 loop {
136 if let Some(config) = stack.config() {
137 return config.clone();
138 }
139 yield_now().await;
140 }
141}
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 @@
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-Pico`](https://www.wiznet.io/product-item/w5500-evb-pico/) board.
4
5#![no_std]
6#![no_main]
7#![feature(type_alias_impl_trait)]
8
9use defmt::*;
10use embassy_executor::Spawner;
11use embassy_futures::yield_now;
12use embassy_net::udp::UdpSocket;
13use embassy_net::{PacketMetadata, Stack, StackResources};
14use embassy_net_w5500::*;
15use embassy_rp::clocks::RoscRng;
16use embassy_rp::gpio::{Input, Level, Output, Pull};
17use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0};
18use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
19use embedded_hal_async::spi::ExclusiveDevice;
20use rand::RngCore;
21use static_cell::StaticCell;
22use {defmt_rtt as _, panic_probe as _};
23
24macro_rules! singleton {
25 ($val:expr) => {{
26 type T = impl Sized;
27 static STATIC_CELL: StaticCell<T> = StaticCell::new();
28 let (x,) = STATIC_CELL.init(($val,));
29 x
30 }};
31}
32
33#[embassy_executor::task]
34async fn ethernet_task(
35 runner: Runner<
36 'static,
37 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>,
38 Input<'static, PIN_21>,
39 Output<'static, PIN_20>,
40 >,
41) -> ! {
42 runner.run().await
43}
44
45#[embassy_executor::task]
46async fn net_task(stack: &'static Stack<Device<'static>>) -> ! {
47 stack.run().await
48}
49
50#[embassy_executor::main]
51async fn main(spawner: Spawner) {
52 let p = embassy_rp::init(Default::default());
53 let mut rng = RoscRng;
54
55 let mut spi_cfg = SpiConfig::default();
56 spi_cfg.frequency = 50_000_000;
57 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
58 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
59 let cs = Output::new(p.PIN_17, Level::High);
60 let w5500_int = Input::new(p.PIN_21, Pull::Up);
61 let w5500_reset = Output::new(p.PIN_20, Level::High);
62
63 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
64 let state = singleton!(State::<8, 8>::new());
65 let (device, runner) = embassy_net_w5500::new(
66 mac_addr,
67 state,
68 ExclusiveDevice::new(spi, cs),
69 w5500_int,
70 w5500_reset,
71 )
72 .await;
73 unwrap!(spawner.spawn(ethernet_task(runner)));
74
75 // Generate random seed
76 let seed = rng.next_u64();
77
78 // Init network stack
79 let stack = &*singleton!(Stack::new(
80 device,
81 embassy_net::Config::Dhcp(Default::default()),
82 singleton!(StackResources::<2>::new()),
83 seed
84 ));
85
86 // Launch network task
87 unwrap!(spawner.spawn(net_task(&stack)));
88
89 info!("Waiting for DHCP...");
90 let cfg = wait_for_config(stack).await;
91 let local_addr = cfg.address.address();
92 info!("IP address: {:?}", local_addr);
93
94 // Then we can use it!
95 let mut rx_buffer = [0; 4096];
96 let mut tx_buffer = [0; 4096];
97 let mut rx_meta = [PacketMetadata::EMPTY; 16];
98 let mut tx_meta = [PacketMetadata::EMPTY; 16];
99 let mut buf = [0; 4096];
100 loop {
101 let mut socket = UdpSocket::new(
102 stack,
103 &mut rx_meta,
104 &mut rx_buffer,
105 &mut tx_meta,
106 &mut tx_buffer,
107 );
108 socket.bind(1234).unwrap();
109
110 loop {
111 let (n, ep) = socket.recv_from(&mut buf).await.unwrap();
112 if let Ok(s) = core::str::from_utf8(&buf[..n]) {
113 info!("rxd from {}: {}", ep, s);
114 }
115 socket.send_to(&buf[..n], ep).await.unwrap();
116 }
117 }
118}
119
120async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
121 loop {
122 if let Some(config) = stack.config() {
123 return config.clone();
124 }
125 yield_now().await;
126 }
127}