aboutsummaryrefslogtreecommitdiff
path: root/src/device.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/device.rs
:rainbow:
Diffstat (limited to 'src/device.rs')
-rw-r--r--src/device.rs161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/device.rs b/src/device.rs
new file mode 100644
index 000000000..3875fde0e
--- /dev/null
+++ b/src/device.rs
@@ -0,0 +1,161 @@
1use crate::socket;
2use crate::spi::SpiInterface;
3use embedded_hal_async::spi::SpiDevice;
4
5pub const MODE: u16 = 0x00;
6pub const MAC: u16 = 0x09;
7pub const SOCKET_INTR: u16 = 0x18;
8pub const PHY_CFG: u16 = 0x2E;
9
10#[repr(u8)]
11pub enum RegisterBlock {
12 Common = 0x00,
13 Socket0 = 0x01,
14 TxBuf = 0x02,
15 RxBuf = 0x03,
16}
17
18/// W5500 in MACRAW mode
19#[derive(Debug)]
20#[cfg_attr(feature = "defmt", derive(defmt::Format))]
21pub struct W5500<SPI> {
22 bus: SpiInterface<SPI>,
23}
24
25impl<SPI: SpiDevice> W5500<SPI> {
26 /// Create and initialize the W5500 driver
27 pub async fn new(spi: SPI, mac_addr: [u8; 6]) -> Result<W5500<SPI>, SPI::Error> {
28 let mut bus = SpiInterface(spi);
29 // Reset device
30 bus.write_frame(RegisterBlock::Common, MODE, &[0x80])
31 .await?;
32
33 // Enable interrupt pin
34 bus.write_frame(RegisterBlock::Common, SOCKET_INTR, &[0x01])
35 .await?;
36 // Enable receive interrupt
37 bus.write_frame(
38 RegisterBlock::Socket0,
39 socket::SOCKET_INTR_MASK,
40 &[socket::Interrupt::Receive as u8],
41 )
42 .await?;
43
44 // Set MAC address
45 bus.write_frame(RegisterBlock::Common, MAC, &mac_addr)
46 .await?;
47
48 // Set the raw socket RX/TX buffer sizes to 16KB
49 bus.write_frame(RegisterBlock::Socket0, socket::TXBUF_SIZE, &[16])
50 .await?;
51 bus.write_frame(RegisterBlock::Socket0, socket::RXBUF_SIZE, &[16])
52 .await?;
53
54 // MACRAW mode with MAC filtering.
55 let mode: u8 = (1 << 2) | (1 << 7);
56 bus.write_frame(RegisterBlock::Socket0, socket::MODE, &[mode])
57 .await?;
58 socket::command(&mut bus, socket::Command::Open).await?;
59
60 Ok(Self { bus })
61 }
62
63 /// Read bytes from the RX buffer. Returns the number of bytes read.
64 async fn read_bytes(&mut self, buffer: &mut [u8], offset: u16) -> Result<usize, SPI::Error> {
65 let rx_size = socket::get_rx_size(&mut self.bus).await? as usize;
66
67 let read_buffer = if rx_size > buffer.len() + offset as usize {
68 buffer
69 } else {
70 &mut buffer[..rx_size - offset as usize]
71 };
72
73 let read_ptr = socket::get_rx_read_ptr(&mut self.bus)
74 .await?
75 .wrapping_add(offset);
76 self.bus
77 .read_frame(RegisterBlock::RxBuf, read_ptr, read_buffer)
78 .await?;
79 socket::set_rx_read_ptr(
80 &mut self.bus,
81 read_ptr.wrapping_add(read_buffer.len() as u16),
82 )
83 .await?;
84
85 Ok(read_buffer.len())
86 }
87
88 /// Read an ethernet frame from the device. Returns the number of bytes read.
89 pub async fn read_frame(&mut self, frame: &mut [u8]) -> Result<usize, SPI::Error> {
90 let rx_size = socket::get_rx_size(&mut self.bus).await? as usize;
91 if rx_size == 0 {
92 return Ok(0);
93 }
94
95 socket::reset_interrupt(&mut self.bus, socket::Interrupt::Receive).await?;
96
97 // First two bytes gives the size of the received ethernet frame
98 let expected_frame_size: usize = {
99 let mut frame_bytes = [0u8; 2];
100 assert!(self.read_bytes(&mut frame_bytes[..], 0).await? == 2);
101 u16::from_be_bytes(frame_bytes) as usize - 2
102 };
103
104 // Read the ethernet frame
105 let read_buffer = if frame.len() > expected_frame_size {
106 &mut frame[..expected_frame_size]
107 } else {
108 frame
109 };
110
111 let recvd_frame_size = self.read_bytes(read_buffer, 2).await?;
112
113 // Register RX as completed
114 socket::command(&mut self.bus, socket::Command::Receive).await?;
115
116 // If the whole frame wasn't read, drop it
117 if recvd_frame_size < expected_frame_size {
118 Ok(0)
119 } else {
120 Ok(recvd_frame_size)
121 }
122 }
123
124 /// Write an ethernet frame to the device. Returns number of bytes written
125 pub async fn write_frame(&mut self, frame: &[u8]) -> Result<usize, SPI::Error> {
126 let max_size = socket::get_tx_free_size(&mut self.bus).await? as usize;
127
128 let write_data = if frame.len() < max_size {
129 frame
130 } else {
131 &frame[..max_size]
132 };
133
134 let write_ptr = socket::get_tx_write_ptr(&mut self.bus).await?;
135 self.bus
136 .write_frame(RegisterBlock::TxBuf, write_ptr, write_data)
137 .await?;
138 socket::set_tx_write_ptr(
139 &mut self.bus,
140 write_ptr.wrapping_add(write_data.len() as u16),
141 )
142 .await?;
143
144 socket::reset_interrupt(&mut self.bus, socket::Interrupt::SendOk).await?;
145 socket::command(&mut self.bus, socket::Command::Send).await?;
146 // Wait for TX to complete
147 while !socket::is_interrupt(&mut self.bus, socket::Interrupt::SendOk).await? {}
148 socket::reset_interrupt(&mut self.bus, socket::Interrupt::SendOk).await?;
149
150 Ok(write_data.len())
151 }
152
153 pub async fn is_link_up(&mut self) -> bool {
154 let mut link = [0];
155 self.bus
156 .read_frame(RegisterBlock::Common, PHY_CFG, &mut link)
157 .await
158 .ok();
159 link[0] & 1 == 1
160 }
161}