Messung der CPU-Last der Interrupt-Routine

8

Ich habe einen ISR, der eine Anzeige mit einer festen Frequenz aktualisiert. Ich möchte meine Routine optimieren, um den Overhead zu minimieren und so viel CPU-Zeit wie möglich für andere Verarbeitungen offen zu halten, aber ich habe keine gute Möglichkeit, Metriken zu sammeln, um meine CPU-Auslastung zu bestimmen.

Ich könnte mir die Baugruppe ansehen und die Routine analysieren, aber ich habe nicht die Geduld oder die Fähigkeit, dies genau zu tun. Ich habe auch nicht das Gefühl, dass ich schrecklich feinkörnige Ergebnisse brauche, nur einen einfachen Prozentsatz der CPU-Zeit, die von der isr belegt wird.

Ich könnte einen Pin nur dann hoch setzen, wenn der isr aktiv ist, und ihn extern messen. Das hat ein Minimum an Overhead im Code, aber ich weiß nicht, womit ich es messen soll. Ich habe kein Oszilloskop oder ähnliches. Gibt es eine einfache IC oder eine einfache Möglichkeit, ein anderes Mikro zur Messung des Arbeitszyklus zu verwenden? Ich habe von dedizierten Frequenzzählerchips gehört, aber gibt es etwas für den Arbeitszyklus?

captncraig
quelle

Antworten:

8

Nur eine halbherzige Idee, Sie können möglicherweise Timer wie diesen verwenden (Pseudocode):

int main(void)
{

    /* ... init timers and uart here, enable your interrupts ... */

    start_timer0();
    while (!timer1Started()){}
    stop_timer1();

    uart_puts("Idle ticks: %d, ISR ticks: %d", timer0_value, timer1_value);

}

und in Ihrem Display ISR ...

ISR_display()
{
    stop_timer0();
    start_timer1();

    /* ... your ISR routine ... */
}

Ich habe hier einige Annahmen getroffen. 1 - dass Sie Ihre Timer für nichts anderes verwenden und dass 2 - der Aufwand für das Starten und Stoppen eines Timers minimal ist (normalerweise mit einem einzelnen Registerschreibvorgang). BEARBEITEN: und eine dritte Annahme: Sie können all dies erfassen, bevor ein Timerüberlauf auftritt, aber vielleicht können Sie dies auch berücksichtigen.

Es wird einen gewissen Overhead für Kontextwechsel geben, den Sie nicht abfangen können, und dies fügt außerdem zwei zusätzliche Operationen in Ihrem ISR hinzu (stellen Sie sicher, dass Sie Makros für Ihren start_timer / stop_timer verwenden, um den Overhead für Funktionsaufrufe zu vermeiden). Wenn Sie die Gesamtzahl der Zyklen erhalten können, die für Start + Stopp-Timer-Makros verwendet werden, können Sie diese Ticks vom timer1_value subtrahieren, um den ISR-Ticks-Wert etwas genauer zu erhalten. Ihre endgültige Berechnung für% der verwendeten CPU-Zeit wäre einfach:

U.seinGecpu=(T.ichcksichsrT.ichcksichsr+T.ichcksichdle)100
Jon L.
quelle
1
+1 für eine Lösung, die keine externe Hardware erfordert. Wahrscheinlich ein umständlicherer Weg, aber es passt zu meinen Einschränkungen. Ich muss jetzt nur noch etwas über Timer lernen. Vielen Dank.
Captncraig
Ich habe dies auf einem AVR für ein ähnliches Projekt verwendet. Es funktioniert sehr gut.
drxzcl
11

Setzen Sie einen Ausgangspin, wenn Sie den ISR eingeben, und löschen Sie ihn, bevor Sie von ihm zurückkehren. Filtern Sie den Ausgang mit einem RC-Filter. Die Spannung am Kondensator sollte Ihnen das ISR-Tastverhältnis geben.
Wenn Ihre Stromversorgung beispielsweise 3,3 V beträgt und Sie 33 mV messen, verbringen Sie 1% der Zeit im ISR.

stevenvh
quelle
2
Dies ist genau das, was wir tun, mit Ausnahme des RC-Filterteils. Wir setzen einen Ausgangspin beim Eingeben des ISR und löschen ihn dann bei der Rückkehr. Wenn Sie dies auf einem O-Scope betrachten, erhalten Sie alle möglichen nützlichen Informationen.
3
@ David - Ich beobachte auch nur die Impulse auf einem Zielfernrohr, aber OP sagt, dass er keinen hat.
Stevenvh
1
Es sieht so aus, als müsste ich für einen guten Umfang mit dem Speichern beginnen.
Captncraig
@stevenvh, genau das, was ich vorschlagen wollte, als ich das Fehlen eines Bereichs sah. Aus diesem Grund lieben diese eingebetteten Typen ein paar zusätzliche digitale Out-Pins.
Kortuk
Filtern nach Messgerät ohne Zielfernrohr ist eine gute Idee. Schalten Sie die LED ein / aus und messen Sie die effektive Helligkeit: -). (Sehr schwer zu erkennen, auch große Variationen - aber niedlich.)
Russell McMahon
7

Der einfachste Weg, dies zu tun, besteht darin, den Code im Simulator auszuführen und die Zyklen zu messen, die von der Interruptroutine ausgeführt werden. Der Microchip MPLAB-Simulator verfügt beispielsweise über eine praktische Stoppuhrfunktion, die für diesen Zweck sehr nützlich ist.

Andernfalls kann es hilfreich sein, zu Beginn des Interrupts einen Stift anzuheben und am Ende abzusenken. Der einfachste Weg, dies zu betrachten, ist mit einem Oszilloskop. Wenn Sie Mikrocontroller- und Elektronikprojekte durchführen, sollten Sie sich trotzdem eines zulegen.

Ohne Zielfernrohr können Sie die Pin-Spannung einfach tieffiltern und dann mit einem Voltmeter messen. Diese Spannung geteilt durch die Prozessorleistungsspannung gibt Ihnen den Bruchteil der Zeit, in der der Pin hoch ist. Wenn der Prozessor beispielsweise mit 3,3 V betrieben wird und die tiefpassgefilterte Pin-Spannung 800 mV beträgt, ist der Pin in 24% der Fälle hoch 800 mV / 3,3 V =.

Da Sie anscheinend einen Compiler verwenden, müssen Sie diese Antwort etwas herabsetzen. Der Compiler fügt wahrscheinlich einen Interrupt-Eingabecode hinzu, bevor Ihr Code ausgeführt wird, und einen Interrupt-Exit-Code, nachdem Ihr Code ausgeführt wird. Die wahre Unterbrechungszeit verlängert einige Zyklen auf beiden Seiten des Impulses. Wenn Sie sich für das Interrupt-Timing interessieren, sollten Sie natürlich überhaupt keinen Compiler verwenden.

Olin Lathrop
quelle