Wie kann ich nachweisen, dass __udelay () auf meinem eingebetteten ARM-System korrekt funktioniert?

9

Wir haben einen ARM9, der den Kernel 3.2 verwendet - alles scheint gut zu funktionieren. Kürzlich wurde ich gebeten, Code hinzuzufügen, um bei einigen GPIO-Leitungen beim Start einen 50-ms-Impuls hinzuzufügen. Der Pulscode ist in Ordnung; Ich kann sehen, dass die Linien wie erwartet nach unten und oben gehen. Was nicht wie erwartet funktioniert, ist die Funktion udelay() . Das Lesen der Dokumente lässt mich glauben, dass die Einheiten in Mikrosekunden sind, aber wie im Logikanalysator gemessen, war es viel zu kurz. Also habe ich diesen Code hinzugefügt, um 50ms zu bekommen.

%Vor%

Ich mag es nicht, aber es funktioniert gut. Es gibt einige ungerade Konstanten und Anweisungen im Code udelay . Kann mir jemand aufklären, wie das funktionieren soll? Dieser Code wird aufgerufen, nachdem alle Uhren initialisiert wurden, also scheint alles andere in Ordnung zu sein.

    
Jeff 15.11.2012, 23:04
quelle

1 Antwort

4

Laut Linus in diesem Thread :

  

Wenn es etwa 1% weniger ist, ist alles in Ordnung. Wenn jemand einen Verzögerungswert gewählt hat   das ist so empfindlich auf kleine Fehler in der Verzögerung, die sie bemerken   das - oder sogar etwas wie 5% bemerken - dann haben sie auch gepflückt   kurz vor einer Verzögerung.

     

udelay () war nie wirklich eine Art von Präzision   Instrument. Vor allem, wenn CPUs mit unterschiedlichen Frequenzen laufen,   Wir hatten in der Vergangenheit einige ziemlich wilde Schwankungen. Das traditionelle   Die busy loop wird nicht nur von Interrupts, sondern auch von   Dinge wie Cache-Ausrichtung (wir haben es inline) und dann später die   TSC basierte natürlich davon, dass TSC stabil war (was sie   waren für eine Weile nicht).

     

In der Vergangenheit haben wir udelay () also wirklich ausgemacht (dh 50% Rabatt)   usw.), ich würde mich nicht um Dinge in der 1% -Bereich kümmern.

     

Linus

Es wird also nicht perfekt sein. Es wird weg sein. Um wieviel hängt von vielen Faktoren ab. Verwenden Sie statt einer for -Schleife stattdessen mdelay . Es könnte ein bisschen genauer sein. Aus dem O'Reilly Linux Device Drivers Buch:

  

Der udelay Aufruf sollte nur für kurze Zeitspannen aufgerufen werden, weil   Die Genauigkeit von loops_per_second ist nur acht Bits und bemerkbar   Fehler häufen sich bei der Berechnung langer Verzögerungen. Obwohl die   Die maximal zulässige Verzögerung beträgt fast eine Sekunde (seit Berechnungen   Überlauf für längere Verzögerungen), der vorgeschlagene Maximalwert für udelay ist   1000 Mikrosekunden (eine Millisekunde). Die Funktion mdelay hilft dabei   Fälle, in denen die Verzögerung länger als eine Millisekunde sein muss.

     

Es ist auch wichtig daran zu denken, dass udelay eine "busy-wait" -Funktion ist   (und so auch mdelay ); Andere Aufgaben können während der Zeit nicht ausgeführt werden   Ablauf. Sie müssen daher sehr vorsichtig sein, insbesondere mit mdelay und   vermeide es, es zu benutzen, es sei denn, es gibt keinen anderen Weg, dein Ziel zu erreichen.

     

Gegenwärtig werden Verzögerungen von mehr als einigen Mikrosekunden unterstützt   kürzer als ein Timer Tick ist sehr ineffizient. Dies ist normalerweise nicht ein   Problem, weil Verzögerungen nur lang genug sein müssen, um von bemerkt zu werden   Menschen oder durch die Hardware. Eine Hundertstel Sekunde ist geeignet   Präzision für mensch-bezogene Zeitintervalle, während eine Millisekunde eine ist   lange genug Verzögerung für Hardware-Aktivitäten.

Speziell die Zeile " der vorgeschlagene Maximalwert für udelay ist 1000 Mikrosekunden (eine Millisekunde) " bei mir, da Sie angeben, dass 2000 der max. Von dieses Dokument zum Einfügen von Verzögerungen:

  

mdelay ist Makro Wrapper um udelay, um für möglich zu berücksichtigen   Überlauf beim Übergeben großer Argumente an udelay

Es ist also möglich, dass Sie in einen Überlauffehler geraten. Obwohl ich 2000 normalerweise nicht für ein "großes Argument" halte.

Aber wenn Sie echte Genauigkeit in Ihrem Timing benötigen, müssen Sie sich mit dem Offset wie Sie beschäftigen, rollen Sie Ihre eigenen oder verwenden Sie einen anderen Kernel. Informationen dazu, wie Sie Ihre eigene Verzögerungsfunktion mit Assembler oder mit harten Echtzeitkerneln steuern können, finden Sie in diesem Artikel auf Hoch -Lösung Timing .

Siehe auch: Linux-Kernel: udelay () kehrt zu früh zurück?

    
embedded.kyle 16.11.2012 14:31
quelle

Tags und Links