Inline-Assembler Delay

OP #1429358
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)
  );
}
Moderator Persönliche Seite #1429508
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.
#1429528
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.
Persönliche Seite #1430134
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
Gast #2579951
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?
Moderator Persönliche Seite #2579998
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>.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 17 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.