aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRiceman2000 <[email protected]>2025-09-12 12:47:55 -0400
committerRiceman2000 <[email protected]>2025-09-12 12:47:55 -0400
commitf829ddd3b236b146701951004b41525de4633c9a (patch)
treeb1ee64270b79dc98a37ba57d751136e4b324202a
parent0ea3478fb5e4fcdcd86e439186794d126ed2eca4 (diff)
Example first draft
-rw-r--r--examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs145
1 files changed, 145 insertions, 0 deletions
diff --git a/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
new file mode 100644
index 000000000..6f4ba4a70
--- /dev/null
+++ b/examples/rp/src/bin/ethernet_w55rp20_tcp_server.rs
@@ -0,0 +1,145 @@
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 W55RP20-EVB-Pico`](https://docs.wiznet.io/Product/ioNIC/W55RP20/w55rp20-evb-pico) board.
4//! Note: the W55RP20 is a single package that contains both a RP2040 and the Wiznet W5500 ethernet
5//! controller
6
7#![no_std]
8#![no_main]
9
10use core::str::FromStr;
11
12use defmt::*;
13use embassy_executor::Spawner;
14use embassy_futures::yield_now;
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::PIO0;
21use embassy_rp::pio_programs::spi::Spi;
22use embassy_rp::spi::{Async, Config as SpiConfig};
23use embassy_rp::{bind_interrupts, pio};
24use embassy_time::{Delay, Duration, Timer};
25use embedded_hal_bus::spi::ExclusiveDevice;
26use embedded_io_async::Write;
27use static_cell::StaticCell;
28use {defmt_rtt as _, panic_probe as _};
29
30bind_interrupts!(struct Irqs {
31 PIO0_IRQ_0 => pio::InterruptHandler<PIO0>;
32});
33
34#[embassy_executor::task]
35async fn ethernet_task(
36 runner: Runner<
37 'static,
38 W5500,
39 ExclusiveDevice<Spi<'static, PIO0, 0, Async>, Output<'static>, Delay>,
40 Input<'static>,
41 Output<'static>,
42 >,
43) -> ! {
44 runner.run().await
45}
46
47#[embassy_executor::task]
48async fn net_task(mut runner: embassy_net::Runner<'static, Device<'static>>) -> ! {
49 runner.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_19, Level::Low);
57
58 // The W55RP20 uses a PIO unit for SPI communication, once the SPI bus has been formed using a
59 // PIO statemachine everything else is generally unchanged from the other examples that use the W5500
60 let mosi = p.PIN_23;
61 let miso = p.PIN_22;
62 let clk = p.PIN_21;
63
64 let pio::Pio { mut common, sm0, .. } = pio::Pio::new(p.PIO0, Irqs);
65
66 // Construct an SPI driver backed by a PIO state machine
67 let mut spi_cfg = SpiConfig::default();
68 spi_cfg.frequency = 50_000_000;
69 let spi = Spi::new(&mut common, sm0, clk, mosi, miso, p.DMA_CH0, p.DMA_CH1, spi_cfg);
70
71 // Further control pins
72 let cs = Output::new(p.PIN_20, Level::High);
73 let w5500_int = Input::new(p.PIN_24, Pull::Up);
74 let w5500_reset = Output::new(p.PIN_25, Level::High);
75
76 let mac_addr = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00];
77 static STATE: StaticCell<State<8, 8>> = StaticCell::new();
78 let state = STATE.init(State::<8, 8>::new());
79 let (device, runner) = embassy_net_wiznet::new(
80 mac_addr,
81 state,
82 ExclusiveDevice::new(spi, cs, Delay),
83 w5500_int,
84 w5500_reset,
85 )
86 .await
87 .unwrap();
88 spawner.spawn(unwrap!(ethernet_task(runner)));
89
90 // Generate random seed
91 let seed = rng.next_u64();
92
93 // Init network stack
94 static RESOURCES: StaticCell<StackResources<3>> = StaticCell::new();
95 let (stack, runner) = embassy_net::new(
96 device,
97 embassy_net::Config::dhcpv4(Default::default()),
98 RESOURCES.init(StackResources::new()),
99 seed,
100 );
101
102 // Launch network task
103 spawner.spawn(unwrap!(net_task(runner)));
104
105 info!("Waiting for DHCP...");
106 let cfg = wait_for_config(stack).await;
107 let local_addr = cfg.address.address();
108 info!("IP address: {:?}", local_addr);
109
110 let mut rx_buffer = [0; 4096];
111 let mut tx_buffer = [0; 4096];
112 loop {
113 let mut socket = embassy_net::tcp::TcpSocket::new(stack, &mut rx_buffer, &mut tx_buffer);
114 socket.set_timeout(Some(Duration::from_secs(10)));
115
116 led.set_low();
117 info!("Connecting...");
118 let host_addr = embassy_net::Ipv4Address::from_str("192.168.1.110").unwrap();
119 if let Err(e) = socket.connect((host_addr, 1234)).await {
120 warn!("connect error: {:?}", e);
121 continue;
122 }
123 info!("Connected to {:?}", socket.remote_endpoint());
124 led.set_high();
125
126 let msg = b"Hello world!\n";
127 loop {
128 if let Err(e) = socket.write_all(msg).await {
129 warn!("write error: {:?}", e);
130 break;
131 }
132 info!("txd: {}", core::str::from_utf8(msg).unwrap());
133 Timer::after_secs(1).await;
134 }
135 }
136}
137
138async fn wait_for_config(stack: Stack<'static>) -> embassy_net::StaticConfigV4 {
139 loop {
140 if let Some(config) = stack.config_v4() {
141 return config.clone();
142 }
143 yield_now().await;
144 }
145}