refactor write_fifo(), don´t copy frame data
Now this function uses frame data directly in the SPI transaction instead making a copy of it. Also fixing some length calculations and refactor/add tests to test this function.
This commit is contained in:
parent
5f5e3bcd18
commit
1d4d11ba25
2 changed files with 258 additions and 415 deletions
|
@ -273,6 +273,15 @@ impl ETH_FSC {
|
||||||
Self(fsc)
|
Self(fsc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn update(self, data: &[u8]) -> Self {
|
||||||
|
let fsc = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| {
|
||||||
|
let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte;
|
||||||
|
CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8)
|
||||||
|
}) ^ u32::MAX;
|
||||||
|
Self(fsc)
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn crc_ok(&self) -> bool {
|
pub fn crc_ok(&self) -> bool {
|
||||||
self.0 == Self::CRC32_OK
|
self.0 == Self::CRC32_OK
|
||||||
|
@ -329,4 +338,21 @@ mod tests {
|
||||||
println!("{:08x}", own_crc.0);
|
println!("{:08x}", own_crc.0);
|
||||||
assert_eq!(own_crc.0, ETH_FSC::CRC32_OK);
|
assert_eq!(own_crc.0, ETH_FSC::CRC32_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn crc32_update() {
|
||||||
|
let full_data = &[
|
||||||
|
0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0x00, 0xe0, 0x4c, 0x68, 0xee, 0xee, 0xdd, 0x06, 0x00, 0x01, 0x08, 0x00,
|
||||||
|
0x06, 0x04, 0x00, 0x02, 0x00, 0xe0, 0x4c, 0x68, 0x09, 0xde, 0xc0, 0xa8, 0x01, 0x02, 0x12, 0x34, 0x56, 0x78,
|
||||||
|
0x9a, 0xbc, 0xc0, 0xa8, 0x01, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x3d, 0x67, 0x7c,
|
||||||
|
];
|
||||||
|
|
||||||
|
let (part_a, part_b) = full_data.split_at(16);
|
||||||
|
let crc_partially = ETH_FSC::new(part_a).update(part_b);
|
||||||
|
|
||||||
|
let crc_full = ETH_FSC::new(full_data);
|
||||||
|
|
||||||
|
assert_eq!(crc_full.0, crc_partially.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,13 +61,17 @@ const ETH_MIN_LEN: usize = 64;
|
||||||
|
|
||||||
/// Ethernet `Frame Check Sequence` length
|
/// Ethernet `Frame Check Sequence` length
|
||||||
const FSC_LEN: usize = 4;
|
const FSC_LEN: usize = 4;
|
||||||
|
/// SPI Header, contains SPI action and register id.
|
||||||
|
const SPI_HEADER_LEN: usize = 2;
|
||||||
|
/// SPI Header CRC length
|
||||||
|
const SPI_HEADER_CRC_LEN: usize = 1;
|
||||||
|
/// Frame Header,
|
||||||
const FRAME_HEADER_LEN: usize = 2;
|
const FRAME_HEADER_LEN: usize = 2;
|
||||||
const WR_HEADER_LEN: usize = 2;
|
|
||||||
|
|
||||||
// P1 = 0x00, P2 = 0x01
|
// P1 = 0x00, P2 = 0x01
|
||||||
const PORT_ID_BYTE: u8 = 0x00;
|
const PORT_ID_BYTE: u8 = 0x00;
|
||||||
|
|
||||||
pub type Packet = Vec<u8, { MTU + FSC_LEN + WR_HEADER_LEN }>;
|
pub type Packet = Vec<u8, { SPI_HEADER_LEN + FRAME_HEADER_LEN + MTU + FSC_LEN + 1 + 4 }>;
|
||||||
|
|
||||||
/// Type alias for the embassy-net driver for ADIN1110
|
/// Type alias for the embassy-net driver for ADIN1110
|
||||||
pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>;
|
pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>;
|
||||||
|
@ -192,7 +196,13 @@ impl<SPI: SpiDevice> ADIN1110<SPI> {
|
||||||
// Packet read of write to the MAC packet buffer must be a multipul of 4!
|
// Packet read of write to the MAC packet buffer must be a multipul of 4!
|
||||||
let read_size = packet_size.next_multiple_of(4);
|
let read_size = packet_size.next_multiple_of(4);
|
||||||
|
|
||||||
if packet_size < (FRAME_HEADER_LEN + FSC_LEN) || read_size > packet.len() {
|
if packet_size < (SPI_HEADER_LEN + FSC_LEN) {
|
||||||
|
return Err(AdinError::PACKET_TOO_SMALL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if read_size > packet.len() {
|
||||||
|
#[cfg(feature = "defmt")]
|
||||||
|
defmt::trace!("MAX: {} WANT: {}", packet.len(), read_size);
|
||||||
return Err(AdinError::PACKET_TOO_BIG);
|
return Err(AdinError::PACKET_TOO_BIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,16 +219,18 @@ impl<SPI: SpiDevice> ADIN1110<SPI> {
|
||||||
// Turn around byte, TODO: Unknown that this is.
|
// Turn around byte, TODO: Unknown that this is.
|
||||||
let _ = tx_buf.push(TURN_AROUND_BYTE);
|
let _ = tx_buf.push(TURN_AROUND_BYTE);
|
||||||
|
|
||||||
let spi_packet = &mut packet[0..read_size as usize];
|
let spi_packet = &mut packet[0..read_size];
|
||||||
|
|
||||||
assert_eq!(spi_packet.len() & 0x03, 0x00);
|
assert_eq!(spi_packet.len() & 0x03, 0x00);
|
||||||
|
|
||||||
let mut pkt_header = [0, 0];
|
let mut pkt_header = [0, 0];
|
||||||
|
let mut fsc = [0, 0, 0, 0];
|
||||||
|
|
||||||
let mut spi_op = [
|
let mut spi_op = [
|
||||||
Operation::Write(&tx_buf),
|
Operation::Write(&tx_buf),
|
||||||
Operation::Read(&mut pkt_header),
|
Operation::Read(&mut pkt_header),
|
||||||
Operation::Read(spi_packet),
|
Operation::Read(spi_packet),
|
||||||
|
Operation::Read(&mut fsc),
|
||||||
];
|
];
|
||||||
|
|
||||||
self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?;
|
self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?;
|
||||||
|
@ -228,80 +240,86 @@ impl<SPI: SpiDevice> ADIN1110<SPI> {
|
||||||
|
|
||||||
/// Write to fifo ethernet packet memory send over the wire.
|
/// Write to fifo ethernet packet memory send over the wire.
|
||||||
pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> {
|
pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> {
|
||||||
let header_len = self.header_write_len();
|
const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + FRAME_HEADER_LEN;
|
||||||
|
const TAIL_LEN: usize = ETH_MIN_LEN - FSC_LEN + FSC_LEN + 1;
|
||||||
|
|
||||||
let mut packet = Packet::new();
|
if frame.len() < (6 + 6 + 2) {
|
||||||
|
return Err(AdinError::PACKET_TOO_SMALL);
|
||||||
|
}
|
||||||
|
if frame.len() > (MAX_BUFF - FRAME_HEADER_LEN) {
|
||||||
|
return Err(AdinError::PACKET_TOO_BIG);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SPI HEADER + [OPTIONAL SPI CRC] + FRAME HEADER
|
||||||
|
let mut head_data = Vec::<u8, HEAD_LEN>::new();
|
||||||
|
// [OPTIONAL PAD DATA] + FCS + [OPTINAL BYTES MAKE SPI FRAME EVEN]
|
||||||
|
let mut tail_data = Vec::<u8, TAIL_LEN>::new();
|
||||||
|
|
||||||
let mut spi_hdr = SpiHeader(0);
|
let mut spi_hdr = SpiHeader(0);
|
||||||
spi_hdr.set_control(true);
|
spi_hdr.set_control(true);
|
||||||
spi_hdr.set_write(true);
|
spi_hdr.set_write(true);
|
||||||
spi_hdr.set_addr(sr::TX);
|
spi_hdr.set_addr(sr::TX);
|
||||||
|
|
||||||
packet
|
head_data
|
||||||
.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice())
|
.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice())
|
||||||
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
|
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
|
||||||
|
|
||||||
if self.crc {
|
if self.crc {
|
||||||
// Add CRC for header data
|
// Add CRC for header data
|
||||||
packet
|
head_data
|
||||||
.push(crc8(&packet[0..2]))
|
.push(crc8(&head_data[0..2]))
|
||||||
.map_err(|_| AdinError::PACKET_TOO_BIG)?;
|
.map_err(|_| AdinError::PACKET_TOO_BIG)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add port number, ADIN1110 its fixed to zero/P1, but for ADIN2111 has two ports.
|
// Add port number, ADIN1110 its fixed to zero/P1, but for ADIN2111 has two ports.
|
||||||
packet
|
head_data
|
||||||
.extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice())
|
.extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice())
|
||||||
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
|
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
|
||||||
|
|
||||||
// Copy packet data to spi buffer.
|
let mut frame_fcs = ETH_FSC::new(frame);
|
||||||
packet
|
|
||||||
.extend_from_slice(frame)
|
|
||||||
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
|
|
||||||
|
|
||||||
// Pad data up to ETH_MIN_LEN - FCS_LEN
|
// ADIN1110 MAC and PHY don´t accept ethernet packet smaller than 64 bytes.
|
||||||
for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN + header_len) {
|
// So padded the data minus the FCS, FCS is automatilly added to by the MAC.
|
||||||
let _ = packet.push(0x00);
|
if let Some(pad_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(frame.len()) {
|
||||||
|
let _ = tail_data.resize(pad_len, 0x00);
|
||||||
|
frame_fcs = frame_fcs.update(&tail_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add ethernet FCS only over the ethernet packet.
|
// Add ethernet FCS only over the ethernet packet.
|
||||||
let crc = ETH_FSC::new(&packet[header_len..]);
|
// Only usefull when `CONFIG0`, `Transmit Frame Check Sequence Validation Enable` bit is enabled.
|
||||||
let _ = packet.extend_from_slice(crc.hton_bytes().as_slice());
|
let _ = tail_data.extend_from_slice(frame_fcs.hton_bytes().as_slice());
|
||||||
|
|
||||||
let send_len =
|
// len = frame_size + optional padding + 2 bytes Frame header
|
||||||
u32::try_from(packet.len() - header_len + FRAME_HEADER_LEN).map_err(|_| AdinError::PACKET_TOO_BIG)?;
|
let send_len_orig = frame.len() + tail_data.len() + FRAME_HEADER_LEN;
|
||||||
|
let spi_pad_len = send_len_orig.next_multiple_of(4);
|
||||||
|
let send_len = u32::try_from(send_len_orig).map_err(|_| AdinError::PACKET_TOO_BIG)?;
|
||||||
|
|
||||||
// Packet read of write to the MAC packet buffer must be a multipul of 4 bytes!
|
// Packet read of write to the MAC packet buffer must be a multipul of 4 bytes!
|
||||||
while packet.len() & 0x3 != 0 {
|
if spi_pad_len != send_len_orig {
|
||||||
let _ = packet.push(DONT_CARE_BYTE);
|
let spi_pad_len = spi_pad_len - send_len_orig;
|
||||||
|
let _ = tail_data.extend_from_slice(&[DONT_CARE_BYTE, DONT_CARE_BYTE, DONT_CARE_BYTE][..spi_pad_len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "defmt")]
|
#[cfg(feature = "defmt")]
|
||||||
defmt::trace!(
|
defmt::trace!(
|
||||||
"TX: hdr {} [{}] {:02x} SIZE: {}",
|
"TX: hdr {} [{}] {:02x}-{:02x}-{:02x} SIZE: {}",
|
||||||
header_len,
|
head_data.len(),
|
||||||
packet.len(),
|
frame.len(),
|
||||||
&packet,
|
head_data.as_slice(),
|
||||||
|
frame,
|
||||||
|
tail_data.as_slice(),
|
||||||
send_len,
|
send_len,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.write_reg(sr::TX_FSIZE, send_len).await?;
|
self.write_reg(sr::TX_FSIZE, send_len).await?;
|
||||||
|
|
||||||
// Spi packet must be half word / even length
|
let mut transaction = [
|
||||||
if send_len & 1 != 0 {
|
Operation::Write(head_data.as_slice()),
|
||||||
let _ = packet.push(0x00);
|
Operation::Write(frame),
|
||||||
}
|
Operation::Write(tail_data.as_slice()),
|
||||||
|
];
|
||||||
|
|
||||||
self.spi.write(&packet).await.map_err(AdinError::Spi)
|
self.spi.transaction(&mut transaction).await.map_err(AdinError::Spi)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn header_write_len(&self) -> usize {
|
|
||||||
// u16 + [CRC] + PORT
|
|
||||||
WR_HEADER_LEN + FRAME_HEADER_LEN + usize::from(self.crc)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn header_len_read(&self) -> usize {
|
|
||||||
// u16 + [CRC] + u8
|
|
||||||
WR_HEADER_LEN + 1 + usize::from(self.crc)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Programs the mac address in the mac filters.
|
/// Programs the mac address in the mac filters.
|
||||||
|
@ -815,12 +833,12 @@ mod tests {
|
||||||
SpiTransaction::write_vec(vec![0xA0, 0x09, 39, 0x12, 0x34, 0x56, 0x78, 28]),
|
SpiTransaction::write_vec(vec![0xA0, 0x09, 39, 0x12, 0x34, 0x56, 0x78, 28]),
|
||||||
SpiTransaction::flush(),
|
SpiTransaction::flush(),
|
||||||
];
|
];
|
||||||
let mut spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
|
// Basic test init block
|
||||||
|
let mut spi = SpiMock::new(&expectations);
|
||||||
let cs = CsPinMock::default();
|
let cs = CsPinMock::default();
|
||||||
let delay = MockDelay {};
|
let delay = MockDelay {};
|
||||||
let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
|
let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
|
||||||
|
|
||||||
let mut spe = ADIN1110::new(spi_dev, true);
|
let mut spe = ADIN1110::new(spi_dev, true);
|
||||||
|
|
||||||
// Write reg: 0x1FFF
|
// Write reg: 0x1FFF
|
||||||
|
@ -829,389 +847,31 @@ mod tests {
|
||||||
spi.done();
|
spi.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn write_packet_to_fifo_less_64b_with_crc() {
|
|
||||||
// // Configure expectations
|
|
||||||
// let mut expectations = vec![
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x30),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(136),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Frame Size
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(66),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(201),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x31),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Port
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(PORT_ID_BYTE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let mut packet = Packet::new();
|
|
||||||
// packet.resize(ETH_MIN_LEN, 0).unwrap();
|
|
||||||
|
|
||||||
// for &byte in &packet[4..] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // padding
|
|
||||||
// for _ in packet.len()..65 {
|
|
||||||
// expectations.push(SpiTransaction::send(0x00));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fcs
|
|
||||||
// for &byte in &[8, 137, 18, 4] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
// let cs = CsPinMock {};
|
|
||||||
// let mut spe = Adin1110::new(spi, cs, true);
|
|
||||||
|
|
||||||
// assert!(spe.write_fifo(&mut packet).is_ok());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn write_packet_to_fifo_less_64b_no_crc() {
|
|
||||||
// // Configure expectations
|
|
||||||
// let mut expectations = vec![
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x30),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Frame Size
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(66),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x31),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Port
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(PORT_ID_BYTE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let mut packet = Packet::new();
|
|
||||||
// packet.resize(ETH_MIN_LEN, 0).unwrap();
|
|
||||||
|
|
||||||
// for &byte in &packet[4..] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // padding
|
|
||||||
// for _ in packet.len() as u32..ETH_MIN_LEN {
|
|
||||||
// expectations.push(SpiTransaction::send(0x00));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fcs
|
|
||||||
// for &byte in &[8, 137, 18, 4] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
// let cs = CsPinMock {};
|
|
||||||
// let mut spe = Adin1110::new(spi, cs, false);
|
|
||||||
|
|
||||||
// assert!(spe.write_fifo(&mut packet).is_ok());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn write_packet_to_fifo_1500b() {
|
|
||||||
// // Configure expectations
|
|
||||||
// let mut expectations = vec![
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x30),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Frame Size
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x05),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0xDE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x31),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Port
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(PORT_ID_BYTE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let mut packet = Packet::new();
|
|
||||||
// packet.resize(1500, 0).unwrap();
|
|
||||||
|
|
||||||
// for &byte in &packet[4..] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fcs
|
|
||||||
// for &byte in &[212, 114, 18, 50] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
// let cs = CsPinMock {};
|
|
||||||
// let mut spe = Adin1110::new(spi, cs, false);
|
|
||||||
|
|
||||||
// assert!(spe.write_fifo(&mut packet).is_ok());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn write_packet_to_fifo_65b() {
|
|
||||||
// // Configure expectations
|
|
||||||
// let mut expectations = vec![
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x30),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Frame Size
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(67),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x31),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Port
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(PORT_ID_BYTE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let mut packet = Packet::new();
|
|
||||||
// packet.resize(65, 0).unwrap();
|
|
||||||
|
|
||||||
// for &byte in &packet[4..] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // padding
|
|
||||||
// for _ in packet.len()..ETH_MIN_LEN {
|
|
||||||
// expectations.push(SpiTransaction::send(0x00));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fcs
|
|
||||||
// for &byte in &[54, 117, 221, 220] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// let spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
// let cs = CsPinMock {};
|
|
||||||
// let mut spe = Adin1110::new(spi, cs, false);
|
|
||||||
|
|
||||||
// assert!(spe.write_fifo(&mut packet).is_ok());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn write_packet_to_fifo_66b() {
|
|
||||||
// // Configure expectations
|
|
||||||
// let mut expectations = vec![
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x30),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Frame Size
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(68),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x31),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Port
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(PORT_ID_BYTE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let mut packet = Packet::new();
|
|
||||||
// packet.resize(66, 0).unwrap();
|
|
||||||
|
|
||||||
// for &byte in &packet[4..] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // padding
|
|
||||||
// for _ in packet.len()..ETH_MIN_LEN {
|
|
||||||
// expectations.push(SpiTransaction::send(0x00));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fcs
|
|
||||||
// for &byte in &[97, 167, 100, 29] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
// let spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
// let cs = CsPinMock {};
|
|
||||||
// let mut spe = Adin1110::new(spi, cs, false);
|
|
||||||
|
|
||||||
// assert!(spe.write_fifo(&mut packet).is_ok());
|
|
||||||
// }
|
|
||||||
|
|
||||||
// #[test]
|
|
||||||
// fn write_packet_to_fifo_67b() {
|
|
||||||
// // Configure expectations
|
|
||||||
// let mut expectations = vec![
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x30),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Frame Size
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(69),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // HEADER
|
|
||||||
// SpiTransaction::send(0xA0),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(0x31),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// // Port
|
|
||||||
// SpiTransaction::send(0x00),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// SpiTransaction::send(PORT_ID_BYTE),
|
|
||||||
// SpiTransaction::read(DONT_CARE_BYTE),
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// let mut packet = Packet::new();
|
|
||||||
// packet.resize(67, 0).unwrap();
|
|
||||||
|
|
||||||
// for &byte in &packet[4..] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // padding
|
|
||||||
// for _ in packet.len()..ETH_MIN_LEN {
|
|
||||||
// expectations.push(SpiTransaction::send(0x00));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // fcs
|
|
||||||
// for &byte in &[228, 218, 170, 232] {
|
|
||||||
// expectations.push(SpiTransaction::send(byte));
|
|
||||||
// expectations.push(SpiTransaction::read(DONT_CARE_BYTE));
|
|
||||||
// }
|
|
||||||
// let spi = SpiMock::new(&expectations);
|
|
||||||
|
|
||||||
// let cs = CsPinMock {};
|
|
||||||
// let mut spe = Adin1110::new(spi, cs, false);
|
|
||||||
|
|
||||||
// assert!(spe.write_fifo(&mut packet).is_ok());
|
|
||||||
// }
|
|
||||||
|
|
||||||
#[futures_test::test]
|
#[futures_test::test]
|
||||||
async fn write_packet_to_fifo_arp_46bytes() {
|
async fn write_packet_to_fifo_minimal_with_crc() {
|
||||||
// Configure expectations
|
// Configure expectations
|
||||||
let mut expectations = vec![];
|
let mut expectations = vec![];
|
||||||
|
|
||||||
let mut packet = Packet::new();
|
|
||||||
//arp packet;
|
|
||||||
packet
|
|
||||||
.extend_from_slice(&[
|
|
||||||
34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120,
|
|
||||||
154, 188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1,
|
|
||||||
])
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let mut spi_packet = Packet::new();
|
|
||||||
|
|
||||||
// Write TX_SIZE reg
|
// Write TX_SIZE reg
|
||||||
expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201]));
|
expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201]));
|
||||||
expectations.push(SpiTransaction::flush());
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
// Write TX reg.
|
// Write TX reg.
|
||||||
// Header
|
// SPI Header + optional CRC + Frame Header
|
||||||
spi_packet.extend_from_slice(&[160, 49, 143, 0, 0]).unwrap();
|
expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0]));
|
||||||
// Packet data
|
// Packet data
|
||||||
spi_packet.extend_from_slice(&packet).unwrap();
|
let packet = [0xFF_u8; 60];
|
||||||
// Packet padding up to 60 (ETH_MIN_LEN - FCS)
|
expectations.push(SpiTransaction::write_vec(packet.to_vec()));
|
||||||
for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN) {
|
|
||||||
spi_packet.push(0x00).unwrap();
|
|
||||||
}
|
|
||||||
// Packet FCS
|
|
||||||
spi_packet.extend_from_slice(&[147, 149, 213, 68]).unwrap();
|
|
||||||
|
|
||||||
// SPI HEADER Padding of u32
|
let mut tail = std::vec::Vec::<u8>::with_capacity(100);
|
||||||
let spi_packet_len = spi_packet.len();
|
// Padding
|
||||||
for _ in spi_packet_len..spi_packet_len.next_multiple_of(4) {
|
if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) {
|
||||||
spi_packet.push(0x00).unwrap();
|
tail.resize(padding_len, 0x00);
|
||||||
}
|
}
|
||||||
|
// Packet FCS + optinal padding
|
||||||
|
tail.extend_from_slice(&[77, 241, 140, 244, DONT_CARE_BYTE, DONT_CARE_BYTE]);
|
||||||
|
|
||||||
expectations.push(SpiTransaction::write_vec(spi_packet.to_vec()));
|
expectations.push(SpiTransaction::write_vec(tail));
|
||||||
expectations.push(SpiTransaction::flush());
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
let mut spi = SpiMock::new(&expectations);
|
let mut spi = SpiMock::new(&expectations);
|
||||||
|
@ -1226,4 +886,161 @@ mod tests {
|
||||||
|
|
||||||
spi.done();
|
spi.done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[futures_test::test]
|
||||||
|
async fn write_packet_to_fifo_max_mtu_with_crc() {
|
||||||
|
assert_eq!(MTU, 1514);
|
||||||
|
// Configure expectations
|
||||||
|
let mut expectations = vec![];
|
||||||
|
|
||||||
|
// Write TX_SIZE reg
|
||||||
|
expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 5, 240, 159]));
|
||||||
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
|
// Write TX reg.
|
||||||
|
// SPI Header + optional CRC + Frame Header
|
||||||
|
expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0]));
|
||||||
|
// Packet data
|
||||||
|
let packet = [0xAA_u8; MTU];
|
||||||
|
expectations.push(SpiTransaction::write_vec(packet.to_vec()));
|
||||||
|
|
||||||
|
let mut tail = std::vec::Vec::<u8>::with_capacity(100);
|
||||||
|
// Padding
|
||||||
|
if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) {
|
||||||
|
tail.resize(padding_len, 0x00);
|
||||||
|
}
|
||||||
|
// Packet FCS + optinal padding
|
||||||
|
tail.extend_from_slice(&[49, 196, 205, 160]);
|
||||||
|
|
||||||
|
expectations.push(SpiTransaction::write_vec(tail));
|
||||||
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
|
let mut spi = SpiMock::new(&expectations);
|
||||||
|
|
||||||
|
let cs = CsPinMock::default();
|
||||||
|
let delay = MockDelay {};
|
||||||
|
let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
|
||||||
|
|
||||||
|
let mut spe = ADIN1110::new(spi_dev, true);
|
||||||
|
|
||||||
|
assert!(spe.write_fifo(&packet).await.is_ok());
|
||||||
|
|
||||||
|
spi.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[futures_test::test]
|
||||||
|
async fn write_packet_to_fifo_invalid_lengths() {
|
||||||
|
assert_eq!(MTU, 1514);
|
||||||
|
|
||||||
|
// Configure expectations
|
||||||
|
let expectations = vec![];
|
||||||
|
|
||||||
|
// Max packet size = MAX_BUFF - FRAME_HEADER_LEN
|
||||||
|
let packet = [0xAA_u8; MAX_BUFF - FRAME_HEADER_LEN + 1];
|
||||||
|
|
||||||
|
let mut spi = SpiMock::new(&expectations);
|
||||||
|
|
||||||
|
let cs = CsPinMock::default();
|
||||||
|
let delay = MockDelay {};
|
||||||
|
let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
|
||||||
|
|
||||||
|
let mut spe = ADIN1110::new(spi_dev, true);
|
||||||
|
|
||||||
|
// minimal
|
||||||
|
assert!(matches!(
|
||||||
|
spe.write_fifo(&packet[0..(6 + 6 + 2 - 1)]).await,
|
||||||
|
Err(AdinError::PACKET_TOO_SMALL)
|
||||||
|
));
|
||||||
|
|
||||||
|
// max + 1
|
||||||
|
assert!(matches!(spe.write_fifo(&packet).await, Err(AdinError::PACKET_TOO_BIG)));
|
||||||
|
|
||||||
|
spi.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[futures_test::test]
|
||||||
|
async fn write_packet_to_fifo_arp_46bytes_with_crc() {
|
||||||
|
// Configure expectations
|
||||||
|
let mut expectations = vec![];
|
||||||
|
|
||||||
|
// Write TX_SIZE reg
|
||||||
|
expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201]));
|
||||||
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
|
// Write TX reg.
|
||||||
|
// Header
|
||||||
|
expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0]));
|
||||||
|
// Packet data
|
||||||
|
let packet = [
|
||||||
|
34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120, 154,
|
||||||
|
188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1,
|
||||||
|
];
|
||||||
|
expectations.push(SpiTransaction::write_vec(packet.to_vec()));
|
||||||
|
|
||||||
|
let mut tail = std::vec::Vec::<u8>::with_capacity(100);
|
||||||
|
// Padding
|
||||||
|
if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) {
|
||||||
|
tail.resize(padding_len, 0x00);
|
||||||
|
}
|
||||||
|
// Packet FCS + optinal padding
|
||||||
|
tail.extend_from_slice(&[147, 149, 213, 68, DONT_CARE_BYTE, DONT_CARE_BYTE]);
|
||||||
|
|
||||||
|
expectations.push(SpiTransaction::write_vec(tail));
|
||||||
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
|
let mut spi = SpiMock::new(&expectations);
|
||||||
|
|
||||||
|
let cs = CsPinMock::default();
|
||||||
|
let delay = MockDelay {};
|
||||||
|
let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
|
||||||
|
|
||||||
|
let mut spe = ADIN1110::new(spi_dev, true);
|
||||||
|
|
||||||
|
assert!(spe.write_fifo(&packet).await.is_ok());
|
||||||
|
|
||||||
|
spi.done();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[futures_test::test]
|
||||||
|
async fn write_packet_to_fifo_arp_46bytes_without_crc() {
|
||||||
|
// Configure expectations
|
||||||
|
let mut expectations = vec![];
|
||||||
|
|
||||||
|
// Write TX_SIZE reg
|
||||||
|
expectations.push(SpiTransaction::write_vec(vec![160, 48, 0, 0, 0, 66]));
|
||||||
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
|
// Write TX reg.
|
||||||
|
// SPI Header + Frame Header
|
||||||
|
expectations.push(SpiTransaction::write_vec(vec![160, 49, 0, 0]));
|
||||||
|
// Packet data
|
||||||
|
let packet = [
|
||||||
|
34, 51, 68, 85, 102, 119, 18, 52, 86, 120, 154, 188, 8, 6, 0, 1, 8, 0, 6, 4, 0, 2, 18, 52, 86, 120, 154,
|
||||||
|
188, 192, 168, 16, 4, 34, 51, 68, 85, 102, 119, 192, 168, 16, 1,
|
||||||
|
];
|
||||||
|
expectations.push(SpiTransaction::write_vec(packet.to_vec()));
|
||||||
|
|
||||||
|
let mut tail = std::vec::Vec::<u8>::with_capacity(100);
|
||||||
|
// Padding
|
||||||
|
if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) {
|
||||||
|
tail.resize(padding_len, 0x00);
|
||||||
|
}
|
||||||
|
// Packet FCS + optinal padding
|
||||||
|
tail.extend_from_slice(&[147, 149, 213, 68, DONT_CARE_BYTE, DONT_CARE_BYTE]);
|
||||||
|
|
||||||
|
expectations.push(SpiTransaction::write_vec(tail));
|
||||||
|
expectations.push(SpiTransaction::flush());
|
||||||
|
|
||||||
|
let mut spi = SpiMock::new(&expectations);
|
||||||
|
|
||||||
|
let cs = CsPinMock::default();
|
||||||
|
let delay = MockDelay {};
|
||||||
|
let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
|
||||||
|
|
||||||
|
let mut spe = ADIN1110::new(spi_dev, false);
|
||||||
|
|
||||||
|
assert!(spe.write_fifo(&packet).await.is_ok());
|
||||||
|
|
||||||
|
spi.done();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue