diff options
| author | Dario Nieuwenhuis <[email protected]> | 2023-08-18 15:45:23 +0200 |
|---|---|---|
| committer | Dario Nieuwenhuis <[email protected]> | 2023-08-18 15:51:48 +0200 |
| commit | 73942f50cb03070026246701e75d641e34d6d308 (patch) | |
| tree | a15ffeadd5f3f25001889610b70e61020f8be2f1 /embassy-net-enc28j60 | |
| parent | 3ebb93e47d47095f35d561cd49f0797a74061465 (diff) | |
net-enc28j60: reset rx logic when buffer corrupts.
Diffstat (limited to 'embassy-net-enc28j60')
| -rw-r--r-- | embassy-net-enc28j60/src/lib.rs | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/embassy-net-enc28j60/src/lib.rs b/embassy-net-enc28j60/src/lib.rs index e958e7e31..b44cefaf2 100644 --- a/embassy-net-enc28j60/src/lib.rs +++ b/embassy-net-enc28j60/src/lib.rs | |||
| @@ -106,19 +106,7 @@ where | |||
| 106 | // disable CLKOUT output | 106 | // disable CLKOUT output |
| 107 | self.write_control_register(bank3::Register::ECOCON, 0); | 107 | self.write_control_register(bank3::Register::ECOCON, 0); |
| 108 | 108 | ||
| 109 | // RX start | 109 | self.init_rx(); |
| 110 | // "It is recommended that the ERXST Pointer be programmed with an even address" | ||
| 111 | self.write_control_register(bank0::Register::ERXSTL, RXST.low()); | ||
| 112 | self.write_control_register(bank0::Register::ERXSTH, RXST.high()); | ||
| 113 | |||
| 114 | // RX read pointer | ||
| 115 | // NOTE Errata #14 so we are using an *odd* address here instead of ERXST | ||
| 116 | self.write_control_register(bank0::Register::ERXRDPTL, RXND.low()); | ||
| 117 | self.write_control_register(bank0::Register::ERXRDPTH, RXND.high()); | ||
| 118 | |||
| 119 | // RX end | ||
| 120 | self.write_control_register(bank0::Register::ERXNDL, RXND.low()); | ||
| 121 | self.write_control_register(bank0::Register::ERXNDH, RXND.high()); | ||
| 122 | 110 | ||
| 123 | // TX start | 111 | // TX start |
| 124 | // "It is recommended that an even address be used for ETXST" | 112 | // "It is recommended that an even address be used for ETXST" |
| @@ -172,12 +160,37 @@ where | |||
| 172 | // Set the per packet control byte; we'll always use the value 0 | 160 | // Set the per packet control byte; we'll always use the value 0 |
| 173 | self.write_buffer_memory(Some(TXST), &mut [0]); | 161 | self.write_buffer_memory(Some(TXST), &mut [0]); |
| 174 | 162 | ||
| 163 | // Enable reception | ||
| 164 | self.bit_field_set(common::Register::ECON1, common::ECON1::mask().rxen()); | ||
| 165 | } | ||
| 166 | |||
| 167 | fn init_rx(&mut self) { | ||
| 168 | // RX start | ||
| 169 | // "It is recommended that the ERXST Pointer be programmed with an even address" | ||
| 170 | self.write_control_register(bank0::Register::ERXSTL, RXST.low()); | ||
| 171 | self.write_control_register(bank0::Register::ERXSTH, RXST.high()); | ||
| 172 | |||
| 173 | // RX read pointer | ||
| 174 | // NOTE Errata #14 so we are using an *odd* address here instead of ERXST | ||
| 175 | self.write_control_register(bank0::Register::ERXRDPTL, RXND.low()); | ||
| 176 | self.write_control_register(bank0::Register::ERXRDPTH, RXND.high()); | ||
| 177 | |||
| 178 | // RX end | ||
| 179 | self.write_control_register(bank0::Register::ERXNDL, RXND.low()); | ||
| 180 | self.write_control_register(bank0::Register::ERXNDH, RXND.high()); | ||
| 181 | |||
| 175 | // decrease the packet count to 0 | 182 | // decrease the packet count to 0 |
| 176 | while self.read_control_register(bank1::Register::EPKTCNT) != 0 { | 183 | while self.read_control_register(bank1::Register::EPKTCNT) != 0 { |
| 177 | self.bit_field_set(common::Register::ECON2, common::ECON2::mask().pktdec()); | 184 | self.bit_field_set(common::Register::ECON2, common::ECON2::mask().pktdec()); |
| 178 | } | 185 | } |
| 179 | 186 | ||
| 180 | // Enable reception | 187 | self.next_packet = RXST; |
| 188 | } | ||
| 189 | |||
| 190 | fn reset_rx(&mut self) { | ||
| 191 | self.bit_field_set(common::Register::ECON1, common::ECON1::mask().rxrst()); | ||
| 192 | self.bit_field_clear(common::Register::ECON1, common::ECON1::mask().rxrst()); | ||
| 193 | self.init_rx(); | ||
| 181 | self.bit_field_set(common::Register::ECON1, common::ECON1::mask().rxen()); | 194 | self.bit_field_set(common::Register::ECON1, common::ECON1::mask().rxen()); |
| 182 | } | 195 | } |
| 183 | 196 | ||
| @@ -198,18 +211,17 @@ where | |||
| 198 | 211 | ||
| 199 | // next packet pointer | 212 | // next packet pointer |
| 200 | let next_packet = u16::from_parts(temp_buf[0], temp_buf[1]); | 213 | let next_packet = u16::from_parts(temp_buf[0], temp_buf[1]); |
| 201 | if next_packet > RXND { | ||
| 202 | panic!("CorruptRxBuffer"); | ||
| 203 | } | ||
| 204 | |||
| 205 | // status vector | 214 | // status vector |
| 206 | let status = header::RxStatus(u32::from_le_bytes(temp_buf[2..].try_into().unwrap())); | 215 | let status = header::RxStatus(u32::from_le_bytes(temp_buf[2..].try_into().unwrap())); |
| 207 | let len = status.byte_count() as u16 - CRC_SZ; | 216 | let len_with_crc = status.byte_count() as u16; |
| 208 | 217 | ||
| 209 | if len > RXND { | 218 | if len_with_crc < CRC_SZ || len_with_crc > 1600 || next_packet > RXND { |
| 210 | panic!("CorruptRxBuffer 2"); | 219 | warn!("RX buffer corrupted, resetting RX logic to recover..."); |
| 220 | self.reset_rx(); | ||
| 221 | return None; | ||
| 211 | } | 222 | } |
| 212 | 223 | ||
| 224 | let len = len_with_crc - CRC_SZ; | ||
| 213 | self.read_buffer_memory(None, &mut buf[..len as usize]); | 225 | self.read_buffer_memory(None, &mut buf[..len as usize]); |
| 214 | 226 | ||
| 215 | // update ERXRDPT | 227 | // update ERXRDPT |
