mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 23:40:19 +08:00
drivers/timers/ptp: support ptp clock driver model
This patch introduces the foundational PTP (Precision Time Protocol) clock driver framework for NuttX, enabling precise time synchronization support based on IEEE 1588 standard. Key changes include: 1. New PTP clock driver infrastructure: - Added drivers/timers/ptp_clock.c implementing upper-half driver - Created include/nuttx/timers/ptp_clock.h with PTP clock interfaces - Implemented upper/lower half driver architecture for hardware abstraction 2. Core functionality: - Clock time get/set operations (gettime, settime) - Frequency adjustment support (adjtime, adjfine) - Phase adjustment capabilities - System-device cross-timestamping for precise synchronization 3. IOCTL commands: - PTP_CLOCK_SETTIME/GETTIME for time manipulation - PTP_CLOCK_GETRES for resolution queries - PTP_CLOCK_ADJTIME for time adjustment - PTP_CLOCK_GETCAPS for capability queries - PTP_SYS_OFFSET* for system offset measurements 4. Supporting structures: - struct ptp_lowerhalf_s: lower-half driver interface - struct ptp_clock_caps: clock capabilities descriptor - struct ptp_sys_offset: system time offset measurement - Added timex structures in include/sys/timex.h for ADJ_* operations 5. Build system integration: - Added CONFIG_PTP_CLOCK Kconfig option - Updated CMakeLists.txt and Make.defs - Added PTPCLK debug macros in include/debug.h This framework provides the base for PTP clock implementations, allowing hardware-specific drivers to register and provide precise time services through a standardized interface. Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
committed by
Alan C. Assis
parent
7298977894
commit
31eb339356
@@ -1031,6 +1031,24 @@
|
||||
# define csinfo _none
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_PTP_ERROR
|
||||
# define ptperr _err
|
||||
#else
|
||||
# define ptperr _none
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_PTP_WARN
|
||||
# define ptpwarn _warn
|
||||
#else
|
||||
# define ptpwarn _none
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_DEBUG_PTP_INFO
|
||||
# define ptpinfo _info
|
||||
#else
|
||||
# define ptpinfo _none
|
||||
#endif
|
||||
|
||||
/* Buffer dumping macros do not depend on varargs */
|
||||
|
||||
#ifdef CONFIG_DEBUG_ERROR
|
||||
|
||||
@@ -91,11 +91,15 @@
|
||||
* CLOCK_PROCESS_CPUTIME_ID - 2
|
||||
* CLOCK_THREAD_CPUTIME_ID - 3
|
||||
* CLOCK_BOOTTIME - 4
|
||||
* bit 3~32: the pid or tid value
|
||||
* CLOCK_FD - 5
|
||||
*
|
||||
* if the clockid value exceeds CLOCK_MASK, it indicates a dynamic clockid.
|
||||
* bit 3~32: the fd, pid or tid value
|
||||
*
|
||||
* The CLOCK_MASK are using to extract the clock_type from the clockid_t
|
||||
*/
|
||||
|
||||
#define CLOCK_FD 5
|
||||
#define CLOCK_MASK 7
|
||||
#define CLOCK_SHIFT 3
|
||||
|
||||
|
||||
@@ -112,6 +112,7 @@
|
||||
#define _I2SOCBASE (0x4400) /* I2S driver ioctl commands */
|
||||
#define _1WIREBASE (0x4500) /* 1WIRE ioctl commands */
|
||||
#define _EEPIOCBASE (0x4600) /* EEPROM driver ioctl commands */
|
||||
#define _PTPBASE (0x4700) /* PTP ioctl commands */
|
||||
#define _WLIOCBASE (0x8b00) /* Wireless modules ioctl network commands */
|
||||
|
||||
/* boardctl() commands share the same number space */
|
||||
@@ -799,6 +800,13 @@
|
||||
#define _EEPIOCVALID(c) (_IOC_TYPE(c)==_EEPIOCBASE)
|
||||
#define _EEPIOC(nr) _IOC(_EEPIOCBASE,nr)
|
||||
|
||||
/* PTP driver ioctl definitions *********************************************/
|
||||
|
||||
/* see nuttx/include/ptp_clock.h */
|
||||
|
||||
#define _PTPIOCVALID(c) (_IOC_TYPE(c)==_PTPBASE)
|
||||
#define _PTPIOC(nr) _IOC(_PTPBASE,nr)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Type Definitions
|
||||
****************************************************************************/
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/timers/ptp_clock.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_NUTTX_TIMERS_PTP_CLOCK_H
|
||||
#define __INCLUDE_NUTTX_TIMERS_PTP_CLOCK_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/timex.h>
|
||||
|
||||
#include <nuttx/clock.h>
|
||||
#include <nuttx/fs/ioctl.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define PTP_CLOCK_SETTIME _PTPIOC(0x1)
|
||||
#define PTP_CLOCK_GETTIME _PTPIOC(0x2)
|
||||
#define PTP_CLOCK_GETRES _PTPIOC(0x3)
|
||||
#define PTP_CLOCK_ADJTIME _PTPIOC(0x4)
|
||||
|
||||
#define PTP_CLOCK_GETCAPS _PTPIOC(0x5)
|
||||
#define PTP_SYS_OFFSET _PTPIOC(0x6)
|
||||
#define PTP_SYS_OFFSET_PRECISE _PTPIOC(0x7)
|
||||
#define PTP_SYS_OFFSET_EXTENDED _PTPIOC(0x8)
|
||||
|
||||
#define PTP_CLOCK_GETCAPS2 _PTPIOC(0x9)
|
||||
#define PTP_SYS_OFFSET2 _PTPIOC(0xa)
|
||||
#define PTP_SYS_OFFSET_PRECISE2 _PTPIOC(0xb)
|
||||
#define PTP_SYS_OFFSET_EXTENDED2 _PTPIOC(0xc)
|
||||
|
||||
/* Maximum allowed offset measurement samples. */
|
||||
|
||||
#define PTP_MAX_SAMPLES 25
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
/* struct system_device_crosststamp - system/device cross-timestamp
|
||||
* (synchronized capture)
|
||||
*/
|
||||
|
||||
struct system_device_crosststamp
|
||||
{
|
||||
struct timespec device; /* Device time */
|
||||
struct timespec realtime; /* Realtime simultaneous with device time */
|
||||
struct timespec monoraw; /* Monotonic raw simultaneous with device time */
|
||||
};
|
||||
|
||||
/* struct ptp_clock_time - represents a time value
|
||||
*
|
||||
* The sign of the seconds field applies to the whole value. The
|
||||
* nanoseconds field is always unsigned. The reserved field is
|
||||
* included for sub-nanosecond resolution, should the demand for
|
||||
* this ever appear.
|
||||
*/
|
||||
|
||||
struct ptp_clock_time
|
||||
{
|
||||
int64_t sec;
|
||||
uint32_t nsec;
|
||||
uint32_t reserved;
|
||||
};
|
||||
|
||||
struct ptp_clock_caps
|
||||
{
|
||||
int max_adj; /* Maximum frequency adjustment in parts per billion. */
|
||||
int cross_timestamping; /* Whether the clock supports precise system-device cross timestamps */
|
||||
int adjust_phase; /* Whether the clock supports phase adjustment */
|
||||
};
|
||||
|
||||
struct ptp_sys_offset
|
||||
{
|
||||
unsigned int n_samples; /* Desired number of measurements. */
|
||||
unsigned int rsv[3]; /* Reserved for future use. */
|
||||
|
||||
/* Array of interleaved system/phc time stamps. The kernel
|
||||
* will provide 2*n_samples + 1 time stamps, with the last
|
||||
* one as a system time stamp.
|
||||
*/
|
||||
|
||||
struct ptp_clock_time ts[2 * PTP_MAX_SAMPLES + 1];
|
||||
};
|
||||
|
||||
struct ptp_sys_offset_extended
|
||||
{
|
||||
unsigned int n_samples; /* Desired number of measurements. */
|
||||
unsigned int rsv[3]; /* Reserved for future use. */
|
||||
|
||||
/* Array of [system, phc, system] time stamps. The kernel will provide
|
||||
* 3*n_samples time stamps.
|
||||
*/
|
||||
|
||||
struct ptp_clock_time ts[PTP_MAX_SAMPLES][3];
|
||||
};
|
||||
|
||||
struct ptp_sys_offset_precise
|
||||
{
|
||||
struct ptp_clock_time device;
|
||||
struct ptp_clock_time sys_realtime;
|
||||
struct ptp_clock_time sys_monoraw;
|
||||
unsigned int rsv[4];
|
||||
};
|
||||
|
||||
/* struct ptp_system_timestamp - system time corresponding to a
|
||||
* PHC timestamp.
|
||||
*/
|
||||
|
||||
struct ptp_system_timestamp
|
||||
{
|
||||
struct timespec pre_ts;
|
||||
struct timespec post_ts;
|
||||
};
|
||||
|
||||
struct ptp_lowerhalf_s;
|
||||
struct ptp_ops_s
|
||||
{
|
||||
/**************************************************************************
|
||||
* Name: adjfine
|
||||
*
|
||||
* Description:
|
||||
* Adjusts the frequency of the hardware clock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half ptp driver
|
||||
* scaled_ppm - Desired frequency offset from nominal frequency in parts
|
||||
* per million, but with a 16 bit binary fractional field.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*adjfine)(FAR struct ptp_lowerhalf_s *lower, long scaled_ppm);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: adjphase
|
||||
*
|
||||
* Description:
|
||||
* Adjusts the phase offset of the hardware clock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half ptp driver.
|
||||
* phase - Desired change in nanoseconds.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*adjphase)(FAR struct ptp_lowerhalf_s *lower, int32_t phase);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: adjtime
|
||||
*
|
||||
* Description:
|
||||
* Shifts the time of the hardware clock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half ptp driver.
|
||||
* delta - Desired change in nanoseconds.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*adjtime)(FAR struct ptp_lowerhalf_s *lower, int64_t delta);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: gettime
|
||||
*
|
||||
* Description:
|
||||
* Reads the current time from the hardware clock and optionally also
|
||||
* also the system clock. The first reading is made right before reading
|
||||
* the lowest bits of the PHC timestamp and the second reading
|
||||
* immediately follows that.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half ptp driver.
|
||||
* ts - Holds the PHC timestamp.
|
||||
* sts - If not NULL, it holds a pair of timestamps from the
|
||||
* system clock.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*gettime)(FAR struct ptp_lowerhalf_s *lower,
|
||||
FAR struct timespec *ts,
|
||||
FAR struct ptp_system_timestamp *sts);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: getcrosststamp
|
||||
*
|
||||
* Description:
|
||||
* Reads the current time from the hardware clock and system clock
|
||||
* simultaneously.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half ptp driver.
|
||||
* cts - Contains timestamp (device,system) pair, where system time is
|
||||
* realtime and monotonic.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*getcrosststamp)(FAR struct ptp_lowerhalf_s *lower,
|
||||
FAR struct system_device_crosststamp *cts);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: settime
|
||||
*
|
||||
* Description:
|
||||
* Set the current time on the hardware clock.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - The instance of lower half ptp driver
|
||||
* ts - Time value to set.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*settime)(FAR struct ptp_lowerhalf_s *lower,
|
||||
FAR const struct timespec *ts);
|
||||
|
||||
/**************************************************************************
|
||||
* Name: getres
|
||||
*
|
||||
* Description:
|
||||
* Finds the resolution (precision) of the specified clock, and, if res
|
||||
* is non-NULL, stores it in the struct timespec pointed to by res.
|
||||
*
|
||||
* Input Parameters:
|
||||
* pc - The instance of lower half ptp driver.
|
||||
* res - Holds the resolution.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero (OK) or positive on success; a negated errno value on failure.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
CODE int (*getres)(FAR struct ptp_lowerhalf_s *lower,
|
||||
FAR struct timespec *res);
|
||||
};
|
||||
|
||||
/* The ptp lower half driver interface, describes a PTP hardware
|
||||
* clock driver.
|
||||
*/
|
||||
|
||||
struct ptp_lowerhalf_s
|
||||
{
|
||||
FAR const struct ptp_ops_s *ops; /* Lower half driver operations. */
|
||||
FAR void *upper; /* The upper handle */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ptp_clockid_to_filep
|
||||
*
|
||||
* Description:
|
||||
* Convert clockid to struct filep.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ptp_clockid_to_filep(clockid_t clock_id, FAR struct file **filep);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ptp_clock_register
|
||||
*
|
||||
* Description:
|
||||
* This function binds an instance of a "lower half" ptp driver with the
|
||||
* "upper half" ptp device and registers that device so that can be used
|
||||
* by application code.
|
||||
*
|
||||
* Input Parameters:
|
||||
* lower - A pointer to an instance of lower half ptp driver. This
|
||||
* instance is bound to the ptp driver and must persists as long
|
||||
* as the driver persists.
|
||||
* mxa_adj - The maximum frequency adjustment in parts per billion.
|
||||
* devno - The user specifies number of device. ex: /dev/ptpX.
|
||||
*
|
||||
* Returned Value:
|
||||
* OK if the driver was successfully register; A negated errno value is
|
||||
* returned on any failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
int ptp_clock_register(FAR struct ptp_lowerhalf_s *lower, int32_t max_adj,
|
||||
int devno);
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ptp_clock_unregister
|
||||
*
|
||||
* Description:
|
||||
* This function unregisters character node and releases all resource from
|
||||
* upper half driver. This API corresponds to the ptp_register.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - A pointer to an instance of lower half ptp driver. This
|
||||
* instance is bound to the ptp driver and must persists as long
|
||||
* as the driver persists.
|
||||
* devno - The user specifies which device of this type, from 0.
|
||||
****************************************************************************/
|
||||
|
||||
void ptp_clock_unregister(FAR struct ptp_lowerhalf_s *dev, int devno);
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __INCLUDE_NUTTX_TIMERS_PTP_CLOCK_H */
|
||||
@@ -0,0 +1,98 @@
|
||||
/****************************************************************************
|
||||
* include/sys/timex.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __INCLUDE_SYS_TIMEX_H
|
||||
#define __INCLUDE_SYS_TIMEX_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Mode codes (timex.mode) */
|
||||
|
||||
#define ADJ_OFFSET 0x0001 /* time offset */
|
||||
#define ADJ_FREQUENCY 0x0002 /* frequency offset */
|
||||
#define ADJ_MAXERROR 0x0004 /* maximum time error */
|
||||
#define ADJ_ESTERROR 0x0008 /* estimated time error */
|
||||
#define ADJ_STATUS 0x0010 /* clock status */
|
||||
#define ADJ_TIMECONST 0x0020 /* pll time constant */
|
||||
#define ADJ_TAI 0x0080 /* set TAI offset */
|
||||
#define ADJ_SETOFFSET 0x0100 /* add 'time' to current time */
|
||||
#define ADJ_MICRO 0x1000 /* select microsecond resolution */
|
||||
#define ADJ_NANO 0x2000 /* select nanosecond resolution */
|
||||
#define ADJ_TICK 0x4000 /* tick value */
|
||||
#define ADJ_OFFSET_SINGLESHOT 0x8001 /* old-fashioned adjtime */
|
||||
#define ADJ_OFFSET_SS_READ 0xa001 /* read-only adjtime */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
****************************************************************************/
|
||||
|
||||
struct timex
|
||||
{
|
||||
unsigned int modes; /* mode selector */
|
||||
long offset; /* time offset (usec) */
|
||||
long freq; /* frequency offset (scaled ppm) */
|
||||
long maxerror; /* maximum error (usec) */
|
||||
long esterror; /* estimated error (usec) */
|
||||
int status; /* clock command/status */
|
||||
long constant; /* pll time constant */
|
||||
long precision; /* clock precision (usec) (read only) */
|
||||
long tolerance; /* clock frequency tolerance (ppm) (read only) */
|
||||
struct timeval time; /* (read only, except for ADJ_SETOFFSET) */
|
||||
long tick; /* (modified) usecs between clock ticks */
|
||||
long ppsfreq; /* pps frequency (scaled ppm) (ro) */
|
||||
long jitter; /* pps jitter (us) (ro) */
|
||||
int shift; /* interval duration (s) (shift) (ro) */
|
||||
long stabil; /* pps stability (scaled ppm) (ro) */
|
||||
long jitcnt; /* jitter limit exceeded (ro) */
|
||||
long calcnt; /* calibration intervals (ro) */
|
||||
long errcnt; /* calibration errors (ro) */
|
||||
long stbcnt; /* stability limit exceeded (ro) */
|
||||
int tai; /* TAI offset (ro) */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __INCLUDE_SYS_TIMEX_H */
|
||||
Reference in New Issue
Block a user