<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic i.MX‑RT1170: Question regarding correctness of ENET_Ptp1588GetTimer() in i.MX RT Crossover MCUs</title>
    <link>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2321742#M36237</link>
    <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;I am working with the i.MX‑RT1170 ENET1588 hardware timestamping unit.&amp;nbsp;While validating the accuracy of PTP timestamp reconstruction, I noticed a potential issue in the SDK function: ENET_Ptp1588GetTimer()&lt;/P&gt;&lt;P&gt;The function builds a timestamp consisting of:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;handle-&amp;gt;msTimerSecond (software second counter updated in the 1‑Hz PTP timer interrupt)&lt;/LI&gt;&lt;LI&gt;ATVR (hardware nanoseconds, captured via ATCR)&lt;/LI&gt;&lt;LI&gt;EIR &amp;amp; kENET_TsTimerInterrupt (wrap flag)&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;After testing various timing edge cases, I have found a problematic scenario where the function may return an incorrect value.&lt;/P&gt;&lt;P&gt;However, I don't have a test program for this; I've only played it through theoretically.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Problem description&lt;BR /&gt;&lt;/STRONG&gt;The issue occurs when a &lt;STRONG&gt;wrap happens close to the nanosecond capture&lt;/STRONG&gt;, but the 1‑Hz ISR (which increments msTimerSecond) cannot run because interrupts are disabled, or because we are already inside an ENET interrupt handler.&lt;/P&gt;&lt;P&gt;Sequence:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;The PTP hardware timestamp counter is close to the wrap event (e.g. around &lt;STRONG&gt;3.999999990 seconds&lt;/STRONG&gt;).&lt;/LI&gt;&lt;LI&gt;Global interrupts become disabled (or we are inside an ENET ISR).&lt;/LI&gt;&lt;LI&gt;A capture is performed via ATCR → the captured nanoseconds may still belong to the &lt;STRONG&gt;old second&lt;/STRONG&gt;, e.g.&lt;BR /&gt;t_nsec = 999999998.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;After&lt;/STRONG&gt; the capture, but &lt;STRONG&gt;before&lt;/STRONG&gt; interrupts are re‑enabled, the hardware second actually wraps to the next second. The hardware sets EIR &amp;amp; kENET_TsTimerInterrupt.&lt;/LI&gt;&lt;LI&gt;However, the 1‑Hz ISR that increments msTimerSecond cannot run, so&lt;BR /&gt;msTimerSecond still holds the &lt;STRONG&gt;old&lt;/STRONG&gt; second value.&lt;/LI&gt;&lt;LI&gt;ENET_Ptp1588GetTimer() interprets a &lt;EM&gt;set wrap flag&lt;/EM&gt; ( if (0U != (base-&amp;gt;EIR &amp;amp; (uint32_t)kENET_TsTimerInterrupt)) ) as “current time is in the new second” and returns:&amp;nbsp;ptpTime-&amp;gt;second++&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;This results in a timestamp such as:&amp;nbsp;4.999999998&amp;nbsp;&amp;nbsp; (incorrect)&lt;BR /&gt;even though the correct time represented by the captured nanoseconds is:&amp;nbsp;3.999999998&amp;nbsp;&amp;nbsp; (correct)&lt;/P&gt;&lt;P&gt;In other words:&lt;BR /&gt;The function cannot distinguish whether the wrap flag was set &lt;STRONG&gt;before&lt;/STRONG&gt; or &lt;STRONG&gt;after&lt;/STRONG&gt; the nanosecond capture, and therefore may add one second incorrectly.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Question&lt;BR /&gt;&lt;/STRONG&gt;Is the current implementation of ENET_Ptp1588GetTimer() intended to work correctly under these timing conditions?&lt;/P&gt;&lt;P&gt;Specifically:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Does NXP consider it correct to use the wrap flag alone (without knowing whether it occurred &lt;EM&gt;before&lt;/EM&gt; or &lt;EM&gt;after&lt;/EM&gt; the nanosecond capture)?&lt;/LI&gt;&lt;LI&gt;Should the function read the wrap flag &lt;STRONG&gt;both before and after&lt;/STRONG&gt; the ATCR capture in order to determine whether the wrap actually happened before the sampled nanoseconds?&lt;/LI&gt;&lt;LI&gt;Or is there an updated or recommended implementation for robust timestamp reconstruction on the i.MX‑RT1170?&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Any clarification or guidance you can provide would be greatly appreciated.&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;Michael&lt;/P&gt;</description>
    <pubDate>Tue, 24 Feb 2026 07:25:28 GMT</pubDate>
    <dc:creator>michael_fischer</dc:creator>
    <dc:date>2026-02-24T07:25:28Z</dc:date>
    <item>
      <title>i.MX‑RT1170: Question regarding correctness of ENET_Ptp1588GetTimer()</title>
      <link>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2321742#M36237</link>
      <description>&lt;P&gt;Hello,&lt;/P&gt;&lt;P&gt;I am working with the i.MX‑RT1170 ENET1588 hardware timestamping unit.&amp;nbsp;While validating the accuracy of PTP timestamp reconstruction, I noticed a potential issue in the SDK function: ENET_Ptp1588GetTimer()&lt;/P&gt;&lt;P&gt;The function builds a timestamp consisting of:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;handle-&amp;gt;msTimerSecond (software second counter updated in the 1‑Hz PTP timer interrupt)&lt;/LI&gt;&lt;LI&gt;ATVR (hardware nanoseconds, captured via ATCR)&lt;/LI&gt;&lt;LI&gt;EIR &amp;amp; kENET_TsTimerInterrupt (wrap flag)&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;After testing various timing edge cases, I have found a problematic scenario where the function may return an incorrect value.&lt;/P&gt;&lt;P&gt;However, I don't have a test program for this; I've only played it through theoretically.&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Problem description&lt;BR /&gt;&lt;/STRONG&gt;The issue occurs when a &lt;STRONG&gt;wrap happens close to the nanosecond capture&lt;/STRONG&gt;, but the 1‑Hz ISR (which increments msTimerSecond) cannot run because interrupts are disabled, or because we are already inside an ENET interrupt handler.&lt;/P&gt;&lt;P&gt;Sequence:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;The PTP hardware timestamp counter is close to the wrap event (e.g. around &lt;STRONG&gt;3.999999990 seconds&lt;/STRONG&gt;).&lt;/LI&gt;&lt;LI&gt;Global interrupts become disabled (or we are inside an ENET ISR).&lt;/LI&gt;&lt;LI&gt;A capture is performed via ATCR → the captured nanoseconds may still belong to the &lt;STRONG&gt;old second&lt;/STRONG&gt;, e.g.&lt;BR /&gt;t_nsec = 999999998.&lt;/LI&gt;&lt;LI&gt;&lt;STRONG&gt;After&lt;/STRONG&gt; the capture, but &lt;STRONG&gt;before&lt;/STRONG&gt; interrupts are re‑enabled, the hardware second actually wraps to the next second. The hardware sets EIR &amp;amp; kENET_TsTimerInterrupt.&lt;/LI&gt;&lt;LI&gt;However, the 1‑Hz ISR that increments msTimerSecond cannot run, so&lt;BR /&gt;msTimerSecond still holds the &lt;STRONG&gt;old&lt;/STRONG&gt; second value.&lt;/LI&gt;&lt;LI&gt;ENET_Ptp1588GetTimer() interprets a &lt;EM&gt;set wrap flag&lt;/EM&gt; ( if (0U != (base-&amp;gt;EIR &amp;amp; (uint32_t)kENET_TsTimerInterrupt)) ) as “current time is in the new second” and returns:&amp;nbsp;ptpTime-&amp;gt;second++&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;This results in a timestamp such as:&amp;nbsp;4.999999998&amp;nbsp;&amp;nbsp; (incorrect)&lt;BR /&gt;even though the correct time represented by the captured nanoseconds is:&amp;nbsp;3.999999998&amp;nbsp;&amp;nbsp; (correct)&lt;/P&gt;&lt;P&gt;In other words:&lt;BR /&gt;The function cannot distinguish whether the wrap flag was set &lt;STRONG&gt;before&lt;/STRONG&gt; or &lt;STRONG&gt;after&lt;/STRONG&gt; the nanosecond capture, and therefore may add one second incorrectly.&lt;BR /&gt;&lt;BR /&gt;&lt;/P&gt;&lt;P&gt;&lt;STRONG&gt;Question&lt;BR /&gt;&lt;/STRONG&gt;Is the current implementation of ENET_Ptp1588GetTimer() intended to work correctly under these timing conditions?&lt;/P&gt;&lt;P&gt;Specifically:&lt;/P&gt;&lt;UL&gt;&lt;LI&gt;Does NXP consider it correct to use the wrap flag alone (without knowing whether it occurred &lt;EM&gt;before&lt;/EM&gt; or &lt;EM&gt;after&lt;/EM&gt; the nanosecond capture)?&lt;/LI&gt;&lt;LI&gt;Should the function read the wrap flag &lt;STRONG&gt;both before and after&lt;/STRONG&gt; the ATCR capture in order to determine whether the wrap actually happened before the sampled nanoseconds?&lt;/LI&gt;&lt;LI&gt;Or is there an updated or recommended implementation for robust timestamp reconstruction on the i.MX‑RT1170?&lt;/LI&gt;&lt;/UL&gt;&lt;P&gt;Any clarification or guidance you can provide would be greatly appreciated.&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;Michael&lt;/P&gt;</description>
      <pubDate>Tue, 24 Feb 2026 07:25:28 GMT</pubDate>
      <guid>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2321742#M36237</guid>
      <dc:creator>michael_fischer</dc:creator>
      <dc:date>2026-02-24T07:25:28Z</dc:date>
    </item>
    <item>
      <title>Re: i.MX‑RT1170: Question regarding correctness of ENET_Ptp1588GetTimer()</title>
      <link>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2322923#M36254</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&lt;a href="https://community.nxp.com/t5/user/viewprofilepage/user-id/214553"&gt;@michael_fischer&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Are you referring to the latest SDK version? The current code also checks the value of&amp;nbsp;&lt;SPAN&gt;ptpTime-&amp;gt;nanosecond on the step 6 -&amp;nbsp;&lt;/SPAN&gt;ENET_Ptp1588GetTimer() interprets a&amp;nbsp;&lt;EM&gt;set wrap flag&lt;/EM&gt;&amp;nbsp;( if (0U != (base-&amp;gt;EIR &amp;amp; (uint32_t)kENET_TsTimerInterrupt)) ) as “current time is in the new second” and returns:&amp;nbsp;ptpTime-&amp;gt;second++&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Please kindly clarify.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Have a great day,&lt;BR /&gt;Kan&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;-------------------------------------------------------------------------------&lt;BR /&gt;Note:&lt;BR /&gt;- If this post answers your question, please click the "Mark Correct" button. Thank you!&lt;BR /&gt;- We are following threads for 7 weeks after the last post, later replies are ignored&lt;BR /&gt;Please open a new thread and refer to the closed one, if you have a related question at a later point in time.&lt;BR /&gt;-------------------------------------------------------------------------------&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 26 Feb 2026 07:11:01 GMT</pubDate>
      <guid>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2322923#M36254</guid>
      <dc:creator>Kan_Li</dc:creator>
      <dc:date>2026-02-26T07:11:01Z</dc:date>
    </item>
    <item>
      <title>Re: i.MX‑RT1170: Question regarding correctness of ENET_Ptp1588GetTimer()</title>
      <link>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2322949#M36255</link>
      <description>&lt;P&gt;Hello Kan,&lt;/P&gt;&lt;P&gt;reference was made to the SDK 25_12_00, here the function looks like:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;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-&amp;gt;EIR &amp;amp; (uint32_t)kENET_TsTimerInterrupt)) &amp;amp;&amp;amp; (ptpTime-&amp;gt;nanosecond &amp;lt; (ENET_NANOSECOND_ONE_SECOND / 2)))
    {
        ptpTime-&amp;gt;second++;
    }

    /* Enables the interrupt. */
    EnableGlobalIRQ(primask);
}&lt;/LI-CODE&gt;&lt;P&gt;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:&lt;/P&gt;&lt;LI-CODE lang="c"&gt;static inline void GetTime (ptp_t *ptp, enet_ptp_time_t *ptpTime)
{
   ENET_Type *base = ptp-&amp;gt;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-&amp;gt;EIR &amp;amp; (uint32_t)kENET_TsTimerInterrupt;

   /* Start to capture the nano seconds */
   base-&amp;gt;ATCR |= ENET_ATCR_CAPTURE_MASK;
   while ( (base-&amp;gt;ATCR &amp;amp; ENET_ATCR_CAPTURE_MASK) != 0U )
   {
      /* Wait until CAPTURE bit auto-clears */
   }
   t_nsec = base-&amp;gt;ATVR;

   /* Event after capture */
   const uint32_t e1 = base-&amp;gt;EIR &amp;amp; (uint32_t)kENET_TsTimerInterrupt;
   
   ptpTime-&amp;gt;second = ptp-&amp;gt;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 -&amp;gt; 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 -&amp;gt; sec = s.
    *
    * Therefore: If the wrap flag is set, increment the second only if nsec &amp;lt; THRESHOLD.
    */   
   if ((e0 == 0U) &amp;amp;&amp;amp; (e1 == 0U))
   {
      /* No wrap, do nothing */
   }
   else if ((e0 == 0U) &amp;amp;&amp;amp; (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 &amp;lt; ENET_PTP_WRAP_NS_THRESHOLD)
      {
         ptpTime-&amp;gt;second++;
      }   
   }

   ptpTime-&amp;gt;nanosecond = t_nsec;
   
} /* GetTime */&lt;/LI-CODE&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;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".&lt;/P&gt;&lt;P&gt;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.&lt;/P&gt;&lt;P&gt;Best regards,&lt;BR /&gt;Michael&lt;/P&gt;</description>
      <pubDate>Thu, 26 Feb 2026 08:13:03 GMT</pubDate>
      <guid>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2322949#M36255</guid>
      <dc:creator>michael_fischer</dc:creator>
      <dc:date>2026-02-26T08:13:03Z</dc:date>
    </item>
    <item>
      <title>Re: i.MX‑RT1170: Question regarding correctness of ENET_Ptp1588GetTimer()</title>
      <link>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2325376#M36274</link>
      <description>&lt;P&gt;Hi&amp;nbsp;&amp;nbsp;&lt;a href="https://community.nxp.com/t5/user/viewprofilepage/user-id/214553"&gt;@michael_fischer&lt;/a&gt;&amp;nbsp;,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks for the clarification! Yes, your understanding is correct, and we recommend handling such adjustment on a higher layer, such as we implement it in&amp;nbsp;&lt;SPAN data-teams="true"&gt;an-ethernet-lwip-ptpd-imxrt , you may fetch this demo from the application code hub, and refer to&amp;nbsp;enet_get_txframe_time() for details.&amp;nbsp; You may refer to&amp;nbsp;&lt;A href="https://docs.nxp.com/bundle/AN12149/page/topics/introduction.html" target="_blank"&gt;https://docs.nxp.com/bundle/AN12149/page/topics/introduction.html&lt;/A&gt;&amp;nbsp;for more details regarding this demo.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN data-teams="true"&gt;Hope that helps,&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Have a great day,&lt;BR /&gt;Kan&lt;/P&gt;
&lt;P&gt;&lt;BR /&gt;-------------------------------------------------------------------------------&lt;BR /&gt;Note:&lt;BR /&gt;- If this post answers your question, please click the "Mark Correct" button. Thank you!&lt;BR /&gt;- We are following threads for 7 weeks after the last post, later replies are ignored&lt;BR /&gt;Please open a new thread and refer to the closed one, if you have a related question at a later point in time.&lt;BR /&gt;-------------------------------------------------------------------------------&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 03 Mar 2026 05:39:38 GMT</pubDate>
      <guid>https://community.nxp.com/t5/i-MX-RT-Crossover-MCUs/i-MX-RT1170-Question-regarding-correctness-of-ENET/m-p/2325376#M36274</guid>
      <dc:creator>Kan_Li</dc:creator>
      <dc:date>2026-03-03T05:39:38Z</dc:date>
    </item>
  </channel>
</rss>

