sched/clock: support using CLOCKFD to call clock_adjtime

This patch implements clock_adjtime() with CLOCKFD support, enabling
precise time and frequency adjustments for PTP clocks through the
standard POSIX clock API.

Key changes include:

1. New clock_adjtime() system call:
   - Added sched/clock/clock_adjtime.c implementation
   - Provides POSIX-compliant time adjustment interface
   - Supports both standard clocks and CLOCKFD-based dynamic clocks
   - Added CONFIG_CLOCK_ADJTIME Kconfig option

2. CLOCKFD support in clock_adjtime():
   - Detects CLOCKFD-encoded clockids via CLOCKFD_TO_FD() check
   - Extracts file descriptor and validates through fs_getfilep()
   - Issues PTP_CLOCK_ADJTIME ioctl to underlying PTP clock device
   - Returns clock status and adjustment results via struct timex

3. Enhanced struct timex support:
   - Extended include/sys/timex.h with additional ADJ_* flags
   - Added ADJ_OFFSET, ADJ_FREQUENCY, ADJ_MAXERROR, ADJ_ESTERROR
   - Added ADJ_STATUS, ADJ_TIMECONST, ADJ_TAI, ADJ_SETOFFSET
   - Added ADJ_MICRO, ADJ_NANO for time unit selection
   - Added STA_* status flags for clock state reporting

4. Clock operations supported:
   - ADJ_SETOFFSET: Apply time offset adjustment
   - ADJ_FREQUENCY: Adjust clock frequency (PPM)
   - ADJ_MAXERROR: Set maximum error estimate
   - ADJ_ESTERROR: Set estimated error
   - ADJ_STATUS: Modify clock status bits
   - ADJ_NANO: Use nanosecond resolution
   - ADJ_SETOFFSET: Set absolute time offset

5. API declarations:
   - Added clock_adjtime() prototype in include/nuttx/clock.h
   - Enabled by CONFIG_CLOCK_ADJTIME configuration
   - Compatible with Linux clock_adjtime() interface

Usage example:
  int fd = open("/dev/ptp0", O_RDWR);
  struct timex tx = {0};
  tx.modes = ADJ_FREQUENCY;
  tx.freq = 10000000;  /* Adjust frequency by 10 PPM */
  clock_adjtime(CLOCKFD(fd), &tx);
  close(fd);

This completes the PTP clock framework's POSIX clock API integration,
providing comprehensive time control capabilities for precision timing
applications including PTP synchronization daemons (ptp4l, timemaster).

Signed-off-by: dongjiuzhu1 <dongjiuzhu1@xiaomi.com>
This commit is contained in:
dongjiuzhu1
2025-03-20 23:08:37 +08:00
committed by Alan C. Assis
parent 6802d3510b
commit 752a405f86
4 changed files with 142 additions and 1 deletions
+13
View File
@@ -29,6 +29,7 @@
#include <nuttx/config.h> #include <nuttx/config.h>
#include <sys/timex.h>
#include <sys/types.h> #include <sys/types.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
@@ -839,6 +840,18 @@ int nxclock_settime(clockid_t clock_id, FAR const struct timespec *tp);
int nxclock_gettime(clockid_t clock_id, FAR struct timespec *tp); int nxclock_gettime(clockid_t clock_id, FAR struct timespec *tp);
/****************************************************************************
* Name: nxclock_adjtime
*
* Description:
* Adjust the frequency and/or phase of a clock.
*
****************************************************************************/
#ifdef CONFIG_CLOCK_ADJTIME
int nxclock_adjtime(clockid_t clock_id, FAR struct timex *buf);
#endif
#undef EXTERN #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }
+31
View File
@@ -90,6 +90,37 @@ extern "C"
#define EXTERN extern #define EXTERN extern
#endif #endif
/****************************************************************************
* Name: clock_adjtime
*
* Description:
* Adjust the frequency and/or phase of a clock.
* This function allows the adjustment of the frequency and/or phase of a
* specified clock. It can be used to synchronize the clock with an
* external time source or to apply a frequency offset.
*
* Input Parameters:
* clk_id - The identifier of the clock to be adjusted. This is typically
* one of the predefined clock IDs such as CLOCK_REALTIME,
* CLOCK_MONOTONIC, or CLOCK_BOOTTIME.
*
* buf - A pointer to a `timex` structure that specifies the adjustment
* parameters. This structure includes fields for the frequency
* adjustment (`freq`), the maximum frequency error (`maxerror`),
* the estimated error (`esterror`), the phase offset (`offset`),
* and flags to indicate the type of adjustment (`status`).
*
* Returned Value:
* Return On success, the function returns 0. On error, it returns
* -1 and sets 'errno` to indicate the specific error that
* occurred.
*
****************************************************************************/
#ifdef CONFIG_CLOCK_ADJTIME
int clock_adjtime(clockid_t clk_id, FAR struct timex *buf);
#endif
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)
} }
+4 -1
View File
@@ -188,7 +188,7 @@ config ARCH_HAVE_ADJTIME
config CLOCK_ADJTIME config CLOCK_ADJTIME
bool "Support adjtime function" bool "Support adjtime function"
default n default n
depends on ARCH_HAVE_ADJTIME || RTC_ADJTIME depends on ARCH_HAVE_ADJTIME || RTC_ADJTIME || PTP_CLOCK
---help--- ---help---
Enables usage of adjtime() interface used to correct the system time Enables usage of adjtime() interface used to correct the system time
clock. This requires specific architecture support. clock. This requires specific architecture support.
@@ -196,6 +196,9 @@ config CLOCK_ADJTIME
Adjustment can affect system timer period and/or high-resolution RTC. Adjustment can affect system timer period and/or high-resolution RTC.
These are implemented by interfaces up_adjtime() and up_rtc_adjtime(). These are implemented by interfaces up_adjtime() and up_rtc_adjtime().
Enables usage of clock_adjtime() interface used to correct the system
and other ptp time clock. This requires ptp clock support.
This is not a POSIX interface but derives from 4.3BSD, System V. This is not a POSIX interface but derives from 4.3BSD, System V.
It is also supported for Linux compatibility. It is also supported for Linux compatibility.
+94
View File
@@ -37,6 +37,8 @@
#include <nuttx/irq.h> #include <nuttx/irq.h>
#include <nuttx/arch.h> #include <nuttx/arch.h>
#include <nuttx/spinlock.h> #include <nuttx/spinlock.h>
#include <nuttx/fs/fs.h>
#include <nuttx/timers/ptp_clock.h>
#include "clock/clock.h" #include "clock/clock.h"
@@ -215,4 +217,96 @@ int adjtime(FAR const struct timeval *delta, FAR struct timeval *olddelta)
} }
} }
/****************************************************************************
* Name: nxclock_adjtime
*
* Description:
* Adjust the frequency and/or phase of a clock.
* This function allows the adjustment of the frequency and/or phase of a
* specified clock. It can be used to synchronize the clock with an
* external time source or to apply a frequency offset.
*
* Input Parameters:
* clk_id - The identifier of the clock to be adjusted. This is typically
* one of the predefined clock IDs such as CLOCK_REALTIME,
* CLOCK_MONOTONIC, or CLOCK_BOOTTIME.
*
* buf - A pointer to a `timex` structure that specifies the adjustment
* parameters. This structure includes fields for the frequency
* adjustment (`freq`), the maximum frequency error (`maxerror`),
* the estimated error (`esterror`), the phase offset (`offset`),
* and flags to indicate the type of adjustment (`status`).
*
* Returned Value:
* Return On success, the function returns 0. On error, it returns
* -1 and sets 'errno` to indicate the specific error that
* occurred.
*
****************************************************************************/
int nxclock_adjtime(clockid_t clock_id, FAR struct timex *buf)
{
int ret = -EINVAL;
#ifdef CONFIG_PTP_CLOCK
if ((clock_id & CLOCK_MASK) == CLOCK_FD)
{
FAR struct file *filep;
ret = ptp_clockid_to_filep(clock_id, &filep);
if (ret < 0)
{
return ret;
}
ret = file_ioctl(filep, PTP_CLOCK_ADJTIME,
(unsigned long)(uintptr_t)buf);
fs_putfilep(filep);
}
#endif
return ret;
}
/****************************************************************************
* Name: clock_adjtime
*
* Description:
* Adjust the frequency and/or phase of a clock.
* This function allows the adjustment of the frequency and/or phase of a
* specified clock. It can be used to synchronize the clock with an
* external time source or to apply a frequency offset.
*
* Input Parameters:
* clk_id - The identifier of the clock to be adjusted. This is typically
* one of the predefined clock IDs such as CLOCK_REALTIME,
* CLOCK_MONOTONIC, or CLOCK_BOOTTIME.
*
* buf - A pointer to a `timex` structure that specifies the adjustment
* parameters. This structure includes fields for the frequency
* adjustment (`freq`), the maximum frequency error (`maxerror`),
* the estimated error (`esterror`), the phase offset (`offset`),
* and flags to indicate the type of adjustment (`status`).
*
* Returned Value:
* Return On success, the function returns 0. On error, it returns
* -1 and sets 'errno` to indicate the specific error that
* occurred.
*
****************************************************************************/
int clock_adjtime(clockid_t clk_id, FAR struct timex *buf)
{
int ret;
ret = nxclock_adjtime(clk_id, buf);
if (ret < 0)
{
set_errno(-ret);
return ERROR;
}
return ret;
}
#endif /* CONFIG_CLOCK_ADJTIME */ #endif /* CONFIG_CLOCK_ADJTIME */