diff options
| author | René van Dorst <[email protected]> | 2023-08-26 01:29:06 +0200 |
|---|---|---|
| committer | René van Dorst <[email protected]> | 2023-08-28 00:28:40 +0200 |
| commit | 13a0be628937125042a961175861bbdba6dcab34 (patch) | |
| tree | acc090bcf291528890471ab518aa74c8b8f9d3c8 | |
| parent | 7f7256050cd8a4f1cb1bb270ee39cb9c8dfdafb2 (diff) | |
Validate FCS in fifo_read() and refactor tests.
Adding TestHarnass to declutter the tests.
Also added a test for FCS and SPI_CRC.
| -rw-r--r-- | embassy-net-adin1110/src/crc32.rs | 29 | ||||
| -rw-r--r-- | embassy-net-adin1110/src/lib.rs | 447 | ||||
| -rw-r--r-- | embassy-net-adin1110/src/regs.rs | 2 |
3 files changed, 305 insertions, 173 deletions
diff --git a/embassy-net-adin1110/src/crc32.rs b/embassy-net-adin1110/src/crc32.rs index a3474f70a..ec020b70c 100644 --- a/embassy-net-adin1110/src/crc32.rs +++ b/embassy-net-adin1110/src/crc32.rs | |||
| @@ -257,29 +257,30 @@ pub const CRC32R_LOOKUP_TABLE: [u32; 256] = [ | |||
| 257 | 0x2D02_EF8D, | 257 | 0x2D02_EF8D, |
| 258 | ]; | 258 | ]; |
| 259 | 259 | ||
| 260 | /// Generate Ethernet Frame Check Sequence | ||
| 260 | #[allow(non_camel_case_types)] | 261 | #[allow(non_camel_case_types)] |
| 261 | #[derive(Debug)] | 262 | #[derive(Debug)] |
| 262 | pub struct ETH_FSC(pub u32); | 263 | pub struct ETH_FCS(pub u32); |
| 263 | 264 | ||
| 264 | impl ETH_FSC { | 265 | impl ETH_FCS { |
| 265 | pub const CRC32_OK: u32 = 0x2144_df1c; | 266 | pub const CRC32_OK: u32 = 0x2144_df1c; |
| 266 | 267 | ||
| 267 | #[must_use] | 268 | #[must_use] |
| 268 | pub fn new(data: &[u8]) -> Self { | 269 | pub fn new(data: &[u8]) -> Self { |
| 269 | let fsc = data.iter().fold(u32::MAX, |crc, byte| { | 270 | let fcs = data.iter().fold(u32::MAX, |crc, byte| { |
| 270 | let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; | 271 | let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; |
| 271 | CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) | 272 | CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) |
| 272 | }) ^ u32::MAX; | 273 | }) ^ u32::MAX; |
| 273 | Self(fsc) | 274 | Self(fcs) |
| 274 | } | 275 | } |
| 275 | 276 | ||
| 276 | #[must_use] | 277 | #[must_use] |
| 277 | pub fn update(self, data: &[u8]) -> Self { | 278 | pub fn update(self, data: &[u8]) -> Self { |
| 278 | let fsc = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| { | 279 | let fcs = data.iter().fold(self.0 ^ u32::MAX, |crc, byte| { |
| 279 | let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; | 280 | let idx = u8::try_from(crc & 0xFF).unwrap() ^ byte; |
| 280 | CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) | 281 | CRC32R_LOOKUP_TABLE[usize::from(idx)] ^ (crc >> 8) |
| 281 | }) ^ u32::MAX; | 282 | }) ^ u32::MAX; |
| 282 | Self(fsc) | 283 | Self(fcs) |
| 283 | } | 284 | } |
| 284 | 285 | ||
| 285 | #[must_use] | 286 | #[must_use] |
| @@ -319,24 +320,24 @@ mod tests { | |||
| 319 | ]; | 320 | ]; |
| 320 | 321 | ||
| 321 | // Packet A | 322 | // Packet A |
| 322 | let own_crc = ETH_FSC::new(&packet_a[0..60]); | 323 | let own_crc = ETH_FCS::new(&packet_a[0..60]); |
| 323 | let crc_bytes = own_crc.hton_bytes(); | 324 | let crc_bytes = own_crc.hton_bytes(); |
| 324 | println!("{:08x} {:02x?}", own_crc.0, crc_bytes); | 325 | println!("{:08x} {:02x?}", own_crc.0, crc_bytes); |
| 325 | assert_eq!(&crc_bytes, &packet_a[60..64]); | 326 | assert_eq!(&crc_bytes, &packet_a[60..64]); |
| 326 | 327 | ||
| 327 | let own_crc = ETH_FSC::new(packet_a); | 328 | let own_crc = ETH_FCS::new(packet_a); |
| 328 | println!("{:08x}", own_crc.0); | 329 | println!("{:08x}", own_crc.0); |
| 329 | assert_eq!(own_crc.0, ETH_FSC::CRC32_OK); | 330 | assert_eq!(own_crc.0, ETH_FCS::CRC32_OK); |
| 330 | 331 | ||
| 331 | // Packet B | 332 | // Packet B |
| 332 | let own_crc = ETH_FSC::new(&packet_b[0..60]); | 333 | let own_crc = ETH_FCS::new(&packet_b[0..60]); |
| 333 | let crc_bytes = own_crc.hton_bytes(); | 334 | let crc_bytes = own_crc.hton_bytes(); |
| 334 | println!("{:08x} {:02x?}", own_crc.0, crc_bytes); | 335 | println!("{:08x} {:02x?}", own_crc.0, crc_bytes); |
| 335 | assert_eq!(&crc_bytes, &packet_b[60..64]); | 336 | assert_eq!(&crc_bytes, &packet_b[60..64]); |
| 336 | 337 | ||
| 337 | let own_crc = ETH_FSC::new(packet_b); | 338 | let own_crc = ETH_FCS::new(packet_b); |
| 338 | println!("{:08x}", own_crc.0); | 339 | println!("{:08x}", own_crc.0); |
| 339 | assert_eq!(own_crc.0, ETH_FSC::CRC32_OK); | 340 | assert_eq!(own_crc.0, ETH_FCS::CRC32_OK); |
| 340 | } | 341 | } |
| 341 | 342 | ||
| 342 | #[test] | 343 | #[test] |
| @@ -349,9 +350,9 @@ mod tests { | |||
| 349 | ]; | 350 | ]; |
| 350 | 351 | ||
| 351 | let (part_a, part_b) = full_data.split_at(16); | 352 | let (part_a, part_b) = full_data.split_at(16); |
| 352 | let crc_partially = ETH_FSC::new(part_a).update(part_b); | 353 | let crc_partially = ETH_FCS::new(part_a).update(part_b); |
| 353 | 354 | ||
| 354 | let crc_full = ETH_FSC::new(full_data); | 355 | let crc_full = ETH_FCS::new(full_data); |
| 355 | 356 | ||
| 356 | assert_eq!(crc_full.0, crc_partially.0); | 357 | assert_eq!(crc_full.0, crc_partially.0); |
| 357 | } | 358 | } |
diff --git a/embassy-net-adin1110/src/lib.rs b/embassy-net-adin1110/src/lib.rs index 4042bd73c..8d73e024f 100644 --- a/embassy-net-adin1110/src/lib.rs +++ b/embassy-net-adin1110/src/lib.rs | |||
| @@ -13,7 +13,7 @@ mod phy; | |||
| 13 | mod regs; | 13 | mod regs; |
| 14 | 14 | ||
| 15 | use ch::driver::LinkState; | 15 | use ch::driver::LinkState; |
| 16 | pub use crc32::ETH_FSC; | 16 | pub use crc32::ETH_FCS; |
| 17 | use crc8::crc8; | 17 | use crc8::crc8; |
| 18 | use embassy_futures::select::{select, Either}; | 18 | use embassy_futures::select::{select, Either}; |
| 19 | use embassy_net_driver_channel as ch; | 19 | use embassy_net_driver_channel as ch; |
| @@ -35,16 +35,22 @@ pub const PHYID: u32 = 0x0283_BC91; | |||
| 35 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | 35 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] |
| 36 | #[allow(non_camel_case_types)] | 36 | #[allow(non_camel_case_types)] |
| 37 | pub enum AdinError<E> { | 37 | pub enum AdinError<E> { |
| 38 | /// SPI-BUS Error | ||
| 38 | Spi(E), | 39 | Spi(E), |
| 39 | SENDERROR, | 40 | /// Ethernet FCS error |
| 40 | READERROR, | 41 | FCS, |
| 41 | CRC, | 42 | /// SPI Header CRC error |
| 43 | SPI_CRC, | ||
| 44 | /// Received or sended ethernet packet is too big | ||
| 42 | PACKET_TOO_BIG, | 45 | PACKET_TOO_BIG, |
| 46 | /// Received or sended ethernet packet is too small | ||
| 43 | PACKET_TOO_SMALL, | 47 | PACKET_TOO_SMALL, |
| 48 | /// MDIO transaction timeout | ||
| 44 | MDIO_ACC_TIMEOUT, | 49 | MDIO_ACC_TIMEOUT, |
| 45 | } | 50 | } |
| 46 | 51 | ||
| 47 | pub type AEResult<T, SPIError> = core::result::Result<T, AdinError<SPIError>>; | 52 | pub type AEResult<T, SPIError> = core::result::Result<T, AdinError<SPIError>>; |
| 53 | /// Internet PHY address | ||
| 48 | pub const MDIO_PHY_ADDR: u8 = 0x01; | 54 | pub const MDIO_PHY_ADDR: u8 = 0x01; |
| 49 | 55 | ||
| 50 | /// Maximum Transmission Unit | 56 | /// Maximum Transmission Unit |
| @@ -59,9 +65,9 @@ const TURN_AROUND_BYTE: u8 = 0x00; | |||
| 59 | /// Packet minimal frame/packet length | 65 | /// Packet minimal frame/packet length |
| 60 | const ETH_MIN_LEN: usize = 64; | 66 | const ETH_MIN_LEN: usize = 64; |
| 61 | /// Ethernet `Frame Check Sequence` length | 67 | /// Ethernet `Frame Check Sequence` length |
| 62 | const FSC_LEN: usize = 4; | 68 | const FCS_LEN: usize = 4; |
| 63 | /// Packet minimal frame/packet length without `Frame Check Sequence` length | 69 | /// Packet minimal frame/packet length without `Frame Check Sequence` length |
| 64 | const ETH_MIN_WITHOUT_FSC_LEN: usize = ETH_MIN_LEN - FSC_LEN; | 70 | const ETH_MIN_WITHOUT_FCS_LEN: usize = ETH_MIN_LEN - FCS_LEN; |
| 65 | 71 | ||
| 66 | /// SPI Header, contains SPI action and register id. | 72 | /// SPI Header, contains SPI action and register id. |
| 67 | const SPI_HEADER_LEN: usize = 2; | 73 | const SPI_HEADER_LEN: usize = 2; |
| @@ -74,7 +80,7 @@ const FRAME_HEADER_LEN: usize = 2; | |||
| 74 | /// Space for last bytes to create multipule 4 bytes on the end of a FIFO read/write. | 80 | /// Space for last bytes to create multipule 4 bytes on the end of a FIFO read/write. |
| 75 | const SPI_SPACE_MULTIPULE: usize = 3; | 81 | const SPI_SPACE_MULTIPULE: usize = 3; |
| 76 | 82 | ||
| 77 | // P1 = 0x00, P2 = 0x01 | 83 | /// P1 = 0x00, P2 = 0x01 |
| 78 | const PORT_ID_BYTE: u8 = 0x00; | 84 | const PORT_ID_BYTE: u8 = 0x00; |
| 79 | 85 | ||
| 80 | /// Type alias for the embassy-net driver for ADIN1110 | 86 | /// Type alias for the embassy-net driver for ADIN1110 |
| @@ -100,12 +106,18 @@ pub struct ADIN1110<SPI> { | |||
| 100 | spi: SPI, | 106 | spi: SPI, |
| 101 | /// Enable CRC on SPI transfer. | 107 | /// Enable CRC on SPI transfer. |
| 102 | /// This must match with the hardware pin `SPI_CFG0` were low = CRC enable, high = CRC disabled. | 108 | /// This must match with the hardware pin `SPI_CFG0` were low = CRC enable, high = CRC disabled. |
| 103 | crc: bool, | 109 | spi_crc: bool, |
| 110 | /// Append FCS by the application of transmit packet, false = FCS is appended by the MAC, true = FCS appended by the application. | ||
| 111 | append_fcs_on_tx: bool, | ||
| 104 | } | 112 | } |
| 105 | 113 | ||
| 106 | impl<SPI: SpiDevice> ADIN1110<SPI> { | 114 | impl<SPI: SpiDevice> ADIN1110<SPI> { |
| 107 | pub fn new(spi: SPI, crc: bool) -> Self { | 115 | pub fn new(spi: SPI, spi_crc: bool, append_fcs_on_tx: bool) -> Self { |
| 108 | Self { spi, crc } | 116 | Self { |
| 117 | spi, | ||
| 118 | spi_crc, | ||
| 119 | append_fcs_on_tx, | ||
| 120 | } | ||
| 109 | } | 121 | } |
| 110 | 122 | ||
| 111 | pub async fn read_reg(&mut self, reg: sr) -> AEResult<u32, SPI::Error> { | 123 | pub async fn read_reg(&mut self, reg: sr) -> AEResult<u32, SPI::Error> { |
| @@ -116,7 +128,7 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 116 | spi_hdr.set_addr(reg); | 128 | spi_hdr.set_addr(reg); |
| 117 | let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); | 129 | let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); |
| 118 | 130 | ||
| 119 | if self.crc { | 131 | if self.spi_crc { |
| 120 | // Add CRC for header data | 132 | // Add CRC for header data |
| 121 | let _ = tx_buf.push(crc8(&tx_buf)); | 133 | let _ = tx_buf.push(crc8(&tx_buf)); |
| 122 | } | 134 | } |
| @@ -126,16 +138,16 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 126 | 138 | ||
| 127 | let mut rx_buf = [0; 5]; | 139 | let mut rx_buf = [0; 5]; |
| 128 | 140 | ||
| 129 | let spi_read_len = if self.crc { rx_buf.len() } else { rx_buf.len() - 1 }; | 141 | let spi_read_len = if self.spi_crc { rx_buf.len() } else { rx_buf.len() - 1 }; |
| 130 | 142 | ||
| 131 | let mut spi_op = [Operation::Write(&tx_buf), Operation::Read(&mut rx_buf[0..spi_read_len])]; | 143 | let mut spi_op = [Operation::Write(&tx_buf), Operation::Read(&mut rx_buf[0..spi_read_len])]; |
| 132 | 144 | ||
| 133 | self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; | 145 | self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; |
| 134 | 146 | ||
| 135 | if self.crc { | 147 | if self.spi_crc { |
| 136 | let crc = crc8(&rx_buf[0..4]); | 148 | let crc = crc8(&rx_buf[0..4]); |
| 137 | if crc != rx_buf[4] { | 149 | if crc != rx_buf[4] { |
| 138 | return Err(AdinError::CRC); | 150 | return Err(AdinError::SPI_CRC); |
| 139 | } | 151 | } |
| 140 | } | 152 | } |
| 141 | 153 | ||
| @@ -156,7 +168,7 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 156 | spi_hdr.set_addr(reg); | 168 | spi_hdr.set_addr(reg); |
| 157 | let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); | 169 | let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); |
| 158 | 170 | ||
| 159 | if self.crc { | 171 | if self.spi_crc { |
| 160 | // Add CRC for header data | 172 | // Add CRC for header data |
| 161 | let _ = tx_buf.push(crc8(&tx_buf)); | 173 | let _ = tx_buf.push(crc8(&tx_buf)); |
| 162 | } | 174 | } |
| @@ -164,7 +176,7 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 164 | let val = value.to_be_bytes(); | 176 | let val = value.to_be_bytes(); |
| 165 | let _ = tx_buf.extend_from_slice(val.as_slice()); | 177 | let _ = tx_buf.extend_from_slice(val.as_slice()); |
| 166 | 178 | ||
| 167 | if self.crc { | 179 | if self.spi_crc { |
| 168 | // Add CRC for header data | 180 | // Add CRC for header data |
| 169 | let _ = tx_buf.push(crc8(val.as_slice())); | 181 | let _ = tx_buf.push(crc8(val.as_slice())); |
| 170 | } | 182 | } |
| @@ -193,18 +205,18 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 193 | /// Read out fifo ethernet packet memory received via the wire. | 205 | /// Read out fifo ethernet packet memory received via the wire. |
| 194 | pub async fn read_fifo(&mut self, frame: &mut [u8]) -> AEResult<usize, SPI::Error> { | 206 | pub async fn read_fifo(&mut self, frame: &mut [u8]) -> AEResult<usize, SPI::Error> { |
| 195 | const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + SPI_HEADER_TA_LEN; | 207 | const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + SPI_HEADER_TA_LEN; |
| 196 | const TAIL_LEN: usize = FSC_LEN + SPI_SPACE_MULTIPULE; | 208 | const TAIL_LEN: usize = FCS_LEN + SPI_SPACE_MULTIPULE; |
| 197 | 209 | ||
| 198 | let mut tx_buf = Vec::<u8, HEAD_LEN>::new(); | 210 | let mut tx_buf = Vec::<u8, HEAD_LEN>::new(); |
| 199 | 211 | ||
| 200 | // Size of the frame, also includes the `frame header` and `FSC`. | 212 | // Size of the frame, also includes the `frame header` and `FCS`. |
| 201 | let fifo_frame_size = self.read_reg(sr::RX_FSIZE).await? as usize; | 213 | let fifo_frame_size = self.read_reg(sr::RX_FSIZE).await? as usize; |
| 202 | 214 | ||
| 203 | if fifo_frame_size < ETH_MIN_LEN + FRAME_HEADER_LEN { | 215 | if fifo_frame_size < ETH_MIN_LEN + FRAME_HEADER_LEN { |
| 204 | return Err(AdinError::PACKET_TOO_SMALL); | 216 | return Err(AdinError::PACKET_TOO_SMALL); |
| 205 | } | 217 | } |
| 206 | 218 | ||
| 207 | let packet_size = fifo_frame_size - FRAME_HEADER_LEN - FSC_LEN; | 219 | let packet_size = fifo_frame_size - FRAME_HEADER_LEN - FCS_LEN; |
| 208 | 220 | ||
| 209 | if packet_size > frame.len() { | 221 | if packet_size > frame.len() { |
| 210 | #[cfg(feature = "defmt")] | 222 | #[cfg(feature = "defmt")] |
| @@ -217,7 +229,7 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 217 | spi_hdr.set_addr(sr::RX); | 229 | spi_hdr.set_addr(sr::RX); |
| 218 | let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); | 230 | let _ = tx_buf.extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()); |
| 219 | 231 | ||
| 220 | if self.crc { | 232 | if self.spi_crc { |
| 221 | // Add CRC for header data | 233 | // Add CRC for header data |
| 222 | let _ = tx_buf.push(crc8(&tx_buf)); | 234 | let _ = tx_buf.push(crc8(&tx_buf)); |
| 223 | } | 235 | } |
| @@ -226,27 +238,36 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 226 | let _ = tx_buf.push(TURN_AROUND_BYTE); | 238 | let _ = tx_buf.push(TURN_AROUND_BYTE); |
| 227 | 239 | ||
| 228 | let mut frame_header = [0, 0]; | 240 | let mut frame_header = [0, 0]; |
| 229 | let mut fsc_and_extra = [0; TAIL_LEN]; | 241 | let mut fcs_and_extra = [0; TAIL_LEN]; |
| 230 | 242 | ||
| 231 | // Packet read of write to the MAC packet buffer must be a multipul of 4! | 243 | // Packet read of write to the MAC packet buffer must be a multipul of 4! |
| 232 | let tail_size = (fifo_frame_size & 0x03) + FSC_LEN; | 244 | let tail_size = (fifo_frame_size & 0x03) + FCS_LEN; |
| 233 | 245 | ||
| 234 | let mut spi_op = [ | 246 | let mut spi_op = [ |
| 235 | Operation::Write(&tx_buf), | 247 | Operation::Write(&tx_buf), |
| 236 | Operation::Read(&mut frame_header), | 248 | Operation::Read(&mut frame_header), |
| 237 | Operation::Read(&mut frame[0..packet_size]), | 249 | Operation::Read(&mut frame[0..packet_size]), |
| 238 | Operation::Read(&mut fsc_and_extra[0..tail_size]), | 250 | Operation::Read(&mut fcs_and_extra[0..tail_size]), |
| 239 | ]; | 251 | ]; |
| 240 | 252 | ||
| 241 | self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; | 253 | self.spi.transaction(&mut spi_op).await.map_err(AdinError::Spi)?; |
| 242 | 254 | ||
| 243 | Ok(packet_size) | 255 | // According to register `CONFIG2`, bit 5 `CRC_APPEND` discription: |
| 256 | // "Similarly, on receive, the CRC32 is forwarded with the frame to the host where the host must verify it is correct." | ||
| 257 | // The application must allways check the FCS. It seems that the MAC/PHY has no option to handle this. | ||
| 258 | let fcs_calc = ETH_FCS::new(&frame[0..packet_size]); | ||
| 259 | |||
| 260 | if fcs_calc.hton_bytes() == fcs_and_extra[0..4] { | ||
| 261 | Ok(packet_size) | ||
| 262 | } else { | ||
| 263 | Err(AdinError::FCS) | ||
| 264 | } | ||
| 244 | } | 265 | } |
| 245 | 266 | ||
| 246 | /// Write to fifo ethernet packet memory send over the wire. | 267 | /// Write to fifo ethernet packet memory send over the wire. |
| 247 | pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> { | 268 | pub async fn write_fifo(&mut self, frame: &[u8]) -> AEResult<(), SPI::Error> { |
| 248 | const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + FRAME_HEADER_LEN; | 269 | const HEAD_LEN: usize = SPI_HEADER_LEN + SPI_HEADER_CRC_LEN + FRAME_HEADER_LEN; |
| 249 | const TAIL_LEN: usize = ETH_MIN_LEN - FSC_LEN + FSC_LEN + SPI_SPACE_MULTIPULE; | 270 | const TAIL_LEN: usize = ETH_MIN_LEN - FCS_LEN + FCS_LEN + SPI_SPACE_MULTIPULE; |
| 250 | 271 | ||
| 251 | if frame.len() < (6 + 6 + 2) { | 272 | if frame.len() < (6 + 6 + 2) { |
| 252 | return Err(AdinError::PACKET_TOO_SMALL); | 273 | return Err(AdinError::PACKET_TOO_SMALL); |
| @@ -269,7 +290,7 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 269 | .extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()) | 290 | .extend_from_slice(spi_hdr.0.to_be_bytes().as_slice()) |
| 270 | .map_err(|_e| AdinError::PACKET_TOO_BIG)?; | 291 | .map_err(|_e| AdinError::PACKET_TOO_BIG)?; |
| 271 | 292 | ||
| 272 | if self.crc { | 293 | if self.spi_crc { |
| 273 | // Add CRC for header data | 294 | // Add CRC for header data |
| 274 | head_data | 295 | head_data |
| 275 | .push(crc8(&head_data[0..2])) | 296 | .push(crc8(&head_data[0..2])) |
| @@ -281,18 +302,22 @@ impl<SPI: SpiDevice> ADIN1110<SPI> { | |||
| 281 | .extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()) | 302 | .extend_from_slice(u16::from(PORT_ID_BYTE).to_be_bytes().as_slice()) |
| 282 | .map_err(|_e| AdinError::PACKET_TOO_BIG)?; | 303 | .map_err(|_e| AdinError::PACKET_TOO_BIG)?; |
| 283 | 304 | ||
| 284 | let mut frame_fcs = ETH_FSC::new(frame); | ||
| 285 | |||
| 286 | // ADIN1110 MAC and PHY don´t accept ethernet packet smaller than 64 bytes. | 305 | // ADIN1110 MAC and PHY don´t accept ethernet packet smaller than 64 bytes. |
| 287 | // So padded the data minus the FCS, FCS is automatilly added to by the MAC. | 306 | // So padded the data minus the FCS, FCS is automatilly added to by the MAC. |
| 288 | if frame.len() < ETH_MIN_WITHOUT_FSC_LEN { | 307 | if frame.len() < ETH_MIN_WITHOUT_FCS_LEN { |
| 289 | let _ = tail_data.resize(ETH_MIN_WITHOUT_FSC_LEN - frame.len(), 0x00); | 308 | let _ = tail_data.resize(ETH_MIN_WITHOUT_FCS_LEN - frame.len(), 0x00); |
| 290 | frame_fcs = frame_fcs.update(&tail_data); | ||
| 291 | } | 309 | } |
| 292 | 310 | ||
| 293 | // Add ethernet FCS only over the ethernet packet. | 311 | // Append FCS by the application |
| 294 | // Only usefull when `CONFIG0`, `Transmit Frame Check Sequence Validation Enable` bit is enabled. | 312 | if self.append_fcs_on_tx { |
| 295 | let _ = tail_data.extend_from_slice(frame_fcs.hton_bytes().as_slice()); | 313 | let mut frame_fcs = ETH_FCS::new(frame); |
| 314 | |||
| 315 | if !tail_data.is_empty() { | ||
| 316 | frame_fcs = frame_fcs.update(&tail_data); | ||
| 317 | } | ||
| 318 | |||
| 319 | let _ = tail_data.extend_from_slice(frame_fcs.hton_bytes().as_slice()); | ||
| 320 | } | ||
| 296 | 321 | ||
| 297 | // len = frame_size + optional padding + 2 bytes Frame header | 322 | // len = frame_size + optional padding + 2 bytes Frame header |
| 298 | let send_len_orig = frame.len() + tail_data.len() + FRAME_HEADER_LEN; | 323 | let send_len_orig = frame.len() + tail_data.len() + FRAME_HEADER_LEN; |
| @@ -583,7 +608,8 @@ pub async fn new<const N_RX: usize, const N_TX: usize, SPI: SpiDevice, INT: Wait | |||
| 583 | spi_dev: SPI, | 608 | spi_dev: SPI, |
| 584 | int: INT, | 609 | int: INT, |
| 585 | mut reset: RST, | 610 | mut reset: RST, |
| 586 | crc: bool, | 611 | spi_crc: bool, |
| 612 | append_fcs_on_tx: bool, | ||
| 587 | ) -> (Device<'_>, Runner<'_, SPI, INT, RST>) { | 613 | ) -> (Device<'_>, Runner<'_, SPI, INT, RST>) { |
| 588 | use crate::regs::{IMask0, IMask1}; | 614 | use crate::regs::{IMask0, IMask1}; |
| 589 | 615 | ||
| @@ -602,7 +628,7 @@ pub async fn new<const N_RX: usize, const N_TX: usize, SPI: SpiDevice, INT: Wait | |||
| 602 | Timer::after(Duration::from_millis(50)).await; | 628 | Timer::after(Duration::from_millis(50)).await; |
| 603 | 629 | ||
| 604 | // Create device | 630 | // Create device |
| 605 | let mut mac = ADIN1110::new(spi_dev, crc); | 631 | let mut mac = ADIN1110::new(spi_dev, spi_crc, append_fcs_on_tx); |
| 606 | 632 | ||
| 607 | // Check PHYID | 633 | // Check PHYID |
| 608 | let id = mac.read_reg(sr::PHYID).await.unwrap(); | 634 | let id = mac.read_reg(sr::PHYID).await.unwrap(); |
| @@ -630,18 +656,15 @@ pub async fn new<const N_RX: usize, const N_TX: usize, SPI: SpiDevice, INT: Wait | |||
| 630 | .unwrap(); | 656 | .unwrap(); |
| 631 | } | 657 | } |
| 632 | 658 | ||
| 633 | // Check if the FCS is valid in the TX path. | ||
| 634 | let tx_fsc_validation_enable = true; | ||
| 635 | |||
| 636 | // Config0 | 659 | // Config0 |
| 637 | let mut config0 = Config0(0x0000_0006); | 660 | let mut config0 = Config0(0x0000_0006); |
| 638 | config0.set_txfcsve(tx_fsc_validation_enable); | 661 | config0.set_txfcsve(mac.append_fcs_on_tx); |
| 639 | mac.write_reg(sr::CONFIG0, config0.0).await.unwrap(); | 662 | mac.write_reg(sr::CONFIG0, config0.0).await.unwrap(); |
| 640 | 663 | ||
| 641 | // Config2 | 664 | // Config2 |
| 642 | let mut config2 = Config2(0x0000_0800); | 665 | let mut config2 = Config2(0x0000_0800); |
| 643 | // crc_append must be disable if tx_fsc_validation_enable is true! | 666 | // crc_append must be disable if tx_fcs_validation_enable is true! |
| 644 | config2.set_crc_append(!tx_fsc_validation_enable); | 667 | config2.set_crc_append(!mac.append_fcs_on_tx); |
| 645 | mac.write_reg(sr::CONFIG2, config2.0).await.unwrap(); | 668 | mac.write_reg(sr::CONFIG2, config2.0).await.unwrap(); |
| 646 | 669 | ||
| 647 | // Pin Mux Config 1 | 670 | // Pin Mux Config 1 |
| @@ -721,6 +744,7 @@ mod tests { | |||
| 721 | use embedded_hal_1::digital::{ErrorType, OutputPin}; | 744 | use embedded_hal_1::digital::{ErrorType, OutputPin}; |
| 722 | use embedded_hal_async::delay::DelayUs; | 745 | use embedded_hal_async::delay::DelayUs; |
| 723 | use embedded_hal_bus::spi::ExclusiveDevice; | 746 | use embedded_hal_bus::spi::ExclusiveDevice; |
| 747 | use embedded_hal_mock::common::Generic; | ||
| 724 | use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction}; | 748 | use embedded_hal_mock::eh1::spi::{Mock as SpiMock, Transaction as SpiTransaction}; |
| 725 | 749 | ||
| 726 | #[derive(Debug, Default)] | 750 | #[derive(Debug, Default)] |
| @@ -759,6 +783,30 @@ mod tests { | |||
| 759 | } | 783 | } |
| 760 | } | 784 | } |
| 761 | 785 | ||
| 786 | struct TestHarnass { | ||
| 787 | spe: ADIN1110<ExclusiveDevice<embedded_hal_mock::common::Generic<SpiTransaction>, CsPinMock, MockDelay>>, | ||
| 788 | spi: Generic<SpiTransaction>, | ||
| 789 | } | ||
| 790 | |||
| 791 | impl TestHarnass { | ||
| 792 | pub fn new(expectations: &[SpiTransaction], spi_crc: bool, append_fcs_on_tx: bool) -> Self { | ||
| 793 | let cs = CsPinMock::default(); | ||
| 794 | let delay = MockDelay {}; | ||
| 795 | let spi = SpiMock::new(expectations); | ||
| 796 | let spi_dev: ExclusiveDevice<embedded_hal_mock::common::Generic<SpiTransaction>, CsPinMock, MockDelay> = | ||
| 797 | ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 798 | let spe: ADIN1110< | ||
| 799 | ExclusiveDevice<embedded_hal_mock::common::Generic<SpiTransaction>, CsPinMock, MockDelay>, | ||
| 800 | > = ADIN1110::new(spi_dev, spi_crc, append_fcs_on_tx); | ||
| 801 | |||
| 802 | Self { spe, spi } | ||
| 803 | } | ||
| 804 | |||
| 805 | pub fn done(&mut self) { | ||
| 806 | self.spi.done(); | ||
| 807 | } | ||
| 808 | } | ||
| 809 | |||
| 762 | #[futures_test::test] | 810 | #[futures_test::test] |
| 763 | async fn mac_read_registers_without_crc() { | 811 | async fn mac_read_registers_without_crc() { |
| 764 | // Configure expectations | 812 | // Configure expectations |
| @@ -772,22 +820,20 @@ mod tests { | |||
| 772 | SpiTransaction::read_vec(vec![0x00, 0x00, 0x06, 0xC3]), | 820 | SpiTransaction::read_vec(vec![0x00, 0x00, 0x06, 0xC3]), |
| 773 | SpiTransaction::flush(), | 821 | SpiTransaction::flush(), |
| 774 | ]; | 822 | ]; |
| 775 | let mut spi = SpiMock::new(&expectations); | ||
| 776 | 823 | ||
| 777 | let cs = CsPinMock::default(); | 824 | // Create TestHarnass |
| 778 | let delay = MockDelay {}; | 825 | let mut th = TestHarnass::new(&expectations, false, true); |
| 779 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 780 | let mut spe = ADIN1110::new(spi_dev, false); | ||
| 781 | 826 | ||
| 782 | // Read PHIID | 827 | // Read PHIID |
| 783 | let val = spe.read_reg(sr::PHYID).await.expect("Error"); | 828 | let val = th.spe.read_reg(sr::PHYID).await.expect("Error"); |
| 784 | assert_eq!(val, 0x0283_BC91); | 829 | assert_eq!(val, 0x0283_BC91); |
| 785 | 830 | ||
| 786 | // Read CAPAVILITY | 831 | // Read CAPAVILITY |
| 787 | let val = spe.read_reg(sr::CAPABILITY).await.expect("Error"); | 832 | let val = th.spe.read_reg(sr::CAPABILITY).await.expect("Error"); |
| 788 | assert_eq!(val, 0x0000_06C3); | 833 | assert_eq!(val, 0x0000_06C3); |
| 789 | 834 | ||
| 790 | spi.done(); | 835 | // Mark end of the SPI test. |
| 836 | th.done(); | ||
| 791 | } | 837 | } |
| 792 | 838 | ||
| 793 | #[futures_test::test] | 839 | #[futures_test::test] |
| @@ -803,26 +849,23 @@ mod tests { | |||
| 803 | SpiTransaction::read_vec(vec![0x00, 0x00, 0x06, 0xC3, 57]), | 849 | SpiTransaction::read_vec(vec![0x00, 0x00, 0x06, 0xC3, 57]), |
| 804 | SpiTransaction::flush(), | 850 | SpiTransaction::flush(), |
| 805 | ]; | 851 | ]; |
| 806 | let mut spi = SpiMock::new(&expectations); | ||
| 807 | |||
| 808 | let cs = CsPinMock::default(); | ||
| 809 | let delay = MockDelay {}; | ||
| 810 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 811 | 852 | ||
| 812 | let mut spe = ADIN1110::new(spi_dev, true); | 853 | // Create TestHarnass |
| 854 | let mut th = TestHarnass::new(&expectations, true, true); | ||
| 813 | 855 | ||
| 814 | assert_eq!(crc8(0x0283_BC91_u32.to_be_bytes().as_slice()), 215); | 856 | assert_eq!(crc8(0x0283_BC91_u32.to_be_bytes().as_slice()), 215); |
| 815 | assert_eq!(crc8(0x0000_06C3_u32.to_be_bytes().as_slice()), 57); | 857 | assert_eq!(crc8(0x0000_06C3_u32.to_be_bytes().as_slice()), 57); |
| 816 | 858 | ||
| 817 | // Read PHIID | 859 | // Read PHIID |
| 818 | let val = spe.read_reg(sr::PHYID).await.expect("Error"); | 860 | let val = th.spe.read_reg(sr::PHYID).await.expect("Error"); |
| 819 | assert_eq!(val, 0x0283_BC91); | 861 | assert_eq!(val, 0x0283_BC91); |
| 820 | 862 | ||
| 821 | // Read CAPAVILITY | 863 | // Read CAPAVILITY |
| 822 | let val = spe.read_reg(sr::CAPABILITY).await.expect("Error"); | 864 | let val = th.spe.read_reg(sr::CAPABILITY).await.expect("Error"); |
| 823 | assert_eq!(val, 0x0000_06C3); | 865 | assert_eq!(val, 0x0000_06C3); |
| 824 | 866 | ||
| 825 | spi.done(); | 867 | // Mark end of the SPI test. |
| 868 | th.done(); | ||
| 826 | } | 869 | } |
| 827 | 870 | ||
| 828 | #[futures_test::test] | 871 | #[futures_test::test] |
| @@ -832,18 +875,15 @@ mod tests { | |||
| 832 | SpiTransaction::write_vec(vec![0xA0, 0x09, 0x12, 0x34, 0x56, 0x78]), | 875 | SpiTransaction::write_vec(vec![0xA0, 0x09, 0x12, 0x34, 0x56, 0x78]), |
| 833 | SpiTransaction::flush(), | 876 | SpiTransaction::flush(), |
| 834 | ]; | 877 | ]; |
| 835 | let mut spi = SpiMock::new(&expectations); | ||
| 836 | |||
| 837 | let cs = CsPinMock::default(); | ||
| 838 | let delay = MockDelay {}; | ||
| 839 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 840 | 878 | ||
| 841 | let mut spe = ADIN1110::new(spi_dev, false); | 879 | // Create TestHarnass |
| 880 | let mut th = TestHarnass::new(&expectations, false, true); | ||
| 842 | 881 | ||
| 843 | // Write reg: 0x1FFF | 882 | // Write reg: 0x1FFF |
| 844 | assert!(spe.write_reg(sr::STATUS1, 0x1234_5678).await.is_ok()); | 883 | assert!(th.spe.write_reg(sr::STATUS1, 0x1234_5678).await.is_ok()); |
| 845 | 884 | ||
| 846 | spi.done(); | 885 | // Mark end of the SPI test. |
| 886 | th.done(); | ||
| 847 | } | 887 | } |
| 848 | 888 | ||
| 849 | #[futures_test::test] | 889 | #[futures_test::test] |
| @@ -854,17 +894,14 @@ mod tests { | |||
| 854 | SpiTransaction::flush(), | 894 | SpiTransaction::flush(), |
| 855 | ]; | 895 | ]; |
| 856 | 896 | ||
| 857 | // Basic test init block | 897 | // Create TestHarnass |
| 858 | let mut spi = SpiMock::new(&expectations); | 898 | let mut th = TestHarnass::new(&expectations, true, true); |
| 859 | let cs = CsPinMock::default(); | ||
| 860 | let delay = MockDelay {}; | ||
| 861 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 862 | let mut spe = ADIN1110::new(spi_dev, true); | ||
| 863 | 899 | ||
| 864 | // Write reg: 0x1FFF | 900 | // Write reg: 0x1FFF |
| 865 | assert!(spe.write_reg(sr::STATUS1, 0x1234_5678).await.is_ok()); | 901 | assert!(th.spe.write_reg(sr::STATUS1, 0x1234_5678).await.is_ok()); |
| 866 | 902 | ||
| 867 | spi.done(); | 903 | // Mark end of the SPI test. |
| 904 | th.done(); | ||
| 868 | } | 905 | } |
| 869 | 906 | ||
| 870 | #[futures_test::test] | 907 | #[futures_test::test] |
| @@ -885,7 +922,7 @@ mod tests { | |||
| 885 | 922 | ||
| 886 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); | 923 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); |
| 887 | // Padding | 924 | // Padding |
| 888 | if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { | 925 | if let Some(padding_len) = (ETH_MIN_LEN - FCS_LEN).checked_sub(packet.len()) { |
| 889 | tail.resize(padding_len, 0x00); | 926 | tail.resize(padding_len, 0x00); |
| 890 | } | 927 | } |
| 891 | // Packet FCS + optinal padding | 928 | // Packet FCS + optinal padding |
| @@ -894,17 +931,49 @@ mod tests { | |||
| 894 | expectations.push(SpiTransaction::write_vec(tail)); | 931 | expectations.push(SpiTransaction::write_vec(tail)); |
| 895 | expectations.push(SpiTransaction::flush()); | 932 | expectations.push(SpiTransaction::flush()); |
| 896 | 933 | ||
| 897 | let mut spi = SpiMock::new(&expectations); | 934 | // Create TestHarnass |
| 935 | let mut th = TestHarnass::new(&expectations, true, true); | ||
| 936 | |||
| 937 | assert!(th.spe.write_fifo(&packet).await.is_ok()); | ||
| 938 | |||
| 939 | // Mark end of the SPI test. | ||
| 940 | th.done(); | ||
| 941 | } | ||
| 942 | |||
| 943 | #[futures_test::test] | ||
| 944 | async fn write_packet_to_fifo_minimal_with_crc_without_fcs() { | ||
| 945 | // Configure expectations | ||
| 946 | let mut expectations = vec![]; | ||
| 947 | |||
| 948 | // Write TX_SIZE reg | ||
| 949 | expectations.push(SpiTransaction::write_vec(vec![160, 48, 136, 0, 0, 0, 62, 186])); | ||
| 950 | expectations.push(SpiTransaction::flush()); | ||
| 951 | |||
| 952 | // Write TX reg. | ||
| 953 | // SPI Header + optional CRC + Frame Header | ||
| 954 | expectations.push(SpiTransaction::write_vec(vec![160, 49, 143, 0, 0])); | ||
| 955 | // Packet data | ||
| 956 | let packet = [0xFF_u8; 60]; | ||
| 957 | expectations.push(SpiTransaction::write_vec(packet.to_vec())); | ||
| 898 | 958 | ||
| 899 | let cs = CsPinMock::default(); | 959 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); |
| 900 | let delay = MockDelay {}; | 960 | // Padding |
| 901 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | 961 | if let Some(padding_len) = (ETH_MIN_LEN - FCS_LEN).checked_sub(packet.len()) { |
| 962 | tail.resize(padding_len, 0x00); | ||
| 963 | } | ||
| 964 | // Packet FCS + optinal padding | ||
| 965 | tail.extend_from_slice(&[DONT_CARE_BYTE, DONT_CARE_BYTE]); | ||
| 966 | |||
| 967 | expectations.push(SpiTransaction::write_vec(tail)); | ||
| 968 | expectations.push(SpiTransaction::flush()); | ||
| 902 | 969 | ||
| 903 | let mut spe = ADIN1110::new(spi_dev, true); | 970 | // Create TestHarnass |
| 971 | let mut th = TestHarnass::new(&expectations, true, false); | ||
| 904 | 972 | ||
| 905 | assert!(spe.write_fifo(&packet).await.is_ok()); | 973 | assert!(th.spe.write_fifo(&packet).await.is_ok()); |
| 906 | 974 | ||
| 907 | spi.done(); | 975 | // Mark end of the SPI test. |
| 976 | th.done(); | ||
| 908 | } | 977 | } |
| 909 | 978 | ||
| 910 | #[futures_test::test] | 979 | #[futures_test::test] |
| @@ -926,7 +995,7 @@ mod tests { | |||
| 926 | 995 | ||
| 927 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); | 996 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); |
| 928 | // Padding | 997 | // Padding |
| 929 | if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { | 998 | if let Some(padding_len) = (ETH_MIN_LEN - FCS_LEN).checked_sub(packet.len()) { |
| 930 | tail.resize(padding_len, 0x00); | 999 | tail.resize(padding_len, 0x00); |
| 931 | } | 1000 | } |
| 932 | // Packet FCS + optinal padding | 1001 | // Packet FCS + optinal padding |
| @@ -935,17 +1004,13 @@ mod tests { | |||
| 935 | expectations.push(SpiTransaction::write_vec(tail)); | 1004 | expectations.push(SpiTransaction::write_vec(tail)); |
| 936 | expectations.push(SpiTransaction::flush()); | 1005 | expectations.push(SpiTransaction::flush()); |
| 937 | 1006 | ||
| 938 | let mut spi = SpiMock::new(&expectations); | 1007 | // Create TestHarnass |
| 1008 | let mut th = TestHarnass::new(&expectations, true, true); | ||
| 939 | 1009 | ||
| 940 | let cs = CsPinMock::default(); | 1010 | assert!(th.spe.write_fifo(&packet).await.is_ok()); |
| 941 | let delay = MockDelay {}; | ||
| 942 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 943 | 1011 | ||
| 944 | let mut spe = ADIN1110::new(spi_dev, true); | 1012 | // Mark end of the SPI test. |
| 945 | 1013 | th.done(); | |
| 946 | assert!(spe.write_fifo(&packet).await.is_ok()); | ||
| 947 | |||
| 948 | spi.done(); | ||
| 949 | } | 1014 | } |
| 950 | 1015 | ||
| 951 | #[futures_test::test] | 1016 | #[futures_test::test] |
| @@ -958,24 +1023,23 @@ mod tests { | |||
| 958 | // Max packet size = MAX_BUFF - FRAME_HEADER_LEN | 1023 | // Max packet size = MAX_BUFF - FRAME_HEADER_LEN |
| 959 | let packet = [0xAA_u8; MAX_BUFF - FRAME_HEADER_LEN + 1]; | 1024 | let packet = [0xAA_u8; MAX_BUFF - FRAME_HEADER_LEN + 1]; |
| 960 | 1025 | ||
| 961 | let mut spi = SpiMock::new(&expectations); | 1026 | // Create TestHarnass |
| 962 | 1027 | let mut th = TestHarnass::new(&expectations, true, true); | |
| 963 | let cs = CsPinMock::default(); | ||
| 964 | let delay = MockDelay {}; | ||
| 965 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 966 | |||
| 967 | let mut spe = ADIN1110::new(spi_dev, true); | ||
| 968 | 1028 | ||
| 969 | // minimal | 1029 | // minimal |
| 970 | assert!(matches!( | 1030 | assert!(matches!( |
| 971 | spe.write_fifo(&packet[0..(6 + 6 + 2 - 1)]).await, | 1031 | th.spe.write_fifo(&packet[0..(6 + 6 + 2 - 1)]).await, |
| 972 | Err(AdinError::PACKET_TOO_SMALL) | 1032 | Err(AdinError::PACKET_TOO_SMALL) |
| 973 | )); | 1033 | )); |
| 974 | 1034 | ||
| 975 | // max + 1 | 1035 | // max + 1 |
| 976 | assert!(matches!(spe.write_fifo(&packet).await, Err(AdinError::PACKET_TOO_BIG))); | 1036 | assert!(matches!( |
| 1037 | th.spe.write_fifo(&packet).await, | ||
| 1038 | Err(AdinError::PACKET_TOO_BIG) | ||
| 1039 | )); | ||
| 977 | 1040 | ||
| 978 | spi.done(); | 1041 | // Mark end of the SPI test. |
| 1042 | th.done(); | ||
| 979 | } | 1043 | } |
| 980 | 1044 | ||
| 981 | #[futures_test::test] | 1045 | #[futures_test::test] |
| @@ -999,7 +1063,7 @@ mod tests { | |||
| 999 | 1063 | ||
| 1000 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); | 1064 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); |
| 1001 | // Padding | 1065 | // Padding |
| 1002 | if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { | 1066 | if let Some(padding_len) = (ETH_MIN_LEN - FCS_LEN).checked_sub(packet.len()) { |
| 1003 | tail.resize(padding_len, 0x00); | 1067 | tail.resize(padding_len, 0x00); |
| 1004 | } | 1068 | } |
| 1005 | // Packet FCS + optinal padding | 1069 | // Packet FCS + optinal padding |
| @@ -1008,17 +1072,13 @@ mod tests { | |||
| 1008 | expectations.push(SpiTransaction::write_vec(tail)); | 1072 | expectations.push(SpiTransaction::write_vec(tail)); |
| 1009 | expectations.push(SpiTransaction::flush()); | 1073 | expectations.push(SpiTransaction::flush()); |
| 1010 | 1074 | ||
| 1011 | let mut spi = SpiMock::new(&expectations); | 1075 | // Create TestHarnass |
| 1076 | let mut th = TestHarnass::new(&expectations, true, true); | ||
| 1012 | 1077 | ||
| 1013 | let cs = CsPinMock::default(); | 1078 | assert!(th.spe.write_fifo(&packet).await.is_ok()); |
| 1014 | let delay = MockDelay {}; | ||
| 1015 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 1016 | 1079 | ||
| 1017 | let mut spe = ADIN1110::new(spi_dev, true); | 1080 | // Mark end of the SPI test. |
| 1018 | 1081 | th.done(); | |
| 1019 | assert!(spe.write_fifo(&packet).await.is_ok()); | ||
| 1020 | |||
| 1021 | spi.done(); | ||
| 1022 | } | 1082 | } |
| 1023 | 1083 | ||
| 1024 | #[futures_test::test] | 1084 | #[futures_test::test] |
| @@ -1042,7 +1102,7 @@ mod tests { | |||
| 1042 | 1102 | ||
| 1043 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); | 1103 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); |
| 1044 | // Padding | 1104 | // Padding |
| 1045 | if let Some(padding_len) = (ETH_MIN_LEN - FSC_LEN).checked_sub(packet.len()) { | 1105 | if let Some(padding_len) = (ETH_MIN_LEN - FCS_LEN).checked_sub(packet.len()) { |
| 1046 | tail.resize(padding_len, 0x00); | 1106 | tail.resize(padding_len, 0x00); |
| 1047 | } | 1107 | } |
| 1048 | // Packet FCS + optinal padding | 1108 | // Packet FCS + optinal padding |
| @@ -1051,17 +1111,13 @@ mod tests { | |||
| 1051 | expectations.push(SpiTransaction::write_vec(tail)); | 1111 | expectations.push(SpiTransaction::write_vec(tail)); |
| 1052 | expectations.push(SpiTransaction::flush()); | 1112 | expectations.push(SpiTransaction::flush()); |
| 1053 | 1113 | ||
| 1054 | let mut spi = SpiMock::new(&expectations); | 1114 | // Create TestHarnass |
| 1055 | 1115 | let mut th = TestHarnass::new(&expectations, false, true); | |
| 1056 | let cs = CsPinMock::default(); | ||
| 1057 | let delay = MockDelay {}; | ||
| 1058 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 1059 | |||
| 1060 | let mut spe = ADIN1110::new(spi_dev, false); | ||
| 1061 | 1116 | ||
| 1062 | assert!(spe.write_fifo(&packet).await.is_ok()); | 1117 | assert!(th.spe.write_fifo(&packet).await.is_ok()); |
| 1063 | 1118 | ||
| 1064 | spi.done(); | 1119 | // Mark end of the SPI test. |
| 1120 | th.done(); | ||
| 1065 | } | 1121 | } |
| 1066 | 1122 | ||
| 1067 | #[futures_test::test] | 1123 | #[futures_test::test] |
| @@ -1070,7 +1126,7 @@ mod tests { | |||
| 1070 | let mut expectations = vec![]; | 1126 | let mut expectations = vec![]; |
| 1071 | 1127 | ||
| 1072 | // Read RX_SIZE reg | 1128 | // Read RX_SIZE reg |
| 1073 | let rx_size: u32 = u32::try_from(ETH_MIN_LEN + FRAME_HEADER_LEN + FSC_LEN).unwrap(); | 1129 | let rx_size: u32 = u32::try_from(ETH_MIN_LEN + FRAME_HEADER_LEN + FCS_LEN).unwrap(); |
| 1074 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); | 1130 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); |
| 1075 | rx_size_vec.push(crc8(&rx_size_vec)); | 1131 | rx_size_vec.push(crc8(&rx_size_vec)); |
| 1076 | 1132 | ||
| @@ -1078,20 +1134,16 @@ mod tests { | |||
| 1078 | expectations.push(SpiTransaction::read_vec(rx_size_vec)); | 1134 | expectations.push(SpiTransaction::read_vec(rx_size_vec)); |
| 1079 | expectations.push(SpiTransaction::flush()); | 1135 | expectations.push(SpiTransaction::flush()); |
| 1080 | 1136 | ||
| 1081 | let mut spi = SpiMock::new(&expectations); | ||
| 1082 | |||
| 1083 | let cs = CsPinMock::default(); | ||
| 1084 | let delay = MockDelay {}; | ||
| 1085 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 1086 | |||
| 1087 | let mut spe = ADIN1110::new(spi_dev, true); | ||
| 1088 | |||
| 1089 | let mut frame = [0; MTU]; | 1137 | let mut frame = [0; MTU]; |
| 1090 | 1138 | ||
| 1091 | let ret = spe.read_fifo(&mut frame[0..ETH_MIN_LEN - 1]).await; | 1139 | // Create TestHarnass |
| 1140 | let mut th = TestHarnass::new(&expectations, true, true); | ||
| 1141 | |||
| 1142 | let ret = th.spe.read_fifo(&mut frame[0..ETH_MIN_LEN - 1]).await; | ||
| 1092 | assert!(matches!(dbg!(ret), Err(AdinError::PACKET_TOO_BIG))); | 1143 | assert!(matches!(dbg!(ret), Err(AdinError::PACKET_TOO_BIG))); |
| 1093 | 1144 | ||
| 1094 | spi.done(); | 1145 | // Mark end of the SPI test. |
| 1146 | th.done(); | ||
| 1095 | } | 1147 | } |
| 1096 | 1148 | ||
| 1097 | #[futures_test::test] | 1149 | #[futures_test::test] |
| @@ -1102,11 +1154,11 @@ mod tests { | |||
| 1102 | // This value is importen for this test! | 1154 | // This value is importen for this test! |
| 1103 | assert_eq!(ETH_MIN_LEN, 64); | 1155 | assert_eq!(ETH_MIN_LEN, 64); |
| 1104 | 1156 | ||
| 1105 | // Packet data, size = `ETH_MIN_LEN` - `FSC_LEN` - 1 | 1157 | // Packet data, size = `ETH_MIN_LEN` - `FCS_LEN` - 1 |
| 1106 | let packet = [0; 64 - FSC_LEN - 1]; | 1158 | let packet = [0; 64 - FCS_LEN - 1]; |
| 1107 | 1159 | ||
| 1108 | // Read RX_SIZE reg | 1160 | // Read RX_SIZE reg |
| 1109 | let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FSC_LEN).unwrap(); | 1161 | let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FCS_LEN).unwrap(); |
| 1110 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); | 1162 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); |
| 1111 | rx_size_vec.push(crc8(&rx_size_vec)); | 1163 | rx_size_vec.push(crc8(&rx_size_vec)); |
| 1112 | 1164 | ||
| @@ -1114,20 +1166,84 @@ mod tests { | |||
| 1114 | expectations.push(SpiTransaction::read_vec(rx_size_vec)); | 1166 | expectations.push(SpiTransaction::read_vec(rx_size_vec)); |
| 1115 | expectations.push(SpiTransaction::flush()); | 1167 | expectations.push(SpiTransaction::flush()); |
| 1116 | 1168 | ||
| 1117 | let mut spi = SpiMock::new(&expectations); | 1169 | let mut frame = [0; MTU]; |
| 1170 | |||
| 1171 | // Create TestHarnass | ||
| 1172 | let mut th = TestHarnass::new(&expectations, true, true); | ||
| 1118 | 1173 | ||
| 1119 | let cs = CsPinMock::default(); | 1174 | let ret = th.spe.read_fifo(&mut frame).await; |
| 1120 | let delay = MockDelay {}; | 1175 | assert!(matches!(dbg!(ret), Err(AdinError::PACKET_TOO_SMALL))); |
| 1121 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 1122 | 1176 | ||
| 1123 | let mut spe = ADIN1110::new(spi_dev, true); | 1177 | // Mark end of the SPI test. |
| 1178 | th.done(); | ||
| 1179 | } | ||
| 1124 | 1180 | ||
| 1181 | #[futures_test::test] | ||
| 1182 | async fn read_packet_from_fifo_packet_corrupted_fcs() { | ||
| 1125 | let mut frame = [0; MTU]; | 1183 | let mut frame = [0; MTU]; |
| 1184 | // Configure expectations | ||
| 1185 | let mut expectations = vec![]; | ||
| 1126 | 1186 | ||
| 1127 | let ret = spe.read_fifo(&mut frame).await; | 1187 | let packet = [0xDE; 60]; |
| 1128 | assert!(matches!(dbg!(ret), Err(AdinError::PACKET_TOO_SMALL))); | 1188 | let crc_en = true; |
| 1189 | |||
| 1190 | // Read RX_SIZE reg | ||
| 1191 | let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FCS_LEN).unwrap(); | ||
| 1192 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); | ||
| 1193 | if crc_en { | ||
| 1194 | rx_size_vec.push(crc8(&rx_size_vec)); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | // SPI Header with CRC | ||
| 1198 | let mut rx_fsize = vec![128, 144, 79, TURN_AROUND_BYTE]; | ||
| 1199 | if !crc_en { | ||
| 1200 | // remove the CRC on idx 2 | ||
| 1201 | rx_fsize.swap_remove(2); | ||
| 1202 | } | ||
| 1203 | expectations.push(SpiTransaction::write_vec(rx_fsize)); | ||
| 1204 | expectations.push(SpiTransaction::read_vec(rx_size_vec)); | ||
| 1205 | expectations.push(SpiTransaction::flush()); | ||
| 1129 | 1206 | ||
| 1130 | spi.done(); | 1207 | // Read RX reg, SPI Header with CRC |
| 1208 | let mut rx_reg = vec![128, 145, 72, TURN_AROUND_BYTE]; | ||
| 1209 | if !crc_en { | ||
| 1210 | // remove the CRC on idx 2 | ||
| 1211 | rx_reg.swap_remove(2); | ||
| 1212 | } | ||
| 1213 | expectations.push(SpiTransaction::write_vec(rx_reg)); | ||
| 1214 | // Frame Header | ||
| 1215 | expectations.push(SpiTransaction::read_vec(vec![0, 0])); | ||
| 1216 | // Packet data | ||
| 1217 | expectations.push(SpiTransaction::read_vec(packet.to_vec())); | ||
| 1218 | |||
| 1219 | let packet_crc = ETH_FCS::new(&packet); | ||
| 1220 | |||
| 1221 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); | ||
| 1222 | |||
| 1223 | tail.extend_from_slice(&packet_crc.hton_bytes()); | ||
| 1224 | // increase last byte with 1. | ||
| 1225 | if let Some(crc) = tail.last_mut() { | ||
| 1226 | *crc = crc.wrapping_add(1); | ||
| 1227 | } | ||
| 1228 | |||
| 1229 | // Need extra bytes? | ||
| 1230 | let pad = (packet.len() + FCS_LEN + FRAME_HEADER_LEN) & 0x03; | ||
| 1231 | if pad != 0 { | ||
| 1232 | // Packet FCS + optinal padding | ||
| 1233 | tail.resize(tail.len() + pad, DONT_CARE_BYTE); | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | expectations.push(SpiTransaction::read_vec(tail)); | ||
| 1237 | expectations.push(SpiTransaction::flush()); | ||
| 1238 | |||
| 1239 | // Create TestHarnass | ||
| 1240 | let mut th = TestHarnass::new(&expectations, crc_en, false); | ||
| 1241 | |||
| 1242 | let ret = th.spe.read_fifo(&mut frame).await.expect_err("Error!"); | ||
| 1243 | assert!(matches!(ret, AdinError::FCS)); | ||
| 1244 | |||
| 1245 | // Mark end of the SPI test. | ||
| 1246 | th.done(); | ||
| 1131 | } | 1247 | } |
| 1132 | 1248 | ||
| 1133 | #[futures_test::test] | 1249 | #[futures_test::test] |
| @@ -1136,7 +1252,7 @@ mod tests { | |||
| 1136 | let mut frame = [0; MTU]; | 1252 | let mut frame = [0; MTU]; |
| 1137 | let mut expectations = std::vec::Vec::with_capacity(16); | 1253 | let mut expectations = std::vec::Vec::with_capacity(16); |
| 1138 | 1254 | ||
| 1139 | // Packet data, size = `ETH_MIN_LEN` - `FSC_LEN` | 1255 | // Packet data, size = `ETH_MIN_LEN` - `FCS_LEN` |
| 1140 | for packet_size in [60, 61, 62, 63, 64, MTU - 4, MTU - 3, MTU - 2, MTU - 1, MTU] { | 1256 | for packet_size in [60, 61, 62, 63, 64, MTU - 4, MTU - 3, MTU - 2, MTU - 1, MTU] { |
| 1141 | for crc_en in [false, true] { | 1257 | for crc_en in [false, true] { |
| 1142 | expectations.clear(); | 1258 | expectations.clear(); |
| @@ -1144,7 +1260,7 @@ mod tests { | |||
| 1144 | let packet = &packet_buffer[0..packet_size]; | 1260 | let packet = &packet_buffer[0..packet_size]; |
| 1145 | 1261 | ||
| 1146 | // Read RX_SIZE reg | 1262 | // Read RX_SIZE reg |
| 1147 | let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FSC_LEN).unwrap(); | 1263 | let rx_size: u32 = u32::try_from(packet.len() + FRAME_HEADER_LEN + FCS_LEN).unwrap(); |
| 1148 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); | 1264 | let mut rx_size_vec = rx_size.to_be_bytes().to_vec(); |
| 1149 | if crc_en { | 1265 | if crc_en { |
| 1150 | rx_size_vec.push(crc8(&rx_size_vec)); | 1266 | rx_size_vec.push(crc8(&rx_size_vec)); |
| @@ -1172,14 +1288,14 @@ mod tests { | |||
| 1172 | // Packet data | 1288 | // Packet data |
| 1173 | expectations.push(SpiTransaction::read_vec(packet.to_vec())); | 1289 | expectations.push(SpiTransaction::read_vec(packet.to_vec())); |
| 1174 | 1290 | ||
| 1175 | let packet_crc = ETH_FSC::new(packet); | 1291 | let packet_crc = ETH_FCS::new(packet); |
| 1176 | 1292 | ||
| 1177 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); | 1293 | let mut tail = std::vec::Vec::<u8>::with_capacity(100); |
| 1178 | 1294 | ||
| 1179 | tail.extend_from_slice(&packet_crc.hton_bytes()); | 1295 | tail.extend_from_slice(&packet_crc.hton_bytes()); |
| 1180 | 1296 | ||
| 1181 | // Need extra bytes? | 1297 | // Need extra bytes? |
| 1182 | let pad = (packet_size + FSC_LEN + FRAME_HEADER_LEN) & 0x03; | 1298 | let pad = (packet_size + FCS_LEN + FRAME_HEADER_LEN) & 0x03; |
| 1183 | if pad != 0 { | 1299 | if pad != 0 { |
| 1184 | // Packet FCS + optinal padding | 1300 | // Packet FCS + optinal padding |
| 1185 | tail.resize(tail.len() + pad, DONT_CARE_BYTE); | 1301 | tail.resize(tail.len() + pad, DONT_CARE_BYTE); |
| @@ -1188,19 +1304,34 @@ mod tests { | |||
| 1188 | expectations.push(SpiTransaction::read_vec(tail)); | 1304 | expectations.push(SpiTransaction::read_vec(tail)); |
| 1189 | expectations.push(SpiTransaction::flush()); | 1305 | expectations.push(SpiTransaction::flush()); |
| 1190 | 1306 | ||
| 1191 | let mut spi = SpiMock::new(&expectations); | 1307 | // Create TestHarnass |
| 1192 | 1308 | let mut th = TestHarnass::new(&expectations, crc_en, false); | |
| 1193 | let cs = CsPinMock::default(); | ||
| 1194 | let delay = MockDelay {}; | ||
| 1195 | let spi_dev = ExclusiveDevice::new(spi.clone(), cs, delay); | ||
| 1196 | |||
| 1197 | let mut spe = ADIN1110::new(spi_dev, crc_en); | ||
| 1198 | 1309 | ||
| 1199 | let ret = spe.read_fifo(&mut frame).await.expect("Error!"); | 1310 | let ret = th.spe.read_fifo(&mut frame).await.expect("Error!"); |
| 1200 | assert_eq!(ret, packet_size); | 1311 | assert_eq!(ret, packet_size); |
| 1201 | 1312 | ||
| 1202 | spi.done(); | 1313 | // Mark end of the SPI test. |
| 1314 | th.done(); | ||
| 1203 | } | 1315 | } |
| 1204 | } | 1316 | } |
| 1205 | } | 1317 | } |
| 1318 | |||
| 1319 | #[futures_test::test] | ||
| 1320 | async fn spi_crc_error() { | ||
| 1321 | // Configure expectations | ||
| 1322 | let expectations = vec![ | ||
| 1323 | SpiTransaction::write_vec(vec![128, 144, 79, TURN_AROUND_BYTE]), | ||
| 1324 | SpiTransaction::read_vec(vec![0x00, 0x00, 0x00, 0x00, 0xDD]), | ||
| 1325 | SpiTransaction::flush(), | ||
| 1326 | ]; | ||
| 1327 | |||
| 1328 | // Create TestHarnass | ||
| 1329 | let mut th = TestHarnass::new(&expectations, true, false); | ||
| 1330 | |||
| 1331 | let ret = th.spe.read_reg(sr::RX_FSIZE).await; | ||
| 1332 | assert!(matches!(dbg!(ret), Err(AdinError::SPI_CRC))); | ||
| 1333 | |||
| 1334 | // Mark end of the SPI test. | ||
| 1335 | th.done(); | ||
| 1336 | } | ||
| 1206 | } | 1337 | } |
diff --git a/embassy-net-adin1110/src/regs.rs b/embassy-net-adin1110/src/regs.rs index 4557929f0..46466c7d1 100644 --- a/embassy-net-adin1110/src/regs.rs +++ b/embassy-net-adin1110/src/regs.rs | |||
| @@ -174,7 +174,7 @@ bitfield! { | |||
| 174 | pub sdf_detect_src, set_sdf_detect_src : 7; | 174 | pub sdf_detect_src, set_sdf_detect_src : 7; |
| 175 | /// Statistics Clear on Reading | 175 | /// Statistics Clear on Reading |
| 176 | pub stats_clr_on_rd, set_stats_clr_on_rd : 6; | 176 | pub stats_clr_on_rd, set_stats_clr_on_rd : 6; |
| 177 | /// Enable CRC Append | 177 | /// Enable SPI CRC |
| 178 | pub crc_append, set_crc_append : 5; | 178 | pub crc_append, set_crc_append : 5; |
| 179 | /// Admit Frames with IFG Errors on Port 1 (P1) | 179 | /// Admit Frames with IFG Errors on Port 1 (P1) |
| 180 | pub p1_rcv_ifg_err_frm, set_p1_rcv_ifg_err_frm : 4; | 180 | pub p1_rcv_ifg_err_frm, set_p1_rcv_ifg_err_frm : 4; |
