This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] AM6421:GPTimer 微秒延迟不准确

Guru**** 2988540 points

Other Parts Discussed in Thread: SYSCONFIG

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1666524/am6421-gptimer-microseconds-delay-not-coming-accurate

器件型号: AM6421
主题: SysConfig 中讨论的其他器件

尊敬的团队

我已在自由运行模式下启用 DMTIMER4 达到 1ms 计时器值、因此重新加载值我输入了 0xFFFC9118、我们已经创建了 PAUSE_us 和 PAUSE_ns 函数等延迟函数、但微秒延迟不准确、持续 1us 时长为 3us、MSO 上显示的延迟时间为 3us。 这种配置可以实现多少? 它能更准确吗?

下面我附加了片段

 
SystemTimerResolution_ns = 1000000000/225000000; //(225Mhz timer freq)

void Pause_us(UWORD32 PauseTime_us)
  {
  UWORD32 StartTicks ;
  WORD32  TargetTicks ;

  StartTicks  = 
Drivers_GPTIMER4GetCount() ;
  TargetTicks = (UWORD32)((((float)PauseTime_us * 1000) / SystemTimerResolution_ns));
  while (TargetTicks >= (
Drivers_GPTIMER4GetCount() - StartTicks)) ;
  }

image.png

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    请允许我有时间看看这个,并返回到你的回答。

    感谢您的耐心。

    谢谢、

    Vaibhav

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Shraddha:

    感谢您共享代码片段和 SysConfig 配置。 我已经审核了 Pause_us 实施、并确定了导致不准确的三个问题。


    问题 1:整数除法截断计时器分辨率(主要原因)

    // cURRENT—整数除法得到 4、而不是 4.444……
    SystemTimerResolution_ns = 100000000 / 225000000;

    由于两个操作数都是整数、因此结果将被截断为 4。 这会导致 TargetTicks 的计算结果为 250、而不是 1µs 请求的正确 225、从而增加 11%的系统过延迟。


    问题 2:TargetTicks 声明为签名 (WORD32)

    对于较大的延迟值、TargetTicks 将换为负数。 当负有符号值与 C 中的无符号值进行比较时、它会隐式提升为非常大的无符号数、从而导致 while 条件立即求值为 false、该函数完全无延迟返回。 这是一个可能出现的错误、持续时间较长。  为此、我已在下面建议的代码中转换为无符号格式。


    问题 3:系统计时器的中断抖动

    您的 SysConfig 会显示 DMTIMER4 配置为系统计时器 (CONFIG_GPTIMER4_SYSTEMTIMER、溢出回调 GPTIMER4_SystemTimerCallback)。 此计时器每 1ms 生成一次 OS 节拍中断。 如果在 Pause_us 执行过程中触发该 ISR,则会使测量增加几微秒的不受控制延迟 — 这很可能是对示波器上 3µs 读数的解释。


    建议的修复

    将浮点运算替换为仅整数数学运算、修复 TargetTicks 的类型、并在延迟期间禁用中断:

    #define TIMER_CLK_HZ 225000000UL
    #define TICKS_PER_US (TIMER_CLK_HZ / 1000000UL) /* = 225, exact */
    
    void Pause_us(UWORD32 PauseTime_us)
    {
    uintptr_t key = HwiP_disable(); /* mask system tick ISR */
    UWORD32 startTicks = Drivers_GPTIMER4GetCount();
    UWORD32 targetTicks = PauseTime_us * TICKS_PER_US;
    while ((Drivers_GPTIMER4GetCount() - startTicks) < targetTicks)
    ;
    HwiP_restore(key);
    }
    
    void Pause_ns(UWORD32 PauseTime_ns)
    {
    /* Min resolution = 1 tick = 1/225MHz ≈ 4.44 ns */
    uintptr_t key = HwiP_disable();
    UWORD32 startTicks = Drivers_GPTIMER4GetCount();
    UWORD32 targetTicks = (UWORD32)(((uint64_t)PauseTime_ns * TIMER_CLK_HZ)
    / 1000000000ULL);
    while ((Drivers_GPTIMER4GetCount() - startTicks) < targetTicks)
    ;
    HwiP_restore(key);
    }


    可实现的精度

    在 225MHz 下、一个计时器节拍为 4.44ns。 通过校正后的代码、1µs 恰好等于 225 个周期(无舍入误差)、因此可实现 1µs 精度。 Pause_ns 的实际下限为 1 节拍≈4.44ns—任何短于该值的请求向下舍入到零并立即返回。

    作为替代方案、SDK 在中提供了 ClockP_usleep(uint32_t usec) 、它已经针对此目的进行了测试、并正确处理了计时器/节拍交互。 我们建议使用它、除非您有特定的理由直接轮询计时器。

    请告知我们更新后的代码是否解决了 3µs 差异问题。

    期待您的答复。

    谢谢、
    Vaibhav