aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-net-adin1110/src/lib.rs187
1 files changed, 165 insertions, 22 deletions
diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs
index c0a9b44ee..8e5fef701 100644
--- a/embassy-net-adin1110/src/lib.rs
+++ b/embassy-net-adin1110/src/lib.rs
@@ -65,14 +65,16 @@ const FSC_LEN: usize = 4;
65const SPI_HEADER_LEN: usize = 2; 65const SPI_HEADER_LEN: usize = 2;
66/// SPI Header CRC length 66/// SPI Header CRC length
67const SPI_HEADER_CRC_LEN: usize = 1; 67const SPI_HEADER_CRC_LEN: usize = 1;
68/// Frame Header, 68/// SPI Header Trun Around length
69const SPI_HEADER_TA_LEN: usize = 1;
70/// Frame Header length
69const FRAME_HEADER_LEN: usize = 2; 71const FRAME_HEADER_LEN: usize = 2;
72/// Space for last bytes to create multipule 4 bytes on the end of a FIFO read/write.
73const SPI_SPACE_MULTIPULE: usize = 3;
70 74
71// P1 = 0x00, P2 = 0x01 75// P1 = 0x00, P2 = 0x01
72const PORT_ID_BYTE: u8 = 0x00; 76const PORT_ID_BYTE: u8 = 0x00;
73 77
74pub type Packet = Vec<u8, { SPI_HEADER_LEN + FRAME_HEADER_LEN + MTU + FSC_LEN + 1 + 4 }>;
75
76/// Type alias for the embassy-net driver for ADIN1110 78/// Type alias for the embassy-net driver for ADIN1110
77pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>; 79pub type Device<'d> = embassy_net_driver_channel::Device<'d, MTU>;
78 80
@@ -187,22 +189,24 @@ impl<SPI: SpiDevice> ADIN1110<SPI> {
187 } 189 }
188 190
189 /// Read out fifo ethernet packet memory received via the wire. 191 /// Read out fifo ethernet packet memory received via the wire.
190 pub async fn read_fifo(&mut self, packet: &mut [u8]) -> AEResult<usize, SPI::Error> { 192 pub async fn read_fifo(&mut self, frame: &mut [u8]) -> AEResult<usize, SPI::Error> {
191 let mut tx_buf = Vec::<u8, 16>::new(); 193 const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + SPI_HEADER_TA_LEN;
194 const TAIL_LEN: usize = FSC_LEN + SPI_SPACE_MULTIPULE;
192 195
193 // Size of the frame, also includes the appednded header. 196 let mut tx_buf = Vec::<u8, HEAD_LEN>::new();
194 let packet_size = self.read_reg(sr::RX_FSIZE).await? as usize;
195 197
196 // Packet read of write to the MAC packet buffer must be a multipul of 4! 198 // Size of the frame, also includes the `frame header` and `FSC`.
197 let read_size = packet_size.next_multiple_of(4); 199 let fifo_frame_size = self.read_reg(sr::RX_FSIZE).await? as usize;
198 200
199 if packet_size < (SPI_HEADER_LEN + FSC_LEN) { 201 if fifo_frame_size < ETH_MIN_LEN + FRAME_HEADER_LEN {
200 return Err(AdinError::PACKET_TOO_SMALL); 202 return Err(AdinError::PACKET_TOO_SMALL);
201 } 203 }
202 204
203 if read_size > packet.len() { 205 let packet_size = fifo_frame_size - FRAME_HEADER_LEN - FSC_LEN;
206
207 if packet_size > frame.len() {
204 #[cfg(feature = "defmt")] 208 #[cfg(feature = "defmt")]
205 defmt::trace!("MAX: {} WANT: {}", packet.len(), read_size); 209 defmt::trace!("MAX: {} WANT: {}", frame.len(), packet_size);
206 return Err(AdinError::PACKET_TOO_BIG); 210 return Err(AdinError::PACKET_TOO_BIG);
207 } 211 }
208 212
@@ -219,29 +223,28 @@ impl<SPI: SpiDevice> ADIN1110<SPI> {
219 // Turn around byte, TODO: Unknown that this is. 223 // Turn around byte, TODO: Unknown that this is.
220 let _ = tx_buf.push(TURN_AROUND_BYTE); 224 let _ = tx_buf.push(TURN_AROUND_BYTE);
221 225
222 let spi_packet = &mut packet[0..read_size]; 226 let mut frame_header = [0, 0];
223 227 let mut fsc_and_extra = [0; TAIL_LEN];
224 assert_eq!(spi_packet.len() & 0x03, 0x00);
225 228
226 let mut pkt_header = [0, 0]; 229 // Packet read of write to the MAC packet buffer must be a multipul of 4!
227 let mut fsc = [0, 0, 0, 0]; 230 let tail_size = (fifo_frame_size & 0x03) + FSC_LEN;
228 231
229 let mut spi_op = [ 232 let mut spi_op = [
230 Operation::Write(&tx_buf), 233 Operation::Write(&tx_buf),
231 Operation::Read(&mut pkt_header), 234 Operation::Read(&mut frame_header),
232 Operation::Read(spi_packet), 235 Operation::Read(&mut frame[0..packet_size]),
233 Operation::Read(&mut fsc), 236 Operation::Read(&mut fsc_and_extra[0..tail_size]),
234 ]; 237 ];
235 238
236 self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; 239 self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?;
237 240
238 Ok(packet_size as usize) 241 Ok(packet_size)
239 } 242 }
240 243
241 /// Write to fifo ethernet packet memory send over the wire. 244 /// Write to fifo ethernet packet memory send over the wire.
242 pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> { 245 pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> {
243 const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + FRAME_HEADER_LEN; 246 const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + FRAME_HEADER_LEN;
244 const TAIL_LEN: usize = ETH_MIN_LEN - FSC_LEN + FSC_LEN + 1; 247 const TAIL_LEN: usize = ETH_MIN_LEN - FSC_LEN + FSC_LEN + SPI_SPACE_MULTIPULE;
245 248
246 if frame.len() < (6 + 6 + 2) { 249 if frame.len() < (6 + 6 + 2) {
247 return Err(AdinError::PACKET_TOO_SMALL); 250 return Err(AdinError::PACKET_TOO_SMALL);
@@ -1043,4 +1046,144 @@ mod tests {
1043 1046
1044 spi.done(); 1047 spi.done();
1045 } 1048 }
1049
1050 #[futures_test::test]
1051 async fn read_packet_from_fifo_packet_too_big_for_frame_buffer() {
1052 // Configure expectations
1053 let mut expectations = vec![];
1054
1055 // Read RX_SIZE reg
1056 let rx_size: u32 = u32::try_from(ETH_MIN_LEN + FRAME_HEADER_LEN + FSC_LEN).unwrap();
1057 let mut rx_size_vec = rx_size.to_be_bytes().to_vec();
1058 rx_size_vec.push(crc8(&rx_size_vec));
1059
1060 expectations.push(SpiTransaction::write_vec(vec![128, 144, 79, TURN_AROUND_BYTE]));
1061 expectations.push(SpiTransaction::read_vec(rx_size_vec));
1062 expectations.push(SpiTransaction::flush());
1063
1064 let mut spi = SpiMock::new(&expectations);
1065
1066 let cs = CsPinMock::default();
1067 let delay = MockDelay {};
1068 let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
1069
1070 let mut spe = ADIN1110::new(spi_dev, true);
1071
1072 let mut frame = [0; MTU];
1073
1074 let ret = spe.read_fifo(&mut frame[0..ETH_MIN_LEN - 1]).await;
1075 assert!(matches!(dbg!(ret), Err(AdinError::PACKET_TOO_BIG)));
1076
1077 spi.done();
1078 }
1079
1080 #[futures_test::test]
1081 async fn read_packet_from_fifo_packet_too_small() {
1082 // Configure expectations
1083 let mut expectations = vec![];
1084
1085 // This value is importen for this test!
1086 assert_eq!(ETH_MIN_LEN, 64);
1087
1088 // Packet data, size = `ETH_MIN_LEN` - `FSC_LEN` - 1
1089 let packet = [0; 64 - FSC_LEN - 1];
1090
1091 // Read RX_SIZE reg
1092 let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FSC_LEN).unwrap();
1093 let mut rx_size_vec = rx_size.to_be_bytes().to_vec();
1094 rx_size_vec.push(crc8(&rx_size_vec));
1095
1096 expectations.push(SpiTransaction::write_vec(vec![128, 144, 79, TURN_AROUND_BYTE]));
1097 expectations.push(SpiTransaction::read_vec(rx_size_vec));
1098 expectations.push(SpiTransaction::flush());
1099
1100 let mut spi = SpiMock::new(&expectations);
1101
1102 let cs = CsPinMock::default();
1103 let delay = MockDelay {};
1104 let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
1105
1106 let mut spe = ADIN1110::new(spi_dev, true);
1107
1108 let mut frame = [0; MTU];
1109
1110 let ret = spe.read_fifo(&mut frame).await;
1111 assert!(matches!(dbg!(ret), Err(AdinError::PACKET_TOO_SMALL)));
1112
1113 spi.done();
1114 }
1115
1116 #[futures_test::test]
1117 async fn read_packet_to_fifo_check_spi_read_multipule_of_u32_valid_lengths() {
1118 let packet_buffer = [0; MTU];
1119 let mut frame = [0; MTU];
1120 let mut expectations = std::vec::Vec::with_capacity(16);
1121
1122 // Packet data, size = `ETH_MIN_LEN` - `FSC_LEN`
1123 for packet_size in [60, 61, 62, 63, 64, MTU - 4, MTU - 3, MTU - 2, MTU - 1, MTU] {
1124 for crc_en in [false, true] {
1125 expectations.clear();
1126
1127 let packet = &packet_buffer[0..packet_size];
1128
1129 // Read RX_SIZE reg
1130 let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FSC_LEN).unwrap();
1131 let mut rx_size_vec = rx_size.to_be_bytes().to_vec();
1132 if crc_en {
1133 rx_size_vec.push(crc8(&rx_size_vec));
1134 }
1135
1136 // SPI Header with CRC
1137 let mut rx_fsize = vec![128, 144, 79, TURN_AROUND_BYTE];
1138 if !crc_en {
1139 // remove the CRC on idx 2
1140 rx_fsize.swap_remove(2);
1141 }
1142 expectations.push(SpiTransaction::write_vec(rx_fsize));
1143 expectations.push(SpiTransaction::read_vec(rx_size_vec));
1144 expectations.push(SpiTransaction::flush());
1145
1146 // Read RX reg, SPI Header with CRC
1147 let mut rx_reg = vec![128, 145, 72, TURN_AROUND_BYTE];
1148 if !crc_en {
1149 // remove the CRC on idx 2
1150 rx_reg.swap_remove(2);
1151 }
1152 expectations.push(SpiTransaction::write_vec(rx_reg));
1153 // Frame Header
1154 expectations.push(SpiTransaction::read_vec(vec![0, 0]));
1155 // Packet data
1156 expectations.push(SpiTransaction::read_vec(packet.to_vec()));
1157
1158 let packet_crc = ETH_FSC::new(packet);
1159
1160 let mut tail = std::vec::Vec::<u8>::with_capacity(100);
1161
1162 tail.extend_from_slice(&packet_crc.hton_bytes());
1163
1164 // Need extra bytes?
1165 let pad = (packet_size + FSC_LEN + FRAME_HEADER_LEN) & 0x03;
1166 if pad != 0 {
1167 // Packet FCS + optinal padding
1168 tail.resize(tail.len() + pad, DONT_CARE_BYTE);
1169 }
1170
1171 expectations.push(SpiTransaction::read_vec(tail));
1172 expectations.push(SpiTransaction::flush());
1173
1174 let mut spi = SpiMock::new(&expectations);
1175
1176 let cs = CsPinMock::default();
1177 let delay = MockDelay {};
1178 let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay);
1179
1180 let mut spe = ADIN1110::new(spi_dev, crc_en);
1181
1182 let ret = spe.read_fifo(&mut frame).await.expect("Error!");
1183 assert_eq!(ret, packet_size);
1184
1185 spi.done();
1186 }
1187 }
1188 }
1046} 1189}