Hallo,
ich konnte leider keine passende Erklärung auf die Schnelle vorfinden,
es geht um Timer bzw. Delays.
Bei einem 4MHz System habe ich eine Tickzeit von 1/4000000 = 0,25us
Wenn ich eine Delayfunktion erstelle,
[code]
//25ms
delay_func(100000);
status delay_func(uint32 param)
{
for(uint32 i=0; i<param;)
{
i++;
}
return OK;
}
[code/]
so wie ich es verstehe bräuchte ich 100000 Ticks um die 25ms zu
überbrücken,
wird aber die komplette for Schleife pro Tick abgearbeitet ?
Mir ist nicht ganz klar, welche Operation pro Tick durchgeführt wird.
VG
Michael
Michael schrieb:> wird aber die komplette for Schleife pro Tick abgearbeitet ?> Mir ist nicht ganz klar, welche Operation pro Tick durchgeführt wird.
Diese Frage ist einer der wenigen Gründe, weshalb man ein bisschen
Assembler können sollte und weshalb es nützlich ist, dass die meisten
(alle?) Compiler auch Assembler mit Mnemonics als Zwischenschritt
ausspuckt.
Wenn die Funktion nicht vom Optimizer weggeschmissen wird, dann kann man
sich mal den Assembler dazu angucken und nachvollziehen, wie viele
Schritte wie oft passieren.
Inkrementieren, Compare, Springen,... Wenn man dann noch weiß, wie viele
Zyklen pro Befehl notwendig sind (ist vom Controller abhängig), findet
man raus, wie lange das Delay ist.
Was du meinst ist die Prozessor-Taktung und dem je nach Prozessor
unterschiedlichen Maschinenzyklus, der aus einem bis vielen
Prozessor-Takten besteht!
https://de.wikipedia.org/wiki/Taktsignal
Michael schrieb:> ich konnte leider keine passende Erklärung auf die Schnelle vorfinden,> es geht um Timer bzw. Delays.
Zwei sehr verschiedene Dinge. Man kann eine Verzögerung zwar mit einem
Timer erzeugen, aber du machst das nicht. Was du machst, nennt man
busy waiting oder auf deutsch: CPU-Zeit verbrennen.
> Bei einem 4MHz System habe ich eine Tickzeit von 1/4000000 = 0,25us> Wenn ich eine Delayfunktion erstelle,
Von Tick spricht man nur bei einem Timer, aber hier ist keiner
beteiligt. Und Systeme haben nur im Ausnahmefall eine einzelne
Taktfrequenz. Aber nehmen wir einfach mal an, die 4MHz wären der
CPU-Takt. Dann sagt man nicht Ticks, sondern Taktzyklen.
1
>statusdelay_func(uint32param)
2
>{
3
>for(uint32i=0;i<param;)
4
>{
5
>i++;
6
>}
7
>
8
>returnOK;
9
>}
> so wie ich es verstehe bräuchte ich 100000 Ticks um die 25ms zu> überbrücken
100.000 Taktzyklen, ja.
> wird aber die komplette for Schleife pro Tick abgearbeitet ?
Sicher nicht.
> Mir ist nicht ganz klar, welche Operation pro Tick durchgeführt wird.
Das kommt auf den Prozessor an. Aber auch im besten Fall kann der nur
einen (Maschinen-) Befehl pro Taktzyklus ausführen. Die Schleife besteht
aber sicher aus mehreren Befehlen: einem 32-Bit Inkrement, einem 32-Bit
Vergleich, einem bedingten Sprung. Aber es ist noch schlimmer: da das C
Code ist, kommt es auch noch darauf an, was der C Compiler daraus für
Maschinencode erzeugt. Das das hängt wieder davon ab, welche
Optimierungseinstellung der Compiler bekommen hat. Und wenn nächsten
Monat eine neue Version des Compilers herauskommen sollte, macht die es
vielleicht noch anders.
Genau ist ein solches busy waiting also nicht. Oder gar portabel. Was du
machen kannst: setze eine große Zahl ein, sagen wir 10.000.000. Und dann
stoppe die Zeit, die deine CPU für die Abarbeitung der Funktion braucht.
Dann kannst du zurückrechnen, wieviel Taktzyklen pro Durchlauf verbraten
werden.
Mit "timer tick" wird normalerweise eine HW Timer Periode gemeint.
z.B. wenn der HW Timer initialisiert wird damit Interrupt auslöst wird
mit 1ms ..., dann sprechen wir von 1ms Timer Tick.
Michael schrieb:> Bei einem 4MHz System habe ich eine Tickzeit von 1/4000000 = 0,25us
NO!
Der Begriff "Tickzeit" wäre eher falsch, besser wäre Instruction Cycle.
und mit "1/4000000" ABER auch nur, WENN das eine One-Cycle MCU wäre.
Auch dann gibt es noch Intructions, die mehr als einen Instruction Cycle
benötigen, e.g. call oder so, wo die Instruction pipeline nichts bringt
...
Michael schrieb:> so wie ich es verstehe bräuchte ich 100000 Ticks um die 25ms zu> überbrücken,> wird aber die komplette for Schleife pro Tick abgearbeitet ?> Mir ist nicht ganz klar, welche Operation pro Tick durchgeführt wird.
Das kommt auf den Compiler und die CPU an.
Meine Glaskugel sagt, du willst das auf einem AVR ausführen, da wird ein
Schleifendurchlauf mit Sicherheit länger als einen CPU-Takt brauchen,
wenn nicht wegoptimiert.
Herausfinden kann man das, indem man sich den vom Compiler generierten
Assembler-Code anschaut und dann im Datenblatt der CPU oder CPU-Familie
nachschaut, wie viele Taktzyklen jeder Befehl braucht.
In vielen verbreiteten Makefiles für gcc für AVR wird der Assembler-Code
direkt mit in eine Datei ausgegeben, mit *.lst oder *.s oder
*.lss-Endung. Das sieht dann (Ausschnitt) zum Beispiel so aus: