From 1d88a91e88652510341648b89954c09f0fc9bf43 Mon Sep 17 00:00:00 2001 From: Jonah Dahlquist Date: Tue, 30 Jul 2019 20:25:18 -0500 Subject: [PATCH 1/4] Updated all dependencies, replaced deprecated v1 OutputPin --- Cargo.lock | 20 +++--- Cargo.toml | 6 +- src/lib.rs | 203 ++++++++++++++++++++++++++++++++++++++++------------- 3 files changed, 168 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9d6f57f..3a8de7d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,21 @@ # It is not intended for manual editing. [[package]] name = "byteorder" -version = "1.2.6" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "embedded-hal" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "nb" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -28,13 +28,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "w5500" version = "0.2.1" dependencies = [ - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "embedded-hal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" -"checksum embedded-hal 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "26944677e4934eb5fb4025501dc0d6cdbcf6bfabd6200fcfee2e7e8eef8c0362" -"checksum nb 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "69f380b5fe9fab8c0d7a6a99cda23e2cc0463bedb2cbc3aada0813b98496ecdc" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum embedded-hal 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ee4908a155094da7723c2d60d617b820061e3b4efcc3d9e293d206a5a76c170b" +"checksum nb 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b1411551beb3c11dedfb0a90a0fa256b47d28b9ec2cdff34c25a2fa59e45dbdc" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" diff --git a/Cargo.toml b/Cargo.toml index 3af94a9..f16859a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,6 @@ license = "MIT OR Apache-2.0" readme = "README.md" [dependencies] -byteorder = { version = "1.2.1", default-features = false } -embedded-hal = "0.2.1" -nb = "0.1.1" +byteorder = { version = "1.3.2", default-features = false } +embedded-hal = "0.2.3" +nb = "0.1.2" diff --git a/src/lib.rs b/src/lib.rs index ee82823..a76e9df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,7 +7,7 @@ extern crate embedded_hal as hal; #[macro_use(block)] extern crate nb; -use hal::digital::OutputPin; +use hal::digital::v2::OutputPin; use hal::spi::FullDuplex; use byteorder::BigEndian; @@ -72,6 +72,12 @@ impl ::core::fmt::Display for MacAddress { } } +#[derive(Copy, Clone, Debug)] +pub enum TransferError { + SpiError(SpiError), + ChipSelectError(ChipSelectError), +} + #[derive(Copy, Clone, PartialOrd, PartialEq)] pub enum OnWakeOnLan { InvokeInterrupt, @@ -101,12 +107,14 @@ pub enum ArpResponses { pub struct UninitializedSocket(Socket); pub struct UdpSocket(Socket); -pub struct W5500<'a, ChipSelect: OutputPin> { +pub struct W5500<'a, ChipSelectError, ChipSelect: OutputPin> { chip_select: &'a mut ChipSelect, sockets: u8, // each bit represents whether the corresponding socket is available for take } -impl<'b, 'a: 'b, ChipSelect: OutputPin> W5500<'a, ChipSelect> { +impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin> + W5500<'a, ChipSelectError, ChipSelect> +{ fn new(chip_select: &'a mut ChipSelect) -> Self { W5500 { chip_select, @@ -121,7 +129,7 @@ impl<'b, 'a: 'b, ChipSelect: OutputPin> W5500<'a, ChipSelect> { ping: OnPingRequest, mode: ConnectionType, arp: ArpResponses, - ) -> Result { + ) -> Result> { let mut w5500 = Self::new(chip_select); { let mut w5500_active = w5500.activate(spi)?; @@ -146,14 +154,31 @@ impl<'b, 'a: 'b, ChipSelect: OutputPin> W5500<'a, ChipSelect> { pub fn activate<'c, E, Spi: FullDuplex>( &'b mut self, spi: &'c mut Spi, - ) -> Result, E> { + ) -> Result< + ActiveW5500<'b, 'a, 'c, E, ChipSelectError, ChipSelect, Spi>, + TransferError, + > { Ok(ActiveW5500(self, spi)) } } -pub struct ActiveW5500<'a, 'b: 'a, 'c, E, ChipSelect: OutputPin, Spi: FullDuplex>(&'a mut W5500<'b, ChipSelect>, &'c mut Spi); +pub struct ActiveW5500< + 'a, + 'b: 'a, + 'c, + SpiError, + ChipSelectError, + ChipSelect: OutputPin, + Spi: FullDuplex, +>(&'a mut W5500<'b, ChipSelectError, ChipSelect>, &'c mut Spi); -impl> ActiveW5500<'_, '_, '_, E, ChipSelect, Spi> { +impl< + SpiError, + ChipSelectError, + ChipSelect: OutputPin, + Spi: FullDuplex, + > ActiveW5500<'_, '_, '_, SpiError, ChipSelectError, ChipSelect, Spi> +{ pub fn take_socket(&mut self, socket: Socket) -> Option { self.0.take_socket(socket) } @@ -164,7 +189,7 @@ impl> ActiveW5500<'_, ' ping: OnPingRequest, mode: ConnectionType, arp: ArpResponses, - ) -> Result<(), E> { + ) -> Result<(), TransferError> { let mut value = 0x00; if let OnWakeOnLan::InvokeInterrupt = wol { @@ -186,23 +211,38 @@ impl> ActiveW5500<'_, ' self.write_to(Register::CommonRegister(0x00_00_u16), &[value]) } - pub fn set_gateway(&mut self, gateway: IpAddress) -> Result<(), E> { + pub fn set_gateway( + &mut self, + gateway: IpAddress, + ) -> Result<(), TransferError> { self.write_to(Register::CommonRegister(0x00_01_u16), &gateway.address) } - pub fn set_subnet(&mut self, subnet: IpAddress) -> Result<(), E> { + pub fn set_subnet( + &mut self, + subnet: IpAddress, + ) -> Result<(), TransferError> { self.write_to(Register::CommonRegister(0x00_05_u16), &subnet.address) } - pub fn set_mac(&mut self, mac: MacAddress) -> Result<(), E> { + pub fn set_mac( + &mut self, + mac: MacAddress, + ) -> Result<(), TransferError> { self.write_to(Register::CommonRegister(0x00_09_u16), &mac.address) } - pub fn set_ip(&mut self, ip: IpAddress) -> Result<(), E> { + pub fn set_ip( + &mut self, + ip: IpAddress, + ) -> Result<(), TransferError> { self.write_to(Register::CommonRegister(0x00_0F_u16), &ip.address) } - pub fn read_ip(&mut self, register: Register) -> Result { + pub fn read_ip( + &mut self, + register: Register, + ) -> Result> { let mut ip = IpAddress::default(); self.read_from(register, &mut ip.address)?; Ok(ip) @@ -211,7 +251,7 @@ impl> ActiveW5500<'_, ' /// This is unsafe because it cannot set taken sockets back to be uninitialized /// It assumes, none of the old sockets will used anymore. Otherwise that socket /// will have undefined behavior. - pub unsafe fn reset(&mut self) -> Result<(), E> { + pub unsafe fn reset(&mut self) -> Result<(), TransferError> { self.write_to( Register::CommonRegister(0x00_00_u16), &[ @@ -222,108 +262,160 @@ impl> ActiveW5500<'_, ' Ok(()) } - fn is_interrupt_set(&mut self, socket: Socket, interrupt: Interrupt) -> Result { + fn is_interrupt_set( + &mut self, + socket: Socket, + interrupt: Interrupt, + ) -> Result> { let mut state = [0u8; 1]; self.read_from(socket.at(SocketRegister::Interrupt), &mut state)?; Ok(state[0] & interrupt as u8 != 0) } - pub fn reset_interrupt(&mut self, socket: Socket, interrupt: Interrupt) -> Result<(), E> { + pub fn reset_interrupt( + &mut self, + socket: Socket, + interrupt: Interrupt, + ) -> Result<(), TransferError> { self.write_to(socket.at(SocketRegister::Interrupt), &[interrupt as u8]) } - fn read_u8(&mut self, register: Register) -> Result { + fn read_u8( + &mut self, + register: Register, + ) -> Result> { let mut buffer = [0u8; 1]; self.read_from(register, &mut buffer)?; Ok(buffer[0]) } - fn read_u16(&mut self, register: Register) -> Result { + fn read_u16( + &mut self, + register: Register, + ) -> Result> { let mut buffer = [0u8; 2]; self.read_from(register, &mut buffer)?; Ok(BigEndian::read_u16(&buffer)) } - fn read_from(&mut self, register: Register, target: &mut [u8]) -> Result<(), E> { - self.chip_select(); + fn read_from( + &mut self, + register: Register, + target: &mut [u8], + ) -> Result<(), TransferError> { + self.chip_select() + .map_err(|error| -> TransferError { + TransferError::ChipSelectError(error) + }); let mut request = [ 0_u8, 0_u8, register.control_byte() | COMMAND_READ | VARIABLE_DATA_LENGTH, ]; BigEndian::write_u16(&mut request[..2], register.address()); - let result = self.write_bytes(&request) + let result = self + .write_bytes(&request) .and_then(|_| self.read_bytes(target)); - self.chip_deselect(); - result + self.chip_deselect() + .map_err(|error| -> TransferError { + TransferError::ChipSelectError(error) + }); + result.map_err(|error| TransferError::SpiError(error)) } - fn read_bytes(&mut self, bytes: &mut [u8]) -> Result<(), E> { + fn read_bytes(&mut self, bytes: &mut [u8]) -> Result<(), SpiError> { for byte in bytes { *byte = self.read()?; } Ok(()) } - fn read(&mut self) -> Result { + fn read(&mut self) -> Result { block!(self.1.send(0x00))?; block!(self.1.read()) } - fn write_u8(&mut self, register: Register, value: u8) -> Result<(), E> { + fn write_u8( + &mut self, + register: Register, + value: u8, + ) -> Result<(), TransferError> { self.write_to(register, &[value]) } - fn write_u16(&mut self, register: Register, value: u16) -> Result<(), E> { + fn write_u16( + &mut self, + register: Register, + value: u16, + ) -> Result<(), TransferError> { let mut data = [0u8; 2]; BigEndian::write_u16(&mut data, value); self.write_to(register, &data) } - fn write_to(&mut self, register: Register, data: &[u8]) -> Result<(), E> { - self.chip_select(); + fn write_to( + &mut self, + register: Register, + data: &[u8], + ) -> Result<(), TransferError> { + self.chip_select() + .map_err(|error| -> TransferError { + TransferError::ChipSelectError(error) + }); let mut request = [ 0_u8, 0_u8, register.control_byte() | COMMAND_WRITE | VARIABLE_DATA_LENGTH, ]; BigEndian::write_u16(&mut request[..2], register.address()); - let result = self.write_bytes(&request) + let result = self + .write_bytes(&request) .and_then(|_| self.write_bytes(data)); - self.chip_deselect(); - result + self.chip_deselect() + .map_err(|error| -> TransferError { + TransferError::ChipSelectError(error) + }); + result.map_err(|error| TransferError::SpiError(error)) } - fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), E> { + fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), SpiError> { for b in bytes { self.write(*b)?; } Ok(()) } - fn write(&mut self, byte: u8) -> Result<(), E> { + fn write(&mut self, byte: u8) -> Result<(), SpiError> { block!(self.1.send(byte))?; block!(self.1.read())?; Ok(()) } - fn chip_select(&mut self) { + fn chip_select(&mut self) -> Result<(), ChipSelectError> { self.0.chip_select.set_low() } - fn chip_deselect(&mut self) { + fn chip_deselect(&mut self) -> Result<(), ChipSelectError> { self.0.chip_select.set_high() } } -pub trait IntoUdpSocket { - fn try_into_udp_server_socket(self, port: u16) -> Result +pub trait IntoUdpSocket { + fn try_into_udp_server_socket(self, port: u16) -> Result where Self: Sized; } -impl> IntoUdpSocket - for (&mut ActiveW5500<'_, '_, '_, E, ChipSelect, Spi>, UninitializedSocket) +impl< + SpiError, + ChipSelectError, + ChipSelect: OutputPin, + Spi: FullDuplex, + > IntoUdpSocket + for ( + &mut ActiveW5500<'_, '_, '_, SpiError, ChipSelectError, ChipSelect, Spi>, + UninitializedSocket, + ) { fn try_into_udp_server_socket(self, port: u16) -> Result { let socket = (self.1).0; @@ -341,22 +433,38 @@ impl> IntoUdpSocket| UninitializedSocket(socket)) } } -pub trait Udp { - fn receive(&mut self, target_buffer: &mut [u8]) -> Result, E>; +pub trait Udp { + fn receive( + &mut self, + target_buffer: &mut [u8], + ) -> Result, TransferError>; fn blocking_send( &mut self, host: &IpAddress, host_port: u16, data: &[u8], - ) -> Result<(), E>; + ) -> Result<(), TransferError>; } -impl> Udp for (&mut ActiveW5500<'_, '_, '_, E, ChipSelect, Spi>, &UdpSocket) { - fn receive(&mut self, destination: &mut [u8]) -> Result, E> { +impl< + SpiError, + ChipSelectError, + ChipSelect: OutputPin, + Spi: FullDuplex, + > Udp + for ( + &mut ActiveW5500<'_, '_, '_, SpiError, ChipSelectError, ChipSelect, Spi>, + &UdpSocket, + ) +{ + fn receive( + &mut self, + destination: &mut [u8], + ) -> Result, TransferError> { let (w5500, UdpSocket(socket)) = self; if w5500.read_u8(socket.at(SocketRegister::InterruptMask))? & 0x04 == 0 { @@ -412,7 +520,7 @@ impl> Udp for (&mut host: &IpAddress, host_port: u16, data: &[u8], - ) -> Result<(), E> { + ) -> Result<(), TransferError> { let (w5500, UdpSocket(socket)) = self; { @@ -486,7 +594,6 @@ impl> Udp for (&mut } } - #[repr(u8)] #[derive(Copy, Clone, PartialEq, Debug)] pub enum SocketRegister { From 72c91266bd0d316b68c4b1dde76831f86145ae06 Mon Sep 17 00:00:00 2001 From: Jonah Dahlquist Date: Wed, 31 Jul 2019 18:42:20 -0500 Subject: [PATCH 2/4] Made chip_(de)select errors propagate properly --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a76e9df..7405ec1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -306,7 +306,7 @@ impl< self.chip_select() .map_err(|error| -> TransferError { TransferError::ChipSelectError(error) - }); + })?; let mut request = [ 0_u8, 0_u8, @@ -319,7 +319,7 @@ impl< self.chip_deselect() .map_err(|error| -> TransferError { TransferError::ChipSelectError(error) - }); + })?; result.map_err(|error| TransferError::SpiError(error)) } @@ -361,7 +361,7 @@ impl< self.chip_select() .map_err(|error| -> TransferError { TransferError::ChipSelectError(error) - }); + })?; let mut request = [ 0_u8, 0_u8, @@ -374,7 +374,7 @@ impl< self.chip_deselect() .map_err(|error| -> TransferError { TransferError::ChipSelectError(error) - }); + })?; result.map_err(|error| TransferError::SpiError(error)) } From e8e44413d387a8e134f5c04210b827e75905214d Mon Sep 17 00:00:00 2001 From: Jonah Dahlquist Date: Thu, 1 Aug 2019 08:38:42 -0500 Subject: [PATCH 3/4] Removed unnecessary generics from structs --- src/lib.rs | 42 ++++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7405ec1..f9c2d28 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -107,13 +107,13 @@ pub enum ArpResponses { pub struct UninitializedSocket(Socket); pub struct UdpSocket(Socket); -pub struct W5500<'a, ChipSelectError, ChipSelect: OutputPin> { +pub struct W5500<'a, ChipSelect: OutputPin> { chip_select: &'a mut ChipSelect, sockets: u8, // each bit represents whether the corresponding socket is available for take } impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin> - W5500<'a, ChipSelectError, ChipSelect> + W5500<'a, ChipSelect> { fn new(chip_select: &'a mut ChipSelect) -> Self { W5500 { @@ -122,14 +122,14 @@ impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin } } - pub fn with_initialisation<'c, E, Spi: FullDuplex>( + pub fn with_initialisation<'c, SpiError, Spi: FullDuplex>( chip_select: &'a mut ChipSelect, spi: &'c mut Spi, wol: OnWakeOnLan, ping: OnPingRequest, mode: ConnectionType, arp: ArpResponses, - ) -> Result> { + ) -> Result> { let mut w5500 = Self::new(chip_select); { let mut w5500_active = w5500.activate(spi)?; @@ -151,33 +151,26 @@ impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin } } - pub fn activate<'c, E, Spi: FullDuplex>( + pub fn activate<'c, SpiError, Spi: FullDuplex>( &'b mut self, spi: &'c mut Spi, - ) -> Result< - ActiveW5500<'b, 'a, 'c, E, ChipSelectError, ChipSelect, Spi>, - TransferError, - > { + ) -> Result, TransferError> + { Ok(ActiveW5500(self, spi)) } } -pub struct ActiveW5500< - 'a, - 'b: 'a, - 'c, - SpiError, - ChipSelectError, - ChipSelect: OutputPin, - Spi: FullDuplex, ->(&'a mut W5500<'b, ChipSelectError, ChipSelect>, &'c mut Spi); +pub struct ActiveW5500<'a, 'b: 'a, 'c, ChipSelect: OutputPin, Spi: FullDuplex>( + &'a mut W5500<'b, ChipSelect>, + &'c mut Spi, +); impl< - SpiError, ChipSelectError, ChipSelect: OutputPin, + SpiError, Spi: FullDuplex, - > ActiveW5500<'_, '_, '_, SpiError, ChipSelectError, ChipSelect, Spi> + > ActiveW5500<'_, '_, '_, ChipSelect, Spi> { pub fn take_socket(&mut self, socket: Socket) -> Option { self.0.take_socket(socket) @@ -407,13 +400,13 @@ pub trait IntoUdpSocket { } impl< - SpiError, ChipSelectError, ChipSelect: OutputPin, + SpiError, Spi: FullDuplex, > IntoUdpSocket for ( - &mut ActiveW5500<'_, '_, '_, SpiError, ChipSelectError, ChipSelect, Spi>, + &mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>, UninitializedSocket, ) { @@ -456,10 +449,7 @@ impl< ChipSelect: OutputPin, Spi: FullDuplex, > Udp - for ( - &mut ActiveW5500<'_, '_, '_, SpiError, ChipSelectError, ChipSelect, Spi>, - &UdpSocket, - ) + for (&mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>, &UdpSocket) { fn receive( &mut self, From 020272b9f933cafbc9ffad56868638b68f4b0b90 Mon Sep 17 00:00:00 2001 From: Jonah Dahlquist Date: Thu, 1 Aug 2019 09:06:05 -0500 Subject: [PATCH 4/4] Removed more redundent generics --- src/lib.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f9c2d28..c5c636f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,14 +122,14 @@ impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin } } - pub fn with_initialisation<'c, SpiError, Spi: FullDuplex>( + pub fn with_initialisation<'c, Spi: FullDuplex>( chip_select: &'a mut ChipSelect, spi: &'c mut Spi, wol: OnWakeOnLan, ping: OnPingRequest, mode: ConnectionType, arp: ArpResponses, - ) -> Result> { + ) -> Result> { let mut w5500 = Self::new(chip_select); { let mut w5500_active = w5500.activate(spi)?; @@ -151,10 +151,10 @@ impl<'b, 'a: 'b, ChipSelectError, ChipSelect: OutputPin } } - pub fn activate<'c, SpiError, Spi: FullDuplex>( + pub fn activate<'c, Spi: FullDuplex>( &'b mut self, spi: &'c mut Spi, - ) -> Result, TransferError> + ) -> Result, TransferError> { Ok(ActiveW5500(self, spi)) } @@ -443,18 +443,13 @@ pub trait Udp { ) -> Result<(), TransferError>; } -impl< - SpiError, - ChipSelectError, - ChipSelect: OutputPin, - Spi: FullDuplex, - > Udp +impl> Udp for (&mut ActiveW5500<'_, '_, '_, ChipSelect, Spi>, &UdpSocket) { fn receive( &mut self, destination: &mut [u8], - ) -> Result, TransferError> { + ) -> Result, TransferError> { let (w5500, UdpSocket(socket)) = self; if w5500.read_u8(socket.at(SocketRegister::InterruptMask))? & 0x04 == 0 { @@ -510,7 +505,7 @@ impl< host: &IpAddress, host_port: u16, data: &[u8], - ) -> Result<(), TransferError> { + ) -> Result<(), TransferError> { let (w5500, UdpSocket(socket)) = self; {