1 Reply Latest reply on Jul 24, 2018 12:11 AM by gani

    Counter_ReadCapture() sometimes returns wrong values from a UDB 32 Bit Counter

    guillermo

      HI,

      I'm working with the CY8CKIT-049-42XX kit to develop a signal timing application, but I'm running into a nasty problem with a UDB 32-bit counter that I'm using to obtain time stamps of two external events. The UDB is configured as a free running up counter of 1MHz signal at the Count input. The clock is system clock @ 22MHz IMO (within specs as per the datasheet). The resulting counter resolution is therefore 1 microsecond.

       

      I have one pin attached to a signal I call trigger that starts the events sequence. There is an ISR attached to this pin that takes the first reading from the counter with Counter_ReadCounter() into a global uint32 variable. It then enables the event capture Interrupt of the UDB counter in question. The second event signal which I call MEP is connected form a second pin to the Capture pin of the UDB. The associated ISR then reads the UDB status register and saves the event time stamp on a second global variable. Both ISRs also toggles an output pin ON and OFF so I can monitor the timing relationship of signals and ISRs physically on the scope.

      Finally, the main loop monitors the event time variable and reports on the serial port both times and the time difference in microseconds. The time between both events hovers around 100 milliseconds (signal sources are not precise on purpose), and the scope confirms that the readings are in agreement …. MOST OF THE TIME.

       

      THE PROBLEM

      After much trial and error, changing interrupt priorities and other things and logging data I nailed down the problem to the following: Sometimes the high word of the event captured is incorrect. Actually the high word of the counter SHOWS THE VALUE OF TWO READINGS BACK. It sounds like a double buffering of the counter gets out of sync. Below is an excerpt of sample logs at different times where you can see the retro values. I have seen this also in the Counter_ReadCounter() as well, but since according to the documentation internally it also uses the capture mechanism the problem is the same. Here are the samples:

       

      Capture: 2786E0D, ReleaseTime: 276C3CD, Offset: 109120

      Capture: 2871F0A, ReleaseTime: 285751C, Offset: 109038

      Capture: 278EBAF, ReleaseTime: 294417B, Offset: 4293175860 (bad capture time high word == of high word of two records back)

      Capture: 3F47D89, ReleaseTime: 3F2D25F, Offset: 109354

      Capture: 402C081, ReleaseTime: 4011632, Offset: 109135

      ....

      Capture: AB7E4076, ReleaseTime: AB7CA3AC, Offset: 105674

      Capture: AB82C60D, ReleaseTime: AB812C1B, Offset: 104946

      Capture: AB7E40F8, ReleaseTime: AB862BE5, Offset: 4294448403 (bad capture time high word == of high word of two records back)

      Capture: AB8CE0B5, ReleaseTime: AB8B45DF, Offset: 105174

      Capture: AB91E416, ReleaseTime: AB904987, Offset: 105103

      ....

      Capture: F1AF6C85, ReleaseTime: F1AE0BA8, Offset: 90333

      Capture: F1B36113, ReleaseTime: F1B212B1, Offset: 85602

      Capture: F1B86902, ReleaseTime: F1B6F36E, Offset: 95636

      Capture: F1B37AB9, ReleaseTime: F1BC3A5A, Offset: 4294393951  (bad capture time high word == of high word of two records back)

      Capture: F1C12F31, ReleaseTime: F1BFF240, Offset: 81137

       

      Here are the trigger and capture ISRs:

      //-------------------------------------------------------
      // Trigger signal ISR -  (interrupt priority 1)
      //-------------------------------------------------------
      CY_ISR(Trigger_ISR)         // ~3.5 us from Trigger pin signal to raising edge to TP0
      {
           TP0_Write(1u);          // start of pulse @ 3.5 us _|-|_  @ 22MHz IMO
         
         /* uint8 intrSrc = */    // not need to find out which pin interrupted if only one pin interrupt is used.
          TRGIN_ClearInterrupt();
         
          MEP_TIMER_SetInterruptMode(0);           // Disable interrupts
         
          ReleaseTime = MEP_TIMER_ReadCounter();      // Get trigger in progress GENERATES INTERRUPT (documentation is incorrect)
          MEP_TIMER_ReadCapture();                               // Clear FIFO ( it seems that sometimes this reading remains in the FIFO)
         
          MEP_TIMER_ReadStatusRegister();               // remove interrupt


          MEP_TIMER_SetInterruptMode(MEP_TIMER_STATUS_CAPTURE_INT_EN_MASK| MEP_TIMER_STATUS_OVERFLOW_INT_EN_MASK ); 
       
          TP0_Write(0u);          //  _|-|_ end of pulse ~15.5 us @ 22MHz IMO
      }

      //-------------------------------------------------------
      // MEP Timer ISR  (interrupt priority 1)
      //-------------------------------------------------------
      CY_ISR(MEP_Timer_ISR)
      {
        char mep_str[200];

        TP1_Write(1u);
         
          MEP_TIMER_SetInterruptMode(0);                      // Disable interrupts
         
          uint8 status = MEP_TIMER_ReadStatusRegister();        // Clears the interrupt
         
          do
          {
              if ((status & MEP_TIMER_STATUS_CAPTURE) )
              {
                  MEP_Capture_Time = MEP_TIMER_ReadCapture();
              }

              if ((status & MEP_TIMER_STATUS_FIFONEMP) )
              {
                 /* MEP_Capture_Time =*/ MEP_TIMER_ReadCapture();
              }
             
              if ((status & MEP_TIMER_STATUS_CMP) )
              {
                  uint32 ct = MEP_TIMER_ReadCounter();
                  sprintf(mep_str,"Compare trigger at: %lu\r\n", ct);
                  UART_2_UartPutString(mep_str);
              }

              if ((status & MEP_TIMER_STATUS_OVERFLOW) ) // Hour rollover
              {
                  TimerHours++;
                 
                  sprintf(mep_str,"MEP timer Roll over: %ld\r\n", TimerHours );
                  UART_2_UartPutString(mep_str);
              }
               status = MEP_TIMER_ReadStatusRegister();
             
          } while(status & (MEP_TIMER_STATUS_OVERFLOW|MEP_TIMER_STATUS_CMP|MEP_TIMER_STATUS_CAPTURE|MEP_TIMER_STATUS_FIFONEMP));
         
          MEP_TIMER_SetInterruptMode(MEP_TIMER_STATUS_OVERFLOW_INT_EN_MASK);   // Keep rollover interrupt only
              
          TP1_Write(0u);   //  _|-|_  pulse 2 ~15.5 us @ 22MHz IMO
      }