diff --git a/CHANGELOG.md b/CHANGELOG.md index 010d5dd..7df0d22 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed an issue where internal function names were conflicting with trait names by [@ryan-summers](https://github.com/ryan-summers) ([#36](https://github.com/kellerkindt/w5500/issues/36)) - Add `RetryTime` and `RetryCount` common register methods to `Device` and `UninitializedDevice` by [@elpiel](https://github.com/elpiel) ([#54][PR54]) - Add `Udp::get_port` and `Udp::set_port` by [@elpiel](https://github.com/elpiel) ([#57](https://github.com/kellerkindt/w5500/pull/57)) +- Add `RawDevice::enable_interrupts` (and `clear_interrupts`, `disable_interrupts`) for interrupt-driven MACRAW mode by [@pdh11](https://github.com/pdh11) ([#60](https://github.com/kellerkindt/w5000/pull/60)) ### Fixed diff --git a/src/raw_device.rs b/src/raw_device.rs index 25b09a9..e9cec64 100644 --- a/src/raw_device.rs +++ b/src/raw_device.rs @@ -39,6 +39,48 @@ impl RawDevice { Ok(Self { bus, raw_socket }) } + /// Enable one or more interrupts + /// + /// # Args + /// * `which` - The interrupts to enable; see `register::socketn::Interrupt` + /// For instance, pass `Interrupt::Receive` to get interrupts + /// on packet reception only. + /// + pub fn enable_interrupts(&mut self, which: u8) -> Result<(), SpiBus::Error> { + self.raw_socket.set_interrupt_mask(&mut self.bus, which)?; + self.bus.write_frame( + register::COMMON, + register::common::SOCKET_INTERRUPT_MASK, + &[1], + )?; + Ok(()) + } + + /// Clear pending interrupts + /// + /// If using RTIC or similar, this should be called from the + /// interrupt handler. If not (i.e., if there's concern that this + /// use of the SPI bus will clobber someone else's use), then you + /// can mask the interrupt *at microcontroller level* in the + /// interrupt handler, then call this from thread mode before + /// unmasking again. + pub fn clear_interrupts(&mut self) -> Result<(), SpiBus::Error> { + self.raw_socket + .reset_interrupt(&mut self.bus, register::socketn::Interrupt::All) + } + + /// Disable all interrupts + /// + pub fn disable_interrupts(&mut self) -> Result<(), SpiBus::Error> { + self.bus.write_frame( + register::COMMON, + register::common::SOCKET_INTERRUPT_MASK, + &[0], + )?; + self.raw_socket.set_interrupt_mask(&mut self.bus, 0xFF)?; + Ok(()) + } + /// Read an ethernet frame from the device. /// /// # Args diff --git a/src/register.rs b/src/register.rs index 3a1acfa..03b885b 100644 --- a/src/register.rs +++ b/src/register.rs @@ -22,6 +22,9 @@ pub mod common { /// Register: INTLEVEL (Interrupt Low Level Timer Register) [R/W] [0x0013 – 0x0014] [0x0000] pub const INTERRUPT_TIMER: u16 = 0x13; + /// Register: SIMR (Socket Interrupt Mask Register) [R/W] [0x0018] [0x00] + pub const SOCKET_INTERRUPT_MASK: u16 = 0x18; + /// Register: RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0] pub const RETRY_TIME: u16 = 0x19; diff --git a/src/tcp.rs b/src/tcp.rs index 7f1075c..e57fca2 100644 --- a/src/tcp.rs +++ b/src/tcp.rs @@ -223,7 +223,7 @@ impl TcpClientStack for DeviceRefMut<'_, SpiBus, Ho remote: SocketAddr, ) -> nb::Result<(), Self::Error> { let SocketAddr::V4(remote) = remote else { - return Err(nb::Error::Other(Self::Error::UnsupportedAddress)) + return Err(nb::Error::Other(Self::Error::UnsupportedAddress)); }; // TODO dynamically select a random port socket.open(&mut self.bus, 49849 + u16::from(socket.socket.index))?; // chosen by fair dice roll. diff --git a/src/udp.rs b/src/udp.rs index aa47008..7937f55 100644 --- a/src/udp.rs +++ b/src/udp.rs @@ -534,7 +534,7 @@ where remote: SocketAddr, ) -> Result<(), Self::Error> { let SocketAddr::V4(remote) = remote else { - return Err(Self::Error::UnsupportedAddress) + return Err(Self::Error::UnsupportedAddress); }; socket.open(&mut self.bus)?; socket.set_destination(&mut self.bus, remote)?; @@ -602,7 +602,7 @@ where buffer: &[u8], ) -> nb::Result<(), Self::Error> { let SocketAddr::V4(remote) = remote else { - return Err(nb::Error::Other(Self::Error::UnsupportedAddress)) + return Err(nb::Error::Other(Self::Error::UnsupportedAddress)); }; socket.socket_send_to(&mut self.bus, remote, buffer)?;