Step 3.3a: PTP servo, clock locks to the GM
- ptp_hw: ptp_hw_adj_freq() (ETH_MAC_ESP_CMD_ADJ_PTP_TIME, absolute ppb vs nominal, clamped +-500 ppm, retried while the addend update is busy) and ptp_hw_step() (read + write time). - ptp_clock: first Sync after a GM is selected seeds the integral with the measured rate and steps the clock; then linuxptp-style PI (kp/ki from the Sync interval: 0.7/0.3 at 1 s). Re-step above 1 ms. Locked after 8 Syncs with |offset| < 1 us, unlocked after 3 above; GM change or loss unlocks and keeps the frequency (holdover). - Verified vs ptp4l: stepped to GM time, locked after ~19 s; locked offset within +-510 ns (mostly < 300 ns), correction +39.9 ppm (crystal -39.8 ppm), path delay ~10.2 us. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,38 @@ esp_err_t ptp_hw_get_time(eth_mac_time_t *t)
|
||||
return esp_eth_ioctl(s_eth, ETH_MAC_ESP_CMD_G_PTP_TIME, t);
|
||||
}
|
||||
|
||||
esp_err_t ptp_hw_adj_freq(double ppb)
|
||||
{
|
||||
if (ppb > 500000) {
|
||||
ppb = 500000; // +-500 ppm is far outside any sane crystal
|
||||
} else if (ppb < -500000) {
|
||||
ppb = -500000;
|
||||
}
|
||||
int32_t v = (int32_t)(ppb >= 0 ? ppb + 0.5 : ppb - 0.5);
|
||||
esp_err_t err = ESP_ERR_INVALID_STATE;
|
||||
// The previous addend update may still be in progress: retry briefly.
|
||||
for (int i = 0; i < 10 && err == ESP_ERR_INVALID_STATE; i++) {
|
||||
err = esp_eth_ioctl(s_eth, ETH_MAC_ESP_CMD_ADJ_PTP_TIME, &v);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t ptp_hw_step(int64_t offset_ns)
|
||||
{
|
||||
eth_mac_time_t t;
|
||||
esp_err_t err = ptp_hw_get_time(&t);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
int64_t ns = (int64_t)t.seconds * 1000000000LL + t.nanoseconds - offset_ns;
|
||||
if (ns < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
t.seconds = ns / 1000000000LL;
|
||||
t.nanoseconds = ns % 1000000000LL;
|
||||
return esp_eth_ioctl(s_eth, ETH_MAC_ESP_CMD_S_PTP_TIME, &t);
|
||||
}
|
||||
|
||||
static uint16_t ip_checksum(const uint8_t *h, size_t len)
|
||||
{
|
||||
uint32_t sum = 0;
|
||||
|
||||
Reference in New Issue
Block a user