This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129 and EMAC IEEE-1588 TimeStamp Read Precision

Other Parts Discussed in Thread: TM4C129ENCPDT

Since the TM4C129 does not have 64 Bit Timers I am forced to use the IEEE-1588 TimeStamp to measure digital event timing which has a 40 nanosecond accuracy. I am using COARSE MODE.

EMACTimestampConfigSet(EMAC0_BASE, (EMAC_TS_PTP_VERSION_2 | EMAC_TS_DIGITAL_ROLLOVER | EMAC_TS_UPDATE_COARSE), 40);

During a digital interrupt routine I read the Seconds and Subseconds using the following statements (I am aware of the Subsecond Rollover and know how to test for it):

subseconds = HWREG(EMAC0_BASE + EMAC_O_TIMNANO);
seconds = HWREG(EMAC0_BASE + EMAC_O_TIMSEC);

The time difference from interrupt to interrupt normally is 0, which is what I expect since I am using a digital signal with a precision frequency.

However, every 5 to 7 reads I see a +120 nanosecond and then a -120 nanosecond which means something in the background is delaying my interrupt response for 3 updates of the IEEE-1588 clock which is 3 x 40 nanoseconds or about 14 - 15 Processor Clock Cycles.

Here is the pattern between successive reads (the left side is the time measurement of 51.199440 milliseconds and the right side is the difference between successive reads);

51199440 0
51199440 0
51199440 0
51199440 0
51199440 0
51199560 120
51199440 -120
51199440 0
51199440 0
51199440 0
51199440 0
51199440 0
51199560 120
51199440 -120
51199440 0
51199440 0
51199440 0
51199440 0
51199560 120
51199440 -120
51199440 0
51199440 0
51199440 0
51199440 0
51199440 0
51199560 120
51199440 -120

The Digital Interrupt is the ONLY interrupt I have programmed.

I have set the interrupt priority for the EMAC Interrupt below the Digital Signal Interrupt.

//Lower EMAC Interrupt Priority
IntPrioritySet(INT_EMAC0, 0x10);

//Enable Interrupt on Port E
IntPrioritySet(INT_GPIOE, 0);

Does anyone know what the problem might be or has anyone tested the IEEE-1588 TimeStamp for real world accuracy?

  • Hello Mark,

    14-15 processor clock cycles seems to be something to do with nested interrupts. When the variation occurs does the GPIO E interrupt get asserted?

    The EMAC time stamp is a hardware mechanism and it should not be affected by interrupts externally though. Also the time stamping is in sub-us range so is a ns accuracy very necessary?

    Regards
    Amit
  • I agree with your assessment.

    Yes, the GPIO E is asserted or else my elapsed time measurement would be twice as long.

    I need to measure time elapsed to less than 40 nanoseconds of difference. When I use a TM4C123 and a 64 Bit Timer I can hold +40 to -40 nanoseconds. My customer needs Ethernet so I am forced to use TM4C129.

    Interestingly, If I remove the IntPrioritySet(INT_EMAC0, 0x10), I measure +120 to -120 on almost every sample as shown here:

    51199560 120
    51199440 -120
    51199560 120
    51199440 -120
    51199560 120
    51199440 -120
    51199440 0
    51199560 120


    There is something else in the background affecting my interrupt response. Perhaps the DMA because I am using the EMACTxDMAPollDemand(EMAC0_BASE) instruction after writing the data to the Ethernet Port.
  • Hello Mark

    It could be. Can we change the priority of EMAC to be higher than GPIO?

    Regards
    Amit
  • Similar results to the first set of data at the beginning of this thread. Occurs a little more often.

    51199440 0
    51199440 0
    51199440 0
    51199560 120
    51199440 -120
    51199440 0
    51199440 0
    51199440 0
    51199560 120
    51199440 -120
    51199440 0
    51199440 0
    51199440 0
    51199560 120
    51199440 -120

    I also tried setting IntPrioritySet(INT_UDMA, 0x10) and IntPrioritySet(INT_EMAC0, 0x10) with same results as first set of data.
  • Mark LoBuono said:
    Since the TM4C129 does not have 64 Bit Timers I am forced to use the IEEE-1588 TimeStamp to measure digital event timing which has a 40 nanosecond accuracy.

    Mark have you considered synthesizing a 64bit timer?

    Robert

  • Hello Mark,

    Also to be noted that in TX path the PTP accuracy is 2 MOSC clocks which amounts to 80ns and on RX path the PTP accuracy is 3 MAC + 2 PTP clock which amounts to 24 (assuming 120MHz) + 80 ns = 104ns

    Regards
    Amit
  • Robert,

    I have but am concerned with latency of the rollover.

    Also, I may need the ability to do absolute time synchronization between multiple nodes which is why I need to understand my issue with reading IEEE-1588 TimeStamps.
  • Amit,

    I do not care about the PTP Ethernet Packet TimeStamping, I just need the ability to capture accurate TimeStamps with +40 to -40 nanoseconds).

    Why do I get so many consecutive 0 readings? Especially after inhibiting EMAC interrupt. Is there anything else you can think of that would affect my reading of the TimeStamp in my GPIO interrupt?

    I want to suspend all background interrupts until I have read the TimeStamp.

    If the MOSC clock does not update at least every 40ns then the TM4C129 is not a good fit for my project.

    Next, I am going to try suspending my Transmit Output to see if I can capture data in internal arrays.
  • Hello Mark,

    The minimum limit of 2 PTP clocks would still affect the accuracy.

    Regards
    Amit
  • Rollover wouldn't introduce any latency in the read value, it would add a little extra time to reading the value but if you really need 64bits that shouldn't be an issue. And there are methods you could use to reduce/eliminate even that extra time.

    Synchronization is another issue

    Robert
  • Amit,

    I have yet to see a reading of +40, +80 or -40,-80 in all of my tests for many weeks. It is always 0 or +120, -120.

    Do you have any explanation for this? There must be a reason for this.

    Can you tell me how TI certified / tested the IEEE-1588 system?
  • Amit,

    I disabled the Transmit Packet and get the same results in internal arrays, So, I am guessing it is not a DMA interrupt situation.
  • Hello Mark

    As I mentioned the inaccuracy can be up to 104 ns on the RX path, which is lesser than 120ns that you are measuring, and I cannot explain based on the documentation why only +/-120ns. However is it possible if you have multiple devices, that you can run to see if this value changes or not across some of the devices?

    Also 40ns is still not possible because 2 MOSC clock cycle transfer error.

    Regards
    Amit
  • Amit,

    I only have 1 TM4C129 and how do you explain all the successive 0 values?

    Can you answer my question about how TI tests this interface? I need to see some test code or just give up on using the TM4C129!
  • Hello Mark

    I cannot explain why 0's and 120 only and not any other value. The prime test for Ethernet is the UNH compliance testing which we have passed. I am finding out how I can get the UNH compliance report.

    Regards
    Amit
  • HI Mark ,I am working on using TM4C129X for IEEE 1588.Do you have any sample code ?Thank you so much
  • I do not have synchronization code examples. I only have code examples for how to read the IEEE-1588 clock values. What kind of time precision do you need?
  • I need 200ns.If you have some code examples,please show me.Thanks
  • Code Example for Capturing IEEE-1588 Timestamp

    // follow emac driverlib examples for any other ethernet functions

    #include "inc/hw_types.h"
    #include "inc/hw_emac.h"
    #include "driverlib/emac.h"
    #include "inc/tm4c129encpdt.h"

    // variables
    uint8_t ui8PHYAddr;
    static volatile uint32_t seconds;
    static volatile uint32_t subseconds;

    //enable ethernet
    SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
    while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));

    ui8PHYAddr = 0;

    // wait for the link to become active.
    while((EMACPHYRead(EMAC0_BASE, ui8PHYAddr, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0);

    // enable IEEE-1588 timestamps
    EMACTimestampConfigSet(EMAC0_BASE, (EMAC_TS_PTP_VERSION_2 | EMAC_TS_DIGITAL_ROLLOVER | EMAC_TS_UPDATE_FINE), 40);
    EMACTimestampAddendSet(EMAC0_BASE, 0x40000000);
    EMACTimestampEnable(EMAC0_BASE);

    // capture timestamp
    subseconds = HWREG(EMAC0_BASE + EMAC_O_TIMNANO);
    seconds = HWREG(EMAC0_BASE + EMAC_O_TIMSEC);

  • Hi Mark,

    How do you handle the subsecond overflow?
  • Here is the driverlib\emac.c way to handle possible nanoseconds overflow. Study the code for yourself.

    void
    EMACTimestampSysTimeGet(uint32_t ui32Base, uint32_t *pui32Seconds,
    uint32_t *pui32SubSeconds)
    {
    //
    // Parameter sanity check.
    //
    ASSERT(ui32Base == EMAC0_BASE);
    ASSERT(pui32Seconds);
    ASSERT(pui32SubSeconds);

    //
    // Read the two-part system time from the seconds and nanoseconds
    // registers. We do this in a way that should guard against us reading
    // the registers across a nanosecond wrap.
    //
    do
    {
    *pui32Seconds = HWREG(ui32Base + EMAC_O_TIMSEC);
    *pui32SubSeconds = HWREG(ui32Base + EMAC_O_TIMNANO);
    }
    while(*pui32SubSeconds > HWREG(ui32Base + EMAC_O_TIMNANO));
    }

    You will notice in my example that I read the nanoseconds first and then the seconds. if the nanoseconds value is 999,999,999 then that is the only time where my code would allow the seconds to increase by one in between the read nanoseconds and then read seconds. That is a 1 in 1 billion chance. If you cannot tolerate that possibility then use the emac.c code example. This will affect accuracy greatly if the roll over occurs during the library read.

    Read the comment above that states "should guard against us reading the registers across a nanosecond wrap". Notice the word "should".

  • Thank you! This is very helpful.
  • I know it's been a while since this post was last updated. Have you found an acceptable solution?

    Here's how I get timestamps with 8.3333 ns resolution.

    I set up TIMER0 so I can just read a value any time I need it and it will count CPU clocks (120 MHz). I set it up like this:

    // configure timer 0 so we can read clock ticks to time things accurately
    MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER0);
    MAP_TimerConfigure(TIMER0_BASE, TIMER_CFG_PERIODIC_UP);
    MAP_TimerLoadSet(TIMER0_BASE, TIMER_A, 0xffffffff);
    MAP_TimerEnable(TIMER0_BASE, TIMER_A);

    Then read it like this when I need a timestamp:

    uint32_t current_clock = TimerValueGet(TIMER0_BASE, TIMER_A);

    It wraps every 35.8 seconds, but I can handle that elsewhere if needed

    Patrick
  • Patrick,

    Thanks for the feedback.

    I never did get this resolved since I need a real time clock with Seconds - Nanoseconds (POSIX Time Format) based on IEEE - 1588 Time Stamps. I gave up on TI Controllers for my application since TI offered no help to me.

    Your elapsed time measurement method is a good one so thanks for that.

  • Converting those timestamps to seconds/nanoseconds would be straightforward, but that's not the point. I hope you found something more useful? I've been using the Tiva processor (and Stellaris before that) for over 3 years now. I really like them and have found lots of ways to make the most of the chip.

    I was looking into implementing 1588 on the Tiva, which is how I found your post. It doesn't look like anyone has posted that they've actually gotten 1588 working on the Tiva, but it looks like the hooks are all there? (certainly in the hardware) We'll see....

    Patrick
  • Patrick,

    If you can live with +120ns / -120ns then the Tiva will work for your applications. The theoretical time stamp resolution is 40ns with a 25MHz clock on the Ethernet. I could have lived with +40ns / -40ns for my application. I had a customer who wanted to measure absolute time precision with +25ns / -25ns. This was I close as I could get using a low cost interface. No one at TI could explain the 120ns deviations and why they were happening. If you ever figure it out then please let me know.

    Were you the one I sent my source code to?

  • I suspect the +/- 40ns issue was due to an edge condition? That's less than 5 CPU clocks. That's why I used the CPU clock in a timer and got my 8.33ns resolution. That would have given you enough resolution for your customer, right?

    No, I was not the one you sent your source code to. I only found this thread today while investigating the possibility of implementing 1588 on the Tiva myself.
  • #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    #include "inc/hw_gpio.h"
    #include "inc/hw_memmap.h"
    #include "inc/hw_sysctl.h"
    #include "inc/hw_types.h"
    #include "inc/hw_emac.h"
    #include "driverlib/gpio.h"
    #include "driverlib/interrupt.h"
    #include "driverlib/pin_map.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/emac.h"
    #include "driverlib/flash.h"
    #include "inc/tm4c129encpdt.h"
    
    //Interrupts Configuration
    #define GPIO_EPINS 0x0F
    #define BUFSIZ 10000
    static volatile uint8_t value;
    static volatile uint32_t seconds;
    static volatile uint32_t subseconds;
    static volatile uint32_t addptr = 0;
    static volatile uint32_t remptr = 0;
    static volatile uint32_t tmpptr = 0;
    uint8_t valuebuf[BUFSIZ];
    uint32_t secondsbuf[BUFSIZ];
    uint32_t subsecondsbuf[BUFSIZ];
    
    void
    IntGPIOE(void)
    {
    	//Capture Timestamp
    	subseconds = HWREG(EMAC0_BASE + EMAC_O_TIMNANO);
    	seconds = HWREG(EMAC0_BASE + EMAC_O_TIMSEC);
    
    	//Capture Value
    	value = 0xF0;
    	value |= GPIO_PORTE_AHB_DATA_R & GPIO_EPINS;
    
    	//Clear Edge Triggered Interrupt
    	GPIOIntClear(GPIO_PORTE_AHB_BASE, GPIO_EPINS);
    
    	//Store Data in Buffers
    	valuebuf[addptr] = ~value;
    	secondsbuf[addptr] = seconds;
    	subsecondsbuf[addptr] = subseconds;
    
    	if (addptr < BUFSIZ - 1)
    		addptr++;
    	else
    		addptr = 0;
    };
    
    //Ethernet Configuration
    #define PKTSIZ 9
    #define PKTHDR 42
    uint8_t databuf[PKTHDR + PKTSIZ];
    uint32_t sendbytes;
    uint32_t ui32User0, ui32User1, ui32SysClock;
    uint8_t ui8PHYAddr;
    uint8_t pui8MACAddr[6];
    
    #define NUM_TX_DESCRIPTORS 3
    tEMACDMADescriptor g_psTxDescriptor[NUM_TX_DESCRIPTORS];
    uint32_t g_ui32TxDescIndex;
    
    void
    InitDescriptors(uint32_t ui32Base)
    {
    	uint32_t ui32Loop;
    
    	//Initialize each of the transmit descriptors
    	for(ui32Loop = 0; ui32Loop < NUM_TX_DESCRIPTORS; ui32Loop++)
    	{
    		g_psTxDescriptor[ui32Loop].ui32Count = DES1_TX_CTRL_SADDR_INSERT;
    		g_psTxDescriptor[ui32Loop].DES3.pLink = (ui32Loop == (NUM_TX_DESCRIPTORS - 1)) ? g_psTxDescriptor : &g_psTxDescriptor[ui32Loop + 1];
    		g_psTxDescriptor[ui32Loop].ui32CtrlStatus = (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_IP_ALL_CKHSUMS);
    	}
    
    	//Set the descriptor pointers in the hardware.
    	EMACTxDMADescriptorListSet(ui32Base, g_psTxDescriptor);
    
    	//Start from the beginning of descriptor chains
    	g_ui32TxDescIndex = NUM_TX_DESCRIPTORS - 1;
    }
    
    //Transmit a packet from the supplied buffer
    static int32_t
    SendPacket(uint8_t *pui8Buf, int32_t i32BufLen)
    {
    
    	//Wait for the transmit descriptor to free up.
    	while(g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus & DES0_TX_CTRL_OWN)
    	{
    		//Spin and waste time.
    	}
    
    	//Move to the next descriptor.
    	g_ui32TxDescIndex++;
    	if(g_ui32TxDescIndex == NUM_TX_DESCRIPTORS)
    	{
    		g_ui32TxDescIndex = 0;
    	}
    
    	//Fill in the packet size and pointer, and tell the transmitter to start
    	g_psTxDescriptor[g_ui32TxDescIndex].ui32Count = (uint32_t)i32BufLen;
    	g_psTxDescriptor[g_ui32TxDescIndex].pvBuffer1 = pui8Buf;
    	g_psTxDescriptor[g_ui32TxDescIndex].ui32CtrlStatus = (DES0_TX_CTRL_LAST_SEG | DES0_TX_CTRL_FIRST_SEG | DES0_TX_CTRL_IP_ALL_CKHSUMS | DES0_TX_CTRL_CHAINED | DES0_TX_CTRL_OWN);
    
    	//Tell the DMA to reacquire the descriptor
    	EMACTxDMAPollDemand(EMAC0_BASE);
    
    	//Return the number of bytes sent.
    	return(i32BufLen);
    }
    
    void
    InitPacket(void)
    {
    	uint32_t count;
    
    	//Clear Data Packet
    	memset(&databuf[0], 0, sizeof(databuf));
    
    	//Ethernet Destination
    	for (count = 0; count < 6; count++)
    	{
    		databuf[count] = 0;
    	}
    
    	//Ethernet Source
    	for (count = 0; count < 6; count++)
    	{
    		databuf[count + 6] = pui8MACAddr[count];
    	}
    
    	//Ethernet Type
    	databuf[12] = 0x08;
    
    	//IP Protocol Version, Header Length
    	databuf[14] = 0x45;
    
    	//IP Protocol Total Length (PKTHDR + PKTSIZ) - 14
    	databuf[16] = 0x00;
    	databuf[17] = (PKTHDR + PKTSIZ) - 14;
    
    	//IP Flags = Do Not Fragment
    	databuf[20] = 0x40;
    
    	//IP Protocol TTL = 64
    	databuf[22] = 0x40;
    
    	//IP Protocol UDP = 17
    	databuf[23] = 0x11;
    
    	//IP Protocol Header Checksum
    	databuf[24] = 0xCE;
    	databuf[25] = 0x7C;
    
    	//IP Protocol Source
    	databuf[26] = 0;
    	databuf[27] = 0;
    	databuf[28] = 0;
    	databuf[29] = 0;
    
    	//IP Protocol Destination
    	databuf[30] = 0;
    	databuf[31] = 0;
    	databuf[32] = 0;
    	databuf[33] = 0;
    
    	//UDP Protocol Source = Port 49999
    	databuf[34] = 0xC3;
    	databuf[35] = 0x4F;
    
    	//UDP Protocol Destination = Port 49999
    	databuf[36] = 0xC3;
    	databuf[37] = 0x4F;
    
    	//UDP Length = PKTSIZ + 8
    	databuf[38] = 0x00;
    	databuf[39] = PKTSIZ + 8;
    }
    
    int
    main(void)
    {
    	uint32_t count, index;
    
    	//Initialize Buffers
    	memset(&valuebuf[0], 0, sizeof(valuebuf));
    	memset(&secondsbuf[0], 0, sizeof(secondsbuf));
    	memset(&subsecondsbuf[0], 0, sizeof(subsecondsbuf));
    
    	//System Clock Setting
    	ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ | SYSCTL_OSC_MAIN | SYSCTL_USE_PLL | SYSCTL_CFG_VCO_480), 120000000);
    
    	//Read the MAC address from the user registers.
    	FlashUserGet(&ui32User0, &ui32User1);
    	if((ui32User0 == 0xffffffff) || (ui32User1 == 0xffffffff))
    	{
    		while(1)
    		{
    		}
    	}
    
    	//MAC Address into the Ethernet Controller registers.
    	pui8MACAddr[0] = ((ui32User0 >> 0) & 0xff);
    	pui8MACAddr[1] = ((ui32User0 >> 8) & 0xff);
    	pui8MACAddr[2] = ((ui32User0 >> 16) & 0xff);
    	pui8MACAddr[3] = ((ui32User1 >> 0) & 0xff);
    	pui8MACAddr[4] = ((ui32User1 >> 8) & 0xff);
    	pui8MACAddr[5] = ((ui32User1 >> 16) & 0xff);
    
    	//Enable Ethernet
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_EMAC0);
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_EPHY0);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_EMAC0));
    
    	ui8PHYAddr = 0;
    	EMACPHYConfigSet(EMAC0_BASE, (EMAC_PHY_TYPE_INTERNAL | EMAC_PHY_AN_100B_T_HALF_DUPLEX));
    	EMACReset(EMAC0_BASE);
    	EMACInit(EMAC0_BASE, ui32SysClock, EMAC_BCONFIG_PRIORITY_FIXED, 4, 4, 0);
    
    	//Set MAC configuration options
    	EMACConfigSet(EMAC0_BASE,
    	(EMAC_CONFIG_HALF_DUPLEX |
    	EMAC_CONFIG_IF_GAP_96BITS |
    	EMAC_CONFIG_BO_LIMIT_1024),
    	(EMAC_MODE_TX_STORE_FORWARD |
    	EMAC_MODE_TX_THRESHOLD_64_BYTES), 146);
    
    	//Initialize the Ethernet DMA descriptors.
    	InitDescriptors(EMAC0_BASE);
    
    	//Initialize UDP Packet
    	InitPacket();
    
    	//EMACFrameFilterSet(EMAC0_BASE, (EMAC_FRMFILTER_HASH_AND_PERFECT | EMAC_FRMFILTER_PASS_MULTICAST));
    	EMACAddrSet(EMAC0_BASE, 0, pui8MACAddr);
    
    	//Wait for the link to become active.
    	while((EMACPHYRead(EMAC0_BASE, ui8PHYAddr, EPHY_BMSR) & EPHY_BMSR_LINKSTAT) == 0)
    	{
    	}
    
    	EMACTxEnable(EMAC0_BASE);
    
    	EMACPHYWrite(EMAC0_BASE, 0, EPHY_BMCR, (EPHY_BMCR_ANEN | EPHY_BMCR_RESTARTAN));
    
    	//Enable IEEE-1588 Timestamps
    	EMACTimestampConfigSet(EMAC0_BASE, (EMAC_TS_PTP_VERSION_2 | EMAC_TS_DIGITAL_ROLLOVER | EMAC_TS_UPDATE_FINE), 40);
    	EMACTimestampAddendSet(EMAC0_BASE, 0x40000000);
    	EMACTimestampEnable(EMAC0_BASE);
    
    	//Configure Port E Inputs
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOE);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOE));
    	SysCtlGPIOAHBEnable(SYSCTL_PERIPH_GPIOE);
    	GPIOPinTypeGPIOInput(GPIO_PORTE_AHB_BASE, GPIO_EPINS);
    	GPIOPadConfigSet(GPIO_PORTE_AHB_BASE, GPIO_EPINS, GPIO_STRENGTH_8MA, GPIO_PIN_TYPE_STD_WPU);
    	GPIOIntRegister(GPIO_PORTE_AHB_BASE, IntGPIOE);
    	GPIOIntTypeSet(GPIO_PORTE_AHB_BASE, GPIO_EPINS, GPIO_BOTH_EDGES);
    
    	//Configure Port F MAC LEDS
    	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    	while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOF));
    	GPIOPinConfigure(GPIO_PF0_EN0LED0);
    	GPIOPinConfigure(GPIO_PF4_EN0LED1);
    	GPIOPinTypeEthernetLED(GPIO_PORTF_BASE, GPIO_PIN_0 | GPIO_PIN_4);
    
    	//Configure Port N User LEDS
        SysCtlPeripheralEnable(SYSCTL_PERIPH_GPION);
        while(!SysCtlPeripheralReady(SYSCTL_PERIPH_GPION));
        GPIOPinTypeGPIOOutput(GPIO_PORTN_BASE, GPIO_PIN_0 | GPIO_PIN_1);
    
        //Turn On User LED 1
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_1, GPIO_PIN_1);
    
        //Turn Off User LED 2
        GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
    
        //Enable Interrupt on Port E
        IntPrioritySet(INT_GPIOE, 0);
        GPIOIntEnable(GPIO_PORTE_AHB_BASE, GPIO_EPINS);
    
        //Control Loop
        while(1)
        {
        	//Freeze Add Pointer
        	tmpptr = addptr;
    
        	//Check for New Data
        	if (tmpptr != remptr)
        	{
        		//Turn On LED 2
        		GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, GPIO_PIN_0);
    
        		//Clear Packet Data
        		for (count = PKTHDR; count < PKTHDR + PKTSIZ; count++)
        		{
        			databuf[count] = 0;
        		}
    
        		//Process Packet Data
        		index = PKTHDR;
        		//Copy Value
        		memcpy(&databuf[index], &valuebuf[remptr], 1);
        		index += 1;
        		//Copy Seconds
        		memcpy(&databuf[index], &secondsbuf[remptr], 4);
        		index += 4;
        		//Copy Subseconds
        		memcpy(&databuf[index], &subsecondsbuf[remptr], 4);
        		index += 4;
    
        		if (remptr < BUFSIZ - 1)
        			remptr++;
        		else
        			remptr = 0;
    
    			//Send Data Packet
    			sendbytes = 0;
        		sendbytes = SendPacket(&databuf[0], sizeof(databuf));
    
        		//Turn Off LED 2
        		GPIOPinWrite(GPIO_PORTN_BASE, GPIO_PIN_0, 0);
        	}
        }
    }
    

  • Patrick,

    I attached the source code for my experiments. Maybe it will help you out. I was using a GPIO Interrupt to get the clock values. Good Luck and I hope it helps.
  • Thanks. I'll check it out.