Hallo! Jedem ist wohl die Prozessorauslastung unter Windows und Linux bekannt. Wie kann man sowas auf einem µC realisieren? Wann weiß ich, dass ein Prozessor voll ausgelastet ist? Wie kann ich das messen? Wie bestimme ich eine theoretisch Auslastung über 100%? Und wie kann man sowas auf Rechenaufgaben umsetzen? Also für die Berechnung von Dem-und-dem habe ich (rechnerisch) eine Auslastung von so-und-soviel Prozent? Danke schon mal! Gruß Klopfer
So nen µC ist immer voll ausgelastet, sofern du ihn nicht in den schlafmodus versetzt
der PC auch, er verbringt die nicht benötigte Zeit im Lerlaufprozess. Es bleibt beiden ja auch nichts weiter übrg, wenn nichts zu tun ist...
@mrl33tn3zZ: nein, das ist blödsinn. @klopfer: beschäftige dich mal mit realzeittheoremen - dann sollte das klar werden. auslastung wirst du sinnvoll nur errechnen können, wenn du verschiedene tasks hast. der simpelste fall dafür ist übrigens auch schon ohne "betriebssystem" zu bekommen: wenn du einen AVR nur periodisch, interrupt-getriggert aktionen durchführen lässt, hast du als auslastung: (rechenzeit aller interrupts in einer periode)/(periodenzeit).
"Realzeittheorem"!? - Sicher, dass das so heißt? Google findet keinen einzigen Treffer! Zu deiner Formel: Da steckt die Variable "Rechenzeit" drin. Woher weiß ich denn, wie lange die Berechnung von etwas dauert?
Einen Timerstand abfragen ist zu ungenau, da bei sehr schnellen Berechnungen einen zu großen Einfluss auf die Gesamtzeit hat, da die Systemzeit und dessen Abfrage ebenfalls Rechenleistung/-zeit beansprucht.
mittlerweile heißt es scheinbar "Echtzeit". das findet man in <10s
raus...
> Einen Timerstand abfragen ist zu ungenau, da bei sehr schnellen
wer schreibt hier etwas von timerständen?
Es bleibt noch immer die Frage, wie ich die Rechenzeit in µs (Taktzyklen) bestimme.
Um Auslastung zu erfassen, muss ich "Nichtstun" definieren. Sonst ist die Auslastung 100%. Wenn in meinem Programm eine Endlosschleife läuft, tut die CPU immer was. Wenn ich in der Schleife entscheide, ob ich was tun soll, dann muss ich erfassen wie lange ich was tue und wie lange ich warte. Es muss also eine Zeitbasis geschaffen und ausgewertet werden. Diese Basis könnte ein Timer mit hoher Eingangsfrequenz sein. Diesen muss ich dann in der Endlosschleife verwalten. Sowas macht normal das Betriebssystem mit dem Scheduler (-> Wikipedia). Gruss
Reagiere nicht so genervt! Ich red hier von nem Blackfin, ARM oder nen großen AVR. Wie soll man das simulieren. Zumal eine Simulation nicht in Echtzeit ablaufen würde. Pin setzten kosten auch wieder einige Taktzyklen. Und dann müsste ich das ganze extern (mit nem Oszi) messen. Ich brauche da Ergebnis aber zur Laufzeit und in mindest µs-Genauigkeit.
Gast wrote: > Um Auslastung zu erfassen, muss ich "Nichtstun" definieren. Sonst ist > die Auslastung 100%. > Wenn in meinem Programm eine Endlosschleife läuft, tut die CPU immer > was. Wenn ich in der Schleife entscheide, ob ich was tun soll, dann muss > ich erfassen wie lange ich was tue und wie lange ich warte. Es muss also > eine Zeitbasis geschaffen und ausgewertet werden. Diese Basis könnte ein > Timer mit hoher Eingangsfrequenz sein. Diesen muss ich dann in der > Endlosschleife verwalten. > Sowas macht normal das Betriebssystem mit dem Scheduler (-> Wikipedia). > > Gruss in meinem system ist die endlosschleife im main() leer. Mein System läuft im RTC (Takt 1 ms). Ansonsten noch ISRs für I2C, SCI und SPI. Nun kann man einen Pin am Anfang der RTC ISR high setzen und am Ende low. Wenn man sich das nun am Oszi anschaut erhält man durch das Tastverhältnis high/low die Auslastung (im Mittel zu betrachten). In meinem System ist dies noch abhängig vom Systemzustand. Aber für eine grobe Abschätzung würde ich sagen ist das schon mal iO. Bei richtigen Echtzeit Betrachtungen brauchst du die Ausführungszeit jedes Tasks und die Periodenzeit jedes Taks. Das ganze zeichnet man in ein Zeitdiagramm + spoardische Interrupts und macht dann eine Worst-Case-Analyse.
Klopfer wrote: > Reagiere nicht so genervt! och möönsch ^^ > Ich red hier von nem Blackfin, ARM oder nen großen AVR. immerhin was anständiges ^^ > Wie soll man das simulieren. Zumal eine Simulation nicht in Echtzeit > ablaufen würde. warum denn echtzeit? für eine realzeit... ääh... echtzeit-analyse reicht eine simulation aus. wenn ich mich recht erinnere, gab es von cadence da mal ein tool dazu. ob das allerdings die modernen rechenarchitekturen kennt, weiß ich nicht. > Pin setzten kosten auch wieder einige Taktzyklen. Und dann müsste ich > das ganze extern (mit nem Oszi) messen. richtig. die zeiten zum pin-setzen sind in 2 zeilen zu errechnen, wenn du dir den assembler-code und das datenblatt des µC dazu anschaust. > Ich brauche da Ergebnis aber zur Laufzeit und in mindest µs-Genauigkeit. sicher? reden wir hier wirklich von einem dynamischen scheduling?
1. Mach dir einen Timer mit 1 msec Takt, in der ISR wird ein Timer inkrementiert. Diesen Wert kannst du an beliebiger Stelle im Programm abfragen und damit messen, wie lange ein Programmteil brauchte. Damit hast du es schon mal auf etwa 1 msec genau. 2. Wenn du es genauer haben willst kannst du noch beim Start und Ende der Laufzeitmessung den Wert des Timer Reload Registers mit einberechnen, also z.B. Reload Value ist 1000, dann hast du ne Auflösung von 1 usec.
Man kann die Rechenzeit jeder Routine bestimmen, indem man den Assemblercode analysiert und die Anzahl der benötigten Taktzyklen bestimmt. Mit dem jeweiligen uC Takt kann man daraus die Rechenzeit bestimmen. Eine experimentelle Methode ist das Setzen eines Portpins zu Beginn einer Routine und das Löschen am Ende. Das hat allerdings den Nachteil, dass die Zeit, die für Registersicherungen beim Funktionseintritt nicht mit in die Messung einfließt. (das kann bei ISRs nützlich sein - aber Achtung wegen der Portzugriffe! Die sollten Atomar sein!) In einer Hauptprogrammschleife kann man die Zykluszeit (Rechenzeitbedarf aller "Tasks" bestimmen - wenn man das näherungsweise als kooperatives Multitasking betrachtet ) Messen (Port toggeln). Diese Methode ist allerdings ein Schätzeisen, wenn der Rechenzeitbedarf von den Daten abhängt. Beispiel AVR und Multiplikation oder allgem. Division, wenn keine HW Unterstützung vorhanden ist. Diese Stellen im Code muss man kennen und eine Abschätzung auf anderem Weg (worst case -> Taktzyklen aus Assemblercode, etc.) bestimmen.
Wenn der Debugger es erlaubt: in zufälligen Abständen den Program Counter auslesen, dazugehörige Funktion/Modul/Aufgabe bestimmen, Histogramm plotten.
> Ich brauche da Ergebnis aber zur Laufzeit und in mindest µs-Genauigkeit.
Was ist denn der Sinn der Uebung?
Juergen
Noname wrote: > 1. Mach dir einen Timer mit 1 msec Takt, in der ISR wird ein Timer > inkrementiert. Diesen Wert kannst du an beliebiger Stelle im Programm > abfragen und damit messen, wie lange ein Programmteil brauchte. Damit > hast du es schon mal auf etwa 1 msec genau. nein! abtasttheorem... außerdem ist das eine methode zu fuß über den holzweg neben der autobahn. wenn du dynamische rechenzeiten zur laufzeit bestimmen willst, würde ich dir zu einem extra task - falls die voraussetzungen dafür gegeben sind - oder zu einem extra controller, der dir allein das scheduling macht, raten. ein extra controller kann wunder wirken, wenn man mit sog dead-locks zu kämpfen hat.
Benedikt K. hatte da mal eine recht pragmatische Methode. Leider finde ich den Thread nicht mehr. War aber hier in einem der Foren. Wenn ich mich recht entsinne, hatte er da einen Portpin gesetzt und den immer gelöscht, sobald der uC was tun sollte. Dann wieder gesetzt, wenn er irgendwo in einer Leerschleife rumhing. Hoffe Benedikt K. liest das hier und kann das nochmal genauer erklären. Jedenfalls erhielt man so eine Art PWM aus deren Tastgrad man auf die Auslastung schliessen konnte.
@ Matthias >Man kann die Rechenzeit jeder Routine bestimmen, indem man den >Assemblercode analysiert und die Anzahl der benötigten Taktzyklen >bestimmt. ... diese Aussage ist schlicht weg falsch!!! Keiner kann die tatsächliche Anzahl von benötigten Takten bestimmen, wenn nur ein einziger bedingter Sprung drin ist! Man müsste zu jeder Zeit den Zustand des µCs kennen! Klaus
sorry, sehe gerade, da ist noch ein Klaus unterwegs. Von jetzt an Klausi.
>Ich brauche da Ergebnis aber zur Laufzeit und in mindest µs-Genauigkeit.
Was hast du denn vor?
Wenn von Prozessorauslastung die Rede ist, dann ist es schlicht und einfach bei den AVRs so, daß pro Taktperiode ein Befehl (RISC, ja es gibt auch Befehle mit 2 Taktzyklen....) ausgeführt wird. Es ist völlig wurscht ob das ein NOP, ADD , SUB oder MOV ist. Das heißt er tut immer was und ist völlig ausgelastet. Der Fehler ist hier von Auslastung zu sprechen. Will man die Rechenleistung messen braucht man eine Referenz z.B. Mikrocontroller XY mit TAKT XY und vergleicht die verstrichenen Zeiten pro Aufgabe.
Noname wrote: > 1. Mach dir einen Timer mit 1 msec Takt, in der ISR wird ein Timer > inkrementiert. Diesen Wert kannst du an beliebiger Stelle im Programm > abfragen und damit messen, wie lange ein Programmteil brauchte. Damit > hast du es schon mal auf etwa 1 msec genau. nein! abtasttheorem... außerdem ist das eine methode zu fuß über den holzweg neben der autobahn. Deswegen steht da ja auch ein "ETWA", schon klar das das nur ne ungefähre Angabe ist ;-). "außerdem ist das eine methode zu fuß über den holzweg neben der autobahn." Wieso das? Was glaubst du denn wie ein Embedded OS das macht?
.. Mal(x) mit zuerwartender Häufigkeit der Aufgaben pro Zeiteinheit.
>nein! abtasttheorem... außerdem ist..
Das Abtasttheorem (fsampling/2 > fsignal) hat damit garnichts zutun.
Das kommt zur Anwendung, wenn es um Frequenzen und deren Rekonstruktion
geht.
Die hier vorgeschlagene Methode nutzt quasi jeder Frequenzzähler.
Diese haben immer einen Fehler von -1Takten...
Unter der Annahme, dass das Abnehmen des Zählerstandes selbst keine Zeit
benötigt, ist dieses Verfahren genau genug.
Beim Lesen des Threads ist mir eine alternative Idee gekommen, wie man die Auswertung der Systemauslastung statt per Pin-Toggeln mit SW lösen kann. Es ist natürlich stark davon abhängig wie das System aufgebaut ist. Aber ich gehe nun von einem "Echtzeit-System" aus, welches seine Task-Abarbeitung in der RTC ISR ausführt. Der Takt der RTC ISR ist 1 ms. Nun muss man natürlich etwas Overhead spendieren um eine solche Systemlast Messung durchführen zu können. Idee: (in Pseudo Code)
1 | _interrupt ISR_RTC (void){ |
2 | |
3 | static unsigned short s_load_buffer[10]; |
4 | static unsigned char s_load_index = 0; |
5 | |
6 | Timer_1_Reset (); /* startet Timer 1 */ |
7 | |
8 | /* Task - Abarbeitung */
|
9 | |
10 | /* Last Messung */
|
11 | s_load_buffer[s_load_index] = Timer_1_Get_Ticks(); |
12 | |
13 | /* ... */
|
14 | |
15 | }
|
Mit etwas Overhead könnte man also einen Extra Hardware Timer starten, der ab einem gewissen Punkt anfängt zu laufen und an an einem bestimmten Punkt abgefragt wird. Anhand der vergangenen Ticks lässt sich die vergangene Zeit ermitteln. dann wäre: Auslastung = vergangene_Zeit / RTC_Perioden_Dauer; Diesen Wert könnte man mitteln etc. und dann per RS232 abfragen, somit könntest du tatsächlich die Systemlast ermitteln und abfragen. Was hier natürlich nicht berücksichtigt wird sind sporadisch auftretende Interrupts. Hier könnte man so vorgehen, dass man die Laufzeit der ISRs separat misst und dann per Offseft auf die gemessene Last addiert. Damit hätte man dann automatisch eine "Worst-Case" Betrachtung. Liegt der Wert dann unter einer bestimmten Schwelle... ca. 70 % dann hat dein System noch etwas Luft nach oben. Grüsse aus der Pfalz ;-)
Naja, um was es genau bei der Sache geht darf ich nicht sagen. Der Prozessor bekommt halt permanent neue Aufgaben zumindest zur Verfügung gestellt. Ein Management soll nun überwachen, dass der Prozessor nicht mehr Aufgaben "annehmen"/"übernehmen" soll, wie er berechnen kann. Und zwar berechnen, ohne dass die Ergebnisse der einzelnen Aufgaben nicht länger als eine bestimmte Zeit brauchen. Also deterministisch sind. Was im übrigen auch als Echtzeit ebszeichnet wird, denn Echtzeit heiß nur, dass das Ergebnis innerhalb eines definierten Zeitfensters vorliegt. Das Zeitfenster kann Stunden oder gar Tage sein, hier geht es stellenweise in den µs-Bereich. Ich brauche also eine Methode/Task/Thread, mit der ich die "freie" Rechenleistung bestimmen kann.
>@ Matthias >>Man kann die Rechenzeit jeder Routine bestimmen, indem man den >>Assemblercode analysiert und die Anzahl der benötigten Taktzyklen >>bestimmt. >>... diese Aussage ist schlicht weg falsch!!! >Keiner kann die tatsächliche Anzahl von benötigten Takten bestimmen, >wenn nur ein einziger bedingter Sprung drin ist! Man müsste zu >jeder Zeit den Zustand des µCs kennen! Aber man kann eine "worst case"<->"best-case" Abschätzung machen. Ob das jetzt 20 Zyklen mehr oder weniger sind ist sowieso meistens egal. Aber ein Programmierer kennt sein Programm normalerweise so gut, dass er eine Abschätzung treffen kann. Ausserdem, wenn nur ein oder zwei Sprünge drin sind (was bei "Eier-Loops" der Falls ist) dann kann man die Anzahl der Zyklen schon genau bestimmen. >>... diese Aussage ist schlicht weg falsch!!! Ist ebenfalls falsch! Richtig wäre, dass man bei bedingten Sprüngen es nicht mehr genau kann, aber trotzdem noch gut abschätzen! ;-)
Klaus wrote: > Keiner kann die tatsächliche Anzahl von benötigten Takten bestimmen, > wenn nur ein einziger bedingter Sprung drin ist! Man müsste zu > jeder Zeit den Zustand des µCs kennen! Und auch diese Aussage ist schlicht weg falsch!!! Natürlich geht das, PIC-Programmierer machen das sehr häufig. Ich hab sowas schonmal gesehen, ein PIC-Programm auf den Zyklus genau, ganz ohne Interrupts. Der Trick ist ganz einfach, sobald ein bedingter Sprung kommt, wird der kürzere Zweig mit NOPs aufgefüllt, bis er gleich lange dauert. Damit hat diese Routine immer eine konstante Laufzeit. Geht natürlich nur mit Assemblerprogrammierung, was ja beim PIC die Regel ist. Natürlich ist ein solcher Programmierstil äußerst zeitaufwendig. Peter
Mach oder benutz einen Systemtimer, rechne in Ticks. Das kann eine 32Khz timer sein, wie auch ein 1ms oder auch 6ms timer, als Beispiel. Normalerweise wird das dann so gemacht, daß die Proceduren in Slices alloziert werden, also ein Slice sind X Ticks. Z.B. 1 Slice sind 64 Ticks. Wenn ein Slice frei ist, dann kann die Procedure angefordert werden. Ist die Prozedur fertig, dann wird in die Yield Prozedure gesprungen. Diese kann dann je nach verfügbaren Ticks verschiedene anstehende Systemaufgaben machen. In Yield kann auch die noch freien Ticks aufsummiert werden, und so der Leerlauf, sprich die Auslastung gemessen werden.
Hm, ich glaube, endgültig und beliebig fein wird sich das nicht bestimmen lassen können. Die Laufzeit vieler Routinen ist auch von den (variablen) Eingangsparametern abhängig. Oder man muss wirklich jede Aktion auf gleiche Laufzeit trimmen - dann hätte man zuverlässige Vorhersagen, insgesamt aber geringere Performance. Könnte schon Anwendungen dafür geben. Einfacher ist offensichtlich der andere Weg - mehr Rechenleistung zur Verfügung zustellen, als im worst-case benötigt wird und den Überschuss zu vertrödeln.
Achso, du willst ARM, Blackfin, AVR32 verwenden. Dann verwende doch ein RTOS. Das kann dir auch die Auslastung zur Verfügung stellen, arbeitet jedoch meistens mit dem oben skizzierten System.
Über ein OS kann ich (noch) keine Aussage machen. Ob überhaupt eins zum Einsatz kommt, oder nicht. Und wenn ja welches. Das liegt nicht in meiner Macht. Aber so wie ich das mitbekommen habe ist hier Linux im Gespräch. mir grauts jetzt schon davor, denn von Linux hab erst recht keine Ahnung.
Dann nimm doch ein RTOS von Segger, das arbeitet nach dem Prinzip wie oben von Noname beschrieben und liefert dir automatisch die Auslastung. Gibt sogar ein PC Tool, ich glaub embOSView heißt das, was dir die Auslastung sogar noch gleich graphisch darstellt, einfacher kannst du es nicht haben.
>Was ist denn der Sinn der Uebung? Spielverderber :-) >Naja, um was es genau bei der Sache geht darf ich nicht sagen. Bravo! Ich sage Knecht Ruprecht Bescheid.
Wahrscheinlich verstehe ich wieder nix... aber wo ist das Problem in der Hauptschleife einfach nur eine Variable hoch zu zaehlen und das mit einem Interrupt jede Sekunde abzufragen (und zu loeschen)? Die freie Rechenzeit ist der maximal erreichbare Zaehlerstand / den tatsaechlich erreichten Zaehlerstand.
Da stellt sich halt die Frage wie Rechenintensiv das Hochzählen und Interrupt-gesteuerte Überprüfen des Zählerstandes ist und in wie weit man es dann in Relation mit der erforderlichen Rechenzeit der ganzen anderen Aufgaben dauert....
Tja, ein bisschen was wirst du fuer dein Gehalt auch noch machen muessen.
Ich frage mich gerade, ob es echt um eine "Echtzeit-Anwendung" geht, oder ob der OP einfach das programmieren am PC gewohnt ist und nun auf nem Mikrocontroller nach einem vergleichbarem Maß sucht, um festzustellen, wieviele Ressourcen er schon verbraucht hat.
!! Achtung kein sinnvoller Vorschlag !! Nimm einen Analogen Auslastungsanzeige: Immer wenn was sinnvolles getan wird Pin einschalten ansonsten ausschalten. Dann ein RC-Glied dran und daran ein analoges Voltmeter... sieht bestimmt cool aus ;)
>!! Achtung kein sinnvoller Vorschlag !!
Warum nicht Sinvoll? Wenn man das RC passend dimensioniert hat das
ungefähr den gleichen Sinn, wie mit nem Oszi die Zeit zu messen. Ist
halt ein
Schätzeisen, aber gar nicht so dumm ;-)
Klopfer wrote: > Naja, um was es genau bei der Sache geht darf ich nicht sagen. > > Der Prozessor bekommt halt permanent neue Aufgaben zumindest zur > Verfügung gestellt. Ein Management soll nun überwachen, dass der > Prozessor nicht mehr Aufgaben "annehmen"/"übernehmen" soll, wie er > berechnen kann. Und zwar berechnen, ohne dass die Ergebnisse der > einzelnen Aufgaben nicht länger als eine bestimmte Zeit brauchen. Also > deterministisch sind.
i = Periodisches Ereignis m = Anzahl der periodischen Ereignisse C_i = benötigte CPU-Zeit in Sekunden P_i = Periode des Ereignisses i Wenn das erfüllt ist, ist das System schedulbar. Algorithmen für das Scheduling wären z.B.: Statisch: Rate Monotonic Scheduling, bei diesem Verfahren ist die maximale Auslastung für m > 1 kleiner 100 %, genauer: m * (2^(1/m) - 1) Dynamisch: Earliest Deadline First Scheduling, Auslastung bis zu 100 % > Ich brauche also eine Methode/Task/Thread, mit der ich die "freie" > Rechenleistung bestimmen kann. Leerlaufthread: Kein weiterer Thread im System: n Durchläufe pro Sekunde, weitere Threads im System: m Durchläufe -> m/n = freie Rechenleistung
> Der Prozessor bekommt halt permanent neue Aufgaben zumindest zur > Verfügung gestellt. Ein Management soll nun überwachen, dass der > Prozessor nicht mehr Aufgaben "annehmen"/"übernehmen" soll, wie er > berechnen kann. Und zwar berechnen, ohne dass die Ergebnisse der > einzelnen Aufgaben nicht länger als eine bestimmte Zeit brauchen. Also > deterministisch sind. > Was im übrigen auch als Echtzeit ebszeichnet wird, denn Echtzeit heiß > nur, dass das Ergebnis innerhalb eines definierten Zeitfensters > vorliegt. Das Zeitfenster kann Stunden oder gar Tage sein, hier geht es > stellenweise in den µs-Bereich. > > Ich brauche also eine Methode/Task/Thread, mit der ich die "freie" > Rechenleistung bestimmen kann. Ein solcher Task ist immer ungenau, weil das Ergebnis eben mit den Eingangsdaten schwankt. Der misst nur, was "gerade jetzt" noch an Rechenpower frei ist, aber die schon laufenden Prozesse können im nächsten Moment schon das doppelte an Rechenpower brauchen. Damit bekommst du es vielleicht ungefährt hin, aber du hast keine Garantie, dass der Prozessor nicht doch irgendwann mal "überfordert" wird, ganz einfach weil die Messung der momentanen Auslastung nicht präzise ist. Was du brauchst ist die max. benötigte Rechenzeit der schon laufenden Aufgaben, aber die bekommst du nicht durch Messen. Die rechnest du besser aus (worst-case-Abschätzung). Dann berechnest du, was der Prozessor max. leisten kann (Verwaltung mit eingerechnet) und vermerkst im laufenden Betrieb, was noch geht. > Aber so wie ich das mitbekommen habe ist hier Linux im > Gespräch. > > mir grauts jetzt schon davor, denn von Linux hab erst recht keine > Ahnung. Dann freu dich schonmal darauf, die worst-case-Abschätzung für den Linuxcode zu machen :)
hey Peter Dannegger (peda) >> Keiner kann die tatsächliche Anzahl von benötigten Takten bestimmen, >> wenn nur ein einziger bedingter Sprung drin ist! Man müsste zu >> jeder Zeit den Zustand des µCs kennen! >> Und auch diese Aussage ist schlicht weg falsch!!! >Der Trick ist ganz einfach, sobald ein bedingter Sprung kommt, wird der >kürzere Zweig mit NOPs aufgefüllt, bis er gleich lange dauert. Damit hat >diese Routine immer eine konstante Laufzeit. wer macht den sowas? Das ist das Perverseste was ich hier bis jetzt gelesen habe!!! Klaus
Hallo, z.B. Leute, die ein Videosignal in Software auf einem AVR erzeugen oder Leute, die auf einem Mega16 einen 6502 Zyklengenau emulieren wollen... Solche Leute sind so pervers. PS: Du hast ähnliches noch nie programmiert, vermute ich mal. PPS: früher hab ich das auf dem C64 so gemacht, weil man ja unbedingt den seitlichen Rahmen des Videocontrollers abschalten wollte, damit die Sprites dort zu sehen waren. Das hatten die Entwickler aber nicht eingeplant. ;) Gruß aus Berlin Michael
Klaus wrote: > ... diese Aussage ist schlicht weg falsch!!! > > Keiner kann die tatsächliche Anzahl von benötigten Takten bestimmen, > wenn nur ein einziger bedingter Sprung drin ist! Man müsste zu > jeder Zeit den Zustand des µCs kennen! > > Klaus Diese Aussage ist schlicht weg falsch!!! Der uC ist deterministisches System. Mann muss nichtmal den ganzen Zustand kennen (den man aber sehr wohl auf grund Determinismus fast vollständig kennen kann), sondern nur die Zustände/Bits von denen Sprünge abhängen. Da die allermeißten Sprünge von boolschen Zuständen abhängen, ist das sogar sehr überschaubar, man muss einfach nur alle Möglichkeiten durchrechnen. Falls z.B. im Fall variabler Zählschleifen oder vieler Abhängigkeiten die mögliche Zustandsmenge zu groß wird lässt sich meißtens immer noch Worst und Best-Case angeben.
Ich habe in meinem Programm auch soetwas einbauen wollen. Ausgehend von einem Programm was als Endlos-Main Schleife aufgebaut ist, aus welcher heraus die verschiedenen Tasks bei Bedarf (!) z.b. durch Flags signalisiert aufgerufen werden. Denn es muss ja der Fall Möglich sein, das beim Nichtstun auch kein Task aufgerufen wird. Mein erster Ansatz war der mit dem Toggle-Pin: Jeweils zu Anfang jedes Tasks der die unterste Main-Ebene verlässt, ebenso Anfangs jeden Interrupts, wird Pin High gesetzt. Falls Interrupt bereits auf einen High-Pin trifft, wird ein Flag gesetzt, das am Ende des Interrupts verhindert, den High-Pin zu löschen obwohl der Main-Task ja noch läuft. Am Ende jedes Tasks, also vor dem ret zu main, sowie am Ende jedes Interrupts (hier wie oben angegeben nur bedingt) wird Pin auf Low gesetzt. Mein zweiter Ansatz kostet mehr Rechenzeit, lässt aber Zeitmessung jedes Tasks einzeln und auch die Idle und Busyzeitmessung insgesammt zu: Wie oben wird jeweils zu Anfang von Task und Interrupt der Wert eines kontinuierlich hochzählenden Systemtimers (ein Hardware-Timer mit niedrigem Preskaling, sowie Software-Erweiterung auf über 16 bit, bzw Überlauferkennung) gespeichert, für jeden Task/Interrupt in einer eigenen Variable. Außerdem setzt der Task ein Flag das laufende Messung anzeigt Trifft ein Task/IRQ auf gesetzte Flags anderer Tasks/IRQs heißt das, das ersterer die Laufzeit der letzteren unterbricht, und deren Laufzeit verfälscht. Um die Laufzeit für die unterbrochenen Tasks zu korrigieren, müssen alle unterbrochenen Tasks als am Ende bei ihrer Laufzeitbestimmtung ebenfalls die Laufzeiten der Tasks abziehen, die sie unterbrochen haben. Dazu hat jeder Task ebenfalls eine Variable, in der die abzuziehenden Laufzeiten aller ihn unterbrechenden Tasks aufaddiert werden. Jeder Task muss als am Ende nach Bestimmtung seiner eigenen Laufzeit, diese zu den Korrektur-Variablen aller laufenden von ihm unterbrochenen Tasks hinzuaddieren. Will man nur die Systemzeiten messen, aber nicht Tasks einzeln, reicht natürlich die Zeitnahme von Start und Endmarken bei allen Tasks und IRQs, die die Mainschleife verlassen. Um das ganze zu optimieren nutzt man vielleicht den Input-Capture Interrupt zur Zeitmarken-Name, (der sich allerdings glaube ich nicht softwaremäßig auslösen lässt). Ein regelmäßiger Timer muss außerdem aus den den angesammelten Laufzeiten die Ausleistung bestimmen und diese zurücksetzen. Von Softtimern die von Timerticks getriggert Laufzeiten direkt messen halte ich nichts, da die Zeitauflösung zu grob wird. Alternativ kann man aber einen Hardwaretimer Anfangs jeden Tasks reseten, nachdem der Timerstand des unterbrochenen Tasks zwischengespeichert wurde. Am Ende resettet der unterbrechende Task wieder und addiert den zwischengespeicherten Timerstand des unterbrochenen Timers zu dessen Laufzeit-Variable. Der unterbrochende Task addiert dann am Ende den Timerstand ebenfalls auf seine Laufzeitvariable. Da bei diesen Ansätzen immer ein niedrig oder garnicht preskaled Hardwaretimer genutzt wird erreicht man echte Cycle-Auflösung.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.