Hello Kan,
reference was made to the SDK 25_12_00, here the function looks like:
void ENET_Ptp1588GetTimer(ENET_Type *base, enet_handle_t *handle, enet_ptp_time_t *ptpTime)
{
assert(handle != NULL);
assert(ptpTime != NULL);
uint32_t primask;
/* Disables the interrupt. */
primask = DisableGlobalIRQ();
ENET_Ptp1588GetTimerNoIrqDisable(base, handle, ptpTime);
/* Get PTP timer wrap event. */
if ((0U != (base->EIR & (uint32_t)kENET_TsTimerInterrupt)) && (ptpTime->nanosecond < (ENET_NANOSECOND_ONE_SECOND / 2)))
{
ptpTime->second++;
}
/* Enables the interrupt. */
EnableGlobalIRQ(primask);
}
Yes, there is a check for the interrupt flag, and I think it's in the wrong place. That's why I'm asking. Here's my example with a check before and after:
static inline void GetTime (ptp_t *ptp, enet_ptp_time_t *ptpTime)
{
ENET_Type *base = ptp->base;
uint32_t primask;
uint32_t t_nsec;
/*
* Note:
* - ptpSeconds is incremented ONLY in the 1-Hz ISR.
* - IRQs are disabled here, so ptpSeconds remains stable.
* - The EIR flag kENET_TsTimerInterrupt is sticky (HW sets it, ISR clears it).
* Therefore, we read it BEFORE and AFTER the capture to correctly detect
* whether the wrap occurred before or after the capture.
*/
primask = DisableGlobalIRQ();
/* Event before capture */
const uint32_t e0 = base->EIR & (uint32_t)kENET_TsTimerInterrupt;
/* Start to capture the nano seconds */
base->ATCR |= ENET_ATCR_CAPTURE_MASK;
while ( (base->ATCR & ENET_ATCR_CAPTURE_MASK) != 0U )
{
/* Wait until CAPTURE bit auto-clears */
}
t_nsec = base->ATVR;
/* Event after capture */
const uint32_t e1 = base->EIR & (uint32_t)kENET_TsTimerInterrupt;
ptpTime->second = ptp->seconds;
EnableGlobalIRQ(primask);
/*
* Note:
*
* The second-wrap flag (kENET_TsTimerInterrupt) is sticky and is cleared
* only by the ISR. If this flag is set, there are two possible cases:
*
* 1) Real second rollover:
* - The nanoseconds value (nsec) right after the capture is very small
* (close to 0 ... a few microseconds).
* - In this case, the captured timestamp belongs to the NEW second -> sec = s + 1.
*
* 2) Old / stale flag:
* - The flag originates from an earlier rollover (the ISR has not yet cleared it).
* - The nanoseconds value is then large (far away from 0).
* - In this case, the captured timestamp still belongs to the OLD second -> sec = s.
*
* Therefore: If the wrap flag is set, increment the second only if nsec < THRESHOLD.
*/
if ((e0 == 0U) && (e1 == 0U))
{
/* No wrap, do nothing */
}
else if ((e0 == 0U) && (e1 != 0U))
{
/* Wrap after capture, t_nsec still belongs to the old second */
}
else
{
/* e0 != 0: wrap was already set check THRESHOLD */
if (t_nsec < ENET_PTP_WRAP_NS_THRESHOLD)
{
ptpTime->second++;
}
}
ptpTime->nanosecond = t_nsec;
} /* GetTime */
I conducted tests in the "TsTimerInterrupt" to determine the value of t_nsec after the interrupt. The maximum value I found was 540ns. Therefore, I generously set THRESHOLD to 5000, which is 5µs.
I've also noticed now that you don't actually need the flag afterwards, but that you should save the flag beforehand, and only then perform the check after querying "ATVR".
Referring to the original NXP function, I would therefore note the flag before ENET_Ptp1588GetTimerNoIrqDisable, and then later increase the time based on the flag if necessary.
Best regards,
Michael