11

PWM 波のデューティ サイクルの変化のタイミングを計るには、1 us レベルの正確なタイミングを行う必要があります。

バックグラウンド

私は、499.92 BogoMIPS で動作するシングル コア ARM Cortex-A8 プロセッサを搭載した Gumstix Over Water COM ( https://www.gumstix.com/store/app.php/products/265/ ) を使用しています (Gumstix ページは、 /proc/cpuinfo によると、800Mhz で 1Ghz を推奨)。OS は、カーネル バージョン 2.6.34 に基づく Linux の Angstrom Image バージョンであり、Gumstix Water COM にストックされています。

問題

私は Linux での正確なタイミングについてかなりの量の読み物をしてきました (そして、そのほとんどを試しました) が、clock_gettime() を使用して CLOCK_MONOTONIC を参照することが最善の方法であるというのがコンセンサスのようです。(最小限の省電力機能を備えたコアが 1 つあるため、RDTSC レジスターをタイミングに使用したかったのですが、これは Intel プロセッサーではありません)。 、実際のタイミング テストでは、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);
}

(二重キャストについて心配しないでください。time_t の tv_sec と tv_nsec は long です。)

コンパイル:

gcc soExample.c -o runSOExample -lrt

実行:

./runSOExample

示されているように nanosleep がコメント化されていると、結果は 0ns または 30517ns のいずれかになり、大部分は 0ns になります。これにより、CLOCK_MONOTONIC は 32.768kHz で更新され、ほとんどの場合、2 回目の clock_gettime() 呼び出しが行われる前にクロックが更新されておらず、結果が 30517ns の場合、呼び出し間でクロックが更新されていると思われます。

開発用コンピューター (1.4 GHz で動作する AMD FX(tm)-6100 6 コア プロセッサ) で同じことを行うと、最小遅延はより一定の 149 ~ 151 ns になり、ゼロはありません。

それでは、これらの結果を CPU 速度と比較してみましょう。Gumstix の場合、その 30517ns (32.768kHz) は 499.93MHz CPU の 15298 サイクルに相当します。私の開発用コンピューターでは、150ns は 1.4Ghz CPU の 210 サイクルに相当します。

コメントを外した clock_nanosleep() 呼び出しの平均結果は次のとおりです。 Gumstix: 平均値 = 213623 で、結果は 30517ns の最小解像度の倍数で上下に変化します。開発用コンピューターの場合、解像度は実際には 1 ns レベルであると予想され、実際に測定された ~150 ns は、2 つの clock_gettime() 呼び出しの間に経過した時間です。

だから、私の質問はこれらです:その最小解像度を決定するものは何ですか? プロセッサが ~2.6 倍速くしか実行されていないのに、開発用コンピューターの解像度が Gumstix よりも 30000 倍優れているのはなぜですか? CLOCK_MONOTONIC が更新される頻度と場所を変更する方法はありますか? カーネルで?

ありがとう!さらに詳しい情報や説明が必要な場合は、お尋ねください。

4

2 に答える 2