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.