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 host;
|
||||
pub mod net;
|
||||
pub mod raw_device;
|
||||
pub mod register;
|
||||
mod socket;
|
||||
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,
|
||||
Tcp = 0b01,
|
||||
Udp = 0b10,
|
||||
MacRaw = 0b100,
|
||||
}
|
||||
pub const COMMAND: u16 = 0x01;
|
||||
#[repr(u8)]
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ use embedded_nal::Ipv4Addr;
|
|||
use crate::bus::{Bus, FourWire, ThreeWire};
|
||||
use crate::device::Device;
|
||||
use crate::host::{Dhcp, Host, Manual};
|
||||
use crate::raw_device::RawDevice;
|
||||
use crate::register;
|
||||
use crate::{MacAddress, Mode};
|
||||
|
||||
|
|
@ -98,6 +99,15 @@ impl<SpiBus: Bus> UninitializedDevice<SpiBus> {
|
|||
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"))]
|
||||
fn assert_chip_version(
|
||||
&mut self,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue