Skip to content

Commit d311ce5

Browse files
committed
Fix timestamp attaching logic for RxDescriptor and update rtic-timestamp
so that it verifies that this works
1 parent 7850052 commit d311ce5

File tree

4 files changed

+47
-29
lines changed

4 files changed

+47
-29
lines changed

examples/rtic-timestamp.rs

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,10 @@ mod app {
188188
});
189189
}
190190

191-
#[task(binds = ETH, shared = [dma, tx_id, ptp, scheduled_time], priority = 2)]
191+
#[task(binds = ETH, shared = [dma, tx_id, ptp, scheduled_time], local = [rx_packet_id: u32 = 0], priority = 2)]
192192
fn eth_interrupt(cx: eth_interrupt::Context) {
193+
let packet_id = cx.local.rx_packet_id;
194+
193195
(
194196
cx.shared.dma,
195197
cx.shared.tx_id,
@@ -212,26 +214,50 @@ mod app {
212214
}
213215
}
214216

215-
let mut packet_id = 0;
217+
let mut buffer = [0u8; 22];
218+
219+
while let Ok((data, rx_timestamp, used_packet_id)) = {
220+
let used_packet_id = *packet_id;
221+
let result = if let Ok(packet) = dma.recv_next(Some(used_packet_id.into())) {
222+
let data_len = packet.len().min(22);
223+
buffer[..data_len].copy_from_slice(&packet[..data_len]);
224+
let data = &buffer[..data_len];
216225

217-
while let Ok(packet) = dma.recv_next(Some(packet_id.into())) {
218-
let mut dst_mac = [0u8; 6];
219-
dst_mac.copy_from_slice(&packet[..6]);
226+
// For RX packets, we can grab the timestamp directly or
227+
// indirectly using [`EthernetDMA::get_timestamp_for_id`].
228+
//
229+
// Using `timestamp` directly is easier, because you don't
230+
// have to re-borrow the DMA for it.
231+
let timestamp = packet.timestamp();
220232

221-
// Note that, instead of grabbing the timestamp from the `RxPacket` directly, it
222-
// is also possible to retrieve a cached version of the timestamp using
223-
// `EthernetDMA::get_timestamp_for_id` (in the same way as for TX timestamps).
224-
let ts = if let Some(timestamp) = packet.timestamp() {
233+
*packet_id += 1;
234+
*packet_id &= !0x8000_0000;
235+
236+
Ok((data, timestamp, used_packet_id))
237+
} else {
238+
Err(())
239+
};
240+
result
241+
} {
242+
let rx_timestamp = if let Some(timestamp) = rx_timestamp {
225243
timestamp
226244
} else {
227245
continue;
228246
};
229247

230-
defmt::debug!("RX timestamp: {}", ts);
248+
// Get the timestamp "the long way" around by asking the DMA to retrieve
249+
// the value cached in the RX packet.
250+
let cached_timestamp = dma.get_timestamp_for_id(used_packet_id);
251+
252+
// Assert that they are the same.
253+
defmt::assert_eq!(cached_timestamp, Ok(rx_timestamp));
231254

232-
let timestamp = if dst_mac == [0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56] {
255+
defmt::debug!("RX timestamp: {}", rx_timestamp);
256+
257+
let dst_mac = &data[..6];
258+
let tx_timestamp = if dst_mac == [0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56] {
233259
let mut timestamp_data = [0u8; 8];
234-
timestamp_data.copy_from_slice(&packet[14..22]);
260+
timestamp_data.copy_from_slice(&data[14..22]);
235261
let raw = i64::from_be_bytes(timestamp_data);
236262

237263
let timestamp = Timestamp::new_raw(raw);
@@ -240,9 +266,9 @@ mod app {
240266
continue;
241267
};
242268

243-
defmt::debug!("Contained TX timestamp: {}", ts);
269+
defmt::debug!("Contained TX timestamp: {}", rx_timestamp);
244270

245-
let diff = timestamp - ts;
271+
let diff = tx_timestamp - rx_timestamp;
246272

247273
defmt::info!("Difference between TX and RX time: {}", diff);
248274

@@ -263,9 +289,6 @@ mod app {
263289
defmt::warn!("Updated time.");
264290
ptp.update_time(diff);
265291
}
266-
267-
packet_id += 1;
268-
packet_id &= !0x8000_0000;
269292
}
270293

271294
if let Some((tx_id, sent_time)) = tx_id.take() {

src/dma/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ pub const MTU: usize = 1522;
5050
/// RX or TX descriptor handled by the DMA.
5151
#[cfg(feature = "ptp")]
5252
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
53+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
5354
pub enum TimestampError {
5455
/// The descriptor with the given packet ID has not been
5556
/// timestamped yet.

src/dma/rx/descriptor.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,11 @@ impl RxDescriptor {
139139
// "Subsequent reads and writes cannot be moved ahead of preceding reads."
140140
atomic::compiler_fence(Ordering::Acquire);
141141

142+
self.packet_id = packet_id;
143+
142144
// Cache the PTP timestamps if PTP is enabled.
143145
#[cfg(feature = "ptp")]
144-
self.attach_timestamp(packet_id);
146+
self.attach_timestamp();
145147

146148
Ok(())
147149
} else {
@@ -184,14 +186,8 @@ impl RxDescriptor {
184186
}
185187
}
186188

187-
fn attach_timestamp(&mut self, packet_id: Option<PacketId>) {
188-
if packet_id != self.packet_id {
189-
self.cached_timestamp.take();
190-
}
191-
192-
if let (Some(timestamp), None) = (self.read_timestamp(), self.cached_timestamp) {
193-
self.cached_timestamp = Some(timestamp);
194-
}
189+
fn attach_timestamp(&mut self) {
190+
self.cached_timestamp = self.read_timestamp();
195191
}
196192

197193
pub(super) fn timestamp(&self) -> Option<&Timestamp> {

src/dma/tx/descriptor.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,7 @@ impl TxDescriptor {
165165
}
166166

167167
pub(super) fn attach_timestamp(&mut self) {
168-
if self.packet_id.is_some() {
169-
self.cached_timestamp = self.read_timestamp();
170-
}
168+
self.cached_timestamp = self.read_timestamp();
171169
}
172170

173171
pub(super) fn timestamp(&self) -> Option<&Timestamp> {

0 commit comments

Comments
 (0)