Hallo, bin ein C++ Head und versuchte eine Klasse (c++ syntax "class") im AVR-Studio mit dem AVR-GCC Compiler zu erzeugen. Ging nicht. Weil ich eine C++ Syntax mit einem C Compiler übersetzen wollte. So viel weiß ich jetzt. Wie erzeuge ich denn eine Klasse in C? (brauche nämlich ein Objekt mit bestimmten Eigenschaften öfter im Programm) Oder besser, wie muss ich AVR-Studio konfigurieren, damit ich C++ Syntax verwenden kann? ..einen ähnlichen Beitrag gab es schon mal in diesem Forum, allerdings brachten mich die Antworten nicht weit. Bitte um Hilfe
> Wie erzeuge ich denn eine Klasse in C? In C gibt's keine Klassen. Du müßtest das dann zu Fuß machen. > Oder besser, wie muss ich AVR-Studio konfigurieren, damit ich C++ > Syntax verwenden kann? Die Datei als C++ compilieren ;-) Du mußt dazu g++ statt gcc nehmen. Wie das mit AVR-Studio geht, weiß ich nicht.
> Wie das mit AVR-Studio geht, weiß > ich nicht. Meines Wissens gar nicht. Muss man halt eine andere Bedien- oberfläche nehmen als AVR Studio, PN2 zum Beispiel.
Ok, danke. Das habe ich mir fast gedacht. Werde es wahrscheinlich dann von Hand, mit dem WinAVR, kompilieren. Schade, das wäre noch eine Erweiterung im AVR-Studio wert.
Das geht schon mit AVR Studio: Dateien können so benannt bleiben (.c). Im Menüpunkt Bulid->ExportMakefile exportierst Du das vom AVRStudio generierte Makefile Im Menüpunkt Project->ConfigurationOptions klickst Du die Checkbox "Use External Makefile" an und wählst das Makefile. Das Makefile musst Du dann öffnen und als Compiler den avr-c++.exe auswählen: CC = avr-c++.exe In der Compile-Section des Makefile noch die Pfade richtig einstellen: ## Compile test.o: ../test.c (hier muss das ../ meistens weg, abhängig vom Pfad des Makefiles zu den .c Dateien. Das AVR Studio kennt schon die C++ Schlüsselworte und highlighted die.
avr-gcc kompiliert C++-Code, wenn die Sourcedatei auf .cpp, .c++, .C (für weiteres siehe manual) endet.
Kommt drauf an, was man machen will. Exceptions und RTTI gehen (noch) nicht, und werden, wenn sie dann gehen, vermutlich viel Platz brauchen. Ich versuche gerade, die Exception-Unterstützung zum laufen zu bringen. Virtuelle Memberfunktionen brauchen RAM (Pro Klasse und virtueller Funktion ein Zeiger), da die vtables bisher dort gespeichert werden. Es gibt keine C++-Standardbibliothek. Der Rest funktioniert soweit und hat keinen besonderen Overhead gegenüber C. Teilweise wird der Code sogar kompakter. Mit Templates und Klassen lassen sich auch so schon ganz nette Sachen auf einem AVR machen.
Solltest zumindest erwähnen, dass es sich dabei um Payware handelt. Das dürfte in der GCC-Gruppe nicht so selbstverständlich sein.
ich arbeite mit der DEMO, geht eben nur der Codewizard nicht... Einschränkungen in punkto Codegröße habe ich nicht bemerkt, ansonsten gibts ja noch Eclips oder DEV++ die gehen sollten, beim der workpad-demo brauchte ich für AVR C++ nix weiter mehr konfigurieren es ging eben einfach ;-)
Rolf Magnus, hast Du new und delete schon zum Laufen bekommen? Ich bin leider beruflich sehr eingespannt würde aber gerne meine (schmale) Unterstützung anbieten: ogni42(at)gmx.de
Hallo Ingo, respekt, ich wäre da so schnell nicht hingekommen. Hab mich an deine Anleitung gehalten und funktioniert. Vielen Dank!!!!!!!!!
Gern geschehn :) Habe aber vergessen darauf hinzuweisen, dass die Nutzung des Debuggers (noch) nicht funktioniert. Rolf Magnus' Hinweis kann ich nur stützen: Bei mir benötigt der C++ tendenziell weniger RAM als ein entsprechender C Code aber etwas mehr Flash (ca. 1%). Das kann aber natürlich auch am Programmierstil liegen.
> Rolf Magnus, hast Du new und delete schon zum Laufen bekommen? Wie man's nimmt. Vom Prinzip her sind die kein Problem. Eine triviale Implementation könnte einfach intern malloc/free aufrufen. Die Version, die in der libsupc++ *) enthalten ist, macht das auch, ruft aber auch noch evtl. installierte new-Handler auf und wirft im eine Exception, wenn malloc 0 zurückgibt. Und da liegt das Problem. Diese Exception zieht ca. 11kB Code in das Programm und funktioniert dann nicht mal. *) libsupc++ ist die Biblitothek, die die grundlegenden Implementationen für C++-Support enthalten, also z.B. operator new, die typeid-Implementatioenen für RTTI oder den unwinding-Code für Exceptions. > Ich bin leider beruflich sehr eingespannt würde aber gerne meine > (schmale) Unterstützung anbieten: ogni42(at)gmx.de Naja, ich habe festgestellt, daß das Wühlen durch die gcc-Eingeweide trotz der eigentlich ziemlich guten Dokumentation recht schwierig und aufwendig ist. Du könntest dich in die Mailingliste avr-gcc-list@nongnu.org eintragen.
Dann werde ich mich am WOchenende mal um einen Eintrag in der Mailinglist kümmern und mir eine Kopie der libsup++ ziehen. Ich melde mich dann hier wieder....
> Diese Exception zieht ca. 11kB Code in das Programm Das ist allerdings heftig. Könntest du dich mit der Variante anfreunden die MS lange Zeit gefahren ist? new liefert im Fehlerfall 0 zurück. Ist zwar nicht Standard-konform, aber Speicherplatz geht in diesem Fall vor :-) > Der Rest funktioniert soweit und hat keinen besonderen Overhead > gegenüber C. Das wäre dann allerdings mal eine Überlegung wert.
> Könntest du dich mit der Variante anfreunden die MS lange > Zeit gefahren ist? new liefert im Fehlerfall 0 zurück. Im Prinzip schon. Man könnte es ja auch davon abhängig machen, ob Exceptions an sind oder nicht. Es ging ja auch erstmal darum, zu schauen, ob die libsupc++ mit dem AVR zum Laufen zu bekommen ist. Vielleicht könnte man den Overhead von Exceptions auch drücken, aber ich habe keine Ahnung davon, wie Exception-Handling intern funktioniert. Nach dem Code zu urteilen, ist es sehr aufwendig. Ich glaube, man kann für bestimmte Targets einzelne Dateien der libsupc++ durch andere Implementationen ersetzen. Das werde ich mal mit Operator new probieren. >> Der Rest funktioniert soweit und hat keinen besonderen Overhead >> gegenüber C. > > Das wäre dann allerdings mal eine Überlegung wert. Ich benutze oft C++ auf den AVRs. Es muß ja nicht immer gleich alles mit Polymorphie und Exceptions sein. Man kann auch mit dem Rest noch viel machen, z.B. ein nettes Klassentemplate für Fixkomma-Zahlen oder Bigint. Ich habe sogar rausgefunden, daß es einen Weg gibt, diese für Berechnungen zur Laufzeit in inline-ASM zu implementieren (z.B. um bei kaskadierten Additionen das Carry-Flag nutzen zu können), aber trotzdem auch Constant-Folding zu ermöglichen. Oder ein Queue-Klassentemplate mit der zu verwendenen Speichergröße als Template-Parameter. So eine benutze ich auch schon, um Textausgaben an eine USART-Interruptroutine zu übergeben, damit ich nicht immer auf die Schnittstelle warten muß. Das war das erste Mal, daß ich Memberfunktionen als volatile deklarieren mußte ;-) Ich habe mir auch schon 'Smart'-Pointers zum Zugriff auf Flash und EEPROM gebastelt. Eine Dereferenzierung macht automatisch den Zugriff. Leider den operator-> nicht brauchbar implementieren. An einer reduzierten iostream-artigen Klasse arbeite ich auch schon rum.
Ups, da war noch ein Name eingstellt, den ich gestern verwendet hab, als ich so entnervt war ;-)
> Ich benutze oft C++ auf den AVRs Ich hab mich bisher noch nicht drübergetraut. Na ja. Ich hatte auch noch keinen wirklichen Bedarf :-) > mit Polymorphie und Exceptions sein. Sehe ich auch so. Auf Exceptions kann ich verzichten. Polymorphie wäre schon schmerzhafter :-) > Ich habe mir auch schon 'Smart'-Pointers zum Zugriff auf Flash und > EEPROM gebastelt. Die wären natürlich toll. Oder auch die std::string wäre natürlich kein Vergleich zu strcpy() und co. Mal eine vernünftige Timer-Klasse ohne jedesmal im Datenblatt nachzuschauen, wo denn nun wieder die Bits rumlungern und wie denn wieder dieser besch... ISR Name war, etc... Oder den USART Kapseln, oder ...
>> mit Polymorphie und Exceptions sein. > > Sehe ich auch so. Auf Exceptions kann ich verzichten. > Polymorphie wäre schon schmerzhafter :-) Naja, Polymorphie funktioniert durchaus mit avr-g++. Leider werden aber die vtables im RAM abgelegt, was dort pro polymorpher Klasse und virtueller Funktion Platz für einen Zeiger kostet. Bisher gibt es keine Lösung, um das komplett im Flash zu machen. Theoretisch möglich wäre es, da die vtables zur Laufzeit eh konstant sind. Das Problem ist, daß beim GCC die vtables im Prinzip einfach als globale Variablen definiert werden. Auf Variablen kann er aber bekanntlich nur zugreifen, wenn sie im RAM stehen, da GCC keinerlei Support für Harvard-Architekturen hat. >> Ich habe mir auch schon 'Smart'-Pointers zum Zugriff auf Flash >> und EEPROM gebastelt. > > Die wären natürlich toll. Funktionieren eigentlich ganz gut ;-) So in der Art sehen meine AVR-Programme heute aus: #include <avr++/pgmspace> const char helloworld[] PROGMEM = "Hello, world"; void put_string(pgmspace_ptr<char> p) { while (*p++) usart::write(*p); usart::write('\n'); } int main() { put_string(pgmspace(helloworld)); } Mittlerweile auch: cout << pgmspace(helloworld) << '\n'; Die cout-Variante könnte sparsamer werden als printf, da printf einen Formatstring-Parser und alle unterstützten Konvertierungen enthält. Selbst wenn ich nur einen String ausgebe, wird gleich alles mit reingenommen. Bei cout fällt der Parser weg und es werden immer nur die Konvertierungen übernommen, die im Programm verwendet werden. Einfache, wie die für char können auch gleich inline expandiert werden und lösen sich damit in Wohlgefallen auf. > Oder auch die std::string wäre natürlich kein Vergleich zu > strcpy() und co. Naja, ob das so sinnvoll ist, ist die Frage. Da muß halt immer viel dynamisch allokiert werden. > Mal eine vernünftige Timer-Klasse ohne jedesmal im Datenblatt > nachzuschauen, wo denn nun wieder die Bits rumlungern und wie > denn wieder dieser besch... ISR Name war, etc... > Oder den USART Kapseln, oder ... Jo, gibt viele nette Sachen, die man machen könnte. Muß nur mal jemand in Angriff nehmen ;-)
Nur als Hinweis: Das WinAvr-Plugin für Eclipse eignet sich auch ganz gut für die C++ Entwicklung. Für die, die Eclipse kennen und lieben, vielleicht eine nette Alternative. Die Kapselung von all den Atmel-internen Funktionen wär aber was :-) Momentan scheint ja jeder fallspezifisch sein eigenes Ding zu entwickeln
@Ingo, "Bei mir benötigt der C++ tendenziell weniger RAM als ein entsprechender C Code aber etwas mehr Flash (ca. 1%). Das kann aber natürlich auch am Programmierstil liegen." Könnte aber auch sein, das dann Variablen mit malloc angelegt werden und nicht mehr in der Statistik auftauchen. Die wirkliche Speicherauslastung läßt sich nur zur Laufzeit ermitteln und das auch nicht gerade einfach. Da ich kein malloc benutze, fülle ich einfach den freien Bereich mit 0x77 und prüfe dann nach einiger Laufzeit, wieviel davon noch unverändert ist. Peter
> Könnte aber auch sein, das dann Variablen mit malloc angelegt > werden und nicht mehr in der Statistik auftauchen. Nein. Es gibt Momentan keine libsupc++. Diese wäre das einzige, was malloc aufrufen könnte. Ich wüßte auch nicht, wo sowas implizit nötig wäre (abgesehen von operator new, für welchen aber auch keine Implementation existiert).
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.