📄 enet_ptpd.c
字号:
//*****************************************************************************
//
// enet_ptpd.c - Sample PTPd Application using lwIP.
//
// Copyright (c) 2007 Luminary Micro, Inc. All rights reserved.
//
// Software License Agreement
//
// Luminary Micro, Inc. (LMI) is supplying this software for use solely and
// exclusively on LMI's microcontroller products.
//
// The software is owned by LMI and/or its suppliers, and is protected under
// applicable copyright laws. All rights are reserved. You may not combine
// this software with "viral" open-source software in order to form a larger
// program. Any use in violation of the foregoing restrictions may subject
// the user to criminal sanctions under applicable laws, as well as to civil
// liability for the breach of the terms and conditions of this license.
//
// THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
// OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
// LMI SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
// CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
//
// This is part of revision 1952 of the Stellaris Peripheral Driver Library.
//
//*****************************************************************************
#include "../../../hw_memmap.h"
#include "../../../hw_types.h"
#include "../../../hw_ints.h"
#include "../../../src/ethernet.h"
#include "../../../src/interrupt.h"
#include "../../../src/sysctl.h"
#include "../../../src/systick.h"
#include "../../../src/flash.h"
#include "../../../src/gpio.h"
#include "../../../src/timer.h"
#include "../../../utils/diag.h"
#include "../../../utils/ustdlib.h"
#include "../../../utils/uartstdio.h"
#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/sys.h"
#include "../rit128x96x4.h"
#include "random.h"
#include "ptpd.h"
#include "globals.h"
//*****************************************************************************
//
//! \addtogroup ek_lm3s8962_list
//! <h1>Ethernet IEEE 1588 (PTPd) with lwIP (enet_ptpd)</h1>
//!
//! This example application demonstrates the operation of the Stellaris
//! Ethernet controller using the lwIP TCP/IP Stack. DHCP is used to obtain an
//! Ethernet address. If DHCP times out without obtaining an address, a static
//! IP address will be used. The DHCP timeout and the default static IP are
//! easily configurable using macros. The address that is selected will be
//! shown on the OLED display.
//!
//! A default set of pages will be served up by an internal file system and
//! the httpd server.
//!
//! The IEEE 1588 (PTP) software has been enabled in this code to synchronize
//! the internal clock to a network master clock source.
//!
//! Two methods of receive packet timestamping are implemented. The default
//! mode uses the Stellaris hardware timestamp mechanism to capture Ethernet
//! packet reception time using timer 3B. On parts which do not support
//! hardware timestamping or if the application is started up with the
//! Evaluation Kit "Select" button pressed, software time stamping is used.
//!
//! For additional details on lwIP, refer to the lwIP web page at:
//! http://www.sics.se/~adam/lwip/
//!
//! For additional details on the PTPd software, refer to the PTPd web page at:
//! http://ptpd.sourceforge.net
//
//*****************************************************************************
//*****************************************************************************
//
// Define the system clock rate here. One of the following must be defined to
// choose the system clock rate.
//
//*****************************************************************************
//#define SYSTEM_CLOCK_8MHZ
//#define SYSTEM_CLOCK_20MHZ
//#define SYSTEM_CLOCK_25MHZ
#define SYSTEM_CLOCK_50MHZ
//*****************************************************************************
//
// Clock and PWM dividers used depend on which system clock rate is chosen.
//
//*****************************************************************************
#if defined(SYSTEM_CLOCK_8MHZ)
#define SYSDIV SYSCTL_SYSDIV_1
#define PWMDIV SYSCTL_PWMDIV_1
#define CLKUSE SYSCTL_USE_OSC
#define TICKNS 125
#elif defined(SYSTEM_CLOCK_20MHZ)
#define SYSDIV SYSCTL_SYSDIV_10
#define PWMDIV SYSCTL_PWMDIV_2
#define CLKUSE SYSCTL_USE_PLL
#define TICKNS 50
#elif defined(SYSTEM_CLOCK_25MHZ)
#define SYSDIV SYSCTL_SYSDIV_8
#define PWMDIV SYSCTL_PWMDIV_2
#define CLKUSE SYSCTL_USE_PLL
#define TICKNS 40
#elif defined(SYSTEM_CLOCK_50MHZ)
#define SYSDIV SYSCTL_SYSDIV_4
#define PWMDIV SYSCTL_PWMDIV_2
#define CLKUSE SYSCTL_USE_PLL
#define TICKNS 20
#else
#error "System clock speed is not defined properly!"
#endif
//*****************************************************************************
//
// Select button GPIO definitions. The GPIO defined here is assumed to be
// attached to a button which, when pressed during application initialization,
// signals that Ethernet packet timestamping hardware is not to be used. If
// the button is not pressed, the hardware timestamp feature will be used if
// it is available on the target IC.
//
//*****************************************************************************
#define SEL_BTN_GPIO_PERIPHERAL SYSCTL_PERIPH_GPIOF
#define SEL_BTN_GPIO_BASE GPIO_PORTF_BASE
#define SEL_BTN_GPIO_PIN GPIO_PIN_1
//*****************************************************************************
//
// Pulse Per Second (PPS) Output Definitions
//
//*****************************************************************************
#define PPS_GPIO_PERIPHERAL SYSCTL_PERIPH_GPIOB
#define PPS_GPIO_BASE GPIO_PORTB_BASE
#define PPS_GPIO_PIN GPIO_PIN_0
//*****************************************************************************
//
// The following group of labels define the priorities of each of the interrupt
// we use in this example. SysTick must be high priority and capable of
// preempting other interrupts to minimize the effect of system loading on the
// timestamping mechanism.
//
// The application uses the default Priority Group setting of 0 which means
// that we have 8 possible preemptable interrupt levels available to us using
// the 3 bits of priority available on the Stellaris microcontrollers with
// values from 0xE0 (lowest priority) to 0x00 (highest priority).
//
//*****************************************************************************
#define SYSTICK_INT_PRIORITY 0x00
#define ETHERNET_INT_PRIORITY 0x80
//*****************************************************************************
//
// The clock rate for the SysTick interrupt. All events in the application
// occur at some fraction of this clock rate.
//
//*****************************************************************************
#define SYSTICKHZ 100
#define SYSTICKMS (1000 / SYSTICKHZ)
#define SYSTICKUS (1000000 / SYSTICKHZ)
#define SYSTICKNS (1000000000 / SYSTICKHZ)
//*****************************************************************************
//
// Event flags (bit positions defined in globals.h)
//
//*****************************************************************************
volatile unsigned long g_ulFlags;
//*****************************************************************************
//
// System Time - Internal representaion.
//
//*****************************************************************************
volatile unsigned long g_ulSystemTimeSeconds;
volatile unsigned long g_ulSystemTimeNanoSeconds;
//*****************************************************************************
//
// System Run Time - Ticks
//
//*****************************************************************************
volatile unsigned long g_ulSystemTimeTicks;
//*****************************************************************************
//
// These debug variables track the number of times the getTime function reckons
// it detected a SysTick wrap occurring during the time when it was reading the
// time. We also record the second value of the timestamp when the wrap was
// detected in case we want to try to correlate this with any external
// measurements.
//
//*****************************************************************************
#ifdef DEBUG
unsigned long g_ulSysTickWrapDetect = 0;
unsigned long g_ulSysTickWrapTime = 0;
unsigned long g_ulGetTimeWrapCount = 0;
#endif
//*****************************************************************************
//
// Local data for clocks and timers.
//
//*****************************************************************************
static volatile unsigned long g_ulNewSystemTickReload = 0;
static volatile unsigned long g_ulSystemTickHigh = 0;
static volatile unsigned long g_ulSystemTickReload = 0;
//*****************************************************************************
//
// Statically allocated runtime options and parameters for PTPd.
//
//*****************************************************************************
static PtpClock g_sPTPClock;
static ForeignMasterRecord g_psForeignMasterRec[DEFUALT_MAX_FOREIGN_RECORDS];
static RunTimeOpts g_sRtOpts;
//*****************************************************************************
//
// External references.
//
//*****************************************************************************
extern void httpd_init(void);
extern void fs_init(void);
extern void lwip_init(void);
extern void lwip_tick(unsigned long ulTickMS);
//*****************************************************************************
//
// Local function prototypes.
//
//*****************************************************************************
void adjust_rx_timestamp(TimeInternal *psRxTime, unsigned long ulRxTime,
unsigned long ulNow);
//*****************************************************************************
//
// The error routine that is called if the driver library encounters an error.
//
//*****************************************************************************
#ifdef DEBUG
void
__error__(char *pcFilename, unsigned long ulLine)
{
}
#endif
//*****************************************************************************
//
// Display Date and Time.
//
//*****************************************************************************
static char g_pucBuf[23];
const char *g_ppcDay[7] =
{
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
const char *g_ppcMonth[12] =
{
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static void
DisplayDate(unsigned long ulSeconds, unsigned long ulRow)
{
tTime sLocalTime;
//
// Convert the elapsed seconds (ulSeconds) into time structure.
//
ulocaltime(ulSeconds, &sLocalTime);
//
// Generate an appropriate date string for OLED display.
//
usprintf(g_pucBuf, "%3s %3s %2d, %4d", g_ppcDay[sLocalTime.ucWday],
g_ppcMonth[sLocalTime.ucMon], sLocalTime.ucMday,
sLocalTime.usYear);
RIT128x96x4StringDraw(g_pucBuf, 12, ulRow, 15);
}
static void
DisplayTime(unsigned long ulSeconds, unsigned long ulRow)
{
tTime sLocalTime;
//
// Convert the elapsed seconds (ulSeconds) into time structure.
//
ulocaltime(ulSeconds, &sLocalTime);
//
// Generate an appropriate date string for OLED display.
//
usprintf(g_pucBuf, "%02d:%02d:%02d (GMT)", sLocalTime.ucHour,
sLocalTime.ucMin, sLocalTime.ucSec);
RIT128x96x4StringDraw(g_pucBuf, 12, ulRow, 15);
}
//*****************************************************************************
//
// The interrupt handler for the SysTick interrupt.
//
//*****************************************************************************
void
SysTickIntHandler(void)
{
//
// Update internal time and set PPS output, if needed.
//
g_ulSystemTimeNanoSeconds += SYSTICKNS;
if(g_ulSystemTimeNanoSeconds >= 1000000000)
{
GPIOPinWrite(PPS_GPIO_BASE, PPS_GPIO_PIN, PPS_GPIO_PIN);
g_ulSystemTimeNanoSeconds -= 1000000000;
g_ulSystemTimeSeconds += 1;
HWREGBITW(&g_ulFlags, FLAG_PPSOUT) = 1;
}
//
// Set a new System Tick Reload Value.
//
if(g_ulSystemTickReload != g_ulNewSystemTickReload)
{
g_ulSystemTickReload = g_ulNewSystemTickReload;
g_ulSystemTimeNanoSeconds = ((g_ulSystemTimeNanoSeconds / SYSTICKNS) *
SYSTICKNS);
}
//
// For each tick, set the next reload value for fine tuning the clock.
//
if((g_ulSystemTimeTicks % TICKNS) < g_ulSystemTickHigh)
{
SysTickPeriodSet(g_ulSystemTickReload + 1);
}
else
{
SysTickPeriodSet(g_ulSystemTickReload);
}
//
// Service the PTPd Timer.
//
timerTick(SYSTICKMS);
//
// Increment the run-time tick counter.
//
g_ulSystemTimeTicks++;
//
// Indicate that a SysTick interrupt has occurred.
//
HWREGBITW(&g_ulFlags, FLAG_SYSTICK) = 1;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -