【问题标题】:Timer wraparound with flexible bit sizes具有灵活位大小的定时器环绕
【发布时间】:2015-08-05 07:47:50
【问题描述】:

给定一个增加并简单地以给定位宽换行的计数器/定时器,这是一个众所周知的解决方案,可以解决两个捕获的计数器值之间的差异问题(其中计数器可能在两个点之间换行)只是对计数器执行无符号减法(如果不知道哪个更大,则可能将结果解释为有符号)。

例如,给定一个 32 位定时器,这样的代码可用于确定某些代码运行所需的时间长度:

uint32_t start = GetSomePlatformSpecificTimer();
RunSomeOtherCode();
uint32_t end = GetSomePlatformSpecificTimer();
uint32_t platformTicksTakenByCode = end - start;

或者检查是否已达到某个时间限制:

uint32_t limit = GetSomePlatformSpecificTimer() + timeLimitInTicks;
while (true)
{
    bool finished = DoSomethingSmall();
    if (finished)
        break;
    if ((int32_t)(GetSomePlatformSpecificTimer() - limit) >= 0)
        return ERROR_TIMEOUT;
}

如果已知定时器为 32 位宽,这将非常有效。也可以通过改变使用的类型来调整为 16 位或 8 位定时器。

在计时器大小与类型大小不匹配的情况下,是否有类似的简单方法来做同样的事情?例如,24 位定时器或 18 位定时器。

假设位大小 #define COUNTER_WIDTH 指定(并且可能会更改)。

将两个计数器值从 COUNTER_WIDTH 符号扩展为 32 位然后使用上面的代码的最佳解决方案是什么?我可以看到这可能适用于 FF -> 00 翻转,但我认为它会破坏 7F -> 80 翻转,所以大概必须对此进行某种检查(如果值接近零,则可能进行符号扩展如果值接近中点,则零扩展)。我认为这也意味着两个值之间的差异不应超过计数器范围的四分之一,否则可能会导致问题。

或者有更好的方法吗?

【问题讨论】:

    标签: c timer bit-manipulation integer-overflow


    【解决方案1】:

    您可以不进行符号扩展,而是将其相乘以使整个范围的大小与您的算术类型相同。换句话说,使用定点算术来填充整数。在你的情况下,使用uint32_t,看起来像

    uint32_t start = GetSomePlatformSpecificTimer();
    RunSomeOtherCode();
    uint32_t end = GetSomePlatformSpecificTimer();
    start <<= 32-COUNTER_WIDTH;
    end <<= 32-COUNTER_WIDTH;
    uint32_t platformTicksTakenByCode = end - start;
    platformTicksTakenByCode >>= 32-COUNTER_WIDTH;
    

    显然你想封装那个算术:

    const uint32_t start = GetScaledTimer();
    RunSomeOtherCode();
    const uint32_t end = GetScaledTimer();
    const uint32_t platformTicksTakenByCode = RescaleDuration(end - start);
    

    uint32_t GetScaledTimer()
    {
        return GetSomePlatformSpecificTimer() << 32-COUNTER_WIDTH;
    }
    
    uint32_t RescaleDuration(uint32_t d)
    {
        return d >> 32-COUNTER_WIDTH;
    }
    

    然后,您的行为与全角计时器大致相同,并且在必要时使用带符号类型的选项相同。

    【讨论】:

    • 对于这种特殊情况,这似乎是一个更简单的解决方案。还有另一种情况,我不确定重新缩放是否有意义,但我需要进一步考虑。
    猜你喜欢
    • 1970-01-01
    • 2014-06-19
    • 2010-11-01
    • 2019-10-19
    • 1970-01-01
    • 1970-01-01
    • 2017-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多