aboutsummaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorkalkyl <[email protected]>2023-05-09 01:51:08 +0200
committerkalkyl <[email protected]>2023-05-09 01:51:08 +0200
commit72b0379125b87bcd274bdb81127dd5f0ab29d661 (patch)
treeb620d67bc9ea930051668d63190dd6de62485b0a /src/lib.rs
:rainbow:
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs114
1 files changed, 114 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 000000000..bf14b05b4
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,114 @@
1#![no_std]
2/// [`embassy-net`](crates.io/crates/embassy-net) driver for the WIZnet W5500 ethernet chip.
3mod device;
4mod socket;
5mod spi;
6
7use crate::device::W5500;
8use embassy_futures::select::{select, Either};
9use embassy_net_driver_channel as ch;
10use embassy_net_driver_channel::driver::LinkState;
11use embassy_time::{Duration, Timer};
12use embedded_hal::digital::OutputPin;
13use embedded_hal_async::digital::Wait;
14use embedded_hal_async::spi::SpiDevice;
15const MTU: usize = 1514;
16
17/// Type alias for the embassy-net driver for W5500
18pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>;
19
20/// Internal state for the embassy-net integration.
21pub struct State<const N_RX: usize, const N_TX: usize> {
22 ch_state: ch::State<MTU, N_RX, N_TX>,
23}
24
25impl<const N_RX: usize, const N_TX: usize> State<N_RX, N_TX> {
26 /// Create a new `State`.
27 pub const fn new() -> Self {
28 Self {
29 ch_state: ch::State::new(),
30 }
31 }
32}
33
34/// Background runner for the W5500.
35///
36/// You must call `.run()` in a background task for the W5500 to operate.
37pub struct Runner<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
38 mac: W5500<SPI>,
39 ch: ch::Runner<'d, MTU>,
40 int: INT,
41 _reset: RST,
42}
43
44/// You must call this in a background task for the W5500 to operate.
45impl<'d, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, SPI, INT, RST> {
46 pub async fn run(mut self) -> ! {
47 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
48 loop {
49 if self.mac.is_link_up().await {
50 state_chan.set_link_state(LinkState::Up);
51 loop {
52 match select(
53 async {
54 self.int.wait_for_low().await.ok();
55 rx_chan.rx_buf().await
56 },
57 tx_chan.tx_buf(),
58 )
59 .await
60 {
61 Either::First(p) => {
62 if let Ok(n) = self.mac.read_frame(p).await {
63 rx_chan.rx_done(n);
64 }
65 }
66 Either::Second(p) => {
67 self.mac.write_frame(p).await.ok();
68 tx_chan.tx_done();
69 }
70 }
71 }
72 } else {
73 state_chan.set_link_state(LinkState::Down);
74 }
75 }
76 }
77}
78
79/// Obtain a driver for using the W5500 with [`embassy-net`](crates.io/crates/embassy-net).
80pub async fn new<
81 'a,
82 const N_RX: usize,
83 const N_TX: usize,
84 SPI: SpiDevice,
85 INT: Wait,
86 RST: OutputPin,
87>(
88 mac_addr: [u8; 6],
89 state: &'a mut State<N_RX, N_TX>,
90 spi_dev: SPI,
91 int: INT,
92 mut reset: RST,
93) -> (Device<'a>, Runner<'a, SPI, INT, RST>) {
94 // Reset the W5500.
95 reset.set_low().ok();
96 // Ensure the reset is registered.
97 Timer::after(Duration::from_millis(1)).await;
98 reset.set_high().ok();
99 // Wait for the W5500 to achieve PLL lock.
100 Timer::after(Duration::from_millis(2)).await;
101
102 let mac = W5500::new(spi_dev, mac_addr).await.unwrap();
103
104 let (runner, device) = ch::new(&mut state.ch_state, mac_addr);
105 (
106 device,
107 Runner {
108 ch: runner,
109 mac,
110 int,
111 _reset: reset,
112 },
113 )
114}