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