Abend zusammen,
nach den üblichen Recherche-Ansätzen habe ich keine abschließende
Antwort gefunden.
Ich möchte mit C++ auf 8 Bit AVR´s gehen und kann mir einige Fragen
nicht sicher beantworten.
Welche Toolchain funktioniert? (Ab Atmel Studio 'X', mit Compiler 'Y',
mit Programmer 'Z')
Ich habe gesehen, es gibt einen Thread in der Richtung
Beitrag "AVR C++ Toolchain"
Da geht es aber nicht dediziert um 8Bitter.
viele Grüße
Ich habe folgendes:
* avr-g++ (aktuell 9.2, oder 10.0 von trunk selbst compilieren)
* make
* QtCreator oder VsCode
* avrdude (für ISP)
* pyupdi für UPDI
Weil oft gefragt: ein C++-StdLib ist beim avr-g++ nicht(!) dabei,
wenngleich man viele templates aus der OSS-Implementierung des g++
kopieren/anpassen kann. Kommt etwas auf Deine C++-Skills an.
Jeder avr-gcc ist ein gcc, und kann daher so viel C++, wie ein gcc halt
so kann. Die üblichen verfügbaren avr-gcc-toolchains machen auch alles
mit.
Es braucht ein paar paar zusätzliche Funktionen für new, delete, und für
einen virtuellen Funktions-Handler (google weiß Bescheid), damit lassen
sich dann C++-Programme problemlos kompilieren.
https://www.avrfreaks.net/forum/avr-c-micro-how?page=all
Es fehlt hat, wie oben schon geschrieben wurde, die C++Standardlib.
Das, was Microchip dazu schreibt, gilt sinngemäß für alle toolchains auf
Basis avr-gcc (also alle):
https://www.microchip.com/webdoc/AVRLibcReferenceManual/FAQ_1faq_cplusplus.html
Oliver
Oliver S. schrieb:> Es braucht ein paar paar zusätzliche Funktionen für new, delete
Darauf würde ich komplett verzichten, und alle Allokationen statisch
machen. Also std::array<> verwenden oder sich einen
FixedCapacityVector<> schreiben.
Ggf. brauch man ein placement-new, falls man einen Ctor in-place
aufrufen will. Kommt aber sehr selten vor, wenn überhaupt ...
Kann jeder halten und machen, wie er will. std::array scheitert zunächst
an der fehlenden Standard-lib, das muß man sich alles selber schreiben.
Wie, ist dann einfach Ermessenssache.
Virtuelle Klassen sind auch nicht optimal, da avr-gcc die vtables ins eh
knappe Ram legt. Wer die aber trotzdem nutzen will, braucht die o.a.
Funktionen. Wer nicht, der nicht.
Oliver
Oliver S. schrieb:> std::array scheitert zunächst> an der fehlenden Standard-lib, das muß man sich alles selber schreiben.
Ich gehe davon aus, dass der TO C++ Erfahrung hat, sonst würde er nicht
mit C++ Richtung µC gehen wollen. Daher sollte ein (für µC optimiertes)
template std::array<> nichts weiter als eine Fingerübung sein.
Wilhelm M. schrieb:> Ich gehe davon aus, dass der TO C++ Erfahrung hat
Die Art der Fragestellung lässt eigentlich nicht erkennen, worin der TO
Erfahrung hat. Sie lässt nur klar erkennen, worin er keine hat...
Oliver
Jasson schrieb:> Welche Toolchain funktioniert? (Ab Atmel Studio 'X', mit Compiler 'Y',> mit Programmer 'Z')
Du müßtest deine Frage konkretisieren.
Welcher µC?
Welche C++ Version?
Weil grundlegend kannst du in Atmel Studio 7 alle 8Bitter ATmegas
programmieren. AS7 kommt standardmäßig mit avr-gcc 5.4.0 daher. Für
C++11 reicht das. Ansonsten kannst du AS7 jederzeit eine neuere
Toolchain an die Hand geben.
Wilhelm M. schrieb:> Oliver S. schrieb:>> std::array scheitert zunächst>> an der fehlenden Standard-lib, das muß man sich alles selber schreiben.>> Ich gehe davon aus, dass der TO C++ Erfahrung hat, sonst würde er nicht> mit C++ Richtung µC gehen wollen. Daher sollte ein (für µC optimiertes)> template std::array<> nichts weiter als eine Fingerübung sein.
In Beitrag "Re: Initialwert von globalen Variablen zur Laufzeit verwenden" hattest du doch
geschrieben, dass es die schon gibt. Du hast da nur nicht verraten, wo.
Rolf M. schrieb:> In Beitrag "Re: Initialwert von globalen Variablen zur Laufzeit> verwenden" hattest du doch> geschrieben, dass es die schon gibt. Du hast da nur nicht verraten, wo.
1) Die C++-Std_Lib ist OSS. Also: reinschauen und/oder kopieren, soweit
es die Lizenz für Dich zulässt.
2) https://www.etlcpp.com/array.html
3) Die non-library-writers Version behandelt man im Anfängerkurs C++
>Also danke schon mal für die konstruktiven Antworten!
Offenbar kann ich´s im Rahmen meines Hobbys mit positiver Hoffnung drauf
ankommen lassen.
Ich setzte einfaches C++ ein. Das komplexeste ist eine abstrakte Klasse,
welche auf eine Templateklasse vererbt wird, aus der dann verschiedene
abgeleitete Klassen erzeugt werden.
Ich hab noch ein Visitor Pattern am Werk - ich werd´s erleben.
Habe oben gelesen, dass das vtables im RAM landen, muss ich dann sehen,
ob´s hinkommt.
Ziel wird wahrscheinlich Mega64/128 o.ä. sein. Etwas mechanisch großes,
was im DIP Format zu kriegen ist.
Wie gesagt, du brauchst dazu eine handvoll Funktionen, ansonsten gibt es
undefined references (zumindest im Debug-Build).
Aus dem avrfreaks-Thread habe ich mit mal das im Amhang
zusammengetsellt, das hat bisher mit allen avr-gcc-toolchains, die ich
benutzt haben, funktioniert. Ob die guard-Funktionen darin tatsächlich
bei aktuellen Compilern noch benötigt werden, habe ich nie ausprobiert.
Der avrfreaks-Thread ist ja doch inzwischen uralt.
Oliver
Jasson J. schrieb:> Ich setzte einfaches C++ ein. Das komplexeste ist eine abstrakte Klasse,> welche auf eine Templateklasse vererbt wird, aus der dann verschiedene> abgeleitete Klassen erzeugt werden.
Ich weiß nicht, ob diesen etwas wirren Satz richtig verstehe. Aber:
Dyn. Polymorphie und statische Polymorphie gleichzeitig (in einer(!)
Klassenhierarchie) zu verwenden, ist meistens keine gute Idee.
Vielleicht meinst Du aber auch das OO template-pattern, was nichts mit
C++-template-Mechanik zu tun hat.
Oliver S. schrieb:> Ob die guard-Funktionen darin tatsächlich> bei aktuellen Compilern noch benötigt werden, habe ich nie ausprobiert.> Der avrfreaks-Thread ist ja doch inzwischen uralt.
Weils mich dann doch jetzt mal interssiert hat: Hier gibts eine gute
Erklärung:
https://iamroman.org/blog/2017/04/cpp11-static-init/
Und -fno-threadsafe-statics ist das Compilerflag der Wahl ;)
Dann brauchts die guards nicht.
Oliver
Wilhelm M. schrieb:> werden die guards immer noch (trotz -fno-threadsafe-statics) generiert,> aber nicht mehr verwendet.
Was in deinem Bespiel daran liegt, daß der Compiler alles wegoptimiert.
Wilhelm M. schrieb:> 00802800 b guard variable for (anonymous namespace)::g()::a
Das erste Byte enthält das Initialisierungsflag, das hat mit den guards
nichts zu tun (und das wird bei der Initialisierung auch gelesen und
geschrieben, auch mit -fno-threadsafe-statics). Warum der Block dafür
allerdings nicht nur 1 Byte, sondern gleich 8 Byte lang ist, wissen wohl
nur die gcc-Götter.
Oliver
Oliver S. schrieb:> Was in deinem Bespiel daran liegt, daß der Compiler alles wegoptimiert.
Nein. Eben nicht. Das init-flag wird gesetzt und die guards nicht
verwendet. Das hat nichts mit der Optimierung zu tun, sondern mit dem
flag -fno-threadsafe-statics.
Was aber eben nicht gut ist, dass die guard-variable nicht auch gleich
unterdrückt wird.