aboutsummaryrefslogtreecommitdiff
path: root/embassy-net-adin1110/src
diff options
context:
space:
mode:
authorRenĂ© van Dorst <[email protected]>2023-08-25 23:39:32 +0200
committerRenĂ© van Dorst <[email protected]>2023-08-27 10:37:45 +0200
commit4b6538c8a86947c64a0cf22fadeac847923f16e2 (patch)
tree3d1f04473a55c44aee8989c1c54bfac92b889bb0 /embassy-net-adin1110/src
parent13f050167346ce262ea33c0757496b832c90fa58 (diff)
Fix read_fifo() better readout and more checks
read_fifo() used part of the frame buffer to readout non-frame data. This results in incorrect readout of the fifo buffer but also the full MTU could not be used. Also added some more tests to check this and that the readout is a multipule of 4 bytes.
Diffstat (limited to 'embassy-net-adin1110/src')
-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}