GPS pulse-per-second precise timing

I have a Fez Panda II with DIO34 connected to the pulse-per-second (PPS) signal on a GPS module. I am trying to precisely measure the processor’s time when PPS is asserted, in order to measure the error of the processor’s clock.

What I’m doing seems to work fine when the Fez is otherwise idle, but when I start introducing a lot of UART traffic, I start to see much more imprecision in my measurements.

This is the RLP code I am using:


void PPS_Interrupt ( unsigned int Pin, unsigned int PinState, void* Param )
{
    RLPext->PostManagedEvent(0);
}

int InitPPS(unsigned int *generalArray, void **args, unsigned int argsCount, unsigned int *argData)
{
    RLP_InterruptInputPinArgs Args;
    Args.GlitchFilterEnable  = RLP_TRUE; // Enable Glitch Filter
    Args.IntEdge = RLP_GPIO_INT_EDGE_HIGH; // Interrupt on Rising Edge
    Args.ResistorState = RLP_GPIO_RESISTOR_PULLUP; // Enable internal pull-up resistor
    RLPext->GPIO.EnableInterruptInputMode(
       12,            // unsigned int Pin, 
       &Args,         // RLP_InterruptInputPinArgs *args, 
       PPS_Interrupt, // RLP_GPIO_INTERRUPT_SERVICE_ROUTINE ISR, 
       (void*)0       // void* ISR_Param
    );
    return 0;
}

and this is the prototype of the RLP Event handler:


static void RLP_RLPEvent(uint data, DateTime TimeStamp)

The TimeStamp value has a precision of 0.1 microseconds, which is great, and I have been able to use this to measure the Fez clock’s error as about 26 microseconds fast; here is what a sequence of my measurements look like:


-26.3
-26.4
-26.4
-26.4
-26.4
-26.4
-26.3
-26.4
-26.4
-26.4
-26.3
-26.4
-26.3
-26.4
-26.4
-26.4
-26.3
-26.3
-26.4
-26.3
-26.4
-26.3
-26.3
-26.4
-26.4
-26.3
-26.3
-26.3
-26.4
-26.3

The problem I’m having is when I start to introduce a lot of UART traffic, my measurements start to look a lot more imprecise, for example:


-26.2
-26.3
-26.2
-26.3
-26.3
-19.7
-32.8
-26.3
-17.5
-35.1
-18.4
-34.1
-17.6
-35.1
-26.3
-26.3
-17.5
19.7
-72.3
-35.2
-26.3
-26.4
-26.3
-17.5
-26.4
-35.1
-26.3
-26.4
-17.5
-26.3
-35.2

I’m guessing that the UART interrupt handler is preventing my GPIO handler from running immediately, causing software latency in the TimeStamp measurement. Does this sound reasonable, and if so, is there a way around this problem?

Thanks,
-Frank

If you don’t use RLP, and just use a normal NETMF interrupt, and use the timestamp there, do you get better performance when the UART fires up more?

Hi Brett,

I actually tried using an NETMF interrupt first. Both approaches show the same effect.

Frank

The solution I found for this problem was to use the timer 0 capture registers to capture the timer count when the PPS signal is asserted. Here are some code snippets:


static uint T0BASE = 0xE0004000;
static Register T0CCR = new Register(T0BASE + 0x28);
static Register T0CR0 = new Register(T0BASE + 0x2c);
static Register T0TC = new Register(T0BASE + 0x08);
static Register PINSEL3 = new Register(0xE002C00C);

This sets up the timer capture:


// Pin P1.26 is CAP0.0
PINSEL3.Write(0x00300000);

// Capture on CAPn.0 rising edge: a sequence of 0 then 1 on
// CAP0.0 will cause CR0 to be loaded with the contents of TC.
T0CCR.Write(1);

In the PPS interrupt handler, I capture the current value of the timer, the current DateTime, and the captured timer value:


uint tc = T0TC.Read();
DateTime now = DateTime.Now;  
uint cr = T0CR0.Read();

I can take the difference of the two timer 0 values:


uint latency = tc - cr;

which will tell me how much time has elapsed between the assertion of PPS and the current time. On my Fez Panda II, one timer 0 tick is 1/18th of a microsecond, so to convert timer 0 ticks to NETMF timer ticks, which are 1/10th of a microsecond:


uint latencySystemTicks = (latency * 10) / 18;

Finally, to determine the DateTime of the PPS assertion:


DateTime ppsDateTime = new DateTime(now.Ticks - latencySystemTicks);

I welcome any comments.

-Frank

I did something very similar on an ADuC (also ARM based). Glad you found a solution.

as Brett said, this can be done simply in managed code. when you get an interrupt store system time passed. then when you get the next gps message, decode the the time. the difference between the gps and stored system time is the system error.