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

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
GuGa_1322886
Level 4
Level 4
5 solutions authored 25 sign-ins First comment on KBA

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
}

0 Likes
1 Reply
VenkataD_41
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi Guillermo Gallo,

ThePlease use the latest version of PSoC Creator i.e PSoC Creator 4.2 to build your application to resolve the  issue.

Thanks

Ganesh

0 Likes