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!
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.
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
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.
>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
> 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) ?
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
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
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 ;).
>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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.