aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDario Nieuwenhuis <[email protected]>2023-08-15 18:19:03 +0200
committerDario Nieuwenhuis <[email protected]>2023-08-15 22:53:22 +0200
commit1d4b941d52a7e257b0305935034e999facb537bd (patch)
tree20e6776b6503dcbb15f4f6afb5c476ba433f94be
parent76276c326aaa4fd64a73253a480e2ea22f5ff740 (diff)
net-w5500: add w5100s support.
-rw-r--r--embassy-net-w5500/Cargo.toml3
-rw-r--r--embassy-net-w5500/src/chip/mod.rs7
-rw-r--r--embassy-net-w5500/src/chip/w5100s.rs61
-rw-r--r--embassy-net-w5500/src/chip/w5500.rs5
-rw-r--r--embassy-net-w5500/src/device.rs41
-rw-r--r--embassy-net-w5500/src/lib.rs24
6 files changed, 123 insertions, 18 deletions
diff --git a/embassy-net-w5500/Cargo.toml b/embassy-net-w5500/Cargo.toml
index 8972b814a..c45598684 100644
--- a/embassy-net-w5500/Cargo.toml
+++ b/embassy-net-w5500/Cargo.toml
@@ -18,4 +18,5 @@ defmt = { version = "0.3", optional = true }
18[package.metadata.embassy_docs] 18[package.metadata.embassy_docs]
19src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-w5500-v$VERSION/embassy-net-w5500/src/" 19src_base = "https://github.com/embassy-rs/embassy/blob/embassy-net-w5500-v$VERSION/embassy-net-w5500/src/"
20src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-w5500/src/" 20src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-net-w5500/src/"
21target = "thumbv7em-none-eabi" \ No newline at end of file 21target = "thumbv7em-none-eabi"
22features = ["defmt"] \ No newline at end of file
diff --git a/embassy-net-w5500/src/chip/mod.rs b/embassy-net-w5500/src/chip/mod.rs
index b7d550e26..562db515a 100644
--- a/embassy-net-w5500/src/chip/mod.rs
+++ b/embassy-net-w5500/src/chip/mod.rs
@@ -1,5 +1,7 @@
1mod w5500; 1mod w5500;
2pub use w5500::W5500; 2pub use w5500::W5500;
3mod w5100s;
4pub use w5100s::W5100S;
3 5
4pub(crate) mod sealed { 6pub(crate) mod sealed {
5 use embedded_hal_async::spi::SpiDevice; 7 use embedded_hal_async::spi::SpiDevice;
@@ -22,6 +24,11 @@ pub(crate) mod sealed {
22 const SOCKET_INTR_MASK: Self::Address; 24 const SOCKET_INTR_MASK: Self::Address;
23 const SOCKET_INTR: Self::Address; 25 const SOCKET_INTR: Self::Address;
24 26
27 const SOCKET_MODE_VALUE: u8;
28
29 const BUF_SIZE: u16;
30 const AUTO_WRAP: bool;
31
25 fn rx_addr(addr: u16) -> Self::Address; 32 fn rx_addr(addr: u16) -> Self::Address;
26 fn tx_addr(addr: u16) -> Self::Address; 33 fn tx_addr(addr: u16) -> Self::Address;
27 34
diff --git a/embassy-net-w5500/src/chip/w5100s.rs b/embassy-net-w5500/src/chip/w5100s.rs
new file mode 100644
index 000000000..07a840370
--- /dev/null
+++ b/embassy-net-w5500/src/chip/w5100s.rs
@@ -0,0 +1,61 @@
1use embedded_hal_async::spi::{Operation, SpiDevice};
2
3const SOCKET_BASE: u16 = 0x400;
4const TX_BASE: u16 = 0x4000;
5const RX_BASE: u16 = 0x6000;
6
7pub enum W5100S {}
8
9impl super::Chip for W5100S {}
10impl super::sealed::Chip for W5100S {
11 type Address = u16;
12
13 const COMMON_MODE: Self::Address = 0x00;
14 const COMMON_MAC: Self::Address = 0x09;
15 const COMMON_SOCKET_INTR: Self::Address = 0x16;
16 const COMMON_PHY_CFG: Self::Address = 0x3c;
17
18 const SOCKET_MODE: Self::Address = SOCKET_BASE + 0x00;
19 const SOCKET_COMMAND: Self::Address = SOCKET_BASE + 0x01;
20 const SOCKET_RXBUF_SIZE: Self::Address = SOCKET_BASE + 0x1E;
21 const SOCKET_TXBUF_SIZE: Self::Address = SOCKET_BASE + 0x1F;
22 const SOCKET_TX_FREE_SIZE: Self::Address = SOCKET_BASE + 0x20;
23 const SOCKET_TX_DATA_WRITE_PTR: Self::Address = SOCKET_BASE + 0x24;
24 const SOCKET_RECVD_SIZE: Self::Address = SOCKET_BASE + 0x26;
25 const SOCKET_RX_DATA_READ_PTR: Self::Address = SOCKET_BASE + 0x28;
26 const SOCKET_INTR_MASK: Self::Address = SOCKET_BASE + 0x2C;
27 const SOCKET_INTR: Self::Address = SOCKET_BASE + 0x02;
28
29 const SOCKET_MODE_VALUE: u8 = (1 << 2) | (1 << 6);
30
31 const BUF_SIZE: u16 = 0x2000;
32 const AUTO_WRAP: bool = false;
33
34 fn rx_addr(addr: u16) -> Self::Address {
35 RX_BASE + addr
36 }
37
38 fn tx_addr(addr: u16) -> Self::Address {
39 TX_BASE + addr
40 }
41
42 async fn bus_read<SPI: SpiDevice>(
43 spi: &mut SPI,
44 address: Self::Address,
45 data: &mut [u8],
46 ) -> Result<(), SPI::Error> {
47 spi.transaction(&mut [
48 Operation::Write(&[0x0F, (address >> 8) as u8, address as u8]),
49 Operation::Read(data),
50 ])
51 .await
52 }
53
54 async fn bus_write<SPI: SpiDevice>(spi: &mut SPI, address: Self::Address, data: &[u8]) -> Result<(), SPI::Error> {
55 spi.transaction(&mut [
56 Operation::Write(&[0xF0, (address >> 8) as u8, address as u8]),
57 Operation::Write(data),
58 ])
59 .await
60 }
61}
diff --git a/embassy-net-w5500/src/chip/w5500.rs b/embassy-net-w5500/src/chip/w5500.rs
index f514e12a7..61e512946 100644
--- a/embassy-net-w5500/src/chip/w5500.rs
+++ b/embassy-net-w5500/src/chip/w5500.rs
@@ -30,6 +30,11 @@ impl super::sealed::Chip for W5500 {
30 const SOCKET_INTR_MASK: Self::Address = (RegisterBlock::Socket0, 0x2C); 30 const SOCKET_INTR_MASK: Self::Address = (RegisterBlock::Socket0, 0x2C);
31 const SOCKET_INTR: Self::Address = (RegisterBlock::Socket0, 0x02); 31 const SOCKET_INTR: Self::Address = (RegisterBlock::Socket0, 0x02);
32 32
33 const SOCKET_MODE_VALUE: u8 = (1 << 2) | (1 << 7);
34
35 const BUF_SIZE: u16 = 0x4000;
36 const AUTO_WRAP: bool = true;
37
33 fn rx_addr(addr: u16) -> Self::Address { 38 fn rx_addr(addr: u16) -> Self::Address {
34 (RegisterBlock::RxBuf, addr) 39 (RegisterBlock::RxBuf, addr)
35 } 40 }
diff --git a/embassy-net-w5500/src/device.rs b/embassy-net-w5500/src/device.rs
index a6ee8f8f7..f367bc3eb 100644
--- a/embassy-net-w5500/src/device.rs
+++ b/embassy-net-w5500/src/device.rs
@@ -43,13 +43,13 @@ impl<C: Chip, SPI: SpiDevice> WiznetDevice<C, SPI> {
43 // Set MAC address 43 // Set MAC address
44 this.bus_write(C::COMMON_MAC, &mac_addr).await?; 44 this.bus_write(C::COMMON_MAC, &mac_addr).await?;
45 45
46 // Set the raw socket RX/TX buffer sizes to 16KB 46 // Set the raw socket RX/TX buffer sizes.
47 this.bus_write(C::SOCKET_TXBUF_SIZE, &[16]).await?; 47 let buf_kbs = (C::BUF_SIZE / 1024) as u8;
48 this.bus_write(C::SOCKET_RXBUF_SIZE, &[16]).await?; 48 this.bus_write(C::SOCKET_TXBUF_SIZE, &[buf_kbs]).await?;
49 this.bus_write(C::SOCKET_RXBUF_SIZE, &[buf_kbs]).await?;
49 50
50 // MACRAW mode with MAC filtering. 51 // MACRAW mode with MAC filtering.
51 let mode: u8 = (1 << 2) | (1 << 7); 52 this.bus_write(C::SOCKET_MODE, &[C::SOCKET_MODE_VALUE]).await?;
52 this.bus_write(C::SOCKET_MODE, &[mode]).await?;
53 this.command(Command::Open).await?; 53 this.command(Command::Open).await?;
54 54
55 Ok(this) 55 Ok(this)
@@ -114,9 +114,21 @@ impl<C: Chip, SPI: SpiDevice> WiznetDevice<C, SPI> {
114 Ok(u16::from_be_bytes(data)) 114 Ok(u16::from_be_bytes(data))
115 } 115 }
116 116
117 /// Read bytes from the RX buffer. Returns the number of bytes read. 117 /// Read bytes from the RX buffer.
118 async fn read_bytes(&mut self, read_ptr: &mut u16, buffer: &mut [u8]) -> Result<(), SPI::Error> { 118 async fn read_bytes(&mut self, read_ptr: &mut u16, buffer: &mut [u8]) -> Result<(), SPI::Error> {
119 self.bus_read(C::rx_addr(*read_ptr), buffer).await?; 119 if C::AUTO_WRAP {
120 self.bus_read(C::rx_addr(*read_ptr), buffer).await?;
121 } else {
122 let addr = *read_ptr % C::BUF_SIZE;
123 if addr as usize + buffer.len() <= C::BUF_SIZE as usize {
124 self.bus_read(C::rx_addr(addr), buffer).await?;
125 } else {
126 let n = C::BUF_SIZE - addr;
127 self.bus_read(C::rx_addr(addr), &mut buffer[..n as usize]).await?;
128 self.bus_read(C::rx_addr(0), &mut buffer[n as usize..]).await?;
129 }
130 }
131
120 *read_ptr = (*read_ptr).wrapping_add(buffer.len() as u16); 132 *read_ptr = (*read_ptr).wrapping_add(buffer.len() as u16);
121 133
122 Ok(()) 134 Ok(())
@@ -155,7 +167,20 @@ impl<C: Chip, SPI: SpiDevice> WiznetDevice<C, SPI> {
155 pub async fn write_frame(&mut self, frame: &[u8]) -> Result<usize, SPI::Error> { 167 pub async fn write_frame(&mut self, frame: &[u8]) -> Result<usize, SPI::Error> {
156 while self.get_tx_free_size().await? < frame.len() as u16 {} 168 while self.get_tx_free_size().await? < frame.len() as u16 {}
157 let write_ptr = self.get_tx_write_ptr().await?; 169 let write_ptr = self.get_tx_write_ptr().await?;
158 self.bus_write(C::tx_addr(write_ptr), frame).await?; 170
171 if C::AUTO_WRAP {
172 self.bus_write(C::tx_addr(write_ptr), frame).await?;
173 } else {
174 let addr = write_ptr % C::BUF_SIZE;
175 if addr as usize + frame.len() <= C::BUF_SIZE as usize {
176 self.bus_write(C::tx_addr(addr), frame).await?;
177 } else {
178 let n = C::BUF_SIZE - addr;
179 self.bus_write(C::tx_addr(addr), &frame[..n as usize]).await?;
180 self.bus_write(C::tx_addr(0), &frame[n as usize..]).await?;
181 }
182 }
183
159 self.set_tx_write_ptr(write_ptr.wrapping_add(frame.len() as u16)) 184 self.set_tx_write_ptr(write_ptr.wrapping_add(frame.len() as u16))
160 .await?; 185 .await?;
161 self.command(Command::Send).await?; 186 self.command(Command::Send).await?;
diff --git a/embassy-net-w5500/src/lib.rs b/embassy-net-w5500/src/lib.rs
index 9b53e9618..3030dfb90 100644
--- a/embassy-net-w5500/src/lib.rs
+++ b/embassy-net-w5500/src/lib.rs
@@ -1,4 +1,4 @@
1//! [`embassy-net`](https://crates.io/crates/embassy-net) driver for the WIZnet W5500 ethernet chip. 1//! [`embassy-net`](https://crates.io/crates/embassy-net) driver for WIZnet ethernet chips.
2#![no_std] 2#![no_std]
3#![feature(async_fn_in_trait)] 3#![feature(async_fn_in_trait)]
4 4
@@ -18,7 +18,7 @@ use crate::device::WiznetDevice;
18 18
19const MTU: usize = 1514; 19const MTU: usize = 1514;
20 20
21/// Type alias for the embassy-net driver for W5500 21/// Type alias for the embassy-net driver.
22pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; 22pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>;
23 23
24/// Internal state for the embassy-net integration. 24/// Internal state for the embassy-net integration.
@@ -35,9 +35,9 @@ impl<const N_RX: usize, const N_TX: usize> State<N_RX, N_TX> {
35 } 35 }
36} 36}
37 37
38/// Background runner for the W5500. 38/// Background runner for the driver.
39/// 39///
40/// You must call `.run()` in a background task for the W5500 to operate. 40/// You must call `.run()` in a background task for the driver to operate.
41pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> { 41pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
42 mac: WiznetDevice<C, SPI>, 42 mac: WiznetDevice<C, SPI>,
43 ch: ch::Runner<'d, MTU>, 43 ch: ch::Runner<'d, MTU>,
@@ -45,7 +45,7 @@ pub struct Runner<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> {
45 _reset: RST, 45 _reset: RST,
46} 46}
47 47
48/// You must call this in a background task for the W5500 to operate. 48/// You must call this in a background task for the driver to operate.
49impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> { 49impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI, INT, RST> {
50 pub async fn run(mut self) -> ! { 50 pub async fn run(mut self) -> ! {
51 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split(); 51 let (state_chan, mut rx_chan, mut tx_chan) = self.ch.split();
@@ -80,7 +80,11 @@ impl<'d, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin> Runner<'d, C, SPI,
80 } 80 }
81} 81}
82 82
83/// Obtain a driver for using the W5500 with [`embassy-net`](https://crates.io/crates/embassy-net). 83/// Create a Wiznet ethernet chip driver for [`embassy-net`](https://crates.io/crates/embassy-net).
84///
85/// This returns two structs:
86/// - a `Device` that you must pass to the `embassy-net` stack.
87/// - a `Runner`. You must call `.run()` on it in a background task.
84pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin>( 88pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevice, INT: Wait, RST: OutputPin>(
85 mac_addr: [u8; 6], 89 mac_addr: [u8; 6],
86 state: &'a mut State<N_RX, N_TX>, 90 state: &'a mut State<N_RX, N_TX>,
@@ -88,13 +92,15 @@ pub async fn new<'a, const N_RX: usize, const N_TX: usize, C: Chip, SPI: SpiDevi
88 int: INT, 92 int: INT,
89 mut reset: RST, 93 mut reset: RST,
90) -> (Device<'a>, Runner<'a, C, SPI, INT, RST>) { 94) -> (Device<'a>, Runner<'a, C, SPI, INT, RST>) {
91 // Reset the W5500. 95 // Reset the chip.
92 reset.set_low().ok(); 96 reset.set_low().ok();
93 // Ensure the reset is registered. 97 // Ensure the reset is registered.
94 Timer::after(Duration::from_millis(1)).await; 98 Timer::after(Duration::from_millis(1)).await;
95 reset.set_high().ok(); 99 reset.set_high().ok();
96 // Wait for the W5500 to achieve PLL lock. 100
97 Timer::after(Duration::from_millis(2)).await; 101 // Wait for PLL lock. Some chips are slower than others.
102 // Slowest is w5100s which is 100ms, so let's just wait that.
103 Timer::after(Duration::from_millis(100)).await;
98 104
99 let mac = WiznetDevice::new(spi_dev, mac_addr).await.unwrap(); 105 let mac = WiznetDevice::new(spi_dev, mac_addr).await.unwrap();
100 106