aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-05-30 23:04:38 +0000
committerGitHub <[email protected]>2023-05-30 23:04:38 +0000
commit4f203ae175cbd89e8b23349ae06561f33b330ac5 (patch)
treee40d00e3f5493cce9ef65e8daa524a174f5fc407 /examples
parent3f90620343a5413423da8b84008cf468ea957d54 (diff)
parentd70994e4a8ea695f07b777fa99d7db4e5d4a7122 (diff)
Merge pull request #1520 from embassy-rs/w5500
Merge embassy-net-w5500 into main repo
Diffstat (limited to 'examples')
-rw-r--r--examples/rp/Cargo.toml4
-rw-r--r--examples/rp/src/bin/ethernet_w5500_multisocket.rs139
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_client.rs127
-rw-r--r--examples/rp/src/bin/ethernet_w5500_tcp_server.rs136
-rw-r--r--examples/rp/src/bin/ethernet_w5500_udp.rs115
5 files changed, 520 insertions, 1 deletions
diff --git a/examples/rp/Cargo.toml b/examples/rp/Cargo.toml
index f77377a6f..58b701915 100644
--- a/examples/rp/Cargo.toml
+++ b/examples/rp/Cargo.toml
@@ -12,7 +12,8 @@ embassy-executor = { version = "0.2.0", path = "../../embassy-executor", feature
12embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] } 12embassy-time = { version = "0.1.0", path = "../../embassy-time", features = ["nightly", "unstable-traits", "defmt", "defmt-timestamp-uptime"] }
13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] } 13embassy-rp = { version = "0.1.0", path = "../../embassy-rp", features = ["defmt", "unstable-traits", "nightly", "unstable-pac", "time-driver", "critical-section-impl"] }
14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] } 14embassy-usb = { version = "0.1.0", path = "../../embassy-usb", features = ["defmt"] }
15embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "dhcpv4", "medium-ethernet"] } 15embassy-net = { version = "0.1.0", path = "../../embassy-net", features = ["defmt", "nightly", "tcp", "udp", "dhcpv4", "medium-ethernet"] }
16embassy-net-w5500 = { version = "0.1.0", path = "../../embassy-net-w5500", features = ["defmt"] }
16embassy-futures = { version = "0.1.0", path = "../../embassy-futures" } 17embassy-futures = { version = "0.1.0", path = "../../embassy-futures" }
17embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" } 18embassy-usb-logger = { version = "0.1.0", path = "../../embassy-usb-logger" }
18embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"] } 19embassy-lora = { version = "0.1.0", path = "../../embassy-lora", features = ["time", "defmt"] }
@@ -48,6 +49,7 @@ static_cell = "1.0.0"
48log = "0.4" 49log = "0.4"
49pio-proc = "0.2" 50pio-proc = "0.2"
50pio = "0.2.1" 51pio = "0.2.1"
52rand = { version = "0.8.5", default-features = false }
51 53
52[profile.release] 54[profile.release]
53debug = true 55debug = true
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..c8e6d46a6
--- /dev/null
+++ b/examples/rp/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-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 embassy_time::Duration;
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
56 let mut spi_cfg = SpiConfig::default();
57 spi_cfg.frequency = 50_000_000;
58 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
59 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
60 let cs = Output::new(p.PIN_17, Level::High);
61 let w5500_int = Input::new(p.PIN_21, Pull::Up);
62 let w5500_reset = Output::new(p.PIN_20, Level::High);
63
64 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
65 let state = singleton!(State::<8, 8>::new());
66 let (device, runner) =
67 embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await;
68 unwrap!(spawner.spawn(ethernet_task(runner)));
69
70 // Generate random seed
71 let seed = rng.next_u64();
72
73 // Init network stack
74 let stack = &*singleton!(Stack::new(
75 device,
76 embassy_net::Config::Dhcp(Default::default()),
77 singleton!(StackResources::<3>::new()),
78 seed
79 ));
80
81 // Launch network task
82 unwrap!(spawner.spawn(net_task(&stack)));
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: &'static Stack<Device<'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: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
133 loop {
134 if let Some(config) = stack.config() {
135 return config.clone();
136 }
137 yield_now().await;
138 }
139}
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..9a7c3ad19
--- /dev/null
+++ b/examples/rp/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-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;
10
11use defmt::*;
12use embassy_executor::Spawner;
13use embassy_futures::yield_now;
14use embassy_net::{Stack, StackResources};
15use embassy_net_w5500::*;
16use embassy_rp::clocks::RoscRng;
17use embassy_rp::gpio::{Input, Level, Output, Pull};
18use embassy_rp::peripherals::{PIN_17, PIN_20, PIN_21, SPI0};
19use embassy_rp::spi::{Async, Config as SpiConfig, Spi};
20use embassy_time::{Duration, Timer};
21use embedded_hal_async::spi::ExclusiveDevice;
22use embedded_io::asynch::Write;
23use rand::RngCore;
24use static_cell::StaticCell;
25use {defmt_rtt as _, panic_probe as _};
26
27macro_rules! singleton {
28 ($val:expr) => {{
29 type T = impl Sized;
30 static STATIC_CELL: StaticCell<T> = StaticCell::new();
31 let (x,) = STATIC_CELL.init(($val,));
32 x
33 }};
34}
35
36#[embassy_executor::task]
37async fn ethernet_task(
38 runner: Runner<
39 'static,
40 ExclusiveDevice<Spi<'static, SPI0, Async>, Output<'static, PIN_17>>,
41 Input<'static, PIN_21>,
42 Output<'static, PIN_20>,
43 >,
44) -> ! {
45 runner.run().await
46}
47
48#[embassy_executor::task]
49async fn net_task(stack: &'static Stack<Device<'static>>) -> ! {
50 stack.run().await
51}
52
53#[embassy_executor::main]
54async fn main(spawner: Spawner) {
55 let p = embassy_rp::init(Default::default());
56 let mut rng = RoscRng;
57 let mut led = Output::new(p.PIN_25, Level::Low);
58
59 let mut spi_cfg = SpiConfig::default();
60 spi_cfg.frequency = 50_000_000;
61 let (miso, mosi, clk) = (p.PIN_16, p.PIN_19, p.PIN_18);
62 let spi = Spi::new(p.SPI0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
63 let cs = Output::new(p.PIN_17, Level::High);
64 let w5500_int = Input::new(p.PIN_21, Pull::Up);
65 let w5500_reset = Output::new(p.PIN_20, Level::High);
66
67 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
68 let state = singleton!(State::<8, 8>::new());
69 let (device, runner) =
70 embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await;
71 unwrap!(spawner.spawn(ethernet_task(runner)));
72
73 // Generate random seed
74 let seed = rng.next_u64();
75
76 // Init network stack
77 let stack = &*singleton!(Stack::new(
78 device,
79 embassy_net::Config::Dhcp(Default::default()),
80 singleton!(StackResources::<2>::new()),
81 seed
82 ));
83
84 // Launch network task
85 unwrap!(spawner.spawn(net_task(&stack)));
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.1.110").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(Duration::from_secs(1)).await;
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}
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..f02543246
--- /dev/null
+++ b/examples/rp/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-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 embassy_time::Duration;
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) =
69 embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await;
70 unwrap!(spawner.spawn(ethernet_task(runner)));
71
72 // Generate random seed
73 let seed = rng.next_u64();
74
75 // Init network stack
76 let stack = &*singleton!(Stack::new(
77 device,
78 embassy_net::Config::Dhcp(Default::default()),
79 singleton!(StackResources::<2>::new()),
80 seed
81 ));
82
83 // Launch network task
84 unwrap!(spawner.spawn(net_task(&stack)));
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: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
130 loop {
131 if let Some(config) = stack.config() {
132 return config.clone();
133 }
134 yield_now().await;
135 }
136}
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..2c54f711e
--- /dev/null
+++ b/examples/rp/src/bin/ethernet_w5500_udp.rs
@@ -0,0 +1,115 @@
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::{PacketMetadata, UdpSocket};
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 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) =
66 embassy_net_w5500::new(mac_addr, state, ExclusiveDevice::new(spi, cs), w5500_int, w5500_reset).await;
67 unwrap!(spawner.spawn(ethernet_task(runner)));
68
69 // Generate random seed
70 let seed = rng.next_u64();
71
72 // Init network stack
73 let stack = &*singleton!(Stack::new(
74 device,
75 embassy_net::Config::Dhcp(Default::default()),
76 singleton!(StackResources::<2>::new()),
77 seed
78 ));
79
80 // Launch network task
81 unwrap!(spawner.spawn(net_task(&stack)));
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
88 // Then we can use it!
89 let mut rx_buffer = [0; 4096];
90 let mut tx_buffer = [0; 4096];
91 let mut rx_meta = [PacketMetadata::EMPTY; 16];
92 let mut tx_meta = [PacketMetadata::EMPTY; 16];
93 let mut buf = [0; 4096];
94 loop {
95 let mut socket = UdpSocket::new(stack, &mut rx_meta, &mut rx_buffer, &mut tx_meta, &mut tx_buffer);
96 socket.bind(1234).unwrap();
97
98 loop {
99 let (n, ep) = socket.recv_from(&mut buf).await.unwrap();
100 if let Ok(s) = core::str::from_utf8(&buf[..n]) {
101 info!("rxd from {}: {}", ep, s);
102 }
103 socket.send_to(&buf[..n], ep).await.unwrap();
104 }
105 }
106}
107
108async fn wait_for_config(stack: &'static Stack<Device<'static>>) -> embassy_net::StaticConfig {
109 loop {
110 if let Some(config) = stack.config() {
111 return config.clone();
112 }
113 yield_now().await;
114 }
115}