Inline Asm

Gast #363091
Lesenswert?
• ▲
▼
Hi, ich habe folgenden Code, um in einer Interruptroutine Port D
einzulesen:
1
unsigned char volatile G_cLastData = 0xAA;
2

3
void __attribute__ ((naked)) SIG_INTERRUPT0 (void) { 
4
  // Port D einlesen 
5
   __asm__ __volatile( 
6
      "push    r2"          "\n\t" 
7
      "in      r2, %1"      "\n\t" 
8
      "sts     %2, r2"      "\n\t" 
9
      "pop     r2"          "\n\t" 
10
      "reti" 
11
      : 
12
      : "M" (_SFR_IO_ADDR(PORTD)) 
13
      : "i" (&G_cLastData) 
14
   ); 
15
}

Leider bringt mir der Compiler folgende Meldung:
[quote]
../Treiber_Parallel.c: In function `__vector_1':
../Treiber_Parallel.c:143: error: parse error before '(' token
C:\AVR\WinAVR\utils\bin\make.exe: *** [Treiber_Parallel.o] Error 1

[/quote]

Zeile 143 ist:
1
: "i" (&G_cLastData)

Kann mir jemand sagen, woher diese Meldung kommt, bzw. wie ich sie weg
bekomme?

Ps:
Für diejenigen, die bei Roboternetz mitlesen, tut mir leid für den
Doppelpost, aber es ist sehr wichtig!

Freundlichen Gruss
Michael
Gast #363092
Lesenswert?
• ▲
▼
Mir scheint die leere Liste von Ausgangsoperanden falsch zu sein. Das i
(&G_cLastData) ist glaub ich auch kein  korrekter Eintrag für die
clobber-Liste. Es scheint alles um eins verschoben zu sein. Mach mal
den ersten Doppelpunkt weg.
Gast #363093
Lesenswert?
• ▲
▼
Hi, danke für deine Antwort.
Ich habe jetzt folgendes ausprobiert:
1
void  __attribute__ ((naked)) SIG_INTERRUPT0 (void){
2
   __asm__ __volatile( 
3
      "push    r2"          "\n\t" 
4
      "in      r2, %1"      "\n\t" 
5
      "sts     %2, r2"      "\n\t" 
6
      "pop     r2"          "\n\t" 
7
      "reti" 
8
      : "M" (_SFR_IO_ADDR(PORTD)) 
9
      : "i" (&G_cLastData) 
10
    );
11
}
liefert:
[quote]
../Treiber_Parallel.c: In function `__vector_1':
../Treiber_Parallel.c:200: error: invalid lvalue in asm statement
../Treiber_Parallel.c:192: error: output operand constraint lacks `='
C:\AVR\WinAVR\utils\bin\make.exe: *** [Treiber_Parallel.o] Error
1
[/quote]
Gast #363094
Lesenswert?
• ▲
▼
Wenn ich das mit der clobber-Liste richtig verstanden habe teilt diese
doch dem Compiler nur mit, welche Werte sich geändert haben, oder?

Und da ich das Speichern in G_cLastData ja bereits im Asm Code mache,
muss ich als Output nichts angeben?! Ansonsten hätte ich mir das
1
"sts     %2, r2"      "\n\t"

sparen können, oder?

Gruss
Michael
Gast #363095
Lesenswert?
• ▲
▼
Der Asm-Code hierzu, wie ich meine dass es ohne Clobber gehört:
1
void  __attribute__ ((naked)) SIG_INTERRUPT0 (void){
2
   __asm__ __volatile( 
3
       "in %0,%1"        "\n\t"
4
       "reti"
5
             : "=&r" (G_cLastData) 
6
             : "I" (_SFR_IO_ADDR(PORTD))
7
    );
8
}

wäre
1
     d5a:  82 b3         in  r24, 0x12  ; 18
2
     d5c:  18 95         reti
3
     d5e:  80 93 79 00   sts  0x0079, r24
4
     d62:  80 91 79 00   lds  r24, 0x0079

allerdings wird hier das R24 verwendet, welches ja vorher nicht
gesichert wird!

Gruss
Michael
Gast #363097
Lesenswert?
• ▲
▼
Ich hatte nicht genau genug hingesehen. Also, du liest aus dem
IO-Register und schreibst in den Speicher. Dann ist _SFR_IO_ADDR(PORTD)
ein Input-Parameter.
Was ist "i" eigentlich für ein Operandentyp? Den kann ich in der
avr-libc-Doku nicht finden. Vielleicht ist das der Fehler?

> Wenn ich das mit der clobber-Liste richtig verstanden habe teilt
> diese doch dem Compiler nur mit, welche Werte sich geändert haben,
> oder?

Ja. Du teilst damit dem Compiler mit, daß deine asm-Routine intern z.B.
mit einem Register arbeitet, das weder input- noch output-Parameter ist
und das von der Routine in geändertem Zustand hinterlassen wird.
Dadurch weiß der Compiler dann, daß er - wenn er den Wert nicht
verlieren darf - diesen sichern muß.

Wegen der Variablen, auf die zugegriffen wird, müßte es eigentlich
reichen, wenn diese als volatile deklariert ist. Als clobber muß man
sie dann nicht mehr angeben.
Ich weiß nur nicht, wie bzw. ob du dieses Adresse als Operand angeben
kannst. Wenn G_cLastData keine globale Variable ist, geht's so eh
nicht, da die Adresse dann erst zur Laufzeit bekannt ist. Bei einer
globalen Variable sehe ich aber das Problem, daß der Compiler die
Adresse noch nicht kennt, da sie erst vom Linker festgelegt wird.
Die avr-libc-Doku schweigt sich leider dazu aus.
Gast #363098
Lesenswert?
• ▲
▼
Ja das ganze ist wirklich nicht sonderlich gut dokumentiert.
Ja ich lese PortD ein, und will es in eine globale Variable G_cLastData
schreiben.

Das Problem scheint nur zu sein, dass meine Funktion naked ist. Wenn
ich also im Asm-Teil das Output benutze, habe ich danach keine
Möglichkeit mehr was zu tun, auchnicht das reti!

Gruss
Michael
Moderator Persönliche Seite #363099
Lesenswert?
• ▲
▼
Schreib das Teil in eine separate Datei und dort komplett in
Assembler, statt derartige Verrenkungen zu machen.

#include <avr/io.h>

.global SIG_INTERRUPT0
SIG_INTERRUPT0:
  push  r2
  in  r2, _SFR_IO_ADDR(PORTD)
  sts  G_cLastData, r2
  pop  r2
  reti

Das Ganze kommt in eine Datei isr.S (per Konvention ein großes S am
Ende) und wird beim Standard-WinAVR-Makefile unter ASRC angegeben.
Gast #363100
Lesenswert?
• ▲
▼
Hi, gute Idee.
Habs gleich ausprobiert und einen Eintrag ASRC = isr.S in meinem
Makefile erzeugt.

Leider bekomme ich dann folgende Meldung:
C:\AVR\WinAVR\utils\bin\make.exe: *** No rule to make target
`isr.o', needed by `AppMain.elf'.  Stop.

Hast du eine Ahnung woran das liegt?

Grüsse
Michael
Moderator Persönliche Seite #363103
Lesenswert?
• ▲
▼
Naja, offenbar fehlt ihm irgendwie die Regel, wie man aus einer
.S-Datei eine .o-Datei erzeugt.  Er erkennt ja noch, dass er
die zugehörige .o-Datei braucht, aber es fehlen die Kommandos,
sie zu bauen.

# Assemble: create object files from assembler source files.
%.o : %.S
  @echo
  @echo $(MSG_ASSEMBLING) $<
  $(CC) -c $(ALL_ASFLAGS) $< -o $@

Sowas steht in Eric Weddington's Makefile-Template herum, ist
GNU-make
Syntax.  Generische make-Syntax wäre:

# Assemble: create object files from assembler source files.
.S.o:
  $(CC) -c $(ALL_ASFLAGS) $< -o $@

Nur so, mit Groß-/Kleinschreibung hast du dich aber nicht
vertan?  Wenn die Datei Isrs.S heißt, wird das make sie nicht
finden, wenn es isrs.o bauen soll.

Antwort schreiben

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.

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.