Finalizing updates to MACRAW support after testing
This commit is contained in:
parent
c25cbe6fdb
commit
30293b65a5
3 changed files with 70 additions and 22 deletions
|
|
@ -15,10 +15,22 @@ impl<SpiBus: Bus> RawDevice<SpiBus> {
|
||||||
/// # Args
|
/// # Args
|
||||||
/// * `bus` - The bus to communicate with the device.
|
/// * `bus` - The bus to communicate with the device.
|
||||||
pub(crate) fn new(mut bus: SpiBus) -> Result<Self, InitializeError<SpiBus::Error>> {
|
pub(crate) fn new(mut bus: SpiBus) -> Result<Self, InitializeError<SpiBus::Error>> {
|
||||||
|
// Set the raw socket to 16KB RX/TX buffer space.
|
||||||
let raw_socket = Socket::new(0);
|
let raw_socket = Socket::new(0);
|
||||||
|
bus.write_frame(raw_socket.register(), register::socketn::TXBUF_SIZE, &[16])?;
|
||||||
|
bus.write_frame(raw_socket.register(), register::socketn::RXBUF_SIZE, &[16])?;
|
||||||
|
|
||||||
// Configure the chip in MACRAW mode with MAC filtering.
|
// Set all socket buffers to 0KB size.
|
||||||
let mode: u8 = (1 << 7) | (register::socketn::Protocol::MacRaw as u8);
|
for socket_index in 1..8 {
|
||||||
|
let socket = Socket::new(socket_index);
|
||||||
|
bus.write_frame(socket.register(), register::socketn::TXBUF_SIZE, &[0])?;
|
||||||
|
bus.write_frame(socket.register(), register::socketn::RXBUF_SIZE, &[0])?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure the chip in MACRAW mode with MAC filtering + Multicast blocking + IPv6
|
||||||
|
// Blocking + Broadcast blocking.
|
||||||
|
let mode: u8 = (1 << 7) | // MAC address filtering
|
||||||
|
(register::socketn::Protocol::MacRaw as u8);
|
||||||
|
|
||||||
bus.write_frame(raw_socket.register(), register::socketn::MODE, &[mode])?;
|
bus.write_frame(raw_socket.register(), register::socketn::MODE, &[mode])?;
|
||||||
raw_socket.command(&mut bus, register::socketn::Command::Open)?;
|
raw_socket.command(&mut bus, register::socketn::Command::Open)?;
|
||||||
|
|
@ -26,6 +38,29 @@ impl<SpiBus: Bus> RawDevice<SpiBus> {
|
||||||
Ok(Self { bus, raw_socket })
|
Ok(Self { bus, raw_socket })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_bytes(&mut self, buffer: &mut [u8], offset: u16) -> Result<usize, SpiBus::Error> {
|
||||||
|
let rx_size = self.raw_socket.get_receive_size(&mut self.bus)? as usize;
|
||||||
|
|
||||||
|
let read_buffer = if rx_size > buffer.len() + offset as usize {
|
||||||
|
buffer
|
||||||
|
} else {
|
||||||
|
&mut buffer[..rx_size - offset as usize]
|
||||||
|
};
|
||||||
|
|
||||||
|
let read_pointer = self
|
||||||
|
.raw_socket
|
||||||
|
.get_rx_read_pointer(&mut self.bus)?
|
||||||
|
.wrapping_add(offset);
|
||||||
|
self.bus
|
||||||
|
.read_frame(self.raw_socket.rx_buffer(), read_pointer, read_buffer)?;
|
||||||
|
self.raw_socket.set_rx_read_pointer(
|
||||||
|
&mut self.bus,
|
||||||
|
read_pointer.wrapping_add(read_buffer.len() as u16),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(read_buffer.len())
|
||||||
|
}
|
||||||
|
|
||||||
/// Read an ethernet frame from the device.
|
/// Read an ethernet frame from the device.
|
||||||
///
|
///
|
||||||
/// # Args
|
/// # Args
|
||||||
|
|
@ -34,37 +69,41 @@ impl<SpiBus: Bus> RawDevice<SpiBus> {
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// The number of bytes read into the provided frame buffer.
|
/// The number of bytes read into the provided frame buffer.
|
||||||
pub fn read_frame(&mut self, frame: &mut [u8]) -> Result<usize, SpiBus::Error> {
|
pub fn read_frame(&mut self, frame: &mut [u8]) -> Result<usize, SpiBus::Error> {
|
||||||
if !self
|
// Check if there is anything to receive.
|
||||||
.raw_socket
|
let rx_size = self.raw_socket.get_receive_size(&mut self.bus)? as usize;
|
||||||
.has_interrupt(&mut self.bus, register::socketn::Interrupt::Receive)?
|
if rx_size == 0 {
|
||||||
{
|
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rx_size = self.raw_socket.get_receive_size(&mut self.bus)? as usize;
|
// The W5500 specifies the size of the received ethernet frame in the first two bytes.
|
||||||
|
// Refer to https://forum.wiznet.io/t/topic/979/2 for more information.
|
||||||
|
let expected_frame_size: usize = {
|
||||||
|
let mut frame_bytes = [0u8; 2];
|
||||||
|
assert!(self.read_bytes(&mut frame_bytes[..], 0)? == 2);
|
||||||
|
|
||||||
let read_buffer = if rx_size > frame.len() {
|
u16::from_be_bytes(frame_bytes) as usize - 2
|
||||||
frame
|
|
||||||
} else {
|
|
||||||
&mut frame[..rx_size]
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read from the RX ring buffer.
|
// Read the ethernet frame
|
||||||
let read_pointer = self.raw_socket.get_rx_read_pointer(&mut self.bus)?;
|
let read_buffer = if frame.len() > expected_frame_size {
|
||||||
self.bus
|
&mut frame[..expected_frame_size]
|
||||||
.read_frame(self.raw_socket.rx_buffer(), read_pointer, read_buffer)?;
|
} else {
|
||||||
self.raw_socket.set_rx_read_pointer(
|
frame
|
||||||
&mut self.bus,
|
};
|
||||||
read_pointer.wrapping_add(read_buffer.len() as u16),
|
|
||||||
)?;
|
let received_frame_size = self.read_bytes(read_buffer, 2)?;
|
||||||
|
|
||||||
// Register the reception as complete.
|
// Register the reception as complete.
|
||||||
self.raw_socket
|
self.raw_socket
|
||||||
.command(&mut self.bus, register::socketn::Command::Receive)?;
|
.command(&mut self.bus, register::socketn::Command::Receive)?;
|
||||||
self.raw_socket
|
|
||||||
.reset_interrupt(&mut self.bus, register::socketn::Interrupt::Receive)?;
|
|
||||||
|
|
||||||
Ok(read_buffer.len())
|
// If we couldn't read the whole check sequence or if we read less bytes than expected,
|
||||||
|
// drop the frame.
|
||||||
|
if received_frame_size < expected_frame_size {
|
||||||
|
Ok(0)
|
||||||
|
} else {
|
||||||
|
Ok(received_frame_size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write an ethernet frame to the device.
|
/// Write an ethernet frame to the device.
|
||||||
|
|
|
||||||
|
|
@ -217,6 +217,10 @@ pub mod socketn {
|
||||||
|
|
||||||
pub const DESTINATION_PORT: u16 = 0x10;
|
pub const DESTINATION_PORT: u16 = 0x10;
|
||||||
|
|
||||||
|
pub const RXBUF_SIZE: u16 = 0x1E;
|
||||||
|
|
||||||
|
pub const TXBUF_SIZE: u16 = 0x1F;
|
||||||
|
|
||||||
pub const TX_FREE_SIZE: u16 = 0x20;
|
pub const TX_FREE_SIZE: u16 = 0x20;
|
||||||
|
|
||||||
pub const TX_DATA_READ_POINTER: u16 = 0x22;
|
pub const TX_DATA_READ_POINTER: u16 = 0x22;
|
||||||
|
|
|
||||||
|
|
@ -103,8 +103,13 @@ impl<SpiBus: Bus> UninitializedDevice<SpiBus> {
|
||||||
mut self,
|
mut self,
|
||||||
mac: MacAddress,
|
mac: MacAddress,
|
||||||
) -> Result<RawDevice<SpiBus>, InitializeError<SpiBus::Error>> {
|
) -> Result<RawDevice<SpiBus>, InitializeError<SpiBus::Error>> {
|
||||||
|
// Reset the device.
|
||||||
|
self.bus
|
||||||
|
.write_frame(register::COMMON, register::common::MODE, &[0x80])?;
|
||||||
|
|
||||||
self.bus
|
self.bus
|
||||||
.write_frame(register::COMMON, register::common::MAC, &mac.octets)?;
|
.write_frame(register::COMMON, register::common::MAC, &mac.octets)?;
|
||||||
|
|
||||||
RawDevice::new(self.bus)
|
RawDevice::new(self.bus)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue