Forum: Mikrocontroller und Digitale Elektronik Arduino und Assembler Programmierung


von Hans K. (hanska)


Lesenswert?

Hallo,
ich habe ein Arduino Programm geschrieben, das aus Arduino C-code und 
Assembler code besteht.
Aus irgendeinem Grund erkennt der Compiler der Arduino IDE das keyword 
'PORTD' im Assembler Programm nicht. Im C-code wird 'PORTD' aber 
erkannt. Ich habe versucht verschiedenste #includes einzubinden, bisher 
ohne Erfolg. Der workaround mit der Registeradresse 0x0B(=PORTD) 
funktioniert zwar, aber vielleicht kann mir jemand helfen, die Ursache 
dieses Verhaltens zu klären. Hier ist ein Beispielprogramm
1
/******************************************************
2
 * PORTD wird im Assembler Programm nicht erkannt
3
*********************************************************/
4
5
byte LED = 4;  //= PD4
6
7
void setup(){
8
  Serial.begin(9600);
9
  Serial.println();
10
  Serial.println("*** Assembler Test");
11
  Serial.println();
12
13
  pinMode(LED,OUTPUT);  
14
}
15
16
void loop()  {
17
  Serial.println("Assembler");
18
  LEDon();
19
  delay(1000);
20
  LEDoff();
21
  delay(1000);
22
  
23
  Serial.println("*** C Programm");
24
  PORTD = 0x10;
25
  delay(1000);
26
  PORTD = 0x00;
27
  delay(1000);
28
}
29
//*******************
30
31
void LEDon ()  {
32
  asm volatile
33
  (
34
     "ldi r16,0x10\n"
35
     //"out PORTD,r16\n" //<----- PORTD wird nicht erkannt
36
     "out 0x0B,r16\n"    // <-- 0x0B = PORTD
37
  );  
38
}
39
40
void LEDoff ()  {
41
  asm volatile
42
  (
43
     "ldi r16,0x00\n"
44
     //"out PORTD,r16\n" //<----- PORTD wird nicht erkannt
45
     "out 0x0B,r16\n"    // <-- 0x0B = PORTD
46
  );  
47
}

und hier die Fehlermeldung, wenn die Auskommentierung von 'PORTD' 
entfernt wird :

C:\Users\hansk\AppData\Local\Temp\ccV87F6x.ltrans0.ltrans.o: In function 
`LEDon':
D:\Arduino\Programme\Assembler\Neuer Ordner\AssPort/AssPort.ino:37: 
undefined reference to `PORTD'
collect2.exe: error: ld returned 1 exit status
exit status 1
Fehler beim Kompilieren für das Board Arduino Uno.

Vielen Dank

von Michael B. (laberkopp)


Lesenswert?

Hans K. schrieb:
> Aus irgendeinem Grund erkennt der Compiler der Arduino IDE das keyword
> 'PORTD' im Assembler Programm nicht.

Kein Wunder, er ist ja auch der Compiler.

Der assembliert nicht, sondern reicht den Assemblercode zum Assembler 
weiter.

Und der Assembler included nicht, nicht das was der Compiler in C 
included, ist ja auch C, kein Assembler.

von MaWin O. (mawin_original)


Lesenswert?

Warum genau schreibst du das in Assembly?

von Oliver S. (oliverso)


Lesenswert?

Entweder so:

https://rn-wissen.de/wiki/index.php/Inline-Assembler_in_avr-gcc#Zugriff_auf_SFRs

oder gleich die Assemblerfunktionen in ein echtes Assemblerfile (*.S 
oder *.sx) auslagern.

Und dazu mal _SFR_IO_ADDR nachschlagen.

Oliver

von Hans K. (hanska)


Lesenswert?

Hallo MaWin,
Das soll nur ein Test sein, wie man Assembler code in der Arduino IDE 
einbindet. Es gibt keinen Grund das in Assembler zu schreiben. Ich 
wollte nur wissen, was man tun muss, daß 'PORTD' im Assembler erkannt 
wird.
Trotzdem Danke für die Antwort.

von MaWin O. (mawin_original)


Lesenswert?

Hans K. schrieb:
> wollte nur wissen, was man tun muss, daß 'PORTD' im Assembler erkannt
> wird.

Ok. Du musst PORTD als Konstante über ein asm-input mit entsprechendem 
Constraint an das asm-Statement übergeben.

https://www.nongnu.org/avr-libc/user-manual/inline_asm.html

von Hans K. (hanska)


Lesenswert?

Hallo Mawin,
Der asm-Befehl
asm("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)) );
ist mir zu umständlich und wenn er mehrfach im Programm auftaucht zu 
viel Tipperei. Ok, vieleicht reicht es das "=r" (value) : "I" 
(_SFR_IO_ADDR(PORTD) Gedöns nur einmal zu benutzen. Aber das muss dann 
für alle SFR_IO's wieder gemacht werden. Es wäre einfacher gewesen die 
keywords 'PORTB,'PORTC','PORTD',... zu benutzen.
Ich hoffte, es geht mit einem geschickten #include an der richtigen 
Stelle.
Dann ist es einfacher einen *.S Tab zu benutzen.
Danke für Deine Antworten.

von Rolf M. (rmagnus)


Lesenswert?

Hans K. schrieb:
> Hallo Mawin,
> Der asm-Befehl
> asm("in %0, %1" : "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)) );
> ist mir zu umständlich und wenn er mehrfach im Programm auftaucht zu
> viel Tipperei.

Dann hast du Pech gehabt, denn das ist der Weg, wie man das macht. 
Bisher ist aber unklar, wofür du das überhaupt brauchst. In der Regel 
steckt man sowas, wenn man es mehrfach benötigt, einfach in ein Makro.

> Ok, vieleicht reicht es das "=r" (value) : "I" (_SFR_IO_ADDR(PORTD)
> Gedöns nur einmal zu benutzen. Aber das muss dann für alle SFR_IO's
> wieder gemacht werden. Es wäre einfacher gewesen die keywords
> 'PORTB,'PORTC','PORTD',... zu benutzen.

Das sind keine Keywords, sondern Präprozessor-Makros.

von Arduino F. (Firma: Gast) (arduinof)


Lesenswert?

Hans K. schrieb:
> Dann ist es einfacher einen *.S Tab zu benutzen.

Das sehe ich auch so!
Das ASM inline Gedönse ist nicht wirklich "hübsch".

Wobei ich da auch keine Notwendigkeit sehe, denn das gezeigte geht in 
C++ genauso effektiv.

: Bearbeitet durch User
von Hans K. (hanska)


Lesenswert?

Hallo,
Nochmal : Es geht nicht um dieses Beispielprogramm! Es ist Schwachsinn 
das in Assembler zu schreiben. Es geht ums Prinzip von (nicht "keywords" 
sondern) Präprozessor-Makros.

Übrigens habe ich doch eine Methode gefunden mein geliebtes 'PORTD' zu 
benutzen. Mit
     ".EQU PORTD, 0x0B ;PORTD definieren\n"
geht's.
Vielen Dank an alle

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
Noch kein Account? Hier anmelden.