Adding macraw support
This commit is contained in:
parent
259550e3b6
commit
c25cbe6fdb
4 changed files with 123 additions and 0 deletions
|
|
@ -6,6 +6,7 @@ pub mod bus;
|
||||||
mod device;
|
mod device;
|
||||||
mod host;
|
mod host;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
|
pub mod raw_device;
|
||||||
pub mod register;
|
pub mod register;
|
||||||
mod socket;
|
mod socket;
|
||||||
pub mod tcp;
|
pub mod tcp;
|
||||||
|
|
|
||||||
111
src/raw_device.rs
Normal file
111
src/raw_device.rs
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
use crate::{bus::Bus, register, socket::Socket, uninitialized_device::InitializeError};
|
||||||
|
|
||||||
|
/// The W5500 operating in MACRAW mode to send and receive ethernet frames.
|
||||||
|
pub struct RawDevice<SpiBus: Bus> {
|
||||||
|
bus: SpiBus,
|
||||||
|
raw_socket: Socket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SpiBus: Bus> RawDevice<SpiBus> {
|
||||||
|
/// Create the raw device.
|
||||||
|
///
|
||||||
|
/// # Note
|
||||||
|
/// The device is configured with MAC filtering enabled.
|
||||||
|
///
|
||||||
|
/// # Args
|
||||||
|
/// * `bus` - The bus to communicate with the device.
|
||||||
|
pub(crate) fn new(mut bus: SpiBus) -> Result<Self, InitializeError<SpiBus::Error>> {
|
||||||
|
let raw_socket = Socket::new(0);
|
||||||
|
|
||||||
|
// Configure the chip in MACRAW mode with MAC filtering.
|
||||||
|
let mode: u8 = (1 << 7) | (register::socketn::Protocol::MacRaw as u8);
|
||||||
|
|
||||||
|
bus.write_frame(raw_socket.register(), register::socketn::MODE, &[mode])?;
|
||||||
|
raw_socket.command(&mut bus, register::socketn::Command::Open)?;
|
||||||
|
|
||||||
|
Ok(Self { bus, raw_socket })
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read an ethernet frame from the device.
|
||||||
|
///
|
||||||
|
/// # Args
|
||||||
|
/// * `frame` - The location to store the received frame
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// The number of bytes read into the provided frame buffer.
|
||||||
|
pub fn read_frame(&mut self, frame: &mut [u8]) -> Result<usize, SpiBus::Error> {
|
||||||
|
if !self
|
||||||
|
.raw_socket
|
||||||
|
.has_interrupt(&mut self.bus, register::socketn::Interrupt::Receive)?
|
||||||
|
{
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let rx_size = self.raw_socket.get_receive_size(&mut self.bus)? as usize;
|
||||||
|
|
||||||
|
let read_buffer = if rx_size > frame.len() {
|
||||||
|
frame
|
||||||
|
} else {
|
||||||
|
&mut frame[..rx_size]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Read from the RX ring buffer.
|
||||||
|
let read_pointer = self.raw_socket.get_rx_read_pointer(&mut self.bus)?;
|
||||||
|
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),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Register the reception as complete.
|
||||||
|
self.raw_socket
|
||||||
|
.command(&mut self.bus, register::socketn::Command::Receive)?;
|
||||||
|
self.raw_socket
|
||||||
|
.reset_interrupt(&mut self.bus, register::socketn::Interrupt::Receive)?;
|
||||||
|
|
||||||
|
Ok(read_buffer.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Write an ethernet frame to the device.
|
||||||
|
///
|
||||||
|
/// # Args
|
||||||
|
/// * `frame` - The ethernet frame to transmit.
|
||||||
|
///
|
||||||
|
/// # Returns
|
||||||
|
/// The number of bytes successfully transmitted from the provided buffer.
|
||||||
|
pub fn write_frame(&mut self, frame: &[u8]) -> Result<usize, SpiBus::Error> {
|
||||||
|
let max_size = self.raw_socket.get_tx_free_size(&mut self.bus)? as usize;
|
||||||
|
|
||||||
|
let write_data = if frame.len() < max_size {
|
||||||
|
frame
|
||||||
|
} else {
|
||||||
|
&frame[..max_size]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Append the data to the write buffer after the current write pointer.
|
||||||
|
let write_pointer = self.raw_socket.get_tx_write_pointer(&mut self.bus)?;
|
||||||
|
|
||||||
|
// Write data into the buffer and update the writer pointer.
|
||||||
|
self.bus
|
||||||
|
.write_frame(self.raw_socket.tx_buffer(), write_pointer, write_data)?;
|
||||||
|
self.raw_socket.set_tx_write_pointer(
|
||||||
|
&mut self.bus,
|
||||||
|
write_pointer.wrapping_add(write_data.len() as u16),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Wait for the socket transmission to complete.
|
||||||
|
self.raw_socket
|
||||||
|
.reset_interrupt(&mut self.bus, register::socketn::Interrupt::SendOk)?;
|
||||||
|
|
||||||
|
self.raw_socket
|
||||||
|
.command(&mut self.bus, register::socketn::Command::Send)?;
|
||||||
|
|
||||||
|
while !self
|
||||||
|
.raw_socket
|
||||||
|
.has_interrupt(&mut self.bus, register::socketn::Interrupt::SendOk)?
|
||||||
|
{}
|
||||||
|
|
||||||
|
Ok(write_data.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -167,6 +167,7 @@ pub mod socketn {
|
||||||
Closed = 0b00,
|
Closed = 0b00,
|
||||||
Tcp = 0b01,
|
Tcp = 0b01,
|
||||||
Udp = 0b10,
|
Udp = 0b10,
|
||||||
|
MacRaw = 0b100,
|
||||||
}
|
}
|
||||||
pub const COMMAND: u16 = 0x01;
|
pub const COMMAND: u16 = 0x01;
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ use embedded_nal::Ipv4Addr;
|
||||||
use crate::bus::{Bus, FourWire, ThreeWire};
|
use crate::bus::{Bus, FourWire, ThreeWire};
|
||||||
use crate::device::Device;
|
use crate::device::Device;
|
||||||
use crate::host::{Dhcp, Host, Manual};
|
use crate::host::{Dhcp, Host, Manual};
|
||||||
|
use crate::raw_device::RawDevice;
|
||||||
use crate::register;
|
use crate::register;
|
||||||
use crate::{MacAddress, Mode};
|
use crate::{MacAddress, Mode};
|
||||||
|
|
||||||
|
|
@ -98,6 +99,15 @@ impl<SpiBus: Bus> UninitializedDevice<SpiBus> {
|
||||||
Ok(Device::new(self.bus, host))
|
Ok(Device::new(self.bus, host))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn initialize_macraw(
|
||||||
|
mut self,
|
||||||
|
mac: MacAddress,
|
||||||
|
) -> Result<RawDevice<SpiBus>, InitializeError<SpiBus::Error>> {
|
||||||
|
self.bus
|
||||||
|
.write_frame(register::COMMON, register::common::MAC, &mac.octets)?;
|
||||||
|
RawDevice::new(self.bus)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no-chip-version-assertion"))]
|
#[cfg(not(feature = "no-chip-version-assertion"))]
|
||||||
fn assert_chip_version(
|
fn assert_chip_version(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue