Auslastung/Rechenleistung eines µC

Gast #1064587
Lesenswert?

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
Gast #1064599
Lesenswert?

@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).
Gast #1064609
Lesenswert?

"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?
Gast #1064610
Lesenswert?

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.
Gast #1064644
Lesenswert?

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
Gast #1064645
Lesenswert?

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.
#1064652
Lesenswert?

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.
Gast #1064655
Lesenswert?

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?
Gast #1064659
Lesenswert?

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.
Gast #1064660
Lesenswert?

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.
Gast #1064681
Lesenswert?

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.
Gast #1064692
Lesenswert?

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.
Gast #1064699
Lesenswert?

@ 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
Gast #1064732
Lesenswert?

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.
Gast #1064739
Lesenswert?

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?
Gast #1064754
Lesenswert?

>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.
#1064852
Lesenswert?

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 ;-)
Gast #1065293
Lesenswert?

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.
Gast #1065309
Lesenswert?

>@ 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! ;-)
#1065319
Lesenswert?

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
#1065323
Lesenswert?

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.
Gast #1065328
Lesenswert?

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.
Gast #1065374
Lesenswert?

Ü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.
Gast #1065397
Lesenswert?

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.
Gast #1065426
Lesenswert?

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.
Gast #1065503
Lesenswert?

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....
Gast #1065511
Lesenswert?

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.
Gast #1065531
Lesenswert?

!! 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 ;)
Gast #1065604
Lesenswert?

>!! 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 ;-)
#1065772
Lesenswert?

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
Gast #1065905
Lesenswert?

> 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 :)
Gast #1066100
Lesenswert?

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
#1066118
Lesenswert?

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
#1066160
Lesenswert?

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.
#1066199
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren