【发布时间】:2013-08-22 23:37:47
【问题描述】:
我需要精确计时到 1 us 级别,以计时 pwm 波占空比的变化。
背景
根据 /proc/cpuinfo,我正在使用 Gumstix Over Water COM (https://www.gumstix.com/store/app.php/products/265/),它有一个以 499.92 BogoMIPS 运行的单核 ARM Cortex-A8 处理器(Gumstix 页面声称最高 1Ghz,建议使用 800Mhz)。该操作系统是基于内核版本 2.6.34 的 Angstrom Image 版本的 Linux,它在 Gumstix Water COM 上有现货。
问题
我已经阅读了大量关于 Linux 中精确计时的文章(并且已经尝试了大部分),并且一致认为使用 clock_gettime() 并引用 CLOCK_MONOTONIC 是最好的方法。 (我本来希望使用 RDTSC 寄存器进行计时,因为我有一个具有最低节能能力的内核,但这不是英特尔处理器。)所以这是奇怪的部分,而 clock_getres() 返回 1,表明分辨率为 1 ns ,实际的时序测试表明最小分辨率为 30517ns 或(不可能是巧合)恰好是 32.768KHz 时钟滴答之间的时间。这就是我的意思:
// Stackoverflow example
#include <stdio.h>
#include <time.h>
#define SEC2NANOSEC 1000000000
int main( int argc, const char* argv[] )
{
// //////////////// Min resolution test //////////////////////
struct timespec resStart, resEnd, ts;
ts.tv_sec = 0; // s
ts.tv_nsec = 1; // ns
int iters = 100;
double resTime,sum = 0;
int i;
for (i = 0; i<iters; i++)
{
clock_gettime(CLOCK_MONOTONIC, &resStart); // start timer
// clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, &ts);
clock_gettime(CLOCK_MONOTONIC, &resEnd); // end timer
resTime = ((double)resEnd.tv_sec*SEC2NANOSEC + (double)resEnd.tv_nsec
- ((double)resStart.tv_sec*SEC2NANOSEC + (double)resStart.tv_nsec);
sum = sum + resTime;
printf("resTime = %f\n",resTime);
}
printf("Average = %f\n",sum/(double)iters);
}
(不要为双重投射而烦恼,tv_sec 在 time_t 中,tv_nsec 很长。)
编译:
gcc soExample.c -o runSOExample -lrt
运行:
./runSOExample
如图所示注释掉 nanosleep 后,结果为 0ns 或 30517ns,大多数为 0ns。这让我相信 CLOCK_MONOTONIC 以 32.768kHz 更新,并且大部分时间在第二次 clock_gettime() 调用之前时钟尚未更新,如果结果为 30517ns,则时钟已在两次调用之间更新。
当我在我的开发计算机(运行在 1.4 GHz 的 AMD FX(tm)-6100 六核处理器)上做同样的事情时,最小延迟是更恒定的 149-151ns,没有零。
所以,让我们将这些结果与 CPU 速度进行比较。对于 Gumstix,30517ns (32.768kHz) 相当于 499.93MHz cpu 的 15298 个周期。对于我的开发计算机,150ns 相当于 1.4Ghz CPU 的 210 个周期。
使用未注释的 clock_nanosleep() 调用,平均结果如下: Gumstix:平均值 = 213623,结果上下变化,以最小分辨率 30517ns 的倍数变化 开发计算机:57710-68065 ns,没有明显趋势。在开发计算机的情况下,我希望分辨率实际上处于 1 ns 水平,而测量到的 ~150ns 确实是两个 clock_gettime() 调用之间经过的时间。
所以,我的问题是: 是什么决定了最小分辨率? 当处理器的运行速度仅快 2.6 倍时,为什么开发计算机的分辨率比 Gumstix 高 30000 倍? 有没有办法改变 CLOCK_MONOTONIC 的更新频率和位置?在内核中?
谢谢!如果您需要更多信息或说明,请询问。
【问题讨论】:
-
只是想知道。不需要某种类型的硬件来从 CPU 时钟中获取周期吗?至少在那个精度水平上。也许Gumstix没有那个? (我只是在谈论一个可以计算滴答声并在滚动之前保持它们的寄存器。)
-
根据您所说的所有阅读内容,您可能已经看过 this link,但还是发帖以防万一。有些材料是相关的。
-
有完全相同的问题。 30517ns 的倍数。我正在使用 Overo Tide。你解决过这个问题吗?
标签: c precision timing gettime gumstix