Allow interrupt-driven MACRAW operation
This commit adds methods to RawDevice that enable interrupt-driven operation. The enable_interrupt() method sets up SIMR so that socket-level (internal) interrupts on Socket 0 cause chip-level (external) interrupts (and as a convenience also sets S0_IR as required). The disable_interrupt() method reverses those changes. The clear_interrupt() method acknowledges all interrupts and is intended to be called from the interrupt handler (or from thread mode soon afterwards). There is no change to existing functionality or operation if enable_interrupt() is never called. I did see PR#34 before filing this, but that change is focused on TCP and UDP sockets, and my use case is MACRAW mode. Tested on a W5500-Pico-EVB board with the RP2040 successfully receiving and acting on active-low GPIO interrupts from W5500 via the INTn signal on W5500 pin 36.
This commit is contained in:
parent
a45c33e54d
commit
d34ef053fd
2 changed files with 45 additions and 0 deletions
|
|
@ -39,6 +39,48 @@ impl<SpiBus: Bus> RawDevice<SpiBus> {
|
||||||
Ok(Self { bus, raw_socket })
|
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_interrupt(&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_interrupt(&mut self) -> Result<(), SpiBus::Error> {
|
||||||
|
self.raw_socket
|
||||||
|
.reset_interrupt(&mut self.bus, register::socketn::Interrupt::All)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Disable all interrupts
|
||||||
|
///
|
||||||
|
pub fn disable_interrupt(&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.
|
/// Read an ethernet frame from the device.
|
||||||
///
|
///
|
||||||
/// # Args
|
/// # Args
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,9 @@ pub mod common {
|
||||||
/// Register: INTLEVEL (Interrupt Low Level Timer Register) [R/W] [0x0013 – 0x0014] [0x0000]
|
/// Register: INTLEVEL (Interrupt Low Level Timer Register) [R/W] [0x0013 – 0x0014] [0x0000]
|
||||||
pub const INTERRUPT_TIMER: u16 = 0x13;
|
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]
|
/// Register: RTR (Retry Time-value Register) [R/W] [0x0019 – 0x001A] [0x07D0]
|
||||||
pub const RETRY_TIME: u16 = 0x19;
|
pub const RETRY_TIME: u16 = 0x19;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue