Forum: Compiler & IDEs Funktionsaufruf


von Niki Hammler (Gast)


Lesenswert?

Hello,

Für ein Programm bräuchte ich genaues Timing. Z.b. 10ns.

Zuerst habe ich es einfach mit

#define rwait() asm volatile(            \
    "ldi  R17, 0x0D" "\n" "WGLOOPx:  dec  R17" "\n\r"  \
    "brne WGLOOPx" "\n\r" "nop")

definiert, damit keine Zeit für einen Funktionsaufruf vergeht.

Dann bin ich aber draufgekommen das das mit WGLOOPx ein Problem ist wenn 
ich das Makro öfter verwenden will. So bin ich gezwungenermassen auf 
eine Funktion umgestiegen:

void rwait(void)
{
  asm volatile(
  "ldi  R17, 0x0D" "\n" "WGLOOPx:  dec  R17" "\n\r"
  "brne WGLOOPx" "nop");
}


Aber erstens: Was ist jetzt, wenn z.B. Register 17 schon vorher benötigt 
worden ist und jetzt einen anderen Wert einnimmt? Oder werden alle 
Register bei einem Funktionsaufruf (wie bei tigcc) auf dem Stack 
gespeichert und nach der Funktion wieder in die Register 
zurückgeschrieben?

Zweitens, wie lange braucht jetzt dann die Version mit dem 
Funktionsaufruf länger? Wenn ich denke das 10us gerade mal 40 
Zyklen,also im Prinzip 40 Befehle sind (bei 4Mhz) ist das ganze nicht 
viel. Wenn ich jetzt den Funktionsaufruf mitrechne, dann kommen ja 
ziemlich viele Befehle dazu und das könnte ja die Dauer verfälschen 
oder?

Hat der Funktionsaufruf eine Bedeutung oder soll ich dafür weniger 
Schleifendurchläufe nehmen?

BTW: Der Code wurde mit AVRDelayLoopGenerator erzeugt.

Niki


PS: Ich will auf den Timer verzichten da er den Code für meine Zwecke 
nur unnötig kompliziert macht. Ich muss einfach nur manchmal 10us warten 
und da wäre eine Funktion die das einfach täte das idealste für mich

von Andreas S. (andreas) (Admin) Benutzerseite


Lesenswert?

Hi,

wie lange der Funktionsaufruf dauert kannst du durch Simulation im 
AVR-Studio rausfinden.

Die Register die du verwenden darfst stehen in der ctoasm.inc, siehe 
auch das AVR-GCC-FAQ (http://www.mikrocontroller.net/avr-gcc-faq.htm).

Mit __attribute__((naked)) kannst du veranlassen dass der Pro- und 
Epilog der Funktion weggelassen wird, du kannst also die benötigten 
Zyklen besser abschätzen. Dann musst du dich aber darum kümmern, dass du 
das SREG und die verwendeten Register auf dem Stack sicherst und am Ende 
der Funktion wieder zurückholst.

MfG
Andreas

von Niki Hammler (Gast)


Lesenswert?

Hmm, danke für den Tipp!

Stimmt, ja, aber die Vorschläge im AVRGCC Tutorial sind mir etwas zu 
aufwendig für so eine einfache Funktion ;)

Wenn ich das richtig verstanden habe, kann ich r26, r27, r30 und r31 
einfach so verwenden, ohne dass ich irgendwas auf den Stack sichern muss 
odr?

Meine Funktion geht jetzt

__attribute__((naked)) void rwait(void)
{
  asm volatile(
  "ldi  R31, 0x0D" "\n" "WGLOOPx:  dec  R31" "\n\r"
  "brne WGLOOPx");
}

und wurde anstandslos kompiliert. Jetzt braucht so ein Aufrug einfach 
nur 2 Anweisungen zusätzlich, nämlich die rjmp Routinen, wenn ich das 
richtig verstanden habe. Und Ich habe R17 durch R31 ersetzt, da ich die 
ja (so glaube ich) verwenden kann.



Das mit dem AVR Studio ist mir heute auch afgefallen, ja. Mein ganzes 
Programm braucht da 70us ;)

ABER: Ich weiss nie wo eine Funktion anfängt und aufhört, da ich ja nur 
die *.bin Datei debuggen kann und da kenne ich mich hinten und vorne 
wieder nicht aus wo jetzt eine Funktion anfängt und wo sie aufhört.

Niki

von Jonas Diemer (Gast)


Lesenswert?

hmm. also ich würde das sreg und die register sichern.

bei den registern kann es ja sein, dass der compiler diese verwendet, um 
daten zu speichern. änderst du das register nun per asm, dann stimmen 
die werte nicht mehr. der compiler checkt meines wissens nach NICHT den 
code des inline assemblers, weiß also nicht, welche register du dort 
verwendest...

das SREG ist evtl. nicht so wichtig... du änderst ja nur die bits S,V, N 
und Z, diese werden bei vergleichen benutzt... da aber deine funktion 
boolsche vergleiche a la x==2 oder so (die ja aus setzen der status bits 
und einem sprungbefehl bestehen) nicht unterbricht, sollte das 
klargehen.

Jonas

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
Noch kein Account? Hier anmelden.