Forum: Compiler & IDEs Assemblerdatei unter Eclipse einbinden


von Florian W. (Gast)


Lesenswert?

Hallo,

programmiere seit Jahren die Atmel AVRs per AVRStudio in Assembler, habe 
aber nun ein Projekt bei dem ich haufenweise 16/32-bit Operationen 
ausführen muss und möchte deswegen diesen Teil in C schreiben.
Habe mir daher unter Ubuntu die Eclipse IDE mit den entsprechenden C/C++ 
und AVR Plugins installiert und mal losgelegt. Einige zeitkritische Subs 
und IRQs habe ich schon in Assembler geschrieben und würde diese gerne 
einbinden, um sie nicht nochmal schreiben zu müssen. (Außerdem sind sie 
schon per Logic Analyzer bis auf einzelne ClkCycles speedoptimiert, was 
vlt auch in C möglich wäre, aber sicher nicht so einfach wie in 
Assembler)

1. Die Suchfunktion hier und das AVR-GCC Tutorial haben mir zwar einige 
Tipps gebracht wie man in WinAVR oder bei selbstgeschriebenen makefiles 
vorgeht (ASRC= oder so ähnlich), aber ich wüsste gerne wo ich das bei 
Eclipse einstelle.

2. Das der gcc Assembler Compiler wohl eine etwas andere Syntax hat als 
der proprietäre Atmel Compiler habe ich auch schon gelesen, aber da kann 
ich ja wohl mit entsprechenden Fehlermeldungen rechnen, aufgrund derer 
ich dann geziehlt nach Lösungen such kann, oder?!

3. Sicher von Experten schnell nebenher beantwortet: Ich habe in meine 
main Funktion eine IO.c per Anführungszeichen eingebunden (#include 
"IO.c"), was wie ich gelesen hab bedeutet, dass er die Datei schlicht an 
diesem Ort in den Code rundherum rein "kopiert". Allerdings bekomme ich 
beim compilern bei allen Zuweisungen der Art "DDRA = 0xFF;" eine 
Fehlermeldungen: ">>int<< ist Standardtyp in Deklaration von >>DDRA<<" 
und gleichzeitig "data definition has no type or storage class". 
"#include <avr/io.h>" steht natürlich in meiner main.c Datei ganz oben, 
noch vor der main Funktion. Die Zuweisung von anderen Registern in der 
main Funktion bereitet auch keine Probleme.

Vielen Dank für eure Hilfe schon im Voraus!

von Florian W. (Gast)


Lesenswert?

PUSH
Sind meine Fragen zu dumm (wahrscheinlich) oder zu schwer (kann ich mir 
nicht vorstellen), um sie zu beantworten?!

Wär auch schon über einen Tipp aufs richtige Manual/Thread froh.

von Oliver (Gast)


Lesenswert?

Mit installiertem Eclipse-plugin und automatischen makefiles gibt es in 
den Project-Properties den Bereich C/C++-Build/Settings, in dem sich 
alles einstellen lässt. Das makefile erstellt Eclipse dann selber.

Alternativ baust du dir ein makefile von Hand (oder besser mit MFile aus 
dem WinAVR-Paket), und nutzt das auch unter Eclipse. Es gibt aber kaum 
Gründe, nicht die automatischen makefiles von Eclipse zu verwenden.

Nicht funktionieren Sourcecode bitte anhängen. Das spart dir seitenlange 
Beschreibungen, die am Ende doch keiner versteht. Prinzipiell ist das 
includieren von .c-Files der falsche Weg.

Oliver

von Florian W. (Gast)


Angehängte Dateien:

Lesenswert?

Oliver schrieb:
> Mit installiertem Eclipse-plugin und automatischen makefiles gibt es in
> den Project-Properties den Bereich C/C++-Build/Settings, in dem sich
> alles einstellen lässt. Das makefile erstellt Eclipse dann selber.

Das hab ich gefunden, allerdings gibts da unter "AVR Assembler"/General 
nur "(-Xassembler) options", "Other GCC Flags" oder "Include paths 
(-I)".
Wobei man bei letzterem nur ein Verzeichnis angeben kann, keine 
einzelnen Dateien. Muss ich nun meine .S Dateien in ein Verzeichnis 
legen und das dann dort angeben?! Oder bin ich bei "AVR Assembler" 
falsch?

Für meine dritte Frage hier meine main.c:
1
/* C Test file */
2
#include <avr/io.h>
3
#include <stdint.h> 
4
#include <avr/interrupt.h>
5
#include </home/florian/eclipse/workspace/Beagle IMU/Sources/IO.h>
6
7
//[... paar Variablen für später ...]
8
9
int main(void) {
10
uint8_t pll_loop=0;
11
12
  #include "IO.c"
13
14
//lis auschalten:
15
16
  lis_off();
17
18
//wait for PLL lock:
19
  do {
20
    if(PING & 1){
21
      pll_loop=0;
22
    }
23
    else{
24
      pll_loop++;
25
    }
26
  } while (pll_loop<100);
27
28
//adis konfigurieren und adis_bias berechnen:
29
30
  adis_conf();
31
  adis_bias();
32
33
//auf BeagleBoard warten:
34
35
//boot completed: lis on, red LED off, global interrupts enabled:
36
  lis_on();
37
  PORTD &= !(LED_RED_MASK);
38
  sei();
39
40
  while(1) {
41
42
  }
43
  return 0;
44
}

Die vier Funktionsaufrufe lis_off(); lis_on(); adis_conf(); und 
adis_bias(); sollen aus der Assemblerdatei kommen, werden im Moment noch 
als undefined reference bemeckert.
Meine dritte Frage war jedoch, warum er innerhalb der IO.c dann bei 
simplen Zuweisungen wie " EICRA = 48; " oder " EIMSK = 0x04; " meckert, 
dass der Datentyp nicht stimmt.
Die IO.c ist etwas länger, deswegen hab ich sie mal als Datei angehängt.

von Oliver (Gast)


Lesenswert?

>Muss ich nun meine .S Dateien in ein Verzeichnis
>legen und das dann dort angeben?!

Assembler-Dateien sind source-Dateien, und werden im source-Ordner des 
Projektes links in der Projektansich angegeben, doert, wo auch main.c 
und IO.c aufgelistet sind.

>#include </home/florian/eclipse/workspace/Beagle IMU/Sources/IO.h>

Macht man nicht, in <> eingeklammerte Pfade sind Systemdateien 
vorbehalten. User-Includes gehören in "". Das macht man nicht nur aus 
optischen Gründen, die Suchpfade unterscheiden sich. Daher musstest du 
auch den vollen Pfad angeben, damit das file gefunden wurde. Der 
Projektordner gehört nicht zu den System-Includepfaden, wohl aber zu den 
Projekt-Includepfaden. Deshalb reicht
1
#include "IO.h"
 wenn das .h-File im gleichen Ordner wie die .c-Dateien steht.

>Meine dritte Frage war jedoch, warum er innerhalb der IO.c dann bei
>simplen Zuweisungen wie " EICRA = 48; " oder " EIMSK = 0x04; " meckert,

Der Compiler compiliert jede Datei einzeln, völlig unabhängig von allen 
anderen. Daher muß jede C-Datei eigenständig kompilierbar sein. In 
deinem IO.c fehlen aber alle erforderliche includes, in diesem Fall 
#include <avr/io.h>. Daß die auch in main.c icludiert ist, ist egal.

Oliver

von klaus (Gast)


Lesenswert?

> Die vier Funktionsaufrufe lis_off(); lis_on(); adis_conf(); und
> adis_bias(); sollen aus der Assemblerdatei kommen, werden im Moment noch
> als undefined reference bemeckert.

Übergibst du dem Linker die aus der Assemblerfile genererierte 
Objektdatei (*.o) ? Falls ja, könnte es sein, dass du für die Funktionen 
keine Prototypen deklarierst (diese per Header-File einbinden) ?

von Peter D. (peda)


Lesenswert?

Ich halte das für den steinigen Weg.

Denn Assembler schreibt man ja ohne Rücksicht auf Linker, Compiler, 
reservierte Register, Parameterübergabe und andere Konventionen.
D.h. für den Mix Assembler + C braucht man schon viel Erfahrung und Du 
wirst vieles in den Assemblerroutinen umschreiben müssen.
Hat man jedoch die nötige C-Erfahrung, braucht man aber Assembler nicht 
mehr.

Wesentlich einfacher finde ich daher den Sprung ins kalte Wasser (pures 
C).

Du darfst Dich auch nicht darin verzetteln, alles auf jeden CPU-Zyklus 
hin zu optimieren. Das ist bei C der falsche Weg (bei Assembler 
eigentlich auch).

Bevor Du was anfaßt zum Optimieren, stelle erst fest, wieviel CPU-Last 
prozentual zum gesamten Programm benötigt das überhaupt.
Bei kleiner 1% lohnt sich Optimieren nur in Ausnahmenfällen.

Laß den Compiler also ruhig mal einige Zyklen mehr brauchen.


Peter

von Peter D. (peda)


Lesenswert?

Florian W. schrieb:
> programmiere seit Jahren die Atmel AVRs per AVRStudio in Assembler, habe
> aber nun ein Projekt bei dem ich haufenweise 16/32-bit Operationen
> ausführen muss und möchte deswegen diesen Teil in C schreiben.

Das ist aber nicht unbedingt ein Grund für C.
Unter Assembler brauchst Du nur ne Lib für die Grundrechenarten zu 
nehmen und fertig.

C: a = a * b;
Assembler: rcall umul32


Peter

von Florian W. (Gast)


Lesenswert?

Erst mal Vielen Dank für die zahlreichen Antworten.

Das heißt bei den Includes unterscheidet <> und "" nur die Suchpfade, 
das erklärt dann auch das verhalten. Demnach ist aber folgende Erklärung 
falsch:

http://www.acm.uiuc.edu/webmonkeys/book/c_guide/1.7.html#include

Denn die suggeriert, dass bei "" der include Befehl ähnlich einem Makro 
einfach die referenzierte Datei an dieser Stelle in den Quellcode rein 
kopiert, so als ob es direkt in der Datei stehen würde.
Da das ja offensichtlich nicht der Fall ist, is auch klar, dass die 
Header in der IO.c nochmal extra eingebunden werden müssen.

Mit der IO.c als korrekter Funktion und einer Header Datei mit 
Deklarationen zu allen Funktionen (auch denen aus der Assemblerdatei) 
und allen globalen Variablen sind nun fast alle Fehler behoben. Er 
scheint jetzt auch die Assemblerdatei zu futtern, war ja im Nachhinein 
doch recht einfach ;).

von Oliver (Gast)


Lesenswert?

>Demnach ist aber folgende Erklärung
>falsch:

>http://www.acm.uiuc.edu/webmonkeys/book/c_guide/1....

Nö. Da steht genau das drin.

#include kopiert IMMER die referenzierte Datei an dieser Stelle in den 
Quellcode. Der Unterschied zwischen <> und "" besteht nur darin, in 
welchen Pfaden der Compiler die zu inkludierende Datei sucht.

Oliver

von Peter D. (peda)


Lesenswert?

Man sollte nicht gleiche Namen verwenden, wie die Standardincludes, also 
nicht "io.h". Sonst wird je nach Suchpfadreihenfolge mal das eine, mal 
das andere zuerst gefunden.

Auch sollten sich Namen nicht nur in Groß-/Kleinschreibung 
unterscheiden.
Unter Linux mag das gehen, unter Windows krachts aber.


Peter

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.