fix(esp_eth): use stored base_increment when computing PTP addend

The addend in `emac_hal_ptp_start()` was derived from the floating-point
`config->ptp_req_accuracy_ns` instead of the integer `base_increment`
register that actually drives the sub-second update. The cast to
`uint8_t` loses the fractional part, so the un-corrected addend leaves
the PTP clock running off-rate.

Example: with a 40 MHz XTAL and the default `req_accuracy_ns = 40`,
`base_increment` rounds 85.899 up to 86, leaving the clock +1170 ppm
fast — well outside the IEEE 802.1AS neighborRateRatio limit (~±200
ppm), so strict-1AS bridges refuse asCapable.

Compute the addend from the stored `base_increment` for both rollover
modes: `addend = 2^32 * clk_period_ns / increment_ns`.

Measured on ESP32-P4: neighborRateRatio drops from +1147.5 ppm to
+4.2 ppm, and asCapable is granted.

Co-authored-by: Ondrej Kosta <panzer412@gmail.com>
This commit is contained in:
Scramble Tools
2026-05-25 23:30:48 -07:00
committed by Euripedes Rocha
parent b3b9ebb516
commit e0becb9e43

View File

@@ -404,12 +404,25 @@ esp_err_t emac_hal_ptp_start(emac_hal_context_t *hal, const emac_hal_ptp_config_
int32_t to = 0;
/* If you are using the Fine correction method */
if (config->upd_method == ETH_PTP_UPDATE_METHOD_FINE) {
/**
* 2^32 2^32 TsysClk(ns)
* Addend = ——————— = —————————————————————————— = 2^32 * ——————————————
* ratio SysClk(MHz)/PTPaccur(MHz) Taccur(ns)
/*
* Compute the addend from the actual integer base_increment written
* to hardware, not from the ideal ptp_req_accuracy_ns. Because
* base_increment is a uint8_t, the cast truncates the fractional
* part, making the real sub-second step differ from the requested
* accuracy. This is especially required for IEEE 802.1AS where the
* uncorrected rate must already be within 200 ppm (neighborRateRatio)
* before Sync messages arrive, so we derive the addend from
* the truncated value directly.
*/
uint32_t base_addend = (1ll << 32) * config->ptp_clk_src_period_ns / config->ptp_req_accuracy_ns;
double increment_ns;
if (emac_ll_is_ts_digital_roll_set(hal->ptp_regs)) {
increment_ns = (double)base_increment;
} else {
increment_ns = (double)base_increment * 1.0e9 / (double)(1ULL << 31);
}
uint32_t base_addend = (uint32_t)((double)(1ULL << 32) *
config->ptp_clk_src_period_ns /
increment_ns);
emac_ll_set_ts_addend_val(hal->ptp_regs, base_addend);
emac_ll_ts_addend_do_update(hal->ptp_regs);
while (!emac_ll_is_ts_addend_update_done(hal->ptp_regs) && to < EMAC_PTP_INIT_TIMEOUT_US) {