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:
René van Dorst 2023-08-24 00:40:01 +02:00
parent 5f5e3bcd18
commit 1d4d11ba25
2 changed files with 258 additions and 415 deletions

View File

@ -273,6 +273,15 @@ impl ETH_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]
pub fn crc_ok(&self) -> bool {
self.0 == Self::CRC32_OK
@ -329,4 +338,21 @@ mod tests {
println!("{:08x}", own_crc.0);
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);
}
}

View File

@ -61,13 +61,17 @@ const ETH_MIN_LEN: usize = 64;
/// Ethernet `Frame Check Sequence` length
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 WR_HEADER_LEN: usize = 2;
// P1 = 0x00, P2 = 0x01
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
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!
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);
}
@ -209,16 +219,18 @@ impl<SPI: SpiDevice> ADIN1110<SPI> {
// Turn around byte, TODO: Unknown that this is.
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);
let mut pkt_header = [0, 0];
let mut fsc = [0, 0, 0, 0];
let mut spi_op = [
Operation::Write(&tx_buf),
Operation::Read(&mut pkt_header),
Operation::Read(spi_packet),
Operation::Read(&mut fsc),
];
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.
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);
spi_hdr.set_control(true);
spi_hdr.set_write(true);
spi_hdr.set_addr(sr::TX);
packet
head_data
.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice())
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
if self.crc {
// Add CRC for header data
packet
.push(crc8(&packet[0..2]))
head_data
.push(crc8(&head_data[0..2]))
.map_err(|_| AdinError::PACKET_TOO_BIG)?;
}
// 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())
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
// Copy packet data to spi buffer.
packet
.extend_from_slice(frame)
.map_err(|_e| AdinError::PACKET_TOO_BIG)?;
let mut frame_fcs = ETH_FSC::new(frame);
// Pad data up to ETH_MIN_LEN - FCS_LEN
for _ in packet.len()..(ETH_MIN_LEN - FSC_LEN + header_len) {
let _ = packet.push(0x00);
// ADIN1110 MAC and PHY don´t accept ethernet packet smaller than 64 bytes.
// So padded the data minus the FCS, FCS is automatilly added to by the MAC.
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.
let crc = ETH_FSC::new(&packet[header_len..]);
let _ = packet.extend_from_slice(crc.hton_bytes().as_slice());
// Add ethernet FCS only over the ethernet packet.
// Only usefull when `CONFIG0`, `Transmit Frame Check Sequence Validation Enable` bit is enabled.
let _ = tail_data.extend_from_slice(frame_fcs.hton_bytes().as_slice());
let send_len =
u32::try_from(packet.len() - header_len + FRAME_HEADER_LEN).map_err(|_| AdinError::PACKET_TOO_BIG)?;
// len = frame_size + optional padding + 2 bytes Frame header
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!
while packet.len() & 0x3 != 0 {
let _ = packet.push(DONT_CARE_BYTE);
if spi_pad_len != send_len_orig {
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")]
defmt::trace!(
"TX: hdr {} [{}] {:02x} SIZE: {}",
header_len,
packet.len(),
&packet,
"TX: hdr {} [{}] {:02x}-{:02x}-{:02x} SIZE: {}",
head_data.len(),
frame.len(),
head_data.as_slice(),
frame,
tail_data.as_slice(),
send_len,
);
self.write_reg(sr::TX_FSIZE, send_len).await?;
// Spi packet must be half word / even length
if send_len & 1 != 0 {
let _ = packet.push(0x00);
}
let mut transaction = [
Operation::Write(head_data.as_slice()),
Operation::Write(frame),
Operation::Write(tail_data.as_slice()),
];
self.spi.write(&packet).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)
self.spi.transaction(&mut transaction).await.map_err(AdinError::Spi)
}
/// 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::flush(),
];
let mut spi = SpiMock::new(&expectations);
// Basic test init block
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);
// Write reg: 0x1FFF
@ -829,389 +847,31 @@ mod tests {
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]
async fn write_packet_to_fifo_arp_46bytes() {
async fn write_packet_to_fifo_minimal_with_crc() {
// Configure expectations
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
expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 66, 201]));
expectations.push(SpiTransaction::flush());
// Write TX reg.
// Header
spi_packet.extend_from_slice(&[160, 49, 143, 0, 0]).unwrap();
// SPI Header + optional CRC + Frame Header
expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0]));
// Packet data
spi_packet.extend_from_slice(&packet).unwrap();
// Packet padding up to 60 (ETH_MIN_LEN - FCS)
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();
let packet = [0xFF_u8; 60];
expectations.push(SpiTransaction::write_vec(packet.to_vec()));
// SPI HEADER Padding of u32
let spi_packet_len = spi_packet.len();
for _ in spi_packet_len..spi_packet_len.next_multiple_of(4) {
spi_packet.push(0x00).unwrap();
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(&[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());
let mut spi = SpiMock::new(&expectations);
@ -1226,4 +886,161 @@ mod tests {
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();
}
}