mikrocontroller.net

Forum: Compiler & IDEs Inline-Assembler Delay


Autor: M. Faid (sajuuk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)
  );
}

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das haben andere schon vor dir getan.  Sieh dir <util/delay_basic.h>
mal an.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: M. Faid (sajuuk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke. deine Info hat mir sehr weiter geholfen.

Mfg Faid

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Davon abgesehen, wie soll es möglich sein, per ldi einen variablen Wert 
in die Register zu laden?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ;-)
void waitXus (uint16_t time) {

  asm volatile (
    "0:                       \n\t"
    "sbiw %[waitTime],1       \n\t"
    "brne 0b                  \n\t"
  :
  :[waitTime] "w" (time)
  );
}

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.

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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:
#include <stdint.h>

static inline void 
waitXus (uint16_t time) 
{
   __asm__ __volatile__ (
     "0: sbiw %[waitTime], 1"     "\n\t"
     "brne 0b"
       : [waitTime] "+w" (time));
}

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

Autor: onkelhotte (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.