flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
Loading...
Searching...
No Matches
Porting and configuration

In the Porting section a guide is presented to help porting flexPTP to a new platform. In the Configuration part basic and initial settings are listed.

Porting

We have included numerous examples into the basic flexPTP package with the intent to clarify purpose and structure of each porting file. The flexPTP accesses the target system using the following modules:

  • a flexptp_options.h configuration file, that defines settings for hardware clock operation, provides handles to the servo, connects flexPTP to the standard output and passes common includes to all flexPTP modules.
  • Network Stack Driver that outsources the message transmission and reception to and from the network. It acts like a glue code between the flexPTP and the network stack.
  • a (simple) hardware clock driver, through which flexPTP can set or tune the hardware clock and query time.

In the sections below you'll see samples for all three configuration module types.

Port option file

Each project that includes flexPTP must provide a flexptp_options.h header file. This file has the purpose to tell flexPTP the basic hardware features (e.g. oscillator frequency), and to define bindings to hardware clock and servo management routines.

Our experience with embedded development shows that a newcomer might run into difficulties on creating a port to a software to be learned. We recommend you to open an example flexptp_options_XXX.h file from the port/example_options location before reading the following. Taking a quick look into a pre-made configuration file might make the interpretation of the section below much easier.

The assembling of a configuration file can be broken down into the following major steps:

  1. Define printing routines or macros:
    • MSG(...): a basic formatted printing function that mimics printf() functionality (called with printf()-fashioned parameters). flexPTP uses the following formatting marks: %d, %i, %u, %lu, %f, %x, %X, %s, %c, %%.
    • CLILOG(en,...): a maskable printing function: if en is true, it behaves like MSG(...)
    • SPRINTF(str,n,...): a basic snprintf() implementation, that supports at least the same set of formatting marks as MSG(...) does
  2. Define hardware clock tick frequency and increment:
    • PTP_MAIN_OSCILLATOR_FREQ_HZ: clock frequency that drives the hardware clock in Hz
    • PTP_INCREMENT_NSEC: amount of time the clock gets incremented each tick expressed in nanoseconds (refer to: Hardware Clock Driver)
  3. Define hardware clock management functions:
  4. Define servo management functions:
  5. Optionally define a function that registers CLI commands:
  6. Optionally define a function for loading retained options:
  7. Optionally define a function for handling flexPTP's user events (this can be done during runtime as well):
    • PTP_USER_EVENT_CALLBACK: a function pointer of the PtpUserEventCallback type
  8. Optionally enable Master operation mode:
    • set PTP_ENABLE_MASTER_OPERATION to 1
    • Optionally set (initial) PTP master capabilities, see Master configuration

We emphasize, that many examples can be found on configuration files in the port/example_options directory.

Throughout the assembling of a new the options file you might find that the Ethernet driver, that came along the target platform lacks routines handling PTP functionality. In that case you it's your duty to extend the driver with the proper features. Many examples on such extensions can be found in the port/example_ports directory.

Example option files

flexptp_options_stm32f407_etherlib.h, flexptp_options_stm32h743_etherlib.h, flexptp_options_stm32h743.h, flexptp_options_tm4c1294.h

Network Stack Driver (NSD)

The flexPTP library expects (only!) the below message transception related functions given. These are the functions, that are declared in network_stack_driver.h. During the porting work, these functions must be implented.

  • void ptp_nsd_init(PtpTransportType tp, PtpDelayMechanism dm): This function initializes (opens and closes) the network connections based on the profile settings passed in the tp and dm parameters. tp and dm can take on any value from PtpTransportType and PtpDelayMechanism, respectively. Passing -1 in either parameter signals that the flexPTP wants the network layer to close all connections. In other words, by passing -1 the flexPTP does not defined a valid profile. It is expected that this function gets called multiple times. On subsequent calls, the function first informs the network that we are leaving the IGMP-group of the profile we abandon and closes connection associated with the profile we are leaving. Then, it takes on the new profile, opens the new connection and joins the new IGMP-groups. Joining and leaving of the IGMP-groups is performed by invoking the ptp_nsd_igmp_join_leave() method.
  • void ptp_nsd_transmit_msg(RawPtpMessage *pMsg): The flexPTP engine calls this function to dispatch a PTP message. The NSD can safely anticipate that fields of the message passed from the PTP engine carry fields reflecting the profile that was set by the latest ptp_nsd_init() call. The function must only fetch the PTP message class from the message passed to determine through which connection it has to be sent.
  • void ptp_nsd_igmp_join_leave(bool join): The flexPTP engine might intend to inform the network about the joining or leaving of the IGMP-group associated with the operating profile (for example upon link recovery). Besides, ptp_nsd_init() references this function as well.
  • void ptp_nsd_get_interface_address(uint8_t * hwa): This function returns with the hardware address of the associated Ethernet interface. Parameter hwa is expected to be able to hold (at least) 6-bytes (the size of an Ethernet Hardware Address).

Finally, it's also the job of the NSD module to make the received messages available to the flexPTP core. This is done by calling the ptp_receive_enqueue() function with the proper parameters: data, size and ingress timestamp split into seconds and nanoseconds field.

Inherently, the fetching and exchangeing of the ingress and egress timestamps with the flexPTP core fall also in the scope of the NSD module.

NSD examples

nsd_lwip.c, nsd_etherlib.c : Sample NSD implementations for lwIP and EtherLib network stacks.

Hardware Clock Driver

General structure of a PTP hardware clock with distinguished high precesion frequency divider and counter

This is the low level driver that controls the hardware clock. We found that in general, hardware clocks can be tuned by altering a so called frequency tuning code word. Usually the code word is an addend of a high-precision frequency divider in the clock's core. The code word is directly proportional with the output frequency. That's why we decided to represent 0 frequency with a zero and the maximum frequency with a 0xFFFFFFFF ( \(2^{32}-1\)) 32 bits code word. The former phrase in the form of a function:

\[ f_\text{clock} = f_\text{osc} \frac{\texttt{CODE WORD}}{2^{32}} \]

Hardware clocks keep time by increasing their stored time value with an increment in every clock cycle (i.e. clock cycle of the divided clock). The increment is usually constant and is set during the initialization. (It is mostly expressed in nanoseconds.)

Addend and increment are the two basic idea that are supported by all hardware clocks, in some forms. These are the fields that the hardware clock driver must be able to control, at least.

More general, the hardware clock driver must provide solutions for:

  • initialize the hardware with
  • setting the clock's time,
  • tuning the clock's frequency using a code word introduced formerly,
  • obtaining the time from the clock.

Usually the hardware clock driver also implements further miscellaneous functionality, like the controlling of the PPS output signal.

Example Hardware Clock Driver files

ptp_port_stm32f407_etherlib.c, ptp_port_stm32f407_lwip.c, ptp_port_stm32h743_etherlib.c, ptp_port_stm32h743.c, ptp_port_tiva_tm4c1294.c

Configuration

Initial configuration

List of definitions, part of the initial configuration, with default values. Default values are used if macros are not defined in flexptp_options.h.

Operation mode parameters

Macros controlling basic internal operation.

Macro Default value Description
PTP_HEARTBEAT_TICKRATE_MS 125 Internal core scheduler period (ms)
PTP_ACCURACY_LIMIT_NS 100 Threshold of the LOCKED state (ns)
PTP_DEFAULT_SERVO_OFFSET_NS 0 Initial servo offset (ns) (can be changed in runtime)
PTP_DEFAULT_COARSE_TRIGGER_NS 20000000 Coarse correction kick-in threshold (ns) (can be changed in runtime)

PTP definitions

Common

Macro Default value Description
PTP_PORT_ID 1 ID of the Ethernet interface assigned to flexPTP

BMCA

Macro Default value Description
PTP_BMCA_LISTENING_TIMEOUT_MS 3000 Timeout of the LISTENING BMCA-state (ms)
PTP_MASTER_QUALIFICATION_TIMEOUT 4 Timeout of PRE_MASTER state (Announce-intervals)
PTP_ANNOUNCE_RECEIPT_TIMEOUT 3 Number of tolerated consecutive lost Announce messages

Master

Macro Default value Description
PTP_ENABLE_MASTER_OPERATION 0 (disabled) Enable/disable master operation (once disabled here CANNOT be enabled in runtime)
PTP_FALLBACK_UTC_OFFSET 37 Initial UTC offset caused by the accumulated leap seconds (s)
PTP_PDELAY_SLAVE_QUALIFICATION 3 Number of consecutive PDelReq-PDelResp iterations after the SLAVE is considered stable
PTP_PDELAY_DROPOUT PTP_PDELAY_SLAVE_QUALIFICATION Maximum number of failed PDelReq-PDelResp cycles before the MASTER drops the SLAVE

Clock dataset

Macro Default value Description
PTP_CLOCK_PRIORITY1 128 Priority 1 field
PTP_CLOCK_PRIORITY2 128 Priority 2 field
PTP_BEST_CLOCK_CLASS PTP_CC_DEFAULT Best clock class (PtpClockClass)
PTP_WORST_ACCURACY PTP_CA_PTP_CA_UNKNOWN Worst clock accuracy (PtpClockAccuracy)
PTP_TIME_SOURCE PTP_TSRC_INTERNAL_OSCILLATOR Time source of this device (PtpTimeSource)

Runtime configuration

Runtime configuration is done through the Settings interface (settings_interface.h).

Also, the same configuration options are available through the CLI interface:

ptp reset Reset PTP subsystem
ptp servo offset [offset_ns] Set or query clock offset
ptp log {def|corr|ts|info|locked|bmca} {on|off} Turn on or off logging
ptp master [[un]prefer] [clockid] Master clock settings
ptp info Print PTP info
ptp domain [domain] Print or get PTP domain
ptp addend [addend] Print or set addend
ptp transport [{ipv4|802.3}] Set or get PTP transport layer
ptp delmech [{e2e|p2p}] Set or get PTP delay mechanism
ptp transpec [{def|gPTP}] Set or get PTP transportSpecific field (majorSdoId)
ptp profile [preset [<name>]] Print or set PTP profile, or list available presets
ptp tlv [preset [name]|unload] Print or set TLV-chain, or list available TLV presets
ptp pflags [<flags>] Print or set profile flags
ptp period <delreq|sync|ann> [<lp>|matched] Print or set log. periods
ptp coarse [threshold] Print or set coarse correction threshold
ptp priority [<p1> <p2>] Print or set clock priority fields
time [ns] Print time