Ich brauche präzise Zeitsteuerung für die 1 us-Ebene zu Zeit eine Änderung im Tastverhältnis einer PWM-Welle.Precise Linux Timing - Was bestimmt die Auflösung von clock_gettime()?
Hintergrund
ich eine Gumstix über Wasser COM bin mit (https://www.gumstix.com/store/app.php/products/265/), die einen Single-Core-ARM-Cortex-A8-Prozessor bei 499,92 BogoMIPS läuft (die Gumstix Seite mit 800Mhz bis 1GHz behauptet bis empfohlen) nach/proc/cpuinfo. Das Betriebssystem ist eine Angstrom-Image-Version von Linux, die auf der Kernel-Version 2.6.34 basiert, und es ist auf der Gumstix Water COM verfügbar.
Das Problem
Ich habe ziemlich viel lesen über präzises Timing in Linux getan (und haben die meisten es versucht) und der Konsens scheint zu sein, dass clock_gettime mit() und Referenzierung CLOCK_MONOTONIC ist die beste Weg, es zu tun. (Ich hätte gerne das RDTSC-Register für das Timing verwendet, da ich einen Kern mit minimalen Energiesparfunktionen habe, aber dies ist kein Intel-Prozessor.) Hier ist der ungerade Teil, während clock_getres() 1 zurückgibt, was eine Auflösung von 1 ns nahelegt , tatsächliche Timing-Tests deuten auf eine minimale Auflösung von 30517ns oder (es kann nicht Zufall sein) genau die Zeit zwischen einem 32.768KHz Clock-Ticks. Hier ist, was ich meine:
// 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);
}
(ärgern Sie sich nicht über den Doppelguss, tv_sec in einem time_t und tv_nsec ist eine lange.)
Compile mit:
gcc soExample.c -o runSOExample -lrt
Run mit:
./runSOExample
mit dem Nanosleep kommentiert, wie gezeigt, ist das Ergebnis entweder 0ns oder 30517ns mit den meisten Wesen 0ns. Dies führt mich zu der Annahme, dass CLOCK_MONOTONIC bei 32,768 kHz aktualisiert wird und die meiste Zeit die Uhr nicht aktualisiert wurde, bevor der zweite clock_gettime() -Aufruf erfolgt, und in Fällen, in denen das Ergebnis 30517ns beträgt, wurde die Uhr zwischen Anrufen aktualisiert.
Wenn ich dasselbe auf meinem Entwicklungscomputer (AMD FX (tm) -6100 Six-Core Prozessor mit 1,4 GHz) mache, ist die minimale Verzögerung eine konstantere 149-151ns ohne Nullen.
Also vergleichen wir diese Ergebnisse mit den CPU-Geschwindigkeiten. Für den Gumstix entsprechen 30517 ns (32,768 kHz) 15298 Zyklen der 499,93 MHz CPU. Für meinen Entwicklungscomputer entspricht 150ns 210 Zyklen der 1,4 GHz CPU.
Mit dem clock_nanosleep() -Aufruf unkommentiert Die durchschnittlichen Ergebnisse sind folgende: Gumstix: Avg-Wert = 213.623, und das Ergebnis verändert sich, oben und unten, um Vielfache von jener min Auflösung von 30517ns Dev Computer: 57.710 bis 68.065 ns mit kein klarer Trend. Im Falle des Entwicklungscomputers erwarte ich, dass die Auflösung tatsächlich auf dem 1-ns-Niveau liegt, und die gemessenen ~ 150 ns sind wirklich die Zeit, die zwischen den zwei clock_gettime() - Aufrufen verstrichen ist.
Also meine Fragen sind diese: Was bestimmt diese minimale Auflösung? Warum ist die Auflösung des Dev-Computers 30000X besser als die des Gumstix, wenn der Prozessor nur ~ 2,6-mal schneller läuft? Gibt es eine Möglichkeit zu ändern, wie oft CLOCK_MONOTONIC aktualisiert wird und wo? Im Kernel?
Danke! Wenn Sie weitere Informationen oder Erläuterungen benötigen, fragen Sie einfach.
Ich frage mich nur. Wäre nicht irgendeine Art von Hardware erforderlich, um Zyklen vom CPU-Takt zu erfassen? Zumindest auf dieser Ebene der Präzision. Vielleicht hat der Gumstix das nicht? (Ich spreche gerade über ein Register, das Zecken zählen kann und sie halten, bevor es rollt.) – Jiminion
Mit dem ganzen Lesen sagten Sie, dass Sie getan haben, haben Sie möglicherweise schon gesehen *** [dieser Link] (http: // gallinazo.flightgear.org/technology/gumstix-overo-rcservos-and-pwm-signal-generation/)***, aber auf jeden Fall nur für den Fall. Ein Teil des Materials ist relevant. – ryyker
Das gleiche Problem haben. Vielfache von 30517ns. Ich benutze eine Overo Tide. Hast du jemals dieses Problem gelöst? – Ryan