📄 enet_ptpd.c
字号:
//*****************************************************************************
//
// Initialization code for PTPD software system tick timer.
//
//*****************************************************************************
void
ptpd_systick_init(void)
{
//
// Initialize the System Tick Timer to run at specified frequency.
//
SysTickPeriodSet(SysCtlClockGet() / SYSTICKHZ);
//
// Initialize the timer reload values for fine-tuning in the handler.
//
g_ulSystemTickReload = SysTickPeriodGet();
g_ulNewSystemTickReload = g_ulSystemTickReload;
//
// Enable the System Tick Timer.
//
SysTickEnable();
SysTickIntEnable();
}
//*****************************************************************************
//
// Initialization code for PTPD software.
//
//*****************************************************************************
void
ptpd_init(void)
{
unsigned long ulTemp;
//
// Clear out all of the run time options and protocol stack options.
//
memset(&g_sRtOpts, 0, sizeof(g_sRtOpts));
memset(&g_sPTPClock, 0, sizeof(g_sPTPClock));
//
// Initialize all PTPd run time options to a valid, default value.
//
g_sRtOpts.syncInterval = DEFUALT_SYNC_INTERVAL;
memcpy(g_sRtOpts.subdomainName, DEFAULT_PTP_DOMAIN_NAME,
PTP_SUBDOMAIN_NAME_LENGTH);
memcpy(g_sRtOpts.clockIdentifier, IDENTIFIER_DFLT, PTP_CODE_STRING_LENGTH);
g_sRtOpts.clockVariance = DEFAULT_CLOCK_VARIANCE;
g_sRtOpts.clockStratum = DEFAULT_CLOCK_STRATUM;
g_sRtOpts.clockPreferred = FALSE;
g_sRtOpts.currentUtcOffset = DEFAULT_UTC_OFFSET;
g_sRtOpts.epochNumber = 0;
memcpy(g_sRtOpts.ifaceName, "LMI", strlen("LMI"));
g_sRtOpts.noResetClock = DEFAULT_NO_RESET_CLOCK;
g_sRtOpts.noAdjust = FALSE;
g_sRtOpts.displayStats = FALSE;
g_sRtOpts.csvStats = FALSE;
g_sRtOpts.unicastAddress[0] = 0;
g_sRtOpts.ap = DEFAULT_AP;
g_sRtOpts.ai = DEFAULT_AI;
g_sRtOpts.s = DEFAULT_DELAY_S;
g_sRtOpts.inboundLatency.seconds = 0;
g_sRtOpts.inboundLatency.nanoseconds = DEFAULT_INBOUND_LATENCY;
g_sRtOpts.outboundLatency.seconds = 0;
g_sRtOpts.outboundLatency.nanoseconds = DEFAULT_OUTBOUND_LATENCY;
g_sRtOpts.max_foreign_records = DEFUALT_MAX_FOREIGN_RECORDS;
g_sRtOpts.slaveOnly = TRUE;
g_sRtOpts.probe = FALSE;
g_sRtOpts.probe_management_key = 0;
g_sRtOpts.probe_record_key = 0;
g_sRtOpts.halfEpoch = FALSE;
//
// Initialize the PTP Clock Fields.
//
g_sPTPClock.foreign = &g_psForeignMasterRec[0];
//
// Configure port "uuid" parameters.
//
g_sPTPClock.port_communication_technology = PTP_ETHER;
EthernetMACAddrGet(ETH_BASE, (unsigned char *)g_sPTPClock.port_uuid_field);
//
// Enable Ethernet Multicast Reception (required for PTPd operation).
// Note: This must follow lwIP/Ethernet initialization.
//
ulTemp = EthernetConfigGet(ETH_BASE);
ulTemp |= ETH_CFG_RX_AMULEN;
if(HWREGBITW(&g_ulFlags, FLAG_HWTIMESTAMP))
{
ulTemp |= ETH_CFG_TS_TSEN;
}
EthernetConfigSet(ETH_BASE, ulTemp);
//
// Run the protocol engine for the first time to initialize the state
// machines.
//
protocol_first(&g_sRtOpts, &g_sPTPClock);
}
//*****************************************************************************
//
// Run the protocol engine loop/poll.
//
//*****************************************************************************
void
ptpd_tick(void)
{
//
// Run the protocol engine for each pass through the main process loop.
//
protocol_loop(&g_sRtOpts, &g_sPTPClock);
}
//*****************************************************************************
//
// Adjust the supplied timestamp to account for interrupt latency.
//
//*****************************************************************************
void
adjust_rx_timestamp(TimeInternal *psRxTime, unsigned long ulRxTime,
unsigned long ulNow)
{
unsigned long ulCorrection;
//
// Time parameters ulNow and ulRxTime are assumed to have originated from
// a 16 bit down counter operating over its full range.
//
//
// Determine the number of cycles between the receive timestamp and the
// point that it was read.
//
if(ulNow < ulRxTime)
{
//
// The timer didn't wrap between the timestamp and now.
//
ulCorrection = ulRxTime - ulNow;
}
else
{
//
// The timer wrapped between the timestamp and now
//
ulCorrection = ulRxTime + (0x10000 - ulNow);
}
//
// Convert the correction from cycles to nanoseconds.
//
ulCorrection *= TICKNS;
//
// Subtract the correction from the supplied timestamp value.
//
if(psRxTime->nanoseconds >= ulCorrection)
{
//
// In this case, we need only adjust the nanoseconds value since there
// is no borrow from the seconds required.
//
psRxTime->nanoseconds -= ulCorrection;
}
else
{
//
// Here, the adjustment affects both the seconds and nanoseconds
// fields. The correction cannot be more than 1 second (16 bit counter
// maximum offset and minimum cycle time of 125nS gives a maximum
// correction of 8.192mS) so we don't need to perform any nasty, slow
// modulo calculations here.
//
psRxTime->seconds--;
psRxTime->nanoseconds += (1000000000 - ulCorrection);
}
}
//*****************************************************************************
//
// Main entry point for sample PTPd/lwIP application.
//
//*****************************************************************************
int
main(void)
{
unsigned long ulUser0, ulUser1;
unsigned char pucMACArray[8];
volatile unsigned long ulDelay;
//
// Set the system clocking as defined above in SYSDIV and CLKUSE.
//
SysCtlClockSet(SYSDIV | CLKUSE | SYSCTL_OSC_MAIN | SYSCTL_XTAL_8MHZ);
//
// Set up for debug output to the UART.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);
GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1);
UARTStdioInit(0);
//
// Initialize the OLED display.
//
RIT128x96x4Init(1000000);
RIT128x96x4StringDraw("PTPd with lwIP", 24, 0, 15);
//
// Enable and Reset the Ethernet Controller.
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_ETH);
SysCtlPeripheralReset(SYSCTL_PERIPH_ETH);
IntPrioritySet(INT_ETH, ETHERNET_INT_PRIORITY);
//
// Enable Port F for Ethernet LEDs.
// LED0 Bit 3 Output
// LED1 Bit 2 Output
//
SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
GPIODirModeSet(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3, GPIO_DIR_MODE_HW);
GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_2 | GPIO_PIN_3,
GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD);
//
// Configure the defined PPS GPIO for output.
//
SysCtlPeripheralEnable(PPS_GPIO_PERIPHERAL);
GPIOPinTypeGPIOOutput(PPS_GPIO_BASE, PPS_GPIO_PIN);
GPIOPinWrite(PPS_GPIO_BASE, PPS_GPIO_PIN, 0);
//
// We test the state of the SELECT button on the board (assuming it is
// present) and, if pressed, disable hardware timestamping of Ethernet
// packets. This allows us to test the PTP clock response in both cases
// without the need to recompile.
//
SysCtlPeripheralEnable(SEL_BTN_GPIO_PERIPHERAL);
GPIOPinTypeGPIOInput(SEL_BTN_GPIO_BASE, SEL_BTN_GPIO_PIN);
GPIOPadConfigSet(SEL_BTN_GPIO_BASE, SEL_BTN_GPIO_PIN, GPIO_STRENGTH_2MA,
GPIO_PIN_TYPE_STD_WPU);
//
// Wait a while before reading the GPIOs since we just modified the
// pad configuration.
//
for(ulDelay = 0; ulDelay < 10000; ulDelay++)
{
}
//
// If the SELECT button is pressed, the GPIO is pulled low so we read 0
// from GPIOPinRead. If we detect this, disable hardware Ethernet
// timestamping if available.
//
if(GPIOPinRead(SEL_BTN_GPIO_BASE, SEL_BTN_GPIO_PIN))
{
//
// Enable timer 3 to capture the timestamps of the incoming packets.
//
HWREGBITW(&g_ulFlags, FLAG_HWTIMESTAMP) = 1;
SysCtlPeripheralEnable(SYSCTL_PERIPH_TIMER3);
SysCtlPeripheralReset(SYSCTL_PERIPH_TIMER3);
//
// Configure Timer 3 as 2 16 bit counters. Timer B is used to capture
// the time of the last Ethernet RX interrupt and we leave Timer A free
// running to allow us to determine how much time has passed between
// the interrupt firing and the ISR actually reading the packet. Had
// we been interested in transmit timestamps, time 3A would have been
// used for this and a second timer block would be needed to provide
// the free-running reference count.
//
TimerConfigure(TIMER3_BASE, (TIMER_CFG_16_BIT_PAIR |
TIMER_CFG_A_PERIODIC |
TIMER_CFG_B_CAP_TIME));
TimerPrescaleSet(TIMER3_BASE, TIMER_BOTH, 0);
TimerLoadSet(TIMER3_BASE, TIMER_BOTH, 0xFFFF);
TimerControlEvent(TIMER3_BASE, TIMER_B, TIMER_EVENT_POS_EDGE);
//
// Start the timers running.
//
TimerEnable(TIMER3_BASE, TIMER_BOTH);
}
else
{
//
// The user was pressing the select button as the application started
// so we disable hardware timestamping.
//
HWREGBITW(&g_ulFlags, FLAG_HWTIMESTAMP) = 0;
RIT128x96x4StringDraw("H/W timestamps off", 0, 32, 15);
}
//
// Write the operating mode information to the display
//
if(HWREGBITW(&g_ulFlags, FLAG_HWTIMESTAMP))
{
RIT128x96x4StringDraw("H/W TS", 0, 72, 15);
}
//
// Configure SysTick for a periodic interrupt in PTPd system.
//
ptpd_systick_init();
//
// Enable processor interrupts.
//
IntMasterEnable();
//
// Configure the hardware MAC address for Ethernet Controller filtering of
// incoming packets.
//
// For the Luminary Micro Evaluation Kits, the MAC address will be stored
// in the non-volatile USER0 and USER1 registers. These registers can be
// read using the FlashUserGet function, as illustrated below.
//
FlashUserGet(&ulUser0, &ulUser1);
if((ulUser0 == 0xffffffff) || (ulUser1 == 0xffffffff))
{
//
// We should never get here. This is an error if the MAC address has
// not been programmed into the device. Exit the program.
//
RIT128x96x4StringDraw("MAC Address", 0, 16, 15);
RIT128x96x4StringDraw("Not Programmed!", 0, 24, 15);
DiagExit(2);
}
//
// Convert the 24/24 split MAC address from NV ram into a 32/16 split MAC
// address needed to program the hardware registers, then program the MAC
// address into the Ethernet Controller registers.
//
pucMACArray[0] = ((ulUser0 >> 0) & 0xff);
pucMACArray[1] = ((ulUser0 >> 8) & 0xff);
pucMACArray[2] = ((ulUser0 >> 16) & 0xff);
pucMACArray[3] = ((ulUser1 >> 0) & 0xff);
pucMACArray[4] = ((ulUser1 >> 8) & 0xff);
pucMACArray[5] = ((ulUser1 >> 16) & 0xff);
//
// Program the hardware with it's MAC address (for filtering).
//
EthernetMACAddrSet(ETH_BASE, pucMACArray);
//
// Initialize the file system.
//
fs_init();
//
// Initialize the Random Number Generator.
//
RandomSeed();
//
// Initialize all of the lwIP code, as needed, which will also initialize
// the low-level Ethernet code.
//
lwip_init();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -