时间戳比定时器更短的同步定时器

sync timer with shorter timestamp than timer

Hy 我有两个设备 A 和 B 都使用 64 位定时器。一个刻度等于 1ns。我想同步两个计时器的漂移。我已经知道 A 和 B 之间的延迟。通常我会经常将 A 的当前时间发送到 B。在 B 中,我会添加传播延迟并将此值用作同步 B 的比较值。在我的情况下,我只能发送每 100ms 降低定时器的 32 位。我试图用 A 的部分简单地替换 B 的下半部分,但只要没有 32 位溢出,这个工作就可以了。有没有办法检测这种溢出?溢出示例(定时器短路):

定时器 B: 0x00FF

定时器A:0x010A

=> 0x0A 到 B 替换导致 计时器 B 0x000A 而不是计时器 B 0x010A。

所以我需要检测 A 中是否已经发生了 B 中没有发生的溢出。

下溢示例(定时器短路):

定时器 B: 0x0205

定时器A:0x01F6

=> 0xF6 => 计时器 B:0x02F6 而不是 0x01F6

在这种情况下,计时器 B 比计时器 A 快。

这是我用来找出 timera 的最接近可能值的方法,给定 timerbmessagetimera 的 32 个低位,以及delay:

中的预期传播延迟
#include <stdint.h>

int64_t expected_timera(const int64_t  timerb,
                        const uint32_t message,
                        const uint32_t delay)
{
    const int64_t  timer1 = (timerb / INT64_C(4294967296)) * INT64_C(4294967296)
                          + (int64_t)message + (int64_t)delay;
    const int64_t  timer0 = timer1 - INT64_C(4294967296);
    const int64_t  timer2 = timer1 + INT64_C(4294967296);

    const uint64_t delta0 = timerb - timer0;
    const uint64_t delta1 = (timer1 > timerb) ? timer1 - timerb : timerb - timer1;
    const uint64_t delta2 = timer2 - timerb;

    if (delta0 < delta1)
        return (delta0 < delta2) ? timer0 : timer2;
    else
        return (delta1 <= delta2) ? timer1 : timer2;
}

就个人而言,我还会使用线性调整从实际计时器 B 计算 timerb

static volatile int64_t real_timer_b;  /* Actual timer b */
static int64_t          timerb_real;   /* real_timer_b at last sync time */
static int64_t          timerb_offset; /* timera at last sync time */
static int32_t          timerb_scale;  /* Q30 scale factor (0,2) */

static inline int64_t timerb(void)
{
    return ((int64_t)(int32_t)(real_timer_b - timerb_real) * (int64_t)timerb_scale) / INT64_C(1073741824) + timerb_offset;
}

timerb_real = 0timerb_offset = 0timerb_scale = 1073741824timerb() == real_timer_b

timera > timerb()时,需要增加timerb_scale。当timera < timerb()时,需要减少timerb_scale。您不想每 100 毫秒计算一次精确值,因为传播延迟中的抖动会直接影响 timerb();你想在几(几十)秒内慢慢调整它。作为奖励,您可以保持 timerb() 单调,而不会突然向前或向后跳跃。

Network Time Protocol 实现做的事情非常相似,您可能会在那里找到进一步的实现帮助。