Hallo
ich beginne gerade mit einem größeren projekt bei dem ich vorhabe einen
ATxmega controller mit C++ zu programmiren.
Leider musste ich feststellen dass die aktuelle avr-libc version weder
meinen controller unterstützt und auch so gut wie keine unterstütung für
c++ besitzt. Deswegen die frage, gibts alternativen zu avr-libc? oder
muss ich mir im bedarfsvall alles selber patchen.
Details:
Der controller mit dem ich arbeite ist ein atxmega128a3u.
Der letzte versuch mit c++ typte_traits zu arbeiten hat mich dazu
gebracht boost ein zu binden, wass leider auch nicht half da weitere
header der standard library fehlten.
Entwiklungsumgebung Linux(debian)
Wasle schrieb:> Hallo>> ich beginne gerade mit einem größeren projekt bei dem ich vorhabe einen> ATxmega controller mit C++ zu programmiren.
Na dann hau rein.
> Leider musste ich feststellen dass die aktuelle avr-libc version weder> meinen controller unterstützt und auch so gut wie keine unterstütung für> c++ besitzt. Deswegen die frage, gibts alternativen zu avr-libc? oder> muss ich mir im bedarfsvall alles selber patchen.
Da wirste einiges zu tun kriegen. Und mal ehrlich: brauchste das
wirklich? Wenn du 'ne UI mit dem Xmega bauen willst, seh ich das ja die
Motivation noch irgendwo ein, glaube aber nicht, dass es das
rechtfertigen würde.
Vielleicht könntest du einfach objektorientiert mit C programmieren?
Also im Stile der WinAPI bzw. GDI wo bestimmte Funktionen an bestimmte
Handles gebunden sind?
> Details:> Der controller mit dem ich arbeite ist ein atxmega128a3u.> Der letzte versuch mit c++ typte_traits zu arbeiten hat mich dazu> gebracht boost ein zu binden, wass leider auch nicht half da weitere> header der standard library fehlten.
Mal stlport probiert?
Wasle schrieb:> Der controller mit dem ich arbeite ist ein atxmega128a3u.
Die aktuelle Release-Serie von GCC (4.8) unterstützt auch den
ATxmega128A3U, ebenso AVR-Libc 1.8.0.
> Der letzte versuch mit c++ typte_traits zu arbeiten hat mich dazu> gebracht boost ein zu binden, wass leider auch nicht half da weitere> header der standard library fehlten.> Entwiklungsumgebung Linux(debian)
Hier wirst du wohl einiges an Entwichlungsarbeit in avr-g++ stecken
müssen.
libsupc++ und libstdc++v3 sind vom gcc Build ausgeschlossen wenn dieser
mit --target=avr configuriert wird. Du musst also die entsprechenden
configure anpassen, alles neu erzeugen und auftretende Fehler
beseitigen. Evtl. fehlen auch Teile im avr-Backend selbst, etwa für
Exception-Handling.
Falk Schilling schrieb:> Vielleicht könntest du einfach objektorientiert mit C programmieren?
Das will man doch nur wenns gar nicht anders geht, in C++ ist das doch
viel eleganter und sicherer...
Johann L. schrieb:> libsupc++ und libstdc++v3 sind vom gcc Build ausgeschlossen wenn dieser> mit --target=avr configuriert wird. Du musst also die entsprechenden> configure anpassen, alles neu erzeugen und auftretende Fehler> beseitigen. Evtl. fehlen auch Teile im avr-Backend selbst, etwa für> Exception-Handling.
Wir suchen seit 9 Jahren jemanden, der sich mit der Problematik
befasst:
https://savannah.nongnu.org/people/viewjob.php?group_id=2140&job_id=378
Steht zwar unter avr-libc, bedeutet aber letztlich, dass sich jemand
mit genügend Interesse und Kenntnissen im Bereich C++ darum kümmern
müsste, dass beides (AVR-GCC und avr-libc) in dieser Hinsicht sauber
miteinander spielt.
Also mal danke für die rückmeldungen
@Falk Schilling
>Vielleicht könntest du einfach objektorientiert mit C programmieren?>Also im Stile der WinAPI bzw. GDI wo bestimmte Funktionen an bestimmte>Handles gebunden sind?
Ist für micht nicht wirklich vergleichbar, da ich weniger die
Objektorientierung von C++ verwende, sondern in erster linie operator
overloading, namespaces, und besonderen Templates.
Auch wenn ich zugebn muss dass der Nutzen dieser funktionen in vielen
fällen gering ist.
@Johann L.
>Die aktuelle Release-Serie von GCC (4.8) unterstützt auch den>ATxmega128A3U, ebenso AVR-Libc 1.8.0.
Was gcc betrifft kann ich das nur bestätigen.
AVR-Libc 1.8.0 http://download.savannah.gnu.org/releases/avr-libc/
Funktionirt bei mir jedoch nicht. Die unterstützen nur 2 verwante
controller ATxmega128A3 bzw. ATxmega128A1U.
Ich versuche momentan den Controller mit hielfe des Headers iox128a3u.h
(kopiert von Atmel Studio) in die library zu integrieren. Leider
scheitere ich noch beim update der Configuration (autotools).
@Jörg Wunsch
Ich werden mir im laufe der woche mal das zusemmanspiel von libsupc++,
libstdc++v3, avr-libc und avr-g++ genauer ansehen. Fileicht läst sich da
ja wirklich was machen.
Christoph Wiesmeier schrieb:> Ist für micht nicht wirklich vergleichbar, da ich weniger die> Objektorientierung von C++ verwende, sondern in erster linie operator> overloading, namespaces, und besonderen Templates.
All das funktioniert doch. Dafür braucht es ja keine Standard-lib, das
macht alles der Compiler.
Oliver
Oliver schrieb:> Christoph Wiesmeier schrieb:>> Ist für micht nicht wirklich vergleichbar, da ich weniger die>> Objektorientierung von C++ verwende, sondern in erster linie operator>> overloading, namespaces, und besonderen Templates.>> All das funktioniert doch. Dafür braucht es ja keine Standard-lib, das> macht alles der Compiler.
In dem Punkt muss ich dir recht geben.
Habe aber auch die Standard-library kennen und lieben gelernt. Ich muss
auch zugeben dass ich mir nicht sicher bin wie viel tatsächlich ohne
dynamischen Speicher geht. Aber besonders bei den Algorithmen habe ich
da Hoffnung.
Christoph Wiesmeier schrieb:> @Johann L.>>Die aktuelle Release-Serie von GCC (4.8) unterstützt auch den>>ATxmega128A3U, ebenso AVR-Libc 1.8.0.>> Was gcc betrifft kann ich das nur bestätigen.> AVR-Libc 1.8.0 http://download.savannah.gnu.org/releases/avr-libc/> Funktionirt bei mir jedoch nicht.
Ok, ich hab bisher immer SVN trunk der 1.8.0 verwendet, weil diese
einige Bugfixes genenüber der 1.8.0 Release enthält, ohne die eine
Distribution mit avr-gcc 4.7+ nicht sinnvoll ist.
Selbst dynamischer Speicher ist ja nicht wirklich ein Problem. Man muß
halt eine eigene new- und delete-Implementierung beistellen, dann klappt
das auch. Da gibts hier im Forum und auch ausserhalb in den schon
mehrfach geführten Diskussionen zum C++ auf dem AVR Vorschläge.
Oliver
Johann L. schrieb:> Christoph Wiesmeier schrieb:>> @Johann L.>>>Die aktuelle Release-Serie von GCC (4.8) unterstützt auch den>>>ATxmega128A3U, ebenso AVR-Libc 1.8.0.>>>> Was gcc betrifft kann ich das nur bestätigen.>> AVR-Libc 1.8.0 http://download.savannah.gnu.org/releases/avr-libc/>> Funktionirt bei mir jedoch nicht.>> Ok, ich hab bisher immer SVN trunk der 1.8.0 verwendet, weil diese> einige Bugfixes genenüber der 1.8.0 Release enthält, ohne die eine> Distribution mit avr-gcc 4.7+ nicht sinnvoll ist.
Bist du dir sicher dass der xmega128a3u unterstützt wird.
Hab auch im svn etwas herum gesucht und nichts gefunden.
http://svn.savannah.nongnu.org/svn/avr-libc/trunk/avr-libc/ scheint ihn
nicht zu enthalten. Oder verwendest du ein anderes repo, wenn ja
welches?
Wasle schrieb:> einem größeren projekt bei dem ich vorhabe einen> ATxmega controller
Tu es nicht. Nimm einen anderen Controller mit den gleichen Specs.
Wasle schrieb:> Der letzte versuch mit c++ typte_traits zu arbeiten hat mich dazu> gebracht boost ein zu binden,
Ich muss das jetzt ganz ernsthaft fragen: Weißt du eigentlich, was du
tust? Also, hast du echte Erfahrung mit Mikrocontrollern der Größe des
Xmegas in einer Freestanding-Umgebung?
Weil, dass klingt alles so wie Großer Hacker will es einem kleinen
Microcontroller mal so richtig zeigen und die große Welt erklären. Wenn
du type_traits bei einem Microcontroller wie dem XMega brauchst, dann
hast du entweder den Überblick über deinen Code verloren (ganz schlecht
beim Embedded-Programmieren), oder du willst eine Show abziehen um zu
zeigen was für cleveren Code du schreiben kannst (der dann zwar schlecht
wartbar ist, aber Hauptsache clever und trickreich geschrieben ...).
Oben drauf dann noch Boost? Weil? Ja, warum eigentlich? Weil man zuviel
Platz in einem uC hat? Weil da ganz tolle, clevere Funktionen drin sind,
die man nie-nicht selber, in einfacher, verständlicher, wartbarer,
nachvollziehbarer Weise programmieren kann? So wie
Template-Metaprogramming (hust, hust)? Weil semi-nichtdeterministische
dynamische Speicherverwaltung in einem uC so viel Spaß macht?
Franz schrieb:> Wasle schrieb:>> einem größeren projekt bei dem ich vorhabe einen>> ATxmega controller>> Tu es nicht. Nimm einen anderen Controller mit den gleichen Specs.
Tu es nicht. Nimm einen anderen Controller mit deutlich erweiterten
Specs ;)
Full-Size C++ in der Variante 11 mit allem, was die Sprache hergibt,
wird auf Mikro-Mikros nichts. Nimm dir einen ausgewachsenen ARM, und
alles wird gut.
Oliver
Oliver schrieb:> Full-Size C++ in der Variante 11 mit allem, was die Sprache hergibt,> wird auf Mikro-Mikros nichts. Nimm dir einen ausgewachsenen ARM, und> alles wird gut.
C geht aber auch nicht auf AVR's, denn malloc,free,fopen,system gehen
auf denen auch nicht so gut.
Malte schrieb:> Wenn> du type_traits bei einem Microcontroller wie dem XMega brauchst
Was haben type_traits mit der Zielplattform zu tun? Wenn man
generischen, wiederverwendbaren Code schreiben möchte sind diese sehr
hilfreich. Da sie ja onehin nur zur Compiletime agieren, sind sie nicht
vom Speicher des Targets abhängig. Warum sollte zB so eine Hilfsfunktion
auf XMega grunsätzlich schlecht sein?
So kann man im User-Code recht praktisch einzelne Bits von Registern
setzen, unabhängig von der Registergröße. Dank inline und
Compiler-Optimierungen wird das auch schön kurz und effizient.
Dabei werden C++11 Features und type_traits verwendet.
Warum habe ich jetzt den Überblick über meinen Code verloren?
Malte schrieb:> Oben drauf dann noch Boost? Weil? Ja, warum eigentlich? Weil man zuviel> Platz in einem uC hat? Weil da ganz tolle, clevere Funktionen drin sind,> die man nie-nicht selber, in einfacher, verständlicher, wartbarer,> nachvollziehbarer Weise programmieren kann? So wie> Template-Metaprogramming (hust, hust)? Weil semi-nichtdeterministische> dynamische Speicherverwaltung in einem uC so viel Spaß macht?
Hier gilt das selbe wie für type_traits; die Boost MPL z.B. verbraucht 0
bytes Flash und 0 Bytes RAM, keine dynamische Speicherverwaltung, und
kann einem beim Aufbau von Funktionen wie oben oder anderer
Metaprogrammierung sehr helfen. Natürlich kann man das auch selber
programmieren, aber wozu, wenn man auch die fertige Implementation der
boost verwenden kann? Warum soll die etablierte boost Library nicht
wartbar oder wiederverwendbar sein?
Malte schrieb:> So wie> Template-Metaprogramming (hust, hust)? Weil semi-nichtdeterministische> dynamische Speicherverwaltung in einem uC so viel Spaß macht?
Wieso braucht mein obiges template Metaprogrammierungs-Beispiel
semi-nichtdeterministische Speicherverwaltung?
Dr. Sommer schrieb:> C geht aber auch nicht auf AVR's, denn malloc,free,fopen,system gehen> auf denen auch nicht so gut.
system ist sowieso nicht portabel.
Ansonsten: malloc und free, ausprobiert (welche Bugs sind dir übern
Weg gelaufen?), oder plapperst du nur nach?
Jörg Wunsch schrieb:> system ist sowieso nicht portabel.
system ist laut C-Standard vorhanden.
> Ansonsten: malloc und free, ausprobiert (welche Bugs sind dir übern> Weg gelaufen?), oder plapperst du nur nach?
Pingelalarm? Klar funktionieren tun die, nur ob das bei 2 KB RAM
wirklich sinnvoll sind ist... kontrovers.
Dr. Sommer schrieb:>> system ist sowieso nicht portabel.> system ist laut C-Standard vorhanden.
Das habe ich nicht in Abrede gestellt. Lies das oben nochmal.
Das standardisierte system() hilft dir überhaupt nicht, wenn du dann
nicht mehr portabel entscheiden kannst, ob du nun system("ls") oder
system("dir") ausführen musst, und wenn es gleich gar keinen vom
C-Standard gedeckten Weg gibt, das Ergebnis dieses Kommandos (mit
Ausnahme eines exit codes) zu nutzen.
>> Ansonsten: malloc und free, ausprobiert (welche Bugs sind dir übern>> Weg gelaufen?), oder plapperst du nur nach?> Pingelalarm? Klar funktionieren tun die, nur ob das bei 2 KB RAM> wirklich sinnvoll sind ist... kontrovers.
Du hast aber eine Pauschalaussage gemacht, die ganze avr-libc
betreffend.
Es gibt ja nicht nur AVRs mit 2 KiB SRAM, sondern die gibt es bis zu
32 KiB. Das ist die halbe Menge dessen, was ein Prozess auf einer
PDP-11 seinerzeit zur Verfügung hatte, und da wäre keiner auf die Idee
gekommen, malloc() als unbrauchbar oder unwichtig einzustufen.
Dr. Sommer schrieb:> Was haben type_traits mit der Zielplattform zu tun? Wenn man> generischen, wiederverwendbaren Code schreiben möchte
Die Mär vom wiederverwendbaren Code ...
Die Realität sieht anders aus. Selber macht man das dann doch nicht,
weil der Code woanders dann nicht ganz passt oder - sehr beliebt - weil
man den eigenen cleveren Code später selber nicht mehr versteht.
Andere nehmen den Code auch nicht, weil der nicht richtig dokumentiert,
getestet und verständlich ist.
Und so ist all der schöne Aufwand, den man in die Wiederverwendbarkeit
gesteckt hat für die Katz.
> sind diese sehr> hilfreich. Da sie ja onehin nur zur Compiletime agieren, sind sie nicht> vom Speicher des Targets abhängig. Warum sollte zB so eine Hilfsfunktion> auf XMega grunsätzlich schlecht sein?template <typename T>> stm32_always_inline T mask (const uint8_t count) {> return (T { 1 } << count) - 1;> }>> template <typename T>> using Plain = typename std::remove_reference<typename> std::remove_volatile<T>::type>::type;>> template <typename T>> inline void setBits (T& reg, const uint8_t bit, const uint8_t size,> const Plain<T> val) {> const Plain<T> bmask = mask<Plain<T>> (size);> const Plain<T> base = reg & ~(bmask << (size * bit));> reg = base | (val << (size * bit));> }>> int main () {> // Setze Bits 7-9 vom Register auf 5.> setBits (someHardwareRegister, 7, 3, 5);> }So kann man im User-Code recht praktisch einzelne Bits von Registern> setzen, unabhängig von der Registergröße. Dank inline und> Compiler-Optimierungen wird das auch schön kurz und effizient.> Dabei werden C++11 Features und type_traits verwendet.> Warum habe ich jetzt den Überblick über meinen Code verloren?
Das ist genau die Art von Angeber-Code den ich meine. Ja, kann man
machen. Bringt einem aber nicht weiter gegenüber einfachem C, nur dass
man der Welt mal gezeigt hat, dass man in der Lage ist die
weltkomplizierteste setBits()-Funktion zu schreiben. Gratulation.
Malte schrieb:> Und so ist all der schöne Aufwand, den man in die Wiederverwendbarkeit> gesteckt hat für die Katz.
Wenn du es nicht hinbekommst, vielleicht. Ich kann meinen Code wunderbar
dokumentieren, verstehen und wiederverwenden.
> Das ist genau die Art von Angeber-Code den ich meine. Ja, kann man> machen. Bringt einem aber nicht weiter gegenüber einfachem C, nur dass> man der Welt mal gezeigt hat, dass man in der Lage ist die> weltkomplizierteste setBits()-Funktion zu schreiben. Gratulation.
Nur weil du sie nicht verstehst? Wie würdest du das denn in einfachem C
machen? Mit einem langen hässlichen Makro in einer Zeile, mit all den
ekligen bekannten Nebenwirkungen?
Dr. Sommer schrieb:> Wie würdest du das denn in einfachem C machen? Mit einem langen> hässlichen Makro in einer Zeile, mit all den ekligen bekannten> Nebenwirkungen?
Es gibt auch inline-Funktionen, wenn dir Makros zu hässlich sind.
Ansonsten ist das Bitgewurschtel sowieso immer auf der untersten
Abstraktionsebene, und das ist genau die, die man beim Wechsel der
Plattform austauschen muss. Da kann man dann (was dein Code nicht
kann) auch gleich noch berücksichtigen, ob die Zielplattform zum
Setzen eines Bits vielleicht ein eigenständiges "bit-set"-IO-Register
hat (ARM, Xmega).
Was willst du hier eigentlich? Was haben deine Auslassungen denn noch
mit der Frage des TE zu tun? Zuerst willst du uns erzählen, dass man
C auf einem Controller nicht benutzen kann, weil es dort kein system()
gibt, und dann tust du so, als könnte man sowas nur programmieren,
indem man mit den neuesten C++11-Features nur so um sich wirft.
Jörg Wunsch schrieb:> Es gibt auch inline-Funktionen, wenn dir Makros zu hässlich sind.
Aber die haben in C feste Parametertypen (C kann keine Templates und
kein Overloading).
> Ansonsten ist das Bitgewurschtel sowieso immer auf der untersten> Abstraktionsebene, und das ist genau die, die man beim Wechsel der> Plattform austauschen muss.
Kommt drauf an, dieser Code ist ziemlich generisch.
> Da kann man dann (was dein Code nicht> kann) auch gleich noch berücksichtigen, ob die Zielplattform zum> Setzen eines Bits vielleicht ein eigenständiges "bit-set"-IO-Register> hat (ARM, Xmega).
Das würde ich auf noch einer Ebene drunter machen, auf der
Hardware-Zugriffs-Ebene, und nicht auf der Bitverarbeitungsebene. Aber
auch wenn nicht, dieser Code ist doch dann ein hübsches Interface, unter
dem man die Implementierung abändern kann (Wiederverwendbarkeit des
darauf aufsetzenden Codes).
> Was willst du hier eigentlich?
Dem "Malte" erläutern, dass C++(11) und type_traits nicht grundsätzlich
schlecht auf Mikrocontrollern ist, auch nicht auf kleinen AVR's.
> Zuerst willst du uns erzählen, dass man> C auf einem Controller nicht benutzen kann, weil es dort kein system()> gibt, und dann tust du so, als könnte man sowas nur programmieren,> indem man mit den neuesten C++11-Features nur so um sich wirft.
Das mit C war natürlich ein Vergleich, weil ja behauptet wurde, dass man
C++ grundsätzlich nicht verwenden kann, weil einige der Features nicht
"Mikrocontroller-geeignet" sind; mit der gleichen Logik wäre C dann aber
auch ungeeignet.
Man kann natürlich auch alles in Assembler oder Brainf*ck programmieren,
aber Features von höheren Sprachen wie C und C++ (C++11 erst recht)
helfen dabei.
Kindergärtner schrieb:> Das würde ich auf noch einer Ebene drunter machen, auf der> Hardware-Zugriffs-Ebene, und nicht auf der Bitverarbeitungsebene.
So'n Quatsch.
Wie willst du das eine Ebene drunter machen, wenn es um Dinge wie ein
Register zum Setzen von Bits geht (also sowas wie PORTA->OUTSET)?
Jörg Wunsch schrieb:> Kindergärtner schrieb:>> Das würde ich auf noch einer Ebene drunter machen, auf der>> Hardware-Zugriffs-Ebene, und nicht auf der Bitverarbeitungsebene.>> So'n Quatsch.>> Wie willst du das eine Ebene drunter machen, wenn es um Dinge wie ein> Register zum Setzen von Bits geht (also sowas wie PORTA->OUTSET)?
Eigentlich kann man auf C-Ebene nicht alles ausdrücken, was man braucht.
Etwa wenn die Änerungen an einem Port atomar sein sollen.
Für einzelne Bits ist das zwar der Fall, falls SBI / CBI vorhanden sind
(AVR) und der Wert des zu schreibenden Bits bekannt ist. Aber
garantieren tut das niemand. Bei einem Toggle wird's schon sehr
speziell, wenn man das als XOR hinschreibt wird der Compiler es auch als
XOR implementieren, nicht als SBI auf PINx wie das bei manchen AVRs
möglich ist.
Garantieren kann man das nur per (Inline) Assembler oder per
entsprechender Builtins, etwa __builtin_avr_atomic_or -- falls es sowas
gäbe.
Hallo alle - da will ich hier auch mal meinen Senf zum Besten geben:
Christoph Wiesmeier schrieb:> Bist du dir sicher dass der xmega128a3u unterstützt wird.> Hab auch im svn etwas herum gesucht und nichts gefunden.> http://svn.savannah.nongnu.org/svn/avr-libc/trunk/avr-libc/ scheint ihn> nicht zu enthalten. Oder verwendest du ein anderes repo, wenn ja> welches?
Ich programmiere derzeit viel fuer ATxmega128a3u - mit den Atmel patches
wird dieser auch unterstuetzt.
Binaries kannst du dir z.B. hier downloaden:
http://matrixstorm.com/avr/tinyusbboard/#asmorc
MfG
Jörg Wunsch schrieb:> Wie willst du das eine Ebene drunter machen, wenn es um Dinge wie ein> Register zum Setzen von Bits geht (also sowas wie PORTA->OUTSET)?
Es wäre zB. denkbar, sich eine Wrapper-Klasse für Register zu
definieren, die die Operatoren |, &, ^, = überlädt, und sich somit
(fast) wie eine Register-Variable verhält, aber bei den Operationen
entsprechende Bitmasken konstruiert und diese beim zuweisen verwendet,
um die Register atomar per Bit-Banding o.ä. zu setzen. Dann würde man
Instanzen dieser Klasse anstelle der Register-Definitionen verwenden.
Die Berechnungen würde man mit constexpr und inline zur Compile-Zeit
durchführen. Die innere Implementation wäre dann Plattform-Spezifisch
(bit-banding bei ARM, sbi/cbi bei AVR etc.). Code, der diese Klasse
nutzt könnte dann plattformunabhängig effizient atomare Register
verwenden mit (fast?) "nativer" Syntax. O.g. setBits-Funktion könnte man
vermutlich unverändert auch auf Instanzen davon anwenden ("statische
Polymorphie" / "Concept").
Dr. Sommer schrieb:> Es wäre zB. denkbar, sich eine Wrapper-Klasse für Register zu definieren
Ja.
Langsam stellt sich mir aber wirklich die Frage: warum einfach, wenn's
auch umständlich geht?
Fast immer muss man auf dieser Ebene beim Wechsel der Plattform ohnehin
den Code anpassen. Da kann man das auch alles leicht und überschaubar
schreiben.
Das Einzige, wo derartige Verrenkungen vielleicht noch irgendwie
sinnvoll sind, sind Sourcecode-Bibliotheken wie die für HD44780, bei
denen man möglichst flexibel auf die Konfiguration des Benutzers
eingehen können möchte und trotzdem auf eine große Zahl von
Architekturen portierbar bleiben.