Step 6.3: PTP hybrid mode (unicast Delay_Req/Resp), step 6 done
- As TimeReceiver in ptp.mode hybrid: Delay_Req unicast to the GM (IP
from its Announce, MAC recorded by the RX hook from its Sync frames),
unicastFlag set.
- As TimeTransmitter: a Delay_Req with the unicastFlag gets a unicast
Delay_Resp; multicast requests get multicast replies.
- EMAC timestamps every received frame (en_ts4all): its PTP filter left
unicast Delay_Req unstamped ("no HW RX timestamp").
- A unicast Delay_Resp's logMessageInterval 0x7F is ignored (use
ptp.log_delay_req); log_us() clamps to -7..6 (the shift was undefined).
- Verified vs ptp4l --hybrid_e2e 1: board hybrid TimeReceiver 18
Delay_Req in 20 s, all answered, locked; board TimeTransmitter
(p1 100): tcpdump shows Sync/Follow_Up/Announce to 224.0.1.129,
Delay_Req 192.168.192.233 -> .244 [unicast] and Delay_Resp .244 ->
.233 [unicast] within 0.4 ms; ptp4l s2.
- Docs: TimeTransmitter/hybrid notes; step 6 ticked.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,7 @@ typedef struct {
|
||||
uint8_t type;
|
||||
uint16_t seq;
|
||||
uint8_t port_id[10];
|
||||
uint8_t mac[6]; // Ethernet source
|
||||
eth_mac_time_t ts;
|
||||
} rx_rec_t;
|
||||
|
||||
@@ -48,6 +49,7 @@ static esp_err_t rx_hook(esp_eth_handle_t eth, uint8_t *buf, uint32_t len, void
|
||||
r->type = ptp[0] & 0x0f;
|
||||
r->seq = (ptp[30] << 8) | ptp[31];
|
||||
memcpy(r->port_id, ptp + 20, 10);
|
||||
memcpy(r->mac, buf + 6, 6);
|
||||
r->ts = *ts;
|
||||
portEXIT_CRITICAL(&s_lock);
|
||||
}
|
||||
@@ -56,6 +58,12 @@ static esp_err_t rx_hook(esp_eth_handle_t eth, uint8_t *buf, uint32_t len, void
|
||||
}
|
||||
|
||||
bool ptp_hw_rx_ts(uint8_t msg_type, uint16_t seq, const uint8_t *src_port_id, eth_mac_time_t *ts)
|
||||
{
|
||||
return ptp_hw_rx_ts_mac(msg_type, seq, src_port_id, ts, NULL);
|
||||
}
|
||||
|
||||
bool ptp_hw_rx_ts_mac(uint8_t msg_type, uint16_t seq, const uint8_t *src_port_id, eth_mac_time_t *ts,
|
||||
uint8_t src_mac[6])
|
||||
{
|
||||
bool found = false;
|
||||
portENTER_CRITICAL(&s_lock);
|
||||
@@ -63,6 +71,9 @@ bool ptp_hw_rx_ts(uint8_t msg_type, uint16_t seq, const uint8_t *src_port_id, et
|
||||
rx_rec_t *r = &s_rx[i];
|
||||
if (r->used && r->type == msg_type && r->seq == seq && memcmp(r->port_id, src_port_id, 10) == 0) {
|
||||
*ts = r->ts;
|
||||
if (src_mac) {
|
||||
memcpy(src_mac, r->mac, 6);
|
||||
}
|
||||
r->used = false;
|
||||
found = true;
|
||||
break;
|
||||
@@ -181,6 +192,9 @@ esp_err_t ptp_hw_init(esp_eth_handle_t eth, esp_netif_t *netif)
|
||||
}
|
||||
// IDF enables timestamping for PTP over Ethernet (L2) only; AES67 uses UDP/IPv4.
|
||||
emac_ll_ts_ptp_ip4_enable(&EMAC_PTP, true);
|
||||
// The PTP packet filter only stamps multicast PTP; unicast Delay_Req (hybrid mode) would get
|
||||
// no timestamp. Stamp every frame instead; rx_hook picks the PTP event messages.
|
||||
emac_ll_ts_all_enable(&EMAC_PTP, true);
|
||||
|
||||
// The netif glue registered its own input path; take it over and forward to the netif.
|
||||
err = esp_eth_update_input_path_info(eth, rx_hook, netif);
|
||||
|
||||
Reference in New Issue
Block a user