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)
|
||||
}
|
||||
|
||||
#[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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue