AVR (8-Bit) / C++ Toolchain

Gast #6069368
Lesenswert?

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
#6069381
Lesenswert?

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.
#6069850
Lesenswert?

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
#6070133
Lesenswert?

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
#6070353
Lesenswert?

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.
#6070355
Lesenswert?

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.
#6070810
Lesenswert?

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++
#6070853
Lesenswert?

>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.
Beitrag #6070859 wurde von einem Moderator gelöscht.
#6070886
Lesenswert?

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
Angehängte Dateien:
#6070938
Lesenswert?

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.
#6071038
Lesenswert?

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
#6071097
Lesenswert?

Bei
1
struct A {
2
  A() {}
3
    int m{42};
4
};
5

6
namespace {
7
    void g() {
8
        static A a;
9
    }
10
}
11

12
int main() {
13
  g();
14
}

werden die guards immer noch (trotz -fno-threadsafe-statics) generiert, 
aber nicht mehr verwendet.
1
$ avr-size bm00.elf
2
text    data     bss     dec     hex filename
3
224       0       8     232      e8 bm00.elf
1
$ avr-nm -C bm00.elf  | grep guard
2
00802800 b guard variable for (anonymous namespace)::g()::a
#6071314
Lesenswert?

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
Beitrag #6071325 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren