Hallo,
ich möchte gerne mit der AVR C-Programmierung unter Linux beginnen.
Unter Windows ging das auf Anhieb mit dem Atmel Studio ohne Probleme.
Ziel: User Led zum blinken bringen ;)
Linux Distribution: Fedora 33, diese kann ich bei Bedarf gerne wechseln.
Folgendes Board habe ich mir zugelegt: ATtiny3217 Xplained Pro
Ich habe mir die Toolchain über den Paketmanager heruntergeladen. Dann
habe ich gemerkt dass die neueren Mikrocontroller nicht unterstützt
werden. Hierzu habe ich mir dann die avr-libc3 herunter geladen, wenn
ich aber als mmcu den attiny3217 oder avrxmega3 angebe, bekomme ich zum
einen die Warnung dass der Typ nicht bekannt ist: "device type not
defined"
Mich verwirren Momentan schon die gcc-Sorten:
gcc: von gnu, hier ist der ATtiny3217 aufgelistet
https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
avr-gcc: über Paketmanager, hier keine ATtiny3217 Unterstützung
https://fedoraproject.org/wiki/Packages_For_Embedded_Development
Hier wird allerdings auf die gnu-Seiten verwiesen!?
avr-gcc: von der Seite Microchip,
Hier ist der ATtiny3217 nicht aufgelistet
http://ww1.microchip.com/downloads/archive/avr8-gnu-toolchain-3.4.3.1072-readme.pdf
Vielen Dank
Da steht alles, was ich dazu weiß.
http://stefanfrings.de/avr_tools/index.html
Außer eins noch: Arch Linux enthält immer sehr aktuelle Compiler. Aber
das System ist eher etwas für Profis die sich mit Linux sehr gut
auskennen oder wollen.
Nur so als Tip: Auch ich nutze Linux (Ubuntu) und als IDE existiert
MPLAB (von Microchip). Die liefern auch einen Compiler (XC8). Die
Toolchain ist frei wählbar (ich toggle oft zwischen gcc und XC8 hin und
her).
Droid E. schrieb:> Mich verwirren Momentan schon die gcc-Sorten:> gcc: von gnu, hier ist der ATtiny3217 aufgelistet> https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html
Das ist die offizielle Doku vom GCC und bezieht sich immer auf die
neueste Version, momentan also auf v10. Hinzugefügt wurde der Support
in v8, siehe Release Notes:
http://gcc.gnu.org/gcc-8/changes.html#avr
Den Unterschied sieht man in den Dokus zu den verschiedenen Versionen,
z.B. v8.3 vs. v7.5:
http://gcc.gnu.org/onlinedocs/gcc-8.4.0/gcc/AVR-Options.htmlhttp://gcc.gnu.org/onlinedocs/gcc-7.5.0/gcc/AVR-Options.html
"Support" auf Compilerebene bedeutet nur, dass avr-gcc eine Specs-Datei
für das Device mitliefert — und natürlich dass die Familie unterstützt
wird, hier avrxmega3. Ein Specs-File ist eine Textdatei, welche die
Kommandozeilenparameter für die verschiedenen Sub-Tools beschreibt wie
Compiler (cc1, cc1plus, lto1), Assembler (as), Linker (ld). Diese Datei
kann man prinzipiell auch selbst beisteuern und dem Compiler sagen, wo
sie liegt. Für alte Versionen ≤ v7 kann man die Devices als avrxmega2
beschreiben; ist zwar suboptimal aber avrxmega3 gibt's ja erst ab v8.
Compilerversion kann man anzeigen lassen mit gcc -v oder gcc
--version.
Eine Toolchain besteht aber aus mehr als dem Compiler; insbesondere
gehört auch die avr-libc dazu, welche Device-Header, Startup-Code und
Device-Lib liefert, für einen ATtiny3217 also iotn3217.h,
crtattiny3217.o, libattiny3217.a und natürlich avrxmega3
Multilib-Varianten für libc.a etc.
Die avr-libc unterstützt zwar avrxmega3, aber für entsprechende Devices
gibt es nur Patches, für die Jörg noch keine Zeit hatte sie einzubauen.
Unpraktischerweise gibt's da Konflikte mit den Patches für
math+double64, und die Konflikte bearbeitet man am besten, indem man
zuerst math+double64 einbaut und erst danach die Patches für die neuen
Devices.
Dann gibt es noch avr-libc3 auf github, ein Branch, der die Devices
unterstützen will, und der entstand weil jemandem der Fortschritt der
avr-libc zu langsam war. Wie gut das supported und getestet und
maintained ist, kann ich nicht sagen.
Und schließlich gibt's noch die Distributionen von Atmel/Microchip,
welche i.d.R. mehr Devices unterstützen als andere Distributionen
gleicher Version.
Man findet auch Device-Packs, welche die benötigten Files enthalten,
Link dazu hab ich aber keinen.
Ich habe das ganze jetzt mal unter Ubuntu getestet, ich konnte jetzt
ohne Probleme compilieren und alle erforderlichen Dateien wurden
erstellt.
Folgende Dateien musste ich mir herunter laden, in der Suche auf der
Seite einfach den gesuchten Mikrocontroller eingeben, die passende Datei
wird dann vorgeschlagen:
https://packs.download.microchip.com/
Jetzt wollte ich das ganze mit Visual Studio Code bearbeiten - anstatt
mit einem Texteditor. Unter includePath (diese befindet sich in der
C/C++ Extension) muss folgender Pfad angegeben werden, damit die
include-Dateien nicht Rot markiert werden:
1
"includePath": [
2
"${workspaceFolder}/**",
3
"/usr/lib/avr/include"
4
],
Folgendes Problem habe ich noch, wenn in meiner main.c so etwas steht
wie:
1
PORTB.DIR |= PIN4_bm;
dann kennst VSCODE natürlich die Register nicht ;)
Hierzu kann ich in meiner main.c noch folgendes definieren:
1
#ifndef __AVR_ATtiny3217__
2
#define __AVR_ATtiny3217__
3
#endif
PROBLEM: Die "__AVR_ATtiny3217__" wird in der io.h nicht abgefragt, so
dass die passende *.h includiert wird...
Idee?
Eher -isystem anstatt -I weil es sich um Systemheader handelt.
> Folgendes Problem habe ich noch, wenn in meiner main.c so etwas steht> wie:>
1
PORTB.DIR |= PIN4_bm;
dann kennt VSCODE natürlich die
> Register nicht ;)>> Hierzu kann ich in meiner main.c noch folgendes definieren:
1
> #ifndef __AVR_ATtiny3217__
2
> #define __AVR_ATtiny3217__
3
> #endif
Das sollte man auf keinen Fall machen; das sind System-Makros, und die
einfach so zu setzen kann Probleme bereiten; etwa wenn man den Code für
nen anderen Controller nimmt.
Die Tools setzen das Makro im Specs-File und damit effektiv per -D
Option (also nicht mehr als Built-in Makro wie boch bis v4.9):
1
*cpp_mcu:
2
-D__AVR_ATtiny3217__
Das kennt VScode natürlich nicht. Außerdem steht das io<device>.h hier
nicht in /usr/lib/... sondern in /home/droid/... Vielleicht hilft das
ja?
Droid E. schrieb:> Hierzu kann ich in meiner main.c noch folgendes definieren:#ifndef> __AVR_ATtiny3217__> #define __AVR_ATtiny3217__> #endif
Ich glaube das habe ich eleganter gelöst, durch einen Eintrag in
<projekt>/.vscode/c_cpp_properties.json
Hallo,
damit das Headerfile wie gewohnt gefunden wird muss du das in der io.h
ergänzen. Das wurde schon lange nicht mehr aktualisiert. Aktuelle µC
muss man immer selbst eintragen. Eine geeignete Position wäre nach dem
letzten ATtiny 1634 ergänzt zu 2 Zeilen ...
1
#elif defined (__AVR_ATtiny3217__)
2
# include <avr/iotn3217.h>
Das Headerfile selbst fehlt natürlich noch. Das kommt in den Pfad wo
auch die io.h liegt. In deinem Toolchain Verzeichnis \avr\include\avr\
Dort siehste dann schon alle anderen Headerfiles liegen. Rausnehmen
tuste das aus dem Atmel Devicepack.
Veit D. schrieb:> damit das Headerfile wie gewohnt gefunden wird muss du das in der io.h> ergänzen.
Braucht man nicht, denn am Ende von io.h steht der Fallback
Es braucht also nur __AVR_DEV_LIB_NAME__ richtig defined zu sein, und
das wiederum sollte das Specs-File erledigen.
Allerdings hat die avr-libc eine ziemlich blöde Namenskonvention für
io*.h, die sich nicht einfach per -mmcu= ergibt und auch keiner
einfachen Heuristik folgt.
Wenn man also ein eigenes Specs hat, dann sollte dessen Ende so
aussehen:
1
# AVR-LibC's avr/io.h uses the device specifying macro to determine
2
# the name of the device header. For example, -mmcu=atmega8a triggers
3
# the definition of __AVR_ATmega8A__ and avr/io.h includes the device
4
# header 'iom8a.h' by means of:
5
#
6
# ...
7
# #elif defined (__AVR_ATmega8A__)
8
# # include <avr/iom8a.h>
9
# #elif ...
10
#
11
# If no device macro is defined, AVR-LibC uses __AVR_DEV_LIB_NAME__
12
# as fallback to determine the name of the device header as
13
#
14
# "avr/io" + __AVR_DEV_LIB_NAME__ + ".h"
15
#
16
# If you provide your own specs file for a device not yet known to
17
# AVR-LibC, you can now define the hook macro __AVR_DEV_LIB_NAME__
18
# as needed so that
19
#
20
# #include <avr/io.h>
21
#
22
# will include the desired device header. For ATmega8A the supplement
wobei die Specs, die avr-gcc mitbringt, so aussehen — schlichtweg weil
man nicht das verkorxte avr-libc Naming im Compiler raten will. Es wird
also davon ausgegangen, dass die avr-libc (bzw. deren io.h) das Device
kennt.
1
...
2
*cpp_avrlibc:
3
-D__AVR_DEVICE_NAME__=attiny3217
4
...
> Das wurde schon lange nicht mehr aktualisiert.
Braucht man wie gesagt auch nicht :-)
Veit D. schrieb:> Microchip Distribution? Meinst du vielleicht deren MPLAB X IDE?
Soweit ich weiß hat µChip 2 AVR-Toolchains im Angebot: Einen avr-gcc und
im XC8 einen verkrüppeltem avr-gcc, wo man für Freischaltung aller
Optimierungen blechen muss.
Hab ich aber nie verwendet oder getestet oder mir angeschaut, von mir
hommt da nichtmal Halbwissen... Da fragst besser jemand, der das
verwendet.
Die Toolchains, die ich hab, sind bis auf einige wie WinAVR alle selbst
generiert, weil ich da oft eigene Patches drinne hab oder es noch keine
offizielle Release gibt. In
https://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20(Win32)/
gibt es auch ein Linux Build, aber ansonsten hab ich da nur Mingw32
Canadian Crosses.
Evtl. auch interessant für jemand, der double64 verwenden will, weil in
der v10 die Patches drin sind, die in der avr-lic noch nicht drinne sind
(und auch nicht in der avr-libc3).
@gjlayde: Es tut mir leid. aber ich habe von dem was du geschrieben hast
leider nichts verstanden! Obwohl dein Ansatz mich sehr interessiert,
zumindest scheint dort die Lösung zu liegen :( !
Wenn ich in der Datei "io.h" dem Ordner "/usr/lib/avr/include/avr" um
folgende Zeilen ergänze, dann findet VSCODE auch folgende Register
"PORTB"
Anbei auch meine C/C++ Konfigurationsdatei für VSCODE
1
{
2
"configurations": [
3
{
4
"name": "Linux",
5
"includePath": [
6
"${workspaceFolder}/**"
7
, "/usr/lib/avr/include"
8
],
9
"defines": [
10
//"F_CPU=3333333"
11
, "__AVR_ATtiny3217__"
12
],
13
"cStandard": "gnu17",
14
"cppStandard": "c++17",
15
"intelliSenseMode": "gcc-x86",
16
"compilerPath": "/usr/bin/avr-gcc"
17
}
18
],
19
"version": 4
20
}
@stefanus: Leider muss "F_CPU=3333333" in der main.c bzw. vor "#include
<util/delay.h>" stehen, sonst bekomme ich eine Warnung: "warning "F_CPU
not defined for <util/delay.h>"
Und außerdem nervt das -B bzw -I im Makefile:
Das mit dem -I.. kann jetzt aber wegen dem kopieren und ergänzen um io.h
entfernt werden?
In dem Ordner "Microchip.ATtiny_DFP.2.5.116" sind auch diese "specs" und
zwei andere Dateien vorhanden:
gcc/dev/attiny3217/device-specs/specs-attiny3217
gcc/dev/attiny3217/avrxmega3/crtattiny3217.o
gcc/dev/attiny3217/avrxmega3/libattiny3217.a
Edit: Nun kann auch -B verschwinden, ich habe diese in den folgenden
Ordner kopiert:
/usr/lib/avr/lib/avrxmega/crtattiny3217.o
/usr/lib/avr/lib/avrxmega/libattiny3217.a
Edit: habe gerade auch flashen können:
Johann L. schrieb:> Die Toolchains, die ich hab, sind bis auf einige wie WinAVR alle selbst> generiert, weil ich da oft eigene Patches drinne hab oder es noch keine> offizielle Release gibt. In>> https://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20(Win32)/>> gibt es auch ein Linux Build, aber ansonsten hab ich da nur Mingw32> Canadian Crosses.>> Evtl. auch interessant für jemand, der double64 verwenden will, weil in> der v10 die Patches drin sind, die in der avr-lic noch nicht drinne sind> (und auch nicht in der avr-libc3).
Ja, darüber wollte ich mit dir sowieso noch sprechen...
Der -mdouble=64 ist aus deiner Feder, oder?
Leider ist da wohl noch ein Fehler am rumdümpeln.
Ohne -mdouble=64 läuft es durch, mit -mdouble=64 bricht der Linker ab.
Fehlermeldung:
Hallo,
@ Johann:
wir reden von unterschiedlichen Wissensständen, da weißt du klar mehr
wie ich, aber ich kann erzählen wie ich das aktuell mache. Sozusagen
Praxis erprobt. Nach unserem damaligen Thread baue ich mir meine
Toolchain zusammen. Danach fehlen natürlich viele neuere Controller,
weil das nun einmal so ist. Für die neueren ATmegas und ATtiny kopiere
ich aus den Atmel Devicepacks die Header- und crt*.o und lib*.a Dateien
raus und kopiere diese in entsprechende Ordner der Toolchain.
Bei ganz frischen AVR128DB zum Bsp. müssen noch die device-specs kopiert
werden.
Danach ergänze ich die io.h um entsprechende Einträge, weil sonst Atmel
Studio meckert, weil es ansonsten die ganzen Controller typischen
defines etc. nicht kennt.
Dafür habe ich mir Batchdateien angelegt die das erledigen.
Nach alledem kann ich die Toolchain für Atmel Studio und für die Arduino
IDE verwenden. Das funktioniert.
Wenn ich das alles nicht mache, kann ich trotz vorhandener spec Dateien
für µC wie den hier ATtiny3217 nichts testweise kompilieren. Selbst für
einen ATmega328PB würde nichts funktionieren.
>Es wird also davon ausgegangen, dass die avr-libc (bzw. deren io.h) das Device
kennt.
Genau das ist ja nicht der Fall, man muss also wie ich das mache das
io.h selbst um Einträge ergänzen, weil ansonsten die include Einträge
fehlen. Alle Controller die nicht in der io.h eingetragen sind, kann man
laut meiner Meinung nicht verwenden. Selbst wenn alle notwendigen
Dateien an Ort und Stelle sind.
@ Alexander:
> https://www.microchip.com/mplab/avr-support/avr-and-sam-downloads-archive
Ja die Toolchains sind hornalt.
MPLABS X gibts für Linux.
@ Droid:
Nimm erstmal die Toolchain von Johann von seinem Link. Die sollte ja
funktionieren. :-)
Oder probierst nochmal wie ich das mache.
iotn3217.h Headerfile:
QUELLE: Atmel.ATtiny_DFP.1.8.332.atpack\include\avr\
ZIEL: deinToolchainOrdner\avr\include\avr\
Bei den crt*.o und lib*.a Files musste aufpassen ob in short call kommt
oder nicht.
Beim ATtiny3217 nicht. Nicht in den short-calls Unterordner.
QUELLE: Atmel.ATtiny_DFP.1.8.332.atpack\gcc\dev\attiny3216\avrxmega3\
ZIEL: deinToolchainOrdner\avr\lib\avrxmega3\
> /usr/lib/avr/lib/avrxmega/crtattiny3217.o> /usr/lib/avr/lib/avrxmega/libattiny3217.a
Das sollte bestimmt der "avrxmega3" Ordner werden ;-)
Veit D. schrieb:> man muss also wie ich das mache das io.h selbst um Einträge ergänzen,> weil ansonsten die include Einträge fehlen.
Wenn man das machen MUSS, heißt das, im Specs-File
1
__AVR_DEV_LIB_NAME__
zu definieren funktioniert NICHT? Wenn du z.B. ein in io.h unbekanntes
device hast, und definierst z.B. auf der Kommandozeile das
Makro korrekt, müsste das doch auch gehen?
Arduino Fanboy D. schrieb:> Johann L. schrieb:>> Die Toolchains, die ich hab, sind bis auf einige wie WinAVR alle selbst>> generiert, weil ich da oft eigene Patches drinne hab oder es noch keine>> offizielle Release gibt. In>>> https://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20(Win32)/>>>> gibt es auch ein Linux Build, aber ansonsten hab ich da nur Mingw32>> Canadian Crosses.>>>> Evtl. auch interessant für jemand, der double64 verwenden will, weil in>> der v10 die Patches drin sind, die in der avr-lic noch nicht drinne sind>> (und auch nicht in der avr-libc3).>> Ja, darüber wollte ich mit dir sowieso noch sprechen...> Der -mdouble=64 ist aus deiner Feder, oder?> Leider ist da wohl noch ein Fehler am rumdümpeln.>> Ohne -mdouble=64 läuft es durch, mit -mdouble=64 bricht der Linker ab.> Fehlermeldung:>
> Fehler beim Kompilieren für das Board Arduino Uno.
26
>
>> Testprogramm im Anhang.
Boah ist das bescheuert; wenn man da die Quelle copiert, hat man
Zeilennummern im Quelltext! Wer überlegt sich denn sowas???
Aber egal, Arduino hab ich eh nicht und kann mit der Quelle nix
anfangen.
Ich hab mal folgendes genommen:
1
doublea=1.23;
2
3
template<typenameT>Tfunktion()
4
{
5
return42;
6
}
7
8
volatilecharvC;
9
volatilefloatvF;
10
volatiledoublevD;
11
12
voidf(constchar&x){vC=x;}
13
voidf(constfloat&x){vF=x;}
14
voidf(constdouble&x){vD=x;}
15
voidd(doublex){vD=x;}
16
17
intmain()
18
{
19
f(funktion<char>());
20
f(funktion<float>());
21
f(funktion<double>());
22
d(funktion<double>());
23
d(funktion<float>());
24
d(vF);
25
a+=10;
26
a*=20;
27
return0;
28
}
Was sich problemlos übersetzen lässt. Compiliert hab ich mit
Fat LTO ist nur damit main.s Assembly enthält und nicht nur LTO-Code.
Ist alles wie erwartet, und funktioniert auch ohne LTO, ohne Debug-Info,
mit -fno-use-linker-plugin, etc.
Bei dir fliegt ja nicht der Linker raus, sondern der LTO-Compiler (der
vom Linker per Plugin aufgerufen wird). Bist du sicher, dass alle
Objekte und Bibliotheken, die Arduino so zusammenbastelt, richtig
übersetzt sind, d.h. _alle_ Bibliotheken und Objekte müssen mit
-mdouble=64 erzeugt worden sein!
Falls das nicht der Fall ist, könnte LTO-Code inkompatibel sein, d.h. es
gibt Byte-Code mit 64-Bit Encoding für double, und es gibt Byte-Code mit
32-Bit Encoding.
Funktioniert es denn mit long double? (Mein Build ist configured mit
--with-long-double=64, d.h. long double ist 64 Bit ohne dass extra
Multilib-Option beim Compilen / Linken gesetzt werden muss).
Udn mit welchem Multilib-Set, werden die *.a und *.o generiert, die
Arduino verwendet?
Hast du ein Minimalbeispiel ohne das ganze Arduino-Gewusel?
Johann L. schrieb:> Udn mit welchem Multilib-Set, werden die *.a und *.o generiert, die> Arduino verwendet?
Arduino selber hat keine *.a oder *.o im Bauch.
Außer in den Toolchains, aber da verwende ich ja die aus deinem Link.
Der Rest wird komplett aus Quellcode generiert.
Johann L. schrieb:> Boah ist das bescheuert; wenn man da die Quelle copiert, hat man> Zeilennummern im Quelltext! Wer überlegt sich denn sowas???
Hmm.
Außerhalb meiner Verantwortung.
Zudem kann ich markieren und ausschneiden, ohne Zeilennummern.
Tests müssen leider noch ein paar Stunden warten, da gerade außer
Reichweite.
Johann L. schrieb:> Veit D. schrieb:>> man muss also wie ich das mache das io.h selbst um Einträge ergänzen,>> weil ansonsten die include Einträge fehlen.>> Wenn man das machen MUSS, heißt das, im> Specs-File
1
__AVR_DEV_LIB_NAME__
zu definieren funktioniert
> NICHT? Wenn du z.B. ein in io.h unbekanntes device hast, und definierst> z.B. auf der Kommandozeile das Makro korrekt, müsste das doch auch> gehen?
Hallo,
ich kann nur von meinem Windows mit Atmel Studio und Arduino IDE reden.
Fehlt der Eintrag in der io.h geht nichts. Dann wird gemeckert das die
Controller spezifischen defines fehlen. Unter Linux auf Kommandozeile
habe ich das noch nicht probiert. Selbst wenn das funktioniert, wäre das
doch nur lästig das jedesmal in die Kommandozeile eingeben zu müssen.
Generell überlegt, warum sollte das dort anders sein wenn es die gleiche
Toolchain ist. Kann ich mir aktuell nicht vorstellen. :-) Ich denke die
io.h ist genau dafür da eine zentrale Stelle zu sein wo nachgeschaut
wird wie das Headerfile heißt was benötigt wird. Warum soll die nicht
genutzt werden?
Habe das soeben nochmal ausprobiert. Den ATmega4809 in der io.h
auskommentiert und in Atmel Studio kompilieren lassen. Geht nicht.
"warning "device type not defined" [Wcpp]
und die Liste welche defines fehlen
Toolchain ist mit avr-gcc 10.2.0 und frischen binutils 2.36.1 / avr-libc
gebaut wurden.
Veit D. schrieb:> Habe das soeben nochmal ausprobiert. Den ATmega4809 in der io.h> auskommentiert und in Atmel Studio kompilieren lassen. Geht nicht.
Und wo und wie hast du __AVR_DEV_LIB_NAME__definiert?
> ich kann nur von meinem Windows mit Atmel Studio und Arduino IDE reden.
Es geht dabei nur darum, die io.h zu sehen bekommt, welche IDE du
verwendest oder welches OS ist egal.
> Fehlt der Eintrag in der io.h geht nichts. Dann wird gemeckert das die> Controller spezifischen defines fehlen. Unter Linux auf Kommandozeile> habe ich das noch nicht probiert. Selbst wenn das funktioniert, wäre das> doch nur lästig das jedesmal in die Kommandozeile eingeben zu müssen.
Ich hatte die Kommandozeile vorgeschlagen, weil das einfach zu testen
ist, und du sagtest dass du dich nicht gut auskennst.
Normal würde man das im Specs-File machen, und das braucht man nur 1× zu
machen. Oder der Ersteller der Specs hat's schon richtig gemacht und
das Makro entsprechend seiner ioxxx.h definiert.
> Generell überlegt, warum sollte das dort anders sein wenn es die gleiche> Toolchain ist. Kann ich mir aktuell nicht vorstellen. :-)
Ist auch nicht anders. Hat mich nur gewundert, weil du sagtest, dass
das NICHT funktioniert: io.h zu ändern sei der einzige Weg hattest du
ja behauptett. Und das trifft m.E. nicht zu.
> Ich denke die io.h ist genau dafür da eine zentrale Stelle zu sein> wo nachgeschaut wird wie das Headerfile heißt was benötigt wird.
Ja.
> Warum soll die nicht genutzt werden?
Die WIRD genutzt, aber sie auf ZWEI Arten genutzt werden:
1) Es wird __AVR_DEV_LIB_NAME__=m4809 definiert irgendwo zum Beispiel
auf der Kommandozeile oder bevorzugt im specs-atmega4809, und die io.h
braucht nicht geändert zu werden. Gleichwohl ist die io.h die Stelle,
die dieses Makro auswertet und in #include <iom4809.h> transformiert.
2) Du erweiterst io.h händisch um #ifdef __AVR_ATmega4809__ und
explizites #include <iom4809.h> oder wie auch immer das Ding benannt
wurde.
Weil bei 1) keine Systemdateien geändert werden müssen, ist es der
bevorzugte Ansatz. Wenn du z.B. kein root-Passwort hast geht 2) i.d.R.
nicht.
Dann habe ich folgenden Test gemacht. Den ATtiny3127 in meiner io.h
auskommentiert. Kompiliert -> erwartete Fehlermeldung.
Dann das spec file vom 3217 wie du oben gezeigt hast geändert.
Kompiliert, andere Fehlermeldung
Übrigens habe ich unter Windows als Standard User auch keine
Zugriffsrechte auf die device-specs. Nur sehe ich das in allen Punkten
als Remis. Weil man entweder bei der installierten Toolchain überall
keine Zugriffsrechte ohne Admin hat. Oder man sowieso seine eigene
aktuellere Toolchain hat und damit sowieso vollen Zugriff. Meinste nicht
auch?
Aktuell sehe ich den Weg über die io.h am Einfachsten. Soweit lehne ich
mich aus dem Fenster und behaupte das ist der Einfachste Weg der auf
Anhieb funktioniert. Meinste nicht auch?
Aus der Betrachtung meiner einfachen Sicht der Dinge. :-)
Veit D. schrieb:> Dann das spec file vom 3217 wie du oben gezeigt hast geändert.> Kompiliert, andere Fehlermeldung> .../avr/io***.h:> Invalid argument
Natürlich nicht *** wörtlich!
Preisfrage: Durch was muss *** ersetzt werden, damit sich der Dateiname
des Headers ergibt?
> Error pasting "io" and "*" does not give a valid preprocessing token
Johann L. schrieb:> Bist du sicher, dass alle> Objekte und Bibliotheken, die Arduino so zusammenbastelt, richtig> übersetzt sind, d.h. alle Bibliotheken und Objekte müssen mit> -mdouble=64 erzeugt worden sein!
Meinen Dank dafür!
So bin endlich zu den ersten Tests gekommen!
Und ja, das war die Lösung!
Jetzt auch die C Quellen, nicht nur die C++ Quellen, mit -mdouble=64
übersetzt.
Abweichungen von der original Arduino Konfiguration:
-std=gnu++2a statt -std=gnu++11
Diese Zeilen sind in der platform.local.txt neben der originalen
platform.txt unter zu bringen.
Der Pfad zur ToolChain muss natürlich den Gegebenheiten angepasst
werden.
Hallo Johann,
oh ja da habe ich gepennt. Man muss auch mal Fehler machen dürfen. :-)
tn3217 eingetippt und es funktioniert auch ohne io.h Änderung.
Vielen Dank.
Frage. Warum steht die Änderung nicht in allen spec files schon drin?
Wer kümmert sich darum oder wer sollte sich darum kümmern? Weil
eigentlich gehe ich an die spec files nicht ran oder nur mit viel
Respekt, weil jedes Leerzeichen oder Leerzeile ausgewertet wird. Hatte
ich damals schon festgestellt.
@ Arduino Fanboy:
Danke für deine offene Info. Bei nächster Gelegenheit wird das
ausprobiert.
Veit D. schrieb:> Frage. Warum steht die Änderung nicht in allen spec files schon drin?
Hatte ich dir hier erklärt:
Johann L. schrieb:> Allerdings hat die avr-libc eine ziemlich blöde Namenskonvention für> io*.h, die sich nicht einfach per -mmcu= ergibt und auch keiner> einfachen Heuristik folgt.
Im Compiler weiß man also schlichtweg nicht, was der richtige Name ist.
ABER: Normalerweise hat man 2 Fälle:
1) Die Tools unterstützen ein Device. In dem Falle braucht man __
AVR_DEV_LIB_NAME __ nicht zu definen weil die avr-libc bereits die
entsprechende Erweiterung in io.h hat.
2) Die Tools unterstützen ein Device nicht. In dem Fall kommt der
Support von einem Device-Pack, das io*.h, crt#.h, lib#.h und specs-#
enthält. Bei korrektem Specs kümmert sich dieses um die richtigen
Optionen und Defines, enthält also adäquates _ AVR_DEV_LIB_NAME _ zum
eigenen io*.h.
Im vorliegenden Fall handelt es sich jedoch um eine komische Mischung:
Der Compiler kennt das Device, avr-libc aber (noch) nicht. Von daher
war es eine blöde Idee von mir, im Compiler Support für ein paar Devices
hinzuzufügen. Betroffen sind: ATtiny202/04/12/14,
ATtiny402/04/06/12/14/16/17, ATtiny804/06/07/14/16/17,
ATtiny1606/07/14/16/17, ATtiny3214/16/17, ATmega808/09, ATmega1608/09,
ATmega3208/09 und ATmega4808/09.
> Wer kümmert sich darum oder wer sollte sich darum kümmern?
Kümmern soll? Am ehesten erwarten würde man es vom Chip-Hersteller,
es ist ja immerhin in dessen ureigensten Interesse. Aber Microchip ist
eher auf dem Trip, Features zu entfernen — es sei denn man kauft 'ne
Lizenz. Bei so einer Attitüde ist kaum zu erwarten, dass die aus freien
Stücken Beiträge zur Toolchain machen.
Ansonsten hat sich immer Jörg um die avr-libc gekümmert, aber seit über
1 Jahr hat er keine Zeit oder kein Nerv mehr dafür. So gibt es Patches
für... ok, hatte ich bereits alles im Beitrag vom 9. Februar erläutert:
Beitrag "Re: AVR C Programmierung unter Linux"
Hallo Johann,
vielen Dank für die weiteren näheren Erläuterungen.
Und falls du mal ein Atmel Devicepack benötigen solltest:
http://packs.download.atmel.com/
runterladen, Endung auf .zip ändern und entpacken.
Arduino Fanboy D. schrieb:> Johann L. schrieb:>> alle Bibliotheken und Objekte müssen mit -mdouble=64 erzeugt>> worden sein!>> Und ja, das war die Lösung! Jetzt auch die C Quellen,> nicht nur die C++ Quellen, mit -mdouble=64 übersetzt.>> compiler.cpp.flags= ... -mdouble=64> compiler.c.extra_flags=-mdouble=64> compiler.c.elf.extra_flags=-mdouble=64
Gibt es denn keinen konsistenten Weg, -mdouble= zu setzen? Die Option
muss ja für alle Module gleich sein, egal ob C/C++ oder Assembler, und
muss auch beim Linken übereinstimmen. Daher will man sie nur an 1
Stelle ändern müssen.
Genauso wie -mmcu= oder andere Optionen wie -f[no-]short-enums,
-fpack-struct, -f[no-][un]signed-char, -f[no-][un]signed-bitfields. All
diese Optionen ändern das ABI, und sie müssen für alle Compile- und
Linkvorgänge gleich sein. Sowas wie multilib.extra_flags oder
abi.extra_flags falls es das gibt. Oder am einfachsten da, wo auch
-mmcu= gesetzt wird; dass muss ja auch nicht für C gemacht werden und
dann für C++ und dann für den Assembler und nochmal für den Link.
Und gibt's dann noch compiler.asm.elf.extra_flags,
compiler.asm.extra_flags, compiler.cpp.elf.extra_flags? Wer blickt denn
da noch durch?
Deinen ICE jedoch kann ich immer noch nicht nachvollziehen:
Wenn ich 2 Module habe mit einem Interface für ein double Objekt, und
die Module mit unterschiedlichen -mdouble= übersetzt werden, bekomm ich
mit LTO:
1
xxx.c:3:15: warning: size of 'vD' differ from the size of original declaration [-Wlto-type-mismatch]
2
3 | extern double vD;
3
| ^
4
yyy.c:1:8: note: 'vD' was previously declared here
5
1 | double vD;
6
| ^
Ohne LTO oder ohne globalen double bekomm ich keine Warnung und keinen
Internal Compiler Error (die sind ohne LTO ist der auch nicht zu
erwarten).
Hallo,
ich muss zu double 64Bit auch noch paar Fragen stellen.
Ist das ab gcc10 standardmäßig eingebaut und vorhanden doch nicht?
Sprich, muss ich die Toolchain explizit für double 64Bit neu bauen?
Laut meiner Lesart verstehe ich nicht was default ist wenn long-double
und double mit 32 und 64Bit angegeben ist?
1
The defaults are --with-long-double=64,32 and --with-double=32,64. The default ‘double’ layout imposed by the latter is compatible with older versions of the compiler that implement ‘double’ as a 32-bit type, which does not comply to the language standard.
Oder muss die Lesart wie folgt sein?
long-double=64,32 >> 64Bit default und 32Bit optional
double=32,64 >> 32Bit default und 64Bit optional
Je nach Reihenfolge beider Angaben?
Was ich mit LibF7 machen soll/muss weiß ich nicht.
Wäre nett wenn du dazu noch etwas sagen könntest.
Allgemeine Frage. Ist double 64Bit nur für die megaAVR0 Serie vorhanden
oder auch für AVR-DB Serie? Oder generell für alle mit Hardware
Multiplikation? Ich hatte damals nur nebenbei mitbekommen das du das für
den ATmega4809 entwickelt hast.
Veit D. schrieb:> ich muss zu double 64Bit auch noch paar Fragen stellen.> Ist das ab gcc10 standardmäßig eingebaut und vorhanden doch nicht?
Ab v10 unterstützt GCC (long)double64, und die Routinen sind als Teil
der libgcc implementiert:
http://gcc.gnu.org/gcc-10/changes.html#avrhttp://gcc.gnu.org/git/?p=gcc.git;a=tree;f=libgcc/config/avr/libf7> Sprich, muss ich die Toolchain explizit für double 64Bit neu bauen?
Kommt drauf an, was du als Multilib-Layout willst bzw. als
Multilib-Default.
> Laut meiner Lesart verstehe ich nicht was default ist wenn long-double> und double mit 32 und 64Bit angegeben ist?
Siehe http://gcc.gnu.org/install/configure.html#avr:
>> • The first value after the ‘=’ specifies the default layout>> (in bits) of the type and also the default for the -mdouble=>> resp. -mlong-double= compiler option.> Oder muss die Lesart wie folgt sein?> long-double=64,32 >> 64Bit default und 32Bit optional> double=32,64 >> 32Bit default und 64Bit optional
Ja.
> Was ich mit LibF7 machen soll/muss weiß ich nicht.
Brauchtst du nix extra machen, auch keine extra configure-Optionen. Ist
ja Teil der libgcc. Extra configure-Optionen brauchst du nur, wenn du
z.B. keine LibF7 in der libgcc haben willst.
> Ist double 64Bit nur für die megaAVR0 Serie vorhanden> oder auch für AVR-DB Serie?
Es gibt Varianten für alle -mmcu= Ausprägungen. Mit den o.g. configure
Defaults wird double=32 und longdouble=64 falls kein -m[long-]double=
angegeben wird. Für andere -m[long-]double= Varianten ist die
Multilib-Struktur erweitert, für avrxmega3 zum Beispiel:
1
./avrxmega3
2
./avrxmega3/double64
3
./avrxmega3/long-double32
4
./avrxmega3/short-calls
5
./avrxmega3/short-calls/double64
6
./avrxmega3/short-calls/long-double32
> Oder generell für alle mit Hardware Multiplikation?
Support ist prinzipiell für alle Devices da, ohne MUL fehlen aber ein
paar Routinen, die MUL verwenden. Prinzipiell kann man die Routinen im
eigenen Projekt nachrüsten wenn man wirklich 64-Bit double auf einem
ATtiny2313 haben will... Und für Reduced Tiny mit nur 16 GPRs fehlt
noch mehr.
> Ich hatte damals nur nebenbei mitbekommen das du das für> den ATmega4809 entwickelt hast.
Ich hab's nicht für dieses Device entwickelt, aber es war einer der
Testfälle wegen dessen linearem Spreichermodell. Aber natürlich werden
auch Xmega und Classic AVRs unterstützt.
Der große Bremsklotz ist aber die avr-libc, weil man Patches braucht,
die da noch nicht integriert sind (und meines Wissens auch nicht in der
avr-libc3):
> #57071: Fix math.h and function names that block 64-bit doublehttp://savannah.nongnu.org/bugs/?57071> #49567: Use meta-info from --print-multi-lib and --print-multi-directoryhttp://savannah.nongnu.org/bugs/?49567
Immerhin sind die Änderungen bedeutend genug, dass Jörg nach Integration
die Major-Version der avr-libc nochzählen wollte; und zwar von 2.0 auf
4.0 damit keine Konfusion mit der avr-libc3 aufkommt.
Hallo Johann,
vielen Dank für deine Geduld mit mir. :-)
Soweit habe ich das nun verstanden was es mit der Konfiguration auf sich
hat.
Eins lese ich noch raus woraus sich eine weitere Frage ergibt.
double64 Bit funktioniert grundlegend auch mit Eigenbau Toolchain.
Die internen Berechnungen bei double 64Bit Verwendung laufen aber nur
optimal mit Patches für die avr-libc. Also müßte ich für optimale
Gegebenheiten deine avr-gcc 10er Toolchain verwenden?
Veit D. schrieb:> Die internen Berechnungen bei double 64Bit Verwendung laufen aber nur> optimal mit Patches für die avr-libc.
Ohne die Patches für avr-libc bekommst du keine konsistente Toolchain.
Probleme, die die Patches beheben, sind:
1) libm: avr-libc implementiert sin(double) für 32-Bit double und
definiert dann sinf als Alias. Das ist natürlich genau falschrum: Zu
implementieren ist sinf(float), und nur falls
1
#if __SIZEOF_DOUBLE__ == 32
darf die avr-libc sin als Alias für sinf zur Verfügung stellen. Dito
für sinl(long double) und den ganzen math.h Zoo. Unabhängig vom
double-Layout stellt math.h der avr-libc Prototypen für float, double
und long double zur Verfügung — jedenfalls macht das der von mir
vorgeschlagene Patch so. Insbesondere stellt avr-gcc kein math.h
Header zur Verfügung, obwohl die libgcc Zeugs aus math.h imlpementiert.
2) math.h: Analog für inline-Funktionen in math.h. Außerdem ist es
schlecht, die Aliase per #define zu machen: Erstens gibt das keine
Prototypen, und zweitens kann das zu fiesen Problemen mit C++ führen.
Ergo: Mit Patch hat man Prototypen wie gewünscht; Aliase werden
konditional auf Assembly-Ebene qua Symbol erstellt.
3) libc: printf-Modifier wie %f und %lf müssen angepasst werden: 64-Bit
double werden immer als "?" ausgegeben, d.h. double64 In- und Output
wird nicht unterstützt. Dennoch muss auch hier nach sizeof([long]
double) unterschieden werden.
4) Build-System: Wie vorhin erklärt, bringt double64 eine Erweiterung
der Multilib-Struktur, und diese Struktur sowie der Multilib-Default
sind abhängig von configure-Optionen, welche avr-libc nicht kennt.
Bisher war es so, dass die Multilib-Struktur händisch ins avr-libc
Buildsystem reingeklöppelt wurde und die ca. 300 Devices darauf verteilt
wurden. Mein Patch wertet gcc --print-multi-lib sowie
--print-multi-directory -mmcu=* aus, erstellt anhand dessen die
Multilib-Struktur und sortiert Devices richtig ein. "make dist"
erstellt eine Quell-Distribution, die mit allen möglichen Layouts von
avr-gcc funktioniert. Binär-Distributionen der avr-libc sind nicht mehr
möglich, da man zur Build-Time der avr-libc wissen muss, wie der
Compiler configured wurde.
Ohne 4) findet der Compiler nicht die (richtigen) Multilibs und CRTs.
Hallo Johann,
vielen Dank. Auch wenn ich von den Details nur die Hälfte verstehe,
merkt man was da für eine Arbeit dahinter steckt. Hut ab.
Danke auch an Jörg für die bisherige Arbeit.
...und falls du ne Toolchain selber generieren willst, kannst du
1) avr-libc Patches #57071 und #49567 einbauen — oder warten, bis sie
jemand in die avr-libc integriert hat (falls das jemals passieren wird).
Oder
2) Toolchain wie üblich generieren und installieren. Meine MingW32 .zip
vom obigen Link runterladen und entpacken. Dann math.h und alle *.a und
*.o der avr-libc in die eigene Installation reinkopieren, wobei die
relativen Pfade erhalten bleiben müssen. Die Objects und Libs sind ja
unabhängig vom Host OS.
Allerdings funktioniert 2) nur, wenn dein configure kompatibel ist mit
--with-double=32,64 --with-long-double=64,32, weil mein .zip dafür
configured wurde und andere Multilibs fehlen.
Tatsächlich enthält mein .zip alle Multilib-Varianten, nämlich
[double=32, ldouble=64], [double=ldouble=64] sowie [double=ldouble=32].
Je nach configure liegen diese aber in unterschiedlichen Sub-Pfaden, und
die Default-Multilib wird gemäß dem -m[long-]double= default generiert.
Prinzipiell könntest du also auch eine andere Konfiguration à la 2)
durch Reinkopieren aus dem .zip pimpen; dazu müsstest du aber die Files
permutieren; am praktikabelsten per Script.
Dazu macht man sich zunächst klar, welches Subdirectory was enthält:
1
.../ # default
2
.../double64 # double=ldouble=64
3
.../double32 # double=32, ldouble=64
4
.../long-double64 # double=32, ldouble=64
5
.../long-double32 # double=ldouble=32
Dann schreibt man ein Skript, das die Abbildung vornimmt und die Dateien
entsprechend vom .zip in den eigenen Build kopiert. Dabei ist auch der
Fall [double=32, ldouble=64] eindeutig benannt, weil die
"*double*" Unterordner immer Abweichung vom Default enthalten.
Wenn man z.B. configure --with-double=32,64 --with-long-double=32,64
verwendet, dann gibt es Multilibs in allen Varianten, und der Default
ist kompatibel mit alten avr-gcc (also double=ldouble=32):
1
.../ # default: double=ldouble=32
2
.../double64 # double=ldouble=64
3
.../long-double64 # double=32, ldouble=64
Beim aktuellen Default configure --with-double=32,64
--with-long-double=64,32 sieht das Layout jedoch so aus:
1
.../ # default: double=32, ldouble=64
2
.../double64 # double=ldouble=64
3
.../long-double32 # double=ldouble=32
Wegen long double ≥ double gibt es pro Inkarnation immer nur maximal 3
Varianten.
Bei einem C/C++ kompatiblen Default mit der Möglichkeit, zum alten
nicht-konformen 32-Bit (long) double umzuschalten, hätte man:
Hallo,
das hier ist ja default
--with-double=32,64
--with-long-double=64,32
und da ich bisher ohne extra Optionen baue sollte das passen.
Ich werde das mit dem kopieren ausprobieren. Vielleicht auch das mit den
Patch einbauen. Danke.
Veit D. schrieb:> Hallo,>> das hier ist ja default> --with-double=32,64> --with-long-double=64,32>> und da ich bisher ohne extra Optionen baue sollte das passen.> Ich werde das mit dem kopieren ausprobieren.
Ja, damit kann man die Multilib-Struktur 1:1 kopieren.
Johann L. schrieb:> ...und falls du ne Toolchain selber generieren willst, kannst du> 2) Toolchain wie üblich generieren und installieren. Meine MingW32 .zip> vom obigen Link runterladen und entpacken. Dann math.h und alle *.a und> *.o der avr-libc in die eigene Installation reinkopieren, wobei die> relativen Pfade erhalten bleiben müssen. Die Objects und Libs sind ja> unabhängig vom Host OS.>> Allerdings funktioniert 2) nur, wenn dein configure kompatibel ist mit> --with-double=32,64 --with-long-double=64,32, weil mein .zip dafür> configured wurde und andere Multilibs fehlen.>> Tatsächlich enthält mein .zip alle Multilib-Varianten, nämlich> [double=32, ldouble=64], [double=ldouble=64] sowie [double=ldouble=32].> Je nach configure liegen diese aber in unterschiedlichen Sub-Pfaden, und> die Default-Multilib wird gemäß dem -m[long-]double= default generiert.
Ich bin aktuell irritiert. In deinen double64 und long-double32 inkl.
short.calls finde ich keine *.o Dateien.
Kurzum, ich würde mir ein Script schreiben um alle double64 und
long-double32 inkl. short.calls Ordner/Dateien je Device-Gruppe zu
kopieren. Egal was da drin ist. Inkl. libc.a und libm.a
Veit D. schrieb:> Ich bin aktuell irritiert. In deinen double64 und long-double32 inkl.> short.calls finde ich keine *.o Dateien.
Es gibt 2 Multilib-Bäume:
Einen der libgcc in
1
<install>/lib/gcc/avr/<version>
an dem man nix ändern muss.
Zu erweitern ist der Ordner der libc in
Hallo,
diese *.o und *.a bei dir im Bsp.
\avr\lib\avr4\
sind die alten Controller. Für diese hast du bei dir in
\avr\lib\avr4\double64\
\avr\lib\avr4\long-doulbe32\
nochmal *.o und *.a liegen.
Das nützt mir aber nichts. Denn ich bräuchte ja in avrxmega2, avrxmega3,
avrxmega4 usw. auch die neuen "64Bit Dateien" für die megaAVR0 und
AVR-DB Serie. Hier sind die Ordner leer. Das meinte ich vorhin ich finde
keine Dateien bei dir.
Außer das sind alles die gleichen Dateien und diese müssen nur doppelt
und dreifach in den Ordnern liegen? Könnte ich aus dem Atmnel-Devicepack
nehmen. Nur wo ist dann die double64 Eigenschaft enthalten?
Beim Toolchain bauen kann ich ja nicht sagen baue mir für Controller xy
alles rein. Ich habe am Ende nur die drin die standardmäßig
"mitgeliefert" werden und den Rest muss ich mir aus dem Devicepack
holen. Nur gibts im Devicepack nichts mit double64 Eigenschaft.
Ich dachte ich hätte es vorhin gerafft was zu tun ist, aber stehe wieder
bei Null.
Hallo,
ich glaube ich habe den roten Faden wieder.
Alles was bspw. direkt in
\avr\lib\av4 liegt muss ich nicht kopieren. Das sollten ja alles Dateien
sein die nichts mit double64 zu tun haben.
Ich muss nur die kompletten Ordner
\avr\lib\av4\double64
\avr\lib\av4\long-double32
kopieren. Richtig?
Das gleiche Schema für bspw. avrxmega3. Alles was direkt drin liegt muss
nicht kopiert werden. Nur die weiteren Unterordner.
\avr\lib\avrxmega3\double64
\avr\lib\avrxmega3\long-double32
Das gleiche für den Unterordner short-calls.
Auch hier nur die Unterordner
double64 und long-double32 kopieren.
Richtig?
Hallo,
je länger ich nachdenke passt dennoch was nicht.
Bleiben wir im \avr\lib\avrxmega3\ Ordner.
Hier habe ich aus dem Devicepack alle notwendigen *.o und *.a Dateien
reinkopiert. Brauche ich nicht davon noch von irgendwoher die 64Bit
fähigen Dateivarianten für die Unterordner double64 und long-double32?
Die gibts ja bei dir nicht. Eben genauso wie bei \avr\lib\avr4\. Mir
raucht der Kopf.
Hallo,
ich habe das jetzt mit einem Script kopiert laut meinem Verständnis.
Morgen werde ich die Toolchain testen. Für heute habe ich dafür keinen
Nerv mehr.
Veit D. schrieb:> Das gleiche für den Unterordner short-calls. Auch hier nur die> Unterordner double64 und long-double32 kopieren. Richtig?
Ja.
Im .zip sieht avr/lib/avrxmega3 so aus:
Veit D. schrieb:> diese *.o und *.a bei dir im Bsp. \avr\lib\avr4\> sind die alten Controller. Für diese hast du bei dir in> \avr\lib\avr4\double64\> \avr\lib\avr4\long-doulbe32\> nochmal *.o und *.a liegen.>> Das nützt mir aber nichts.
War nur ein Beispiel, weil ich nicht 825 CRTs auflisten wollte...
1
> find avr/lib -name crt*.o | wc -l
2
825
> Denn ich bräuchte ja in avrxmega2, avrxmega3, avrxmega4 usw.> auch die neuen "64Bit Dateien" für die megaAVR0 und AVR-DB Serie.
Für DB gibt's bei mir nix, da musst dich selbst drum kümmern.
> Hier sind die Ordner leer. Das meinte ich vorhin ich finde> keine Dateien bei dir.
Doch, siehe obiges Listing von avr/lib/avrxmega3, allerdings beschränkt
sich das Listing auf crt*14.o.
> Außer das sind alles die gleichen Dateien und diese müssen nur> doppelt und dreifach in den Ordnern liegen?
Ja. Was GCC brauch ist eine korrekte Multilib-Struktur. Hier:
Links vom ";" steht der Multi-Ordner, rechts vom ";" durch "@" getrennt
die Optionen, die hinführen. In jedem Ordner der libc gibt es libc.a,
libm.a, libprintf_flt.a, etc. welche mit diesen Optionen generiert
wurden.
Und wo das CRT steht, ergibt sich auch durch Optionen:
[/pre]
> avr-gcc --print-multi-directory -mdouble=64 -mmcu=attiny412
avrxmega3/short-calls/double64[/pre]
> Könnte ich aus dem Atmel-Devicepack nehmen.> Nur wo ist dann die double64 Eigenschaft enthalten?
In der Verzeichnisstruktur.
Aber wenn du Device-Packs verwendest, dann verwende halt Device-Packs.
Im alten avr-gcc brauch man die Dateien ja auch nicht händisch in die
Verzeichnisse reinkopieren. Daran hat sich nix dran geändert.
Wenn allerdings die Toolchain ein Device von Hause aus unterstützen
soll, so wie bei dann braucht's die CRTs am richtigen Platz.
Was du aber auf jeden Fall AUCH brauchst sind die richtigen *.a: Wenn
du z.B. mit -mdouble=64 compilierst, dann sucht der Compiler die Libs in
und wenn da keine libm.a ist, dann gibt's keinen Fehler, sonder es
wird die default Multilib gelinkt, also die in ".". Und die ist eben
für 32-Bit double compiliert, du bekommst also falschen Code — mal ganz
angesehen davon, dass diese libm.a für eine andere Device-Familie ist
(avr2).
Hallo,
der Ehrgeiz das Ergbenis zu sehen war dann doch noch da.
µC ATmega2560 (Arduino Mega2560)
Allerdings stimmt überhaupt nichts an den Zahlen.
Ich habe das in der Arduino IDE ausprobiert mit den Optionen von Arduino
Fanboy.
Mit meiner "normalen" Toolchain erhalte ich was man so erwartet:
1
1.234567880
2
1.234567880
3
1.524157905
4
1.524157905
Mit der double64 aufgebohrten Toolchain:
1
1.235000000
2
1.235000000
3
2.000000000
4
2.000000000
Sagt mir bitte das das ein Witz ist! Kann doch nicht sein.
Testcode
1
floatf=1.234567890;
2
doubled=1.234567890;
3
4
voidsetup(void)
5
{
6
Serial.begin(250000);
7
Serial.println("\nStart");
8
9
Serial.println(f,9);
10
Serial.println(d,9);
11
12
Serial.println(f*f,9);
13
Serial.println(d*d,9);
14
}
15
16
voidloop(void)
17
{
18
19
}
Fehlermeldung beim kompilieren erhalte ich keine.
platform.local.txt
Hallo,
okay, deine Antwort hat sich mit meiner zeitlich überschnitten.
Ich muss noch paar andere Dateien kopieren. libc.a. libm.a usw.
Nur wo soll ich die double64 fähigen Dateien für die AVR-DB Serie
hernehmen? Beim Toolchain bauen werden die doch nicht erzeugt.
Hallo,
ich habe mich jetzt nochmal auf den mmc Ordner avr6 konzentriert für den
ATmega2560. Habe auch alle anderen Dateien kopiert. Das gleiche in
Toolchain\lib\gcc\avr\10.2.0\avr6\
Klappt noch nicht. Genau die falschen Ergebnisse wie vorher. An
Serial.print liegts nicht, gleiches Ergebnis mit vorheriger
Typkonvertierung auf float.
float a = (float)d*d;
Serial.println(a,9);
Veit D. schrieb:> Nur wo soll ich die double64 fähigen Dateien für die AVR-DB Serie> hernehmen? Beim Toolchain bauen werden die doch nicht erzeugt.
Das ist eine neue Family??? D.h. es gibt ein neues -mmcu=avr* dafür?
Dann kannst du es mit meinem Compiler eh nicht übersetzen, weil das nur
die Familien unterstützt, die es offiziell gibt:
1
avr2/25/3/35/4/5/51/6
2
avrxmega2/3/4/5/6/7
3
avrtiny
Hier noch ein Beispiel samt Ausgabe. Das Beispiel ist für den avrtest
Core-Simulator, weil mir auf die Schnelle nix anderes einfällt, 64-Bit
double auszugeben. (avr-libc "unterstützt" das nur, indem ein "?"
ausgegeben wird). Bei avrtest geschieht die LOG_* Ausgabe auf dem
Host, und die Format-Strings beziehen sich auf's Host-OS!
Veit D. schrieb:> Das gleiche in Toolchain\lib\gcc\avr\10.2.0\avr6\
Das ist libgcc. Oben hab ich erklärt, dass diese Ordner der libgcc
nicht angepasst werden müssen:
Johann L. schrieb:> Es gibt 2 Multilib-Bäume: Einen der libgcc in
1
<install>/lib/gcc/avr/<version>
> an dem man nix ändern muss.>> Zu erweitern ist der Ordner der libc in
Hallo,
ja, AVR-DA, AVR-DB und die kommende AVR-DD ist eine neue Atmega Familie.
Aufgebohrte megaAVR0. Je nach Flashgröße gehören die zur avrxmega2,
avrxmega3 oder avrxmega4 Kategorie.
<install>/lib/gcc/avr/<version>
Hier hatte ich nur eine letzte Verzweifelungstat unternommen. Ich hatte
das schon gelesen das man hier nichts ändern müßte.
Ich habe nun deine Toolchain genommen und mit dem Arduino Mega2560
getestet. Ich habe exakt die gleichen falschen Ergebnisse im seriellen
Monitor.
Dann wollte ich mit deiner Toolchain den Arduino Nano Every testen, der
mit ATmega4809 drauf. Da ist irgendwas mit den spec Files nicht okay.
> avr-gcc: fatal error: specs file malformed after 2597 characters> compilation terminated.
Habe deine mit meinen aktuellen verglichen. Alles okay. Habe dann die
spec files und alle anderen mit meinem Script kopiert was ich für mein
Toolchain bauen verwende.
> exit status -1073741819
Geht auch nicht. Jetzt weiß ich nicht ob in der Toolchain nochwas fehlt
oder ob es an der Arduino IDE liegt.
Dann habe ich nochmal deine Toolchain mit dem ATmega2560 probiert. Die
Datentypgrößen stimmen. float 4 Byte und double 8 Byte. Also sollte auch
richtig gerechnet werden. Serial zerlegt eigentlich den Wert Ziffer für
Ziffer und bringt es zur Anzeige. Ich habe in der Printklasse die
Methode aufgetrennt für printFloat und printDouble. Es wird für Double
aber immer noch Standard verwendet. Das erkenne ich, weil ich die
Mindestkommastellen für double erhöht habe. Ich weiß noch nicht was los
ist.
Wenn ich neue Muse gefunden habe probiere ich das einmal nackt in Atmel
Studio, ohne Arduino IDE. Hierfür habe ich einen ATmega328PB und einen
ATmega4808 nackt zur Verfügung, die zumindestens mit deiner Toolchain
funktionieren müssen. Erstmal Danke für die Unterstützung.
Ich hätte gern von Arduino Fanboy gewusst mit welchen Arduinoboard er
double64 getestet hat? Und ob Rechenwerte stimmen?
Veit D. schrieb:> ja, AVR-DA, AVR-DB und die kommende AVR-DD ist eine neue Atmega Familie.> Aufgebohrte megaAVR0. Je nach Flashgröße gehören die zur avrxmega2,> avrxmega3 oder avrxmega4 Kategorie.
Also keine neue Falilie, was avr-gcc angeht.
Seltsam ist aber, dass avrxmega3 ein lineares Speichermodell ist mit
Flash im RAM Adressraum sichtbar. Alle anderen avrxmega Familien haben
jedoch kein lineares Modell. Ich geh mal davon aus, dass Microchip
den sub-optimalen Ansatz wählt, genauso wie sie z.B. avrxmega2 für einen
ATmega808 genommen hatten...
> <install>/lib/gcc/avr/<version>> Hier hatte ich nur eine letzte Verzweifelungstat unternommen.
Ber der vorherrschenden Verwirrung war es wohl keine gute Idee,
vorzuschlagen, die Libs in selbst generierte Tools zu kopieren... Da
wärst mit den avr-libc Patches schneller durch gewesen.
> Ich habe nun deine Toolchain genommen und mit dem Arduino Mega2560> getestet. Ich habe exakt die gleichen falschen Ergebnisse im seriellen> Monitor.
Vielleicht hat du ja einen Arduino-freien Testfall?
> Dann wollte ich mit deiner Toolchain den Arduino Nano Every testen, der> mit ATmega4809 drauf.
Vielleicht mal mit avrtest testen? Da bist du nicht auf ein spezielles
Device festgelegt, brauchst keine bestimmte Hardware, und die Ausgabe
erledigt der Host. Und du kannst Logs einsehen und was jede einzelne
Instruktion macht.
>> avr-gcc: fatal error: specs file malformed after 2597 characters>> compilation terminated.
War da wieder jemand schlampig mit Leerzeilen?
Hallo,
Danke Arduino Fanboy. Dann sollte das theoretisch auch bei mir
funktionieren.
Zwischen einem Uno und Mega2560 sollte es eigentlich keine Unterschiede
geben.
>> avr-gcc: fatal error: specs file malformed after 2597 characters>> compilation terminated.> War da wieder jemand schlampig mit Leerzeilen?
Ich konnte in deinem spec File keine Abweichungen finden. Das war deine
frisch entpackte Toolchain. Wer weiß mit was die Meldung noch
zusammenhängt. Ich will da gar nichts beschuldigen.
Mein Problem ist, ich habe hierbei zu viele Baustellen zur gleichen Zeit
die alle zusammenhängen. avrtest wäre dann bestimmt die nächste
Baustelle. Ich muss erstmal alle Gedanken sortieren und überlegen ...
Irgendwie hab ich den Eindruch, du hast ne Toolchain wo überall der
Wurm drin ist, egal wo du hinfasst...
Hast du mal meine Toochain versucht ohne was zu ändern?
https://sourceforge.net/projects/mobilechessboar/files/avr-gcc%20snapshots%20(Win32)/
Von 2019-12-16 gibt's ne MinGW32, und von 2020-01-14 eine Linux 64-Bit
Version. Soweit ich weiß verwendet Arduino Fanboy den MinGW Build, und
bei dem funktioniert's ja.
In meiner letzten Antwort hatte ich eigentlich geschrieben das ich deine
unveränderte Toolchain verwendet hatte. Deswegen wundert es mich umso
mehr das es bei mir mit der Arduino IDE nicht funktioniert und bei
Fanboy funktioniert.
Ich bin dabei in Atmel Studio etwas mit einem ATMEGA4808 zum Laufen zu
bringen. Für deine Toolchain muss ich dafür erneut fehlende Dateien
kopieren. Die benötige ich ja zwangsweise zum Vergleich. Mit meiner
Toolchain werden zumindest keine unsinnigen Werte ausgegeben. Auch wenn
die hinteren Kommastellen noch nicht so passen.
Soviel zum aktuellen Stand. Es bleibt spannend.
@ Arduino Fanboy. Ich muss nochmal was nachfragen. Du hast an Johanns
Toolchain nichts geändert und nur die platform.local.txt wie gezeigt
geändert?
Auch in anderen Arduino Dateien hast du nichts geändert?
Veit D. schrieb:> Du hast an Johanns Toolchain nichts geändert
Nichts.
Veit D. schrieb:> nur die platform.local.txt wie gezeigt geändert?
Ja.
Veit D. schrieb:> Auch in anderen Arduino Dateien hast du nichts geändert?
Schon...
Aber nichts, was dieses float/double Problem betrifft.
Hallo,
ich fasse die Ereignisse zusammen.
Nachdem ich die entsprechenden Dateien in meiner Toolchain nochmals
kopiert hatte und in Johann's Toolchain die fehlenden Controller Dateien
reinkopiert habe und nach alldem bei allen Tests auf die gleichen
falschen Werte kam, dachte ich das kann ja jetzt alles nicht wahr sein.
Am Ende liegt es "vorläufig" am Testcode. Der war nicht 1:1 das womit
Arduino Fanboy getestet hat. Ich nahm an wenn ich d/3.0 rechne wird in
double gerechnet wenn 'd' double ist. Nein, es wird immer in float
gerechnet. Also habe ich den Testcode angepasst und alle Variablen
explizit deklariert. Keine Literale.
Nun erhalte ich aber dennoch je nach Controller unterschiedliche Werte.
Wie soll es auch bei mir anders sein ... :-)
Ab jetzt ist es egal welche Toolchain ich nehme. Ergebnisse sind immer
die gleichen.
Arduino Mega2560 mit Arduino IDE:
1
floatf=1.123456789;
2
floatg=3.0;
3
4
doubled=1.123456789;
5
doublee=3.0;
6
7
voidsetup(void)
8
{
9
Serial.begin(250000);
10
Serial.println("\nStart");
11
12
Serial.println(sizeof(float));
13
Serial.println(sizeof(double));
14
15
Serial.println("float:");
16
Serial.println(f,20);
17
Serial.println(f/g,20);
18
Serial.println("double:");
19
Serial.println(d,20);
20
Serial.println(d/e,20);
21
Serial.println();
22
23
f=1.0;
24
d=1.0;
25
Serial.println("float:");
26
Serial.println(f,20);
27
Serial.println(f/g,20);
28
Serial.println("double:");
29
Serial.println(d,20);
30
Serial.println(d/e,20);
31
}
32
33
voidloop(void)
34
{}
Ausgabe
1
Start
2
4
3
8
4
float:
5
1.12350000000000000000
6
0.40000000000000000000
7
double:
8
1.12350000000000000000
9
0.40000000000000000000
10
11
float:
12
1.00000000000000000000
13
0.33333334330000000000
14
double:
15
1.00000000000000000000
16
0.33333333333333330400
Schön ist, dass ich bei 1.0/3.0 die gleiche Ziffernfolge erhalte wie
Arduino Fanboy. double ist präziser als float. Soweit so gut.
Was aber nachwievor nicht sein kann, ist die gleiche Ziffernfolge des
initialisierten Startwertes für float und double. double müßte ja
genauer ausgegeben werden. Und das die erste Division mit 0.4 gleich
falsch gerundet wird macht mich auch stutzig.
Jetzt in Atmel Studio mit einem ATmega4808. Hier habe ich mir für die
Fließkommaausgabe die Methode von Arduino genommen.
1
#include<avr/io.h>
2
#include<stdio.h>
3
#include<stdlib.h>
4
#include<string.h>
5
#include<avr/interrupt.h>
6
#include<util/delay.h>
7
#include<util/atomic.h>
8
9
#include"initClock.h"
10
#include"megaAVR0_Usart.h"
11
12
usart<0,115200,A8N1>usart0;// Pin Tx=30, Rx=31
13
14
intmain(void)
15
{
16
initClock();
17
usart0.init();
18
19
while(1)
20
{
21
_delay_ms(2000);
22
23
usart0.println("Hallo ich bin USART.0.");
24
25
usart0.println(sizeof(float));
26
usart0.println(sizeof(double));
27
28
floatf=1.123456789;
29
floatg=3.0;
30
31
doubled=1.123456789;
32
doublee=3.0;
33
34
usart0.println("float:");
35
usart0.println(f,20);
36
usart0.println(f/g,20);
37
usart0.println("double:");
38
usart0.println(d,20);
39
usart0.println(d/e,20);
40
41
f=1.0;
42
d=1.0;
43
usart0.println("float:");
44
usart0.println(f,20);
45
usart0.println(f/g,20);
46
usart0.println("double:");
47
usart0.println(d,20);
48
usart0.println(d/e,20);
49
}
50
}
Ausgabe
1
Hallo ich bin USART.0.
2
4
3
8
4
float:
5
1.12345683574676513671 float
6
0.37448561191558837890 float
7
double:
8
1.12345683574676513671 double
9
0.37448558807373046875 double
10
float:
11
1.00000000000000000000 float
12
0.33333334922790527343 float
13
double:
14
1.00000000000000000000 double
15
0.33333334922790527343 double
Hier ist die Ausgabe von 1.123456789 / 3.0 mit double präziser. Ob es
wirklich das mögliche Optimum darstellt kann ich nicht prüfen. Was mich
hier allerdings wiederum stutzig macht ist die exakt gleiche
Ziffernfolge von 1.0/3.0 und komplett anders als beim Mega2560. Mit dem
dahinter stehenden "float/double" prüfe ich nur das auch die richtige
Ausgabefunktion verwendet wird. Also das er auch den Datentyp richtig
erkennt.
Also double64 wird schon irgendwie verwendet, aber nirgends immer und
überall richtig. Ist derzeit Controller abhängig. Ich bin nun langsam
aber sicher mit meinem Latein am Ende. ¯\_(ツ)_/¯
Meine usart Ausgabe für Atmel Studio hängt dran. Das Grundkonzept
basiert auf Peters Fleury uart Lib. Angepasst für megaAVR0 und C++. Ist
noch nicht schön aber funktioniert erstmal. Wo ich mir nicht ganz sicher
bin ist ob die printFloat Methode für double64 wirklich geeignet ist.
Weil hier mit 32Bit bestimmt was verloren geht nehme ich an.
1
uint32_tint_part=(uint32_t)input;
2
doubleremainder=input-(double)int_part;
1
voidprintFloat(doubleinput,uint8_tdigits)
2
{
3
// Handle negative numbers
4
if(input<0)
5
{
6
putChar('-');
7
input=-input;
8
}
9
10
// Round correctly so that print(1.999, 2) prints as "2.00"
11
doublerounding=0.5;
12
for(uint8_ti=0;i<digits;++i)
13
rounding/=10.0;
14
15
input+=rounding;
16
17
// Extract the integer part of the number and print it
18
unsignedlonglongint_part=(uint32_t)input;
19
doubleremainder=input-(double)int_part;
20
print(int_part);
21
22
// Print the decimal point, but only if there are digits beyond
23
if(digits>0){
24
putChar('.');
25
}
26
27
// Extract digits from the remainder one at a time
Veit D. schrieb:> 1.123456789 / 3.0
float: 0.40000000000000000000
double: 0.40000000000000000000
!?!?!?
Zudem funktionieren printf und seine Brüder bei mit nicht mit
-mdouble=64
Problem ist hier:
Veit D. schrieb:> uint32_t toPrint = (uint32_t)(remainder);
also Workaround gehen:
1
uint32_ttoPrint=(uint64_t)remainder;
1
uint32_ttoPrint=(float)remainder;
Arduino Fanboy D. schrieb:> Zudem funktionieren printf und seine Brüder bei mit nicht mit> -mdouble=64
Für 64-Bit double wird nur ein "?" ausgegeben, um die printf-Funktionen
nicht aufzublasen — auch nicht die in libprintf_flt.a. Die Anpassing in
der libc beschränkt sich darauf, die richtige Zahl von Argument-Bytes zu
überlesen.
funktioniert mit der Arduino IDE und Mega2560. Beide Wertausgaben und
Rechnungen sind präziser gewurden.
1
Start
2
4
3
8
4
float:
5
1.12345683574676513671
6
0.37448561191558837890
7
double:
8
1.12345678900000001121
9
0.37448559633333333707
10
11
float:
12
1.00000000000000000000
13
0.33333334326744079589
14
double:
15
1.00000000000000000000
16
0.33333333333333330372
Allerdings bleibt mit Atmel Studio und ATmega4808 alles unverändert.
Auch eine Änderung auf
1
uint32_tint_part=(uint64_t)input;
2
uint32_ttoPrint=(double)(remainder);
ändert leider nichts.
Allerdings verstehe ich den Workaround nicht. Man kastet eine Variable
nach float um sie sofort in einen Integer zu casten? Normalerweise ist
doch der cast Datentyp gleich dem Ziel-Datentyp. Ich stehe auf dem
Schlauch.
Edit:
kann noch an meiner printInteger Methode liegen. Da müßte ich auch
einmal die printNumber Methode von Arduino ausprobieren. Ich konvertiere
ja mit ltoa/ultoa für die letztliche Ausgabe.
Johann L. schrieb:> Für 64-Bit double wird nur ein "?" ausgegeben,
Für float dann leider auch!
Johann L. schrieb:> um die printf-Funktionen nicht aufzublasen
Interessant...
Arduino Fanboy D. schrieb:> Johann L. schrieb:>> Für 64-Bit double wird nur ein "?" ausgegeben,> Für float dann leider auch!
Da kann ich aber nix für, ist der Sprachstandard: printf und Konsorten
promoten float zu double. Wenn man float-Ausgabe will kann man
-mdouble=32 -mlong-double=64 verwenden (also den momentanen default) und
dann long double für 64-Bit Berechnungen; zur Ausgabe dann "%Lf". Das
promotet zwar immer noch float zu double, ist aber eine no-op weil beide
das gleiche Layout haben.
Hallo,
ich verstehe deinen Bugreport nicht. Worauf bezieht der sich?
Es muss eine Änderung in libgcc/libf7 gemacht werden, soweit klar. Nur
was bewirkt das?
Eine noch höhere generelle Genauigkeit als das was ich derzeit mit der
Arduino IDE erzielt habe?
Oder ist das auf mich und meinem AS Code bezogen? Mir fehlt jetzt der
Zusammenhang irgendwie.
Weil mit meinem AS Code ändert sich nichts, auch wenn ich alles uint64_t
mache. Die Genauigkeit hinkt der Arduino IDE hinterher und in beiden
Fällen verwende ich die gleiche Toolchain. Also kann es jetzt nicht
unbedingt an der libgcc/libf7 liegen.
Hallo,
ich habe die Änderungen die ich für den Mega2560 in der Arduino IDE
gemacht habe, wodurch es präziser wurde, für den Nano Every (ATmega4809)
in der Arduino IDE wiederholt. Hierbei ändert sich jedoch nichts. Ich
erhalte die gleichen ungenauen Werte wie für den ATmega4808 den ich in
Atmel Studio verwende.
Demzufolge vermute ich jetzt das in der libgcc/libf7 der Fehler nicht
allgemeiner Natur ist sondern nur für die megaAVR0 Serie gilt? Richtig?
Dann solltest du jedoch den Bugreport konkretisieren?
Hallo Johann,
ich wollte das nochmal mit einem ATmega328PB überprüfen. Nur fehlen mir
dafür die Controller spezifischen "double64" *.o und *.a Files. Hast du
die zufällig zur Hand oder existieren die noch nicht?