Um meinen Code etwas modularer zu gestalten, wollte ich aus Spaß an der
Freude auf C++11 Features zurückgreifen (der Compiler lässt sich
problemlos mit *-std=c++11* aufrufen).
Ich hab eine einfache Klasse mit statischen Methoden, eine davon liefert
das größte bzw. kleinste Element eines Arrays zurück. Das habe ich
aktuell so gelöst:
wobei get_value_with_compare eine private Methode der Klasse Util ist,
nur get_highest_value und get_lowest_value sind öffentlich
aufrufbar.
Ich weiß nicht, ob man sich mit dem Namespace std irgendwelchen großen
Dateien dazuholt, aber nun bekomme ich die Meldung:
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .output/eagle/debug/image/eagle.app.v6.out section `.text' will not fit in region `iram1_0_seg'
In der Headerdatei hab ich außerdem dieses include:
1
#include<functional>
.
Hat jemand Erfahrung damit?
Edit: Ich hatte das zuvor mit Funktionspointer anstatt lambdas gelöst,
da hat es einwandfrei kompiliert.
Edit_2: Mir fällt gerade auf, dass es sich hier um einen Linker-Error
handelt, d.h. der Compiler hat schon alles erfolgreich kompiliert.
Sven P. schrieb:> Der Linker will .text ins RAM packen?
Das ist glaub ich eine Methode des ESP8266 um bestimmten Code schneller
ausführen zu können da der Flash nur über SPI angebunden und
entsprechend langsam ist. Ich hab aber alle Methoden mit
ICACHE_FLASH_ATTR markiert, d.h. ich erwarte, dass die ins Flash und
nicht in den internen RAM gepackt werden.
Der Compiler verwendet bereits das Optimierungsflag -Os, kleiner
bekomme ich es also nicht mehr.
Ich vermute, dass man sich mit *#include<functional>* zu viel Zeug dazu
holt?
Max M. schrieb:> Ich vermute, dass man sich mit *#include<functional>* zu viel Zeug dazu> holt?
Du verwendest nichts aus dem functional header. Demnach benötigt das
include kein einziges Byte.
/edit
Ah doch, das std::function hab ich nicht gesehn. Aber trotzdem nein.
<functional> ist im Prinzip zero-cost. std::function hat auf Grund der
internen Type-Erasure natürlich etwas overhead, aber das beläuft sich
auf ein paar Byte...
/edit2
proof: https://godbolt.org/z/gbDLeR
Der is zwar für ARM, zeigt aber dass der Mehraufwand wirklich gering
ist.
Max M. schrieb:> Danke dir, Vincent.>> Jetzt steht ich nur vor dem Problem nicht zu wissen, an was es sonst> noch liegen könnte :(
Nachdem der Linker explizit mit
> `.text' will not fit in region `iram1_0_seg'
meckert, scheint "ICACHE_FLASH_ATTR" wohl nicht so funktioniert zu
haben, wie Du dir das gedacht hast?
Was sagt das mapfile?
Markus F. schrieb:> Was sagt das mapfile?
Ich kenne das von meinen AVR-GCC Projekten, in dem man den Linker
explizit ein map-File mit angibt (zusätzlich zu den ganzen
Object-Files).
Hier sehe ich im Linker-Aufruf (siehe erster Beitrag) keine Angabe eines
mapfiles. Im Projektordner, in dem die Sourcen und Object-Files liegen,
finde ich auch nichts.
Max M. schrieb:> Hier sehe ich im Linker-Aufruf (siehe erster Beitrag) keine Angabe eines> mapfiles.
Dann schreib' doch eins hin?
Im map File sagt einem der Linker ausführlich (wenn man ihn - mit
"-Wl,-Map -Wl,"mapfile" dazu auffordert), was er wohin getan hat.
Und das interessiert dich doch eigentlich, oder?
Markus F. schrieb:> Und das interessiert dich doch eigentlich, oder?
Achso, jetzt verstehe ich - danke!
Hast du eine Idee, wonach ich da suchen soll? Ist ehrlich gesagt das
erste mal, dass ich mir so eine Mapdatei ansehe.
Max M. schrieb:> Das ist glaub ich eine Methode des ESP8266 um bestimmten Code schneller> ausführen zu können da der Flash nur über SPI angebunden und> entsprechend langsam ist. Ich hab aber alle Methoden mit> ICACHE_FLASH_ATTR markiert, d.h. ich erwarte, dass die ins Flash und> nicht in den internen RAM gepackt werden.
Ich kenn mich mit dem ESP8266 leider nicht aus, aber eine kurze Google
Suche ergab das hier
https://www.esp8266.com/viewtopic.php?f=159&t=11966
Check mal ob das Macro an der Stelle wo du es nutzt überhaupt richtig
definiert ist oder re-define es testweise(!!!) in der entsprechenden
Source-Datei mal kurz neu.
Anbei nochmal die komplette Ausgabe auf der Konsole:
1
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .output/eagle/debug/image/eagle.app.v6.out section `.text' will not fit in region `iram1_0_seg'
2
Util/.output/eagle/debug/lib/Util.a(Util.o):(.text._ZNSt14_Function_base13_Base_managerIZN4Util16get_lowest_valueEPKiEUliiE_E10_M_managerERSt9_Any_dataRKS6_St18_Manager_operation+0x4): undefined reference to `operator new(unsigned int)'
3
Util/.output/eagle/debug/lib/Util.a(Util.o):(.text._ZNSt14_Function_base13_Base_managerIZN4Util16get_lowest_valueEPKiEUliiE_E10_M_managerERSt9_Any_dataRKS6_St18_Manager_operation+0x8): undefined reference to `operator delete(void*)'
4
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_clone':
5
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1910: undefined reference to `operator new(unsigned int)'
6
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_destroy':
7
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1926: undefined reference to `operator delete(void*)'
8
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_get_pointer':
9
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1893: undefined reference to `operator new(unsigned int)'
10
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_clone':
11
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1910: undefined reference to `operator delete(void*)'
12
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `Util::printFloat(float, char*)':
13
/mnt/c/Users/Standardbenutzer/Documents/ESP8266/Projects/ESP8266/Util/Util.cpp:13: undefined reference to `std::__throw_bad_function_call()'
14
/mnt/c/Users/Standardbenutzer/Documents/ESP8266/Projects/ESP8266/Util/Util.cpp:18: undefined reference to `std::__throw_bad_function_call()'
15
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `std::function<bool (int, int)>::operator()(int, int) const':
16
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:2464: undefined reference to `operator new(unsigned int)'
17
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `Util::get_value_with_compare(int const*, std::function<bool (int, int)>)':
18
/mnt/c/Users/Standardbenutzer/Documents/ESP8266/Projects/ESP8266/Util/Util.cpp:36: undefined reference to `operator new(unsigned int)'
19
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `~function':
20
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:2174: undefined reference to `operator new(unsigned int)'
21
Util/.output/eagle/debug/lib/Util.a(Util.o):(.rodata._ZTIZN4Util17get_highest_valueEPKiEUliiE_+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
22
Util/.output/eagle/debug/lib/Util.a(Util.o):(.rodata._ZTIZN4Util16get_lowest_valueEPKiEUliiE_+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
23
../lib/libc.a(lib_a-abort.o):(.literal+0x0): undefined reference to `_exit'
24
../lib/libc.a(lib_a-abort.o): In function `abort':
25
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/stdlib/abort.c:63: undefined reference to `_exit'
26
../lib/libc.a(lib_a-signal.o):(.literal+0x0): undefined reference to `_malloc_r'
27
../lib/libc.a(lib_a-signal.o):(.literal+0x4): undefined reference to `_getpid_r'
28
../lib/libc.a(lib_a-signal.o):(.literal+0x8): undefined reference to `_kill_r'
29
../lib/libc.a(lib_a-signal.o): In function `_init_signal_r':
30
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/signal/signal.c:110: undefined reference to `_malloc_r'
31
../lib/libc.a(lib_a-signal.o): In function `_raise_r':
32
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/signal/signal.c:163: undefined reference to `_getpid_r'
33
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/signal/signal.c:163: undefined reference to `_kill_r'
34
collect2: error: ld returned 1 exit status
35
../Makefile:403: recipe for target '.output/eagle/debug/image/eagle.app.v6.out' failed
section `.text' will not fit in region `iram1_0_seg'
auf eben diesen Fehler zurückzuführen sind, oder ob es sich um
"eigenständige" Fehler handelt.
Vincent H. schrieb:> Ich kenn mich mit dem ESP8266 leider nicht aus, aber eine kurze Google> Suche ergab das hier
Danke dir für den Hinweis, wie im verlinkten Beitrag angemerkt, sollte
ICACHE_FLASH definiert sein, dass ist in den Flags beim Kompilieren
enthalten:
hinzugefügt. Leider immer noch das selbe Verhalten.
Ich vermute, dass einfach irgendwas beim Linken schief läuft, sobald
Lambdas ins Spiel kommen. Mit Funktionspointern klappt das ja alles
wunderbar. Zu wenig Platz ist also definitiv nicht.
Max M. schrieb:> Ich vermute, dass einfach irgendwas beim Linken schief läuft, sobald> Lambdas ins Spiel kommen. Mit Funktionspointern klappt das ja alles> wunderbar. Zu wenig Platz ist also definitiv nicht.
Lambdas sind zwar ein tolles Sprachfeature, genau genommen sind sie aber
nur "syntactic sugar" für structs mit operator() overload. Das heißt für
den Linker ist ein Lambda ein Methodenaufruf wie jeder andere auch und
wenn das nicht funktionieren würde, dann wäre der Linker komplett
kaputt. :)
Der Rest des Outputs verrät mir aber das dein eigentliches Problem (bzw.
Probleme) ganz wo anders liegt. Zum einen siehts so aus als würdest du
mit RTTI compilieren
(https://en.wikipedia.org/wiki/Run-time_type_information) was via
Compiler-Flag "-fno-rtti" abstellen lässt. Und weiters dürften da eine
Reihe syscalls ala _exit, _malloc_r, _kill_r, usw. fehlen wobei ich
nicht grad sicher bin ob das nicht ein Folgefehler ist...
Probier mal mit fno-rtti zu compilieren und dann schau ma weiter ;)
Vincent H. schrieb:> Und weiters dürften da eine> Reihe syscalls ala _exit, _malloc_r, _kill_r, usw. fehlen wobei ich> nicht grad sicher bin ob das nicht ein Folgefehler ist...
So wie ich das sehe, meckert der Linker da bloß, weil er für das Zeug
keinen Platz mehr hatte.
Danke für eure Hilfe!
Vincent H. schrieb:> Probier mal mit fno-rtti zu compilieren und dann schau ma weiter ;)
Hier die Ausgabe, es hat sich leider nicht viel getan :(
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld: .output/eagle/debug/image/eagle.app.v6.out section `.text' will not fit in region `iram1_0_seg'
3
Util/.output/eagle/debug/lib/Util.a(Util.o):(.text._ZNSt14_Function_base13_Base_managerIZN4Util16get_lowest_valueEPKiEUliiE_E10_M_managerERSt9_Any_dataRKS6_St18_Manager_operation+0x0): undefined reference to `operator new(unsigned int)'
4
Util/.output/eagle/debug/lib/Util.a(Util.o):(.text._ZNSt14_Function_base13_Base_managerIZN4Util16get_lowest_valueEPKiEUliiE_E10_M_managerERSt9_Any_dataRKS6_St18_Manager_operation+0x4): undefined reference to `operator delete(void*)'
5
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_clone':
6
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1910: undefined reference to `operator new(unsigned int)'
7
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_destroy':
8
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1926: undefined reference to `operator delete(void*)'
9
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_get_pointer':
10
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1893: undefined reference to `operator new(unsigned int)'
11
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `_M_clone':
12
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:1910: undefined reference to `operator delete(void*)'
13
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `Util::printFloat(float, char*)':
14
/mnt/c/Users/Standardbenutzer/Documents/ESP8266/Projects/ESP8266/Util/Util.cpp:13: undefined reference to `std::__throw_bad_function_call()'
15
/mnt/c/Users/Standardbenutzer/Documents/ESP8266/Projects/ESP8266/Util/Util.cpp:18: undefined reference to `std::__throw_bad_function_call()'
16
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `std::function<bool (int, int)>::operator()(int, int) const':
17
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:2464: undefined reference to `operator new(unsigned int)'
18
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `Util::get_value_with_compare(int const*, std::function<bool (int, int)>)':
19
/mnt/c/Users/Standardbenutzer/Documents/ESP8266/Projects/ESP8266/Util/Util.cpp:36: undefined reference to `operator new(unsigned int)'
20
Util/.output/eagle/debug/lib/Util.a(Util.o): In function `~function':
21
/opt/esp/crosstool-NG/builds/xtensa-lx106-elf/xtensa-lx106-elf/include/c++/4.8.2/functional:2174: undefined reference to `operator new(unsigned int)'
22
../lib/libc.a(lib_a-abort.o):(.literal+0x0): undefined reference to `_exit'
23
../lib/libc.a(lib_a-abort.o): In function `abort':
24
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/stdlib/abort.c:63: undefined reference to `_exit'
25
../lib/libc.a(lib_a-signal.o):(.literal+0x0): undefined reference to `_malloc_r'
26
../lib/libc.a(lib_a-signal.o):(.literal+0x4): undefined reference to `_getpid_r'
27
../lib/libc.a(lib_a-signal.o):(.literal+0x8): undefined reference to `_kill_r'
28
../lib/libc.a(lib_a-signal.o): In function `_init_signal_r':
29
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/signal/signal.c:110: undefined reference to `_malloc_r'
30
../lib/libc.a(lib_a-signal.o): In function `_raise_r':
31
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/signal/signal.c:163: undefined reference to `_getpid_r'
32
/home/wjg/Repo/esp-open-sdk-20170622/crosstool-NG/.build/src/newlib-2.0.0/newlib/libc/signal/signal.c:163: undefined reference to `_kill_r'
33
collect2: error: ld returned 1 exit status
34
../Makefile:403: recipe for target '.output/eagle/debug/image/eagle.app.v6.out' failed
Vincent H. schrieb:> Und weiters dürften da eine> Reihe syscalls ala _exit, _malloc_r, _kill_r, usw. fehlen wobei ich> nicht grad sicher bin ob das nicht ein Folgefehler ist
Soweit ich das richtig im Kopf habe, hat espressif im SDK eigene,
äquivalente Funktionen implementiert (z.B. os_malloc anstatt malloc)
und die normalen Funktionsnamen sind nicht verfügbar.
Vincent H. schrieb:> dann wäre der Linker komplett> kaputt. :)
Danke für die Erklärung, das macht natürlich Sinn.
Kann es sein, dass der Linker aufgrund der Lambda-Geschichte nun die
ganzen C-Standardbibliothek nachlädt, deren Funktionen natürlich nicht
das Attribute ICACHE_FLASH_ATTR aufweisen und daher in den RAM gepackt
werden?
Wie gesagt ist ein Lambda ein Sprachfeature und nicht Teil der
Bibliothek.
Was aber auf jeden Fall Probleme macht ist std::function. Der
"std::__throw_bad_function_call()" etwa ist eine Exception die von
std::function geworfen werden kann. An der Stelle sei erwähnt dass
"fno-exceptions" wohl auch ein sinnvolles Flag wäre...
Weiters kann std::function allozieren falls der interne Buffer für das
Callable das man hineinspeichern will nicht ausreicht. Das verursacht
dann vermutlich die Linkerfehler in Bezug auf malloc und Co.
Und ja, falls es von Espriff keine angepasste Bibliothek gibt, dann wird
das ICACHE_FLASH_ATTR Attribut wohl überall fehlen... :/
Max M. schrieb:> deren Funktionen natürlich nicht> das Attribute ICACHE_FLASH_ATTR aufweisen und daher in den RAM gepackt> werden?
Kannst Du mal dein Linker-Script und das .h-File, in dem das
ICACHE_FLASH_ATTR Macro definiert ist posten?
Lässt sich denn ein C++ Programm ohne Lambdas und std::funktion
compilieren?
Eine undefined reference auf new etc. deutet ja eher auf ein
grundsätzliches Problem hin.
Falls da die newlib verwendet wird, hilft RTFM.
Oliver
Oliver S. schrieb:> Lässt sich denn ein C++ Programm ohne Lambdas und std::funktion> compilieren?
Ja, das funktioniert alles einwandfrei.
Markus F. schrieb:> Kannst Du mal dein Linker-Script
Wie der Linker aufgerufen wird siehst du meinen Beiträgen weiter oben.
Max M. schrieb:> Wie der Linker aufgerufen wird siehst du meinen Beiträgen weiter oben.
Ja. Und da sehe ich auch, daß ein Linker-Script (../ld/eagle.app.v6.ld)
verwendet wird. Du weißt, was ein Linker-Script macht?
Das Script würde ich gerne sehen. Und das Macro auch.
Aber natürlich nur, falls Du (noch) Hilfe haben möchtest.
Markus F. schrieb:> Ja. Und da sehe ich auch, daß ein Linker-Script (../ld/eagle.app.v6.ld)> verwendet wird.
Danke für den Hinweis. Ich hab das Dokument angehängt.
Markus F. schrieb:> Du weißt, was ein Linker-Script macht?
Ehrlich gesagt nicht so richtig, ich würde vermuten, es bastelt aus den
.o-Dateien eine .hex-Datei, die in den Controller geflasht wird.
Markus F. schrieb:> Aber natürlich nur, falls Du (noch) Hilfe haben möchtest.
Unbedingt, sehr gerne. Vielen Dank!
Oliver S. schrieb:> Lässt sich denn ein C++ Programm ohne Lambdas und std::funktion> compilieren?
Auch mit Lambda-Ausdrücken kein Problem.
Oft verwendet um z.B. Handler für HTTP-Pfade anzugeben.
z.B.
std::function hat seine Berechtigung. Ganz sicher aber nicht für die
hier gestellte Aufgabe. The way to go ist, get_value_with_compare() als
Template zu implementieren. Ich bin mir sicher, dass dann deine Probleme
wieder auf dem Stand sind, den du mit Funktionspointern hattest (nämlich
keine).
Das Linker-Script stopft Code aller möglichen Libraries in das
irom0_0_seg Segment, allerdings nicht die libc.a und die libstdc++.a
Ich würde mal versuchen, diese Libraries auch dort reinzupacken, also im
Linker-Script hinter
*libmbedtls.a:(.literal.* .text.*)
analog die libstdc++.a und libc.a aufführen.
Was versteckt sich in
"../ld/eagle.rom.addr.v6.ld"?
Das ist eine Erweiterung des Linker-Scripts, die Du noch nicht gezeigt
hast.
So, gerade wieder von der Arbeit zu Hause:
Markus F. schrieb:> Was versteckt sich in>> "../ld/eagle.rom.addr.v6.ld"?
Hab ich nun auch angefügt.
Vielen Dank, dass du dir die Mühe machst, die Dateien durchzusehen!
Markus F. schrieb:> analog die libstdc++.a und libc.a aufführen.
Also so?
Max M. schrieb:> Markus F. schrieb:>> Was versteckt sich in>>>> "../ld/eagle.rom.addr.v6.ld"?>> Hab ich nun auch angefügt.
Aha. Das scheint mir der "RAM-Cache" für's ROM zu sein (viel genutzte
Routinen im RAM gehalten). Damit wird wohl der Startup-Code rumtricksen.
Da sind auch Routinen aus der C-Library dabei. Kann sein, daß man ohne
den Startup-Code (bzw. die libc.a) zu ändern da gar nichts tun kann.
gdfgsdgsg schrieb:> damit liegt laut linkerfile .text im ITCM RAM
... um das sicher sagen zu können, brauchen wir (ich zumindest) das
Macro - aber das zeigt der TO ja nicht (trotz mehrfacher Aufforderung).
Markus F. schrieb:> um das sicher sagen zu können, brauchen wir (ich zumindest) das> Macro - aber das zeigt der TO ja nicht (trotz mehrfacher Aufforderung).
Ich hab mal gesucht, ist das die Information, die du benötigst?
Max M. schrieb:> Markus F. schrieb:>> um das sicher sagen zu können, brauchen wir (ich zumindest) das>> Macro - aber das zeigt der TO ja nicht (trotz mehrfacher Aufforderung).>> Ich hab mal gesucht, ist das die Information, die du benötigst?
Fast. Den gesamten Überblick hätten wir, wenn Du von c_types.h mal die
Zeilen 90 - 110 oder so zeigen würdest.
P.S.: hast Du jetzt den Umbau des Linkerscripts mal ausprobiert? Laß'
dir doch nicht immer alles einzeln aus der Nase ziehen...