Wie kann ich in der Praxis die Auslastung eines Mikrocontrollers messen?
Ich habe über Keil einen Stm32F1 programmiert. Dieser steuert nur ein
Display und sollte deshalb überdimensioniert sein.
Doch wie kann ich jetzt die aktuelle Auslastung in Prozent ermitteln und
genaue Werte zu erhalten?
Ich nehme an, du hast deine Applikation nichtblockerend als
Zustandsmaschine geschrieben, wo genau an einem Ort im Main die Zeit
verbraten wird. Dann mach dort ein Bit-Toggle hin und miss dessen
Aktivitaet mit einem Oszilloskop.
martin schrieb:> Doch wie kann ich jetzt die aktuelle Auslastung in Prozent ermitteln und> genaue Werte zu erhalten?
Ich messe die Zykluszeit der Haupschleife. Und wenn dieser Zyklus länger
wird als 5..10ms, dann sehe ich nach, wo denn da Zeit verplempert wird.
> Doch wie kann ich jetzt die aktuelle Auslastung in Prozent ermitteln und> genaue Werte zu erhalten?
Definiere "Auslastung". Ein µC ist eigentlich immer zu 100% ausgelastet,
weil er ja nie "wartet", sondern auch in einer Warteschleife wild vor
sich hinrechnet.
Oder andersrum: dein µC ist dann zu 100% asgelastet, wenn du nichts mehr
"dazuprogrammieren" kannst, ohne dass irgendwas anderes nicht mehr
funktioniert. Ein µC, der also nur jede Minute die Temperatur abliefern
muss, hat zwar eigentlich fast nichts zu tun, kann aber schon
"überlastet" sein, wenn er diese Temperatur auf 5µs genau abliefern
muss...
Tastenklopper schrieb:> Pin frei? High setzen während der uC arbeitet, low bei sleep/idle.
Das ist die einfachste Form, die aber nur funktioniert, wenn man den
Sleepmode tatsächlich ausgiebig nutzt.
martin schrieb:> Stm32F1 programmiert. Dieser steuert nur ein> Display und sollte deshalb überdimensioniert sein.> Doch wie kann ich jetzt die aktuelle Auslastung in Prozent ermitteln und> genaue Werte zu erhalten?
Ich aktualisiere ein Display nur 4x pro Sekunde, mehr lann ich eh nicht
lesen.
Messwerte ermitteln, Display schreiben, je einen Port am Anfang setzen
und am Ende löschen, das kann ich mit dem Oszi prüfen oder einen
Hardware Timer und ausgeben wie lange was dauert, ist genug Luft
vorhanden oder stoßen die beiden zusammen?
Joachim B. schrieb:> Ich aktualisiere ein Display nur 4x pro Sekunde, mehr lann ich eh nicht> lesen.
Ich aktualisiere in einem üblichen Text-Display zyklisch von links oben
nach rechts unten pro ms (im Timertic) ein Zeichen. Das hat sich als am
einfachsten und deterministischsten herausgestellt.
Lothar M. schrieb:> Ich aktualisiere in einem üblichen Text-Display zyklisch von links oben> nach rechts unten pro ms (im Timertic) ein Zeichen. Das hat sich als am> einfachsten und deterministischsten herausgestellt.
das mag sein kostet aber mehr Zeit,
warum soll ich alle ms was machen?
kommt halt auf die Anbindung des Displays an, SPI sind oft schneller als
I2C
Ich bin ja nicht der Profiprogrammierer also schreibe ich nicht zu oft,
zumal ich nicht immer weiss welche Bytes da übertragen werden müssen mit
Init, Zeilen Spalten ansprechen Command/Data Wechsel usw.
Ich verwende in meinen Programmen kein OS/RTOS.
Im Main-Loop zähle ich eine INT Variable hoch. Jede Sekunde, im Sekunden
Timer kopiere ich die in eine zweite Variable und nulle den Zähler.
Diese Zahl zeige ich im Display an und zeigt somit die Main Durchläufe.
Um so größer diese ist um so weniger "Arbeit" steht gerade an.
Wenn ich eine Änderung mache und diese Zahl reduziert sich deutlich,
dann habe ich entweder extrem schlecht was geändert (viel Warten im
Code) oder die Berechnung zieht tatsächlich das System herunter, wo man
dann wiederum überlegen sollte diese in mehr Teilaufgaben zu zerlegen
oder doch besser anders rechnet.
Dieser Indikator hat schon einige Male mir geholfen und ist sehr einfach
zu programmieren. Der Systic-Counter ist bei ohnehin immer aktiv.
martin schrieb:> Doch wie kann ich jetzt die aktuelle Auslastung in Prozent ermitteln und> genaue Werte zu erhalten?
Auslastung bedeutet doch nichts anders als das Verhältnis zwischen
Arbeiten und nichts tun (wobei letzteres auch eine sinnlose nop-Schleife
sein kann).
Hast Du zeitkritische Dinge zu erledigen, so ist die Auslastung bei
100%, wenn diese nicht mehr zeitgerecht ausgeführt werden können.
Hast Du einen Maximalverbauch einzuhalten, so ist die Auslastung bei
100%, sobald dieser überschritten wurde. Du kannst also den Prozessor
nicht mehr entsprechend lange schlafen lassen, da er "zu viel" zu tun
hat.
Lothar M. schrieb:
> Ich aktualisiere in einem üblichen Text-Display zyklisch von links> oben nach rechts unten pro ms (im Timertic) ein Zeichen. Das hat> sich als am einfachsten und deterministischsten herausgestellt.
Bei einem 2 x 16 Display sind das 32 ms Updaterate.
OK, fast (!) schnell genug für's Auge.
Aber wozu?
Gibt man alles in einem Schwupp raus, spart man sich die Cursor-
Positionierung und ist in wenigen ms fertig - wobei wichtige
Ereignisse zwischendrin immer mit Interrupt erfasst werden
können.
Wenn es zeitlich eng wird, verschwendet man damit unnötig
µC-Zeit.
Brummbär schrieb:> Hast Du zeitkritische Dinge zu erledigen, so ist die Auslastung bei> 100%, wenn diese nicht mehr zeitgerecht ausgeführt werden können.
Das in ähnlicher Form wurd ein diesem Thread schon um die 5 mal erwähnt.
Denke aber der TE will nicht wissen ob bei Programm X die Auslastung bei
100% liegt oder nicht (also ne binäre Antwort), sondern eine konkrete
Prozentangabe damit er weiss wieviel Spielraum er noch hat.
Davon ist z.B. abhängig was für algorithmen man für ein konkretes
Problem wählt oder auch ob er noch bestimmte optionale Features (die
einige Arbeitsstunden brauchen bis zum ersten Test) überhaupt noch
realisierbar sind, oder nicht (weil das sonst verschwendete Arbeitszeit
wäre).
Also das klingt jedenfalls nützlich.
Eine smarte Lösung die mir einfallen würde, welche es nicht erfordert
dass man an vielen Stellen im Code was ändert, wäre einsetzbar wenn man
ein Echtzeit Betriebssystem verwendet. Bei fast allen gibt es die
Möglichkeit den Threads eine Priorität zu geben.
Dann braucht man einen Thread mit einer Priorität neidriger als alle
nützlichen Programmthreads und darin werden dann die Zyklen gezählt,
denn der Scheduler wird immer dann in diesen Thread springen wenn sonst
nichts anderes etwas zutun hat.
EDIT: Wenn Stromsparmaßnahmen aktiv sind, muss man das natürlich
berücksichtigen wobei man diesen Auslastungswert ja eher nur während der
Entwicklung bzw. zu Debugzwecken braucht. Dann kann man die
Stromsparmaßnahmen abschalten und den Thread mit einer Endlosschleife
laufen lassen.
An den Unglaeubigen, der ein display auf's Mal beschreiben will ...
Schon mal das Datenblatt angeschaut wie lange du nach einem Zeichen
schreiben warten musst ? Of ist das in den Mikrosekunden, nicht in den
Nanosekunden.
Du kannst natuerlich auch das Ready auswerten. Und waehrend ready nicht
da ist nichts machen, Zeit verbloeden, was man eben genau nicht machen
sollte.
Die einfachere und effizientere Loesung wie auf Ready warten ist eben
der Timer. Damit kann man sich das Ready schenken, den Code dazu, wie
auch den Anschluss.
Jacko schrieb:>> Ich aktualisiere in einem üblichen Text-Display zyklisch von links>> oben nach rechts unten pro ms (im Timertic) ein Zeichen. Das hat>> sich als am einfachsten und deterministischsten herausgestellt.>> Bei einem 2 x 16 Display sind das 32 ms Updaterate.> OK, fast (!) schnell genug für's Auge.
Man kann ja auch in jedem 10. 1kHz Interrupt ein Zeichen schreiben, dann
sind es immer noch 3 Hz Wiederholfrequenz.
>> Aber wozu?
Der Witz an der Sache ist der, daß diese LCDs langsam ohne Ende sind.
Das eigentliche Schreiben eines Zeichens dauert ca. 1us (Puls an Signal
E), dann muss man ca. 40us warten, sprich, die CPU ist blockiert. Das
Ganze dann 4x20=80 mal. Effektive CPU-Nutzung nicht mal 5%. Im Interrupt
spart man sich das Warten. Außerdem geht das Scheiben in den Puffer im
SRAM des Mikrocontrollers um Größenordnungen schneller als eine direkte
Ausgabe auf das LCD.
Trotzdem sind beide Varianten praktikabel!
Ich verwende bei PIC24 und PIC32 einen kleinen "Trick", der auch bei
STM32 klappen könte.
Es setzt voraus, dass man den Idle-Modus benutzt. Aber das will man
sowieso.
Ich setze zwei Timer auf, einer zählt im Idle weiter, der zweite nicht
(die Timer der PIC32 kann man so konfigurieren). Einen Timer kann man
sparen, solange man eine akurrate Vergleichsbasis hat (z.B. einen
RTCC-Interrupt oder dergleichen).
Den Timer, der nicht im Idle-Modus zählt, liest man nach einer
definierten Zeit aus und dividiert man durch den Zahlenwert, den er
hätte, würde er die ganze Zeit zählen. Schon hat man die CPU-Auslastung.
Inklusive der Zeit, die er in ISRs verbringt.
Man kann sich sogar ein Flag setzen, wenn sie einen Schwellwert
erreicht, oder man kann sich den Maxwert anzeigen lassen. Was praktisch
ist, wenn man feststellen möchte, wie knapp man dabei ist. Oder wenn man
Stromsparen muss.
Man kann einen Timer auch benutzen, um Laufzeiten von bestimmten
Programmteilen zu messen - beim Eintritt in eine Programmteil starten,
danach anhalten.
Die gemessenen Zeiten kann man sich bequem in ein Array oder eine
Struktur speichern. Ich nutze das zur Optimierung. Meistens komme ich da
mit der Taktfrequenz ziemlich weit hinunter, und es sind oft
Kleinigkeiten die ziemlich bremsen.
Möglicherweise könnte sich der Core-Timer eignen, falls ein ARM sowas
hat. Ich habe keine Ahnung, ob ein ARM sowas hat, und ob der im idle
weiterzählt. Anschauen kann aber lohnen.
> Ich aktualisiere in einem üblichen Text-Display zyklisch von links oben> nach rechts unten pro ms (im Timertic) ein Zeichen. Das hat sich als am> einfachsten und deterministischsten herausgestellt.
Das mache ich auch so. In meiner aktuellen Variante brauche ich sogar 4
Ticks für ein Zeichen. Damit kann ich die Dauer des Taktsignals von der
CPU-Frequenz entkoppeln und die Routine läuft vom 8MHz AVR bis zum
120MHz SPC56xxx ohne Änderungen. Bei 1KHz Tick komme ich bei 2x16 auf
ca. 8Hz Refresh-Rate, das reicht im Allgemeinen aus.
Um die Auslastung zu messen kann man das entweder über "Bitwackeln" oder
auch über die Stromaufnahme (Shunt) machen, wenn man den Controller in
den Pausen in den Sleep schickt. Ohne Oszi ist das halt leider nicht
besonders genau.