@@ -41,15 +41,13 @@ extern crate async_rtic as rtic;
41
41
mod app {
42
42
43
43
use async_rtic as rtic;
44
+ use rtic_channel:: { Channel , Receiver , Sender } ;
44
45
45
46
use crate :: common:: EthernetPhy ;
46
47
47
- use fugit:: ExtU64 ;
48
-
49
- use arbiter:: Arbiter ;
48
+ use rtic_arbiter:: Arbiter ;
50
49
51
50
use ieee802_3_miim:: { phy:: PhySpeed , Phy } ;
52
- use systick_monotonic:: Systick ;
53
51
54
52
use stm32_eth:: {
55
53
dma:: { EthernetDMA , PacketId , RxRing , RxRingEntry , TxRing , TxRingEntry } ,
@@ -66,25 +64,24 @@ mod app {
66
64
#[ shared]
67
65
struct Shared { }
68
66
69
- #[ monotonic( binds = SysTick , default = true ) ]
70
- type Monotonic = Systick < 1000 > ;
71
-
72
67
#[ init( local = [
73
68
rx_ring: [ RxRingEntry ; 2 ] = [ RxRingEntry :: new( ) , RxRingEntry :: new( ) ] ,
74
69
tx_ring: [ TxRingEntry ; 2 ] = [ TxRingEntry :: new( ) , TxRingEntry :: new( ) ] ,
75
70
dma: MaybeUninit <EthernetDMA <' static , ' static >> = MaybeUninit :: uninit( ) ,
76
71
arbiter: MaybeUninit <Arbiter <EthernetPTP > > = MaybeUninit :: uninit( ) ,
72
+ // We use a channel to signal when 1 second has passed.
73
+ // We should use `rtic_monotonic`, but its embedded-hal
74
+ // version requirements conflict with that of stm32f4xx-hal.
75
+ tx_channel: Channel <( ) , 1 > = Channel :: new( ) ,
77
76
] ) ]
78
- fn init ( cx : init:: Context ) -> ( Shared , Local , init :: Monotonics ) {
77
+ fn init ( cx : init:: Context ) -> ( Shared , Local ) {
79
78
defmt:: info!( "Pre-init" ) ;
80
- let core = cx. core ;
81
79
let p = cx. device ;
82
80
83
81
let rx_ring = cx. local . rx_ring ;
84
82
let tx_ring = cx. local . tx_ring ;
85
83
86
84
let ( clocks, gpio, ethernet) = crate :: common:: setup_peripherals ( p) ;
87
- let mono = Systick :: new ( core. SYST , clocks. hclk ( ) . raw ( ) ) ;
88
85
89
86
defmt:: info!( "Setting up pins" ) ;
90
87
let ( pins, mdio, mdc, pps) = crate :: common:: setup_pins ( gpio) ;
@@ -104,6 +101,7 @@ mod app {
104
101
dma. enable_interrupt ( ) ;
105
102
106
103
let ( rx, tx) = dma. split ( ) ;
104
+ let ( do_tx_send, do_tx_recv) = cx. local . tx_channel . split ( ) ;
107
105
108
106
match EthernetPhy :: from_miim ( mac, 0 ) {
109
107
Ok ( mut phy) => {
@@ -137,11 +135,11 @@ mod app {
137
135
}
138
136
} ;
139
137
140
- sender:: spawn ( tx) . ok ( ) ;
138
+ sender:: spawn ( tx, do_tx_recv ) . ok ( ) ;
141
139
receiver:: spawn ( rx, arbiter) . ok ( ) ;
142
- ptp_scheduler:: spawn ( arbiter) . ok ( ) ;
140
+ ptp_scheduler:: spawn ( arbiter, do_tx_send ) . ok ( ) ;
143
141
144
- ( Shared { } , Local { } , init :: Monotonics ( mono ) )
142
+ ( Shared { } , Local { } )
145
143
}
146
144
147
145
#[ task]
@@ -211,34 +209,51 @@ mod app {
211
209
}
212
210
213
211
#[ task]
214
- async fn ptp_scheduler ( _: ptp_scheduler:: Context , ptp : & ' static Arbiter < EthernetPTP > ) {
212
+ async fn ptp_scheduler (
213
+ _: ptp_scheduler:: Context ,
214
+ ptp : & ' static Arbiter < EthernetPTP > ,
215
+ mut do_tx_recv : Sender < ' static , ( ) , 1 > ,
216
+ ) {
217
+ let mut last_tx = EthernetPTP :: now ( ) ;
215
218
loop {
216
219
let mut ptp = ptp. access ( ) . await ;
217
- let start = EthernetPTP :: now ( ) ;
218
- let int_time = start + Timestamp :: new_raw ( Subseconds :: MAX_VALUE as i64 ) ;
220
+
221
+ let int_time = last_tx + Timestamp :: new_raw ( Subseconds :: MAX_VALUE as i64 / 2 ) ;
219
222
ptp. wait_until ( int_time) . await ;
223
+
220
224
let now = EthernetPTP :: now ( ) ;
221
225
222
- defmt:: info!( "Got to PTP time after {}." , now - start) ;
226
+ do_tx_recv. send ( ( ) ) . await . ok ( ) ;
227
+ defmt:: info!( "Got to PTP time after {}. It is now {}" , now - last_tx, now) ;
228
+
229
+ last_tx = int_time;
223
230
}
224
231
}
225
232
226
233
#[ task]
227
- async fn sender ( _: sender:: Context , tx : & ' static mut TxRing < ' static > ) {
234
+ async fn sender (
235
+ _: sender:: Context ,
236
+ tx : & ' static mut TxRing < ' static > ,
237
+ mut receiver : Receiver < ' static , ( ) , 1 > ,
238
+ ) {
228
239
let mut tx_id_ctr = 0x8000_0000 ;
229
240
230
241
const SIZE : usize = 42 ;
231
242
232
243
loop {
244
+ receiver. recv ( ) . await . ok ( ) ;
245
+
246
+ defmt:: info!( "Starting TX. It is now {}" , EthernetPTP :: now( ) ) ;
247
+
233
248
// Obtain the current time to use as the "TX time" of our frame. It is clearly
234
249
// incorrect, but works well enough in low-activity systems (such as this example).
235
- let now = EthernetPTP :: now ( ) ;
236
- let start = monotonics:: now ( ) ;
237
250
238
251
const DST_MAC : [ u8 ; 6 ] = [ 0xAB , 0xCD , 0xEF , 0x12 , 0x34 , 0x56 ] ;
239
252
const SRC_MAC : [ u8 ; 6 ] = [ 0x00 , 0x00 , 0xDE , 0xAD , 0xBE , 0xEF ] ;
240
253
const ETH_TYPE : [ u8 ; 2 ] = [ 0xFF , 0xFF ] ; // Custom/unknown ethertype
241
254
255
+ let now = EthernetPTP :: now ( ) ;
256
+
242
257
let tx_id_val = tx_id_ctr;
243
258
let packet_id = PacketId ( tx_id_val) ;
244
259
let mut tx_buffer = tx. prepare_packet ( SIZE , Some ( packet_id. clone ( ) ) ) . await ;
@@ -259,8 +274,6 @@ mod app {
259
274
if let Ok ( Some ( timestamp) ) = timestamp {
260
275
defmt:: info!( "Tx timestamp: {}" , timestamp) ;
261
276
}
262
-
263
- monotonics:: delay_until ( start + 500 . millis ( ) ) . await ;
264
277
}
265
278
}
266
279
0 commit comments