![]() |
flexPTP 1.0
An IEEE 1588 PTP implementation designed for microcontrollers
|
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.
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:
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.In the sections below you'll see samples for all three configuration module types.
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:
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(...)
doesPTP_MAIN_OSCILLATOR_FREQ_HZ
: clock frequency that drives the hardware clock in HzPTP_INCREMENT_NSEC
: amount of time the clock gets incremented each tick expressed in nanoseconds (refer to: Hardware Clock Driver)PTP_HW_INIT(increment, addend)
: a method that initializes the hardware clock. increment
: clock increment, addend
: initial frequency tuningPTP_SET_CLOCK(s, ns)
: a method that sets the hardware clock. s
: seconds part of the UNIX time, ns
: nanoseconds of the UNIX timePTP_SET_ADDEND(addend)
: a method that sets the hardware clock frequency tuning word. addend
: 32-bit tuning value (0x00000000..0xFFFFFFFF)PTP_HW_GET_TIME(pt)
: a method that fetches the time right from the hardware clock. pt
: time of type TimestampI *
; time is stored to *pt
(refer to: Hardware Clock Driver)PTP_SERVO_INIT()
: a function that initializes the controller algorithmPTP_SERVO_DEINIT()
: a function that de-initializes the controller algorithmPTP_SERVO_RESET()
: a function that resets the controller algorithmPTP_SERVO_RUN(d, pscd)
: a function that invokes the controller and returns with a tuning value in PPB. d
: time error in nanoseconds, pscd
: pointer to synchronization cycle auxiliary context data of type PtpServoAuxInput *
. (refer to: Clock servo)CLI_REG_CMD(cmd_hintline,n_cmd,n_min_arg,cb)
: for parameter meanings and types refer to cli_cmds.cPTP_CONFIG_PTR()
: a macro that evaluates to a const void *
pointer to the area where the flexPTP config was stored previously. flexPTP expects to find a populated PtpConfig on address returned by PTP_CONFIG_PTR()
, that was previously generated by ptp_store_config()
.PTP_USER_EVENT_CALLBACK
: a function pointer of the PtpUserEventCallback typePTP_ENABLE_MASTER_OPERATION
to 1
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.
flexptp_options_stm32f407_etherlib.h, flexptp_options_stm32h743_etherlib.h, flexptp_options_stm32h743.h, flexptp_options_tm4c1294.h
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_lwip.c, nsd_etherlib.c : Sample NSD implementations for lwIP and EtherLib network stacks.
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:
Usually the hardware clock driver also implements further miscellaneous functionality, like the controlling of the PPS output signal.
ptp_port_stm32f407_etherlib.c, ptp_port_stm32f407_lwip.c, ptp_port_stm32h743_etherlib.c, ptp_port_stm32h743.c, ptp_port_tiva_tm4c1294.c
List of definitions, part of the initial configuration, with default values. Default values are used if macros are not defined in flexptp_options.h
.
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) |
Macro | Default value | Description |
---|---|---|
PTP_PORT_ID | 1 | ID of the Ethernet interface assigned to flexPTP |
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 |
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 |
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 is done through the Settings interface (settings_interface.h).
Also, the same configuration options are available through the CLI interface: