@@ -45,7 +45,7 @@ mod app {
45
45
use stm32_eth:: {
46
46
dma:: { EthernetDMA , PacketId , RxRingEntry , TxRingEntry } ,
47
47
mac:: Speed ,
48
- ptp:: { EthernetPTP , Timestamp } ,
48
+ ptp:: { EthernetPTP , Subseconds , Timestamp } ,
49
49
Parts ,
50
50
} ;
51
51
@@ -57,6 +57,7 @@ mod app {
57
57
dma : EthernetDMA < ' static , ' static > ,
58
58
ptp : EthernetPTP ,
59
59
tx_id : Option < ( u32 , Timestamp ) > ,
60
+ scheduled_time : Option < Timestamp > ,
60
61
}
61
62
62
63
#[ monotonic( binds = SysTick , default = true ) ]
@@ -88,57 +89,74 @@ mod app {
88
89
defmt:: info!( "Enabling interrupts" ) ;
89
90
dma. enable_interrupt ( ) ;
90
91
91
- if let Ok ( mut phy) = EthernetPhy :: from_miim ( mac, 0 ) {
92
- defmt:: info!(
93
- "Resetting PHY as an extra step. Type: {}" ,
94
- phy. ident_string( )
95
- ) ;
92
+ match EthernetPhy :: from_miim ( mac, 0 ) {
93
+ Ok ( mut phy) => {
94
+ defmt:: info!(
95
+ "Resetting PHY as an extra step. Type: {}" ,
96
+ phy. ident_string( )
97
+ ) ;
96
98
97
- phy. phy_init ( ) ;
99
+ phy. phy_init ( ) ;
98
100
99
- defmt:: info!( "Waiting for link up." ) ;
101
+ defmt:: info!( "Waiting for link up." ) ;
100
102
101
- while !phy. phy_link_up ( ) { }
103
+ while !phy. phy_link_up ( ) { }
102
104
103
- defmt:: info!( "Link up." ) ;
105
+ defmt:: info!( "Link up." ) ;
104
106
105
- if let Some ( speed) = phy. speed ( ) . map ( |s| match s {
106
- PhySpeed :: HalfDuplexBase10T => Speed :: HalfDuplexBase10T ,
107
- PhySpeed :: FullDuplexBase10T => Speed :: FullDuplexBase10T ,
108
- PhySpeed :: HalfDuplexBase100Tx => Speed :: HalfDuplexBase100Tx ,
109
- PhySpeed :: FullDuplexBase100Tx => Speed :: FullDuplexBase100Tx ,
110
- } ) {
111
- phy. get_miim ( ) . set_speed ( speed) ;
112
- defmt:: info!( "Detected link speed: {}" , speed) ;
113
- } else {
114
- defmt:: warn!( "Failed to detect link speed." ) ;
107
+ if let Some ( speed) = phy. speed ( ) . map ( |s| match s {
108
+ PhySpeed :: HalfDuplexBase10T => Speed :: HalfDuplexBase10T ,
109
+ PhySpeed :: FullDuplexBase10T => Speed :: FullDuplexBase10T ,
110
+ PhySpeed :: HalfDuplexBase100Tx => Speed :: HalfDuplexBase100Tx ,
111
+ PhySpeed :: FullDuplexBase100Tx => Speed :: FullDuplexBase100Tx ,
112
+ } ) {
113
+ phy. get_miim ( ) . set_speed ( speed) ;
114
+ defmt:: info!( "Detected link speed: {}" , speed) ;
115
+ } else {
116
+ defmt:: warn!( "Failed to detect link speed." ) ;
117
+ }
118
+ }
119
+ Err ( _) => {
120
+ defmt:: info!( "Not resetting unsupported PHY. Cannot detect link speed." ) ;
115
121
}
116
- } else {
117
- defmt:: info!( "Not resetting unsupported PHY. Cannot detect link speed." ) ;
118
- }
122
+ } ;
119
123
120
124
sender:: spawn ( ) . ok ( ) ;
121
125
122
126
(
123
127
Shared {
124
128
dma,
125
129
tx_id : None ,
130
+ scheduled_time : None ,
126
131
ptp,
127
132
} ,
128
133
Local { } ,
129
134
init:: Monotonics ( mono) ,
130
135
)
131
136
}
132
137
133
- #[ task( shared = [ dma, tx_id, ptp] , local = [ tx_id_ctr: u32 = 0x8000_0000 ] ) ]
134
- fn sender ( mut cx : sender:: Context ) {
138
+ #[ task( shared = [ dma, tx_id, ptp, scheduled_time ] , local = [ tx_id_ctr: u32 = 0x8000_0000 ] ) ]
139
+ fn sender ( cx : sender:: Context ) {
135
140
sender:: spawn_after ( 1u64 . secs ( ) ) . ok ( ) ;
136
141
137
142
const SIZE : usize = 42 ;
138
143
139
144
// Obtain the current time to use as the "TX time" of our frame. It is clearly
140
145
// incorrect, but works well enough in low-activity systems (such as this example).
141
- let now = cx. shared . ptp . lock ( |ptp| ptp. get_time ( ) ) ;
146
+ let now = ( cx. shared . ptp , cx. shared . scheduled_time ) . lock ( |ptp, sched_time| {
147
+ let now = ptp. get_time ( ) ;
148
+ let in_half_sec = now
149
+ + Timestamp :: new (
150
+ false ,
151
+ 0 ,
152
+ Subseconds :: new_from_nanos ( 500_000_000 ) . unwrap ( ) . raw ( ) ,
153
+ )
154
+ . unwrap ( ) ;
155
+ ptp. configure_target_time_interrupt ( in_half_sec) ;
156
+ * sched_time = Some ( now) ;
157
+
158
+ now
159
+ } ) ;
142
160
143
161
const DST_MAC : [ u8 ; 6 ] = [ 0xAB , 0xCD , 0xEF , 0x12 , 0x34 , 0x56 ] ;
144
162
const SRC_MAC : [ u8 ; 6 ] = [ 0x00 , 0x00 , 0xDE , 0xAD , 0xBE , 0xEF ] ;
@@ -162,77 +180,94 @@ mod app {
162
180
} ) ;
163
181
}
164
182
165
- #[ task( binds = ETH , shared = [ dma, tx_id, ptp] , priority = 2 ) ]
183
+ #[ task( binds = ETH , shared = [ dma, tx_id, ptp, scheduled_time ] , priority = 2 ) ]
166
184
fn eth_interrupt ( cx : eth_interrupt:: Context ) {
167
- ( cx. shared . dma , cx. shared . tx_id , cx. shared . ptp ) . lock ( |dma, tx_id, ptp| {
168
- dma. interrupt_handler ( ) ;
185
+ (
186
+ cx. shared . dma ,
187
+ cx. shared . tx_id ,
188
+ cx. shared . ptp ,
189
+ cx. shared . scheduled_time ,
190
+ )
191
+ . lock ( |dma, tx_id, ptp, sched_time| {
192
+ dma. interrupt_handler ( ) ;
193
+
194
+ if ptp. interrupt_handler ( ) {
195
+ if let Some ( sched_time) = sched_time. take ( ) {
196
+ let now = ptp. get_time ( ) ;
197
+ defmt:: info!(
198
+ "Got a timestamp interrupt {} seconds after scheduling" ,
199
+ now - sched_time
200
+ ) ;
201
+ }
202
+ }
169
203
170
- let mut packet_id = 0 ;
204
+ let mut packet_id = 0 ;
171
205
172
- while let Ok ( packet) = dma. recv_next ( Some ( packet_id. into ( ) ) ) {
173
- let mut dst_mac = [ 0u8 ; 6 ] ;
174
- dst_mac. copy_from_slice ( & packet[ ..6 ] ) ;
206
+ while let Ok ( packet) = dma. recv_next ( Some ( packet_id. into ( ) ) ) {
207
+ let mut dst_mac = [ 0u8 ; 6 ] ;
208
+ dst_mac. copy_from_slice ( & packet[ ..6 ] ) ;
175
209
176
- // Note that, instead of grabbing the timestamp from the `RxPacket` directly, it
177
- // is also possible to retrieve a cached version of the timestamp using
178
- // `EthernetDMA::get_timestamp_for_id` (in the same way as for TX timestamps).
179
- let ts = if let Some ( timestamp) = packet. timestamp ( ) {
180
- timestamp
181
- } else {
182
- continue ;
183
- } ;
210
+ // Note that, instead of grabbing the timestamp from the `RxPacket` directly, it
211
+ // is also possible to retrieve a cached version of the timestamp using
212
+ // `EthernetDMA::get_timestamp_for_id` (in the same way as for TX timestamps).
213
+ let ts = if let Some ( timestamp) = packet. timestamp ( ) {
214
+ timestamp
215
+ } else {
216
+ continue ;
217
+ } ;
184
218
185
- let timestamp = if dst_mac == [ 0xAB , 0xCD , 0xEF , 0x12 , 0x34 , 0x56 ] {
186
- let mut timestamp_data = [ 0u8 ; 8 ] ;
187
- timestamp_data. copy_from_slice ( & packet[ 14 ..22 ] ) ;
188
- let raw = i64:: from_be_bytes ( timestamp_data) ;
219
+ defmt:: debug!( "RX timestamp: {}" , ts) ;
189
220
190
- let timestamp = Timestamp :: new_raw ( raw) ;
191
- timestamp
192
- } else {
193
- continue ;
194
- } ;
221
+ let timestamp = if dst_mac == [ 0xAB , 0xCD , 0xEF , 0x12 , 0x34 , 0x56 ] {
222
+ let mut timestamp_data = [ 0u8 ; 8 ] ;
223
+ timestamp_data. copy_from_slice ( & packet[ 14 ..22 ] ) ;
224
+ let raw = i64:: from_be_bytes ( timestamp_data) ;
195
225
196
- defmt:: debug!( "RX timestamp: {}" , ts) ;
197
- defmt:: debug!( "Contained TX timestamp: {}" , ts) ;
226
+ let timestamp = Timestamp :: new_raw ( raw) ;
227
+ timestamp
228
+ } else {
229
+ continue ;
230
+ } ;
231
+
232
+ defmt:: debug!( "Contained TX timestamp: {}" , ts) ;
198
233
199
- let diff = timestamp - ts;
234
+ let diff = timestamp - ts;
200
235
201
- defmt:: info!( "Difference between TX and RX time: {}" , diff) ;
236
+ defmt:: info!( "Difference between TX and RX time: {}" , diff) ;
202
237
203
- let addend = ptp. addend ( ) ;
204
- let nanos = diff. nanos ( ) as u64 ;
238
+ let addend = ptp. addend ( ) ;
239
+ let nanos = diff. nanos ( ) as u64 ;
205
240
206
- if nanos <= 20_000 {
207
- let p1 = ( ( nanos * addend as u64 ) / 1_000_000_000 ) as u32 ;
241
+ if nanos <= 20_000 {
242
+ let p1 = ( ( nanos * addend as u64 ) / 1_000_000_000 ) as u32 ;
208
243
209
- defmt:: debug!( "Addend correction value: {}" , p1) ;
244
+ defmt:: debug!( "Addend correction value: {}" , p1) ;
210
245
211
- if diff. is_negative ( ) {
212
- ptp. set_addend ( addend - p1 / 2 ) ;
246
+ if diff. is_negative ( ) {
247
+ ptp. set_addend ( addend - p1 / 2 ) ;
248
+ } else {
249
+ ptp. set_addend ( addend + p1 / 2 ) ;
250
+ } ;
213
251
} else {
214
- ptp. set_addend ( addend + p1 / 2 ) ;
215
- } ;
216
- } else {
217
- defmt:: warn!( "Updated time." ) ;
218
- ptp. update_time ( diff) ;
219
- }
252
+ defmt:: warn!( "Updated time." ) ;
253
+ ptp. update_time ( diff) ;
254
+ }
220
255
221
- packet_id += 1 ;
222
- packet_id &= !0x8000_0000 ;
223
- }
256
+ packet_id += 1 ;
257
+ packet_id &= !0x8000_0000 ;
258
+ }
224
259
225
- if let Some ( ( tx_id, sent_time) ) = tx_id. take ( ) {
226
- if let Ok ( ts) = dma. get_timestamp_for_id ( PacketId ( tx_id) ) {
227
- defmt:: info!( "TX timestamp: {}" , ts) ;
228
- defmt:: debug!(
260
+ if let Some ( ( tx_id, sent_time) ) = tx_id. take ( ) {
261
+ if let Ok ( ts) = dma. get_timestamp_for_id ( PacketId ( tx_id) ) {
262
+ defmt:: info!( "TX timestamp: {}" , ts) ;
263
+ defmt:: debug!(
229
264
"Diff between TX timestamp and the time that was put into the packet: {}" ,
230
265
ts - sent_time
231
266
) ;
232
- } else {
233
- defmt:: warn!( "Failed to retrieve TX timestamp" ) ;
267
+ } else {
268
+ defmt:: warn!( "Failed to retrieve TX timestamp" ) ;
269
+ }
234
270
}
235
- }
236
- } ) ;
271
+ } ) ;
237
272
}
238
273
}
0 commit comments