Ich würde gern in Assembler ein delay schreiben. Leider bekomme ich beim compilieren immer eine Fehlermeldung. Fehlermeldung: Compiling C: lcd.c avr-gcc -c -mmcu=atmega16 -I. -gdwarf-2 -DF_CPU=8000000UL -O0 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -Wa,-adhlns=./lcd.lst -std=gnu99 -Wundef -MMD -MP -MF .dep/lcd.o.d lcd.c -o lcd.o C:\DOKUME~1\fiedler\LOKALE~1\Temp/cc4OaRcs.s: Assembler messages: C:\DOKUME~1\fiedler\LOKALE~1\Temp/cc4OaRcs.s:38: Error: garbage at end of line C:\DOKUME~1\fiedler\LOKALE~1\Temp/cc4OaRcs.s:39: Error: garbage at end of line make.exe: *** [lcd.o] Error 1 Als Compiler benutze ich AVR-GCC. Ich hoffe jemand kann mir weiter helfen. Danke schonmal. Code: void __waitXus(u16 time) { register u16 __time = time; asm volatile ( "ldi R25,HIGH(%B[waitTime]); \n\t" "ldi R24,LOW(%A[waitTime]); \n\t" "Loop: \n\t" "sbiw R24,1; \n\t" "brne Loop; \n\t" : :[waitTime] "r" (__time) ); }
Das haben andere schon vor dir getan. Sieh dir <util/delay_basic.h> mal an.
Btw.: der "garbage" da sind die Semikolons, denke ich. Die verwendung eines nicht-lokalen labels innerhalb einer inline-asm-Anweisung ist aber wenig zweckmäßig, und das Überbügeln von r24/25 ist so nicht akzeptabel.
Davon abgesehen, wie soll es möglich sein, per ldi einen variablen Wert in die Register zu laden?
Stefan Ernst schrieb: > Davon abgesehen, wie soll es möglich sein, per ldi einen variablen Wert > in die Register zu laden? ;-) Es gibt bei genauerem Hinsehen noch mehr Enten: . ldi erwartet einen immediate value, aber der constraint gibt ein Register vor . das Schlüsselwort "register" ist Unsinn; es ist ohnehin das constraint, das dem Compiler mitteilt, in welcher Form __temp implementiert werden muss . __temp ist ein reservierter Bezeichner, der in einem Nutzerprogramm nichts zu suchen hat . das separate Anlegen der Variablen __temp ist gar nicht nötig, man kann gleich den Parameter temp benutzen . man braucht eigentlich das Registerpaar auch gar nicht im inline asm zu laden, sondern kann das komplett dem Compiler über die constraints aufdrängeln Das nur der Vollständigkeit halber, falls jemand noch den Thread später liest. Hatte vorhin halt nicht so genau hingeschaut.
Jörg Wunsch schrieb: > Das nur der Vollständigkeit halber, falls jemand noch den Thread > später liest. Ok, dann noch als Ergänzung etwas konkreten Code zu den gemachten Einwendungen ;-)
1 | void waitXus (uint16_t time) { |
2 | |
3 | asm volatile ( |
4 | "0: \n\t" |
5 | "sbiw %[waitTime],1 \n\t" |
6 | "brne 0b \n\t" |
7 | :
|
8 | :[waitTime] "w" (time) |
9 | );
|
10 | }
|
Und als weitere Ergänzung: Die Semikolons sind natürlich nicht der "garbage" (die machen ja nur den Rest der Zeile zum Kommentar). Es sind diese unsinnigen "HIGH(%B[waitTime])" Konstruktionen.
Stefan Ernst schrieb: > Jörg Wunsch schrieb: > >> Das nur der Vollständigkeit halber, falls jemand noch den Thread >> später liest. > > Ok, dann noch als Ergänzung etwas konkreten Code zu den gemachten > Einwendungen ;-) Noch ein Einwand: time wird verändert. Falls waitXus einmal als static oder inline-Funktion (sehr sinnvoll, also im Header als static inline) definiert wird, crasht es früher oder später. Daher:
1 | #include <stdint.h> |
2 | |
3 | static inline void |
4 | waitXus (uint16_t time) |
5 | {
|
6 | __asm__ __volatile__ ( |
7 | "0: sbiw %[waitTime], 1" "\n\t" |
8 | "brne 0b"
|
9 | : [waitTime] "+w" (time)); |
10 | }
|
Das Label hab ich in die gleiche Zeile geschrieben, weil gcc 4 die Anzahl der Instruktionen anhand der Zeilen im Inline Asm abschätzt (für relative Sprünge darüber). Johann
Die Funktion soll ja eigentlich x Mikrosekunden warten. Allerdings muss dafür ja der CPU-Takt berücksichtigt werden, oder? Wenn ich richtig liege, dann benötigt die Abarbeitung der Inline-Funktion 4*time Takte. Mikrosekunden sind es also nur bei 4MHz CPU-Takt, oder habe ich da was missverstanden?
Lohnt es sich wirklich, dafür die Threadleiche zu exhumieren? Der Parameter "time" hat ja dort keine Maßeinheit. Hat also niemand behauptet, dass es sich um Mikrosekunden handeln würde. Ja, um mit Absolutzeiten zu arbeiten, muss man mit der CPU-Frequenz umrechnen. Dann bist du genau bei den Funktionen aus <util/delay.h>.
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.