Hallo Ich will einen aduc7026 programmieren. Dazu verwende ich Eclipse, gnuarm und OpenOCD. Ich versuche mich gerade in der dynamischen Speicherverwaltung. Ich verwende dies für ein Menu bestehend aus verketteten Listen. Mit -O0 funktioniert das ganze. Mit -O1 oder -O2 leider nicht mehr. Der Debugger bleibt an der ersten stelle stehen, an der malloc() aufgerufen wird. Leider habe ich keine Ahnung wieso. Meine erste Idee war, dass vielleicht ein Fehler in den syscalls, vor allem sbrk, steckt. Ich habe daher ein kleines Projekt erzeugt, in dem fast nur der malloc() Aufruf drin ist. Natürlich funktioniert darin alles :( In meinem eigentlichen Projekt sind noch ca. 30kb Flash und 4kb Ram laut map-File frei. Daher denke ich nicht, dass beim ersten malloc() Aufruf schon der Speicher voll ist. Leider kenne ich mich mit allem, was die newlib betrifft, noch nicht so wirklich aus. Ich wüsste auch nicht, welche Variablen wegoptimiert werden könnten. Hat einer von euch ein paar Tips, wonach ich schauen könnte? Viele Grüsse, Tilo
Ich konnte das Problem jetzt deutlich eingrenzen. Bei -O2 wird mehr SRam verbraucht. Ich verwende folgende sbrk Funktion:
1 | void * _sbrk_r( |
2 | struct _reent *_s_r, |
3 | ptrdiff_t nbytes) |
4 | {
|
5 | static char *heap_ptr = end; /* Points to current end of the heap. */ |
6 | char *base; /* errno should be set to ENOMEM on error */ |
7 | base = heap_ptr; /* Point to end of heap. */ |
8 | //heap_ptr += nbytes; /* Increase heap. */
|
9 | /* Zero new allocated memory */
|
10 | for (i=0; i<nbytes; i++) { |
11 | *heap_ptr = 0; |
12 | heap_ptr++; |
13 | }
|
14 | return base; /* Return pointer to start of new heap area. */ |
15 | }
|
Mit folgendem Code versuche ich nun, auf den Speicher zuzugreifen:
1 | int tmp = sizeof(*ListIter); |
2 | Menu_Main = malloc(tmp); |
tmp ist 12. malloc() ruft die sbrk funktion 2x auf. Bei ersten mal werden 32Bytes angefragt, beim zweiten mal werden ganze 3920Bytes angefordert. Laut der MAP-File liegt der letze belegte Speicherblock bei: 0x00011090 PROVIDE (end, .) Der Speicher geht bis Adresse 0x12000. Der gesammte "freie" Speicher sind also genau 3920+32Bytes. Leider liegt der Stack bei 0x00011FFC. Versucht hier malloc Speicher zu reservieren, der vom Stack verwendet wird? Wie kann ich das verhindern? Warum versucht malloc den gesammten freien Speicher beim ersten aufruf zu reservieren? Warum nicht nur das, was wirklich gebraucht wird? Vielen Dank, Tilo
Gast wrote: Zumindest einen wenig ideenreicheren Nickname würde man sich wünschen - egal. > Ich konnte das Problem jetzt deutlich eingrenzen. Bei -O2 wird mehr SRam > verbraucht. > > Ich verwende folgende sbrk Funktion: >
1 | > void * _sbrk_r( |
2 | > struct _reent *_s_r, |
3 | > ptrdiff_t nbytes) |
4 | > { |
5 | > static char *heap_ptr = end; /* Points to current end of the heap. |
6 | > */
|
7 | > char *base; /* errno should be set to ENOMEM on error */ |
8 | > base = heap_ptr; /* Point to end of heap. */ |
9 | > //heap_ptr += nbytes; /* Increase heap. */ |
10 | > /* Zero new allocated memory */ |
11 | > for (i=0; i<nbytes; i++) { |
12 | > *heap_ptr = 0; |
13 | > heap_ptr++; |
14 | > } |
15 | > return base; /* Return pointer to start of new heap area. */ |
16 | > } |
17 | >
|
> > Mit folgendem Code versuche ich nun, auf den Speicher zuzugreifen: >
1 | > int tmp = sizeof(*ListIter); |
2 | > Menu_Main = malloc(tmp); |
3 | >
|
> > tmp ist 12. malloc() ruft die sbrk funktion 2x auf. Bei ersten mal > werden 32Bytes angefragt, beim zweiten mal werden ganze 3920Bytes > angefordert. Nicht mehr ganz genau in Erinnerung aber so ungefähr: Der erste Aufruf dient dazu, den Anfang des Heaps zu bestimmen, dann kommt erst die eigentliche Anforderung für eine "Page". > Laut der MAP-File liegt der letze belegte Speicherblock > bei: > 0x00011090 PROVIDE (end, .) > Der Speicher geht bis Adresse 0x12000. Der gesammte "freie" Speicher > sind also genau 3920+32Bytes. Soweit erinnert, ist die Standardgröße in der newlib für eine Page 4kBytes, der ""freie" Speicher"" reicht also nach den gemachten Angaben nicht aus dafür. sbrk ist ja nur ein kleiner Teil der dynamischen Speicherverwaltung, der die Verbindung zur Hardware herstellt. Der Rest ist in der Newlib (newlib/libc/stdlib...), die nicht grade ideal für Kleinstrechner mit wenig RAM. ist aber es gibt wohl keine kostenlose Alternative mit ähnlich liberaler Lizenz. > Leider liegt der Stack bei 0x00011FFC. Versucht hier malloc Speicher zu > reservieren, der vom Stack verwendet wird? > > Wie kann ich das verhindern? Wenn meine Vermutung stimmt: indem man im code der newlib etwas anpasst und sie neu zusammenbaut. Irgendwo im Code gibt es eine Einstellung für die pagesize. Wenn richtig erinnert ist da ein #if SMALLMEM o.ä., wenn definiert wird die Seitengröße 128(256?) Bytes gesetzt. Evtl. gibt es auch noch irgend einen config-Schalter. Nie selbst ausprobiert. > Warum versucht malloc den gesammten freien Speicher beim ersten aufruf > zu reservieren? Denke, das ist nur augenscheinlich so, da der "gesammmte freie Speicher" kleiner ist als die Pagesize. >Warum nicht nur das, was wirklich gebraucht wird? Wird wohl innerhalb der 'Verwaltungseinheiten' auch so sein, nur soviel Platz muss man wohl zumindest bereitstellen. Alles nur meine Vermutung/Halbwissen, hatte das Problem bis dato noch nicht, nutze malloc auch nur selten auf Controllern. Genaueres kann man evtl. in der newlib mailing-liste erfahren, wenn der Quellcode nicht informativ genug ist. Falls es so knapp ist und eine Art zeitweise Speichernutzung angestrebt wird, kann man evtl. das Konzept der Memory-Bags nutzen. Ist ein Art Pseudo-Malloc, das aber auf Speicher in data-segment Zugreift (=byte/word/dword-arrays). Etwas weniger flexibel aber einfacher zu überschauen und mglw. auch sicherer. Vgl. z.B. DB101 Beispielcode von Atmel.
Martin Thomas wrote: > ... ist aber es gibt wohl keine kostenlose > Alternative mit ähnlich liberaler Lizenz. 2.11BSD könnte mal einen Blick Wert sein. Das ist ja nun auch seit einigen Jahren komplett frei erhältlich, und seine Zweckbestimmung war einstmals, auf einer PDP-11 zu laufen. Die dürfte speichermäßig ähnlich limitiert gewesen sein wie ein ARM7 oder großer AVR.
Guten morgen Vielen Dank für eure Erläuterungen. Das bringt ein wenig Licht ins Dunkle. Es hat mich verwundert, dass der Speicher genau bis zum Ende genutzt werden sollte. Das muss aber wirklich ein Zufall gewesen sein, da Änderungen im Linker-Skript keine Auswirkungen haben. Ich dachte, die Newlib würde mit einem kleinen arm etwas mehr "Spaß" machen. Bei meinen Versuchen mit printf() hat es sich schon angedeutet, dass dem nciht so ist. Mein eigener Code um eine Zeile per Uart auszugeben hatte 4kb, mit printf ohne Floats waren es 15kb. @Martin: Danke für deine Tips zu Newlib. Das Compilerersymbol lautet "SMALL_MEMORY". Damit werden bei den ersten durchläufen 32Bytes und danach 128Byte Blöcke reserviert. Mit diesem Parameter läuft es jetzt. Ich habe meine Toolchain nach der Anleitung für OSX erzeugt: http://embdev.net/wikisoftware_en/index.php?title=ARM_GCC_toolchain_for_Linux_and_Mac_OS_X Ich habe den Wiki-Eintrag mit einem Hinweis ergänzt. Ich brauche keine echte dynamische Speicherverwaltung. Ich benutze das ganze nur, um meine Menüs zu erzeugen. Der Speicher muss nicht mehr freigegeben werden. Ich habe daher die sbrk Funktion ein wenig angepasst und verwende jetzt die statt malloc(). Bisher funktioniert das gut. Viele Grüsse, Tilo
Tilo wrote: > Guten morgen > > Vielen Dank für eure Erläuterungen. Das bringt ein wenig Licht ins > Dunkle. Es hat mich verwundert, dass der Speicher genau bis zum Ende > genutzt werden sollte. Das muss aber wirklich ein Zufall gewesen sein, > da Änderungen im Linker-Skript keine Auswirkungen haben. > > Ich dachte, die Newlib würde mit einem kleinen arm etwas mehr "Spaß" > machen. ""Spaß"" mit einer libc...egal. Wenn man ungefähr weiss, was man besser mit Vorsicht benutzt, ist das ja auch so. In neueren Versionen ist sogar ein wenig "handoptimierter" ARM-Assemblercode für einige Funktionen enthalten. > Bei meinen Versuchen mit printf() hat es sich schon angedeutet, > dass dem nciht so ist. Mein eigener Code um eine Zeile per Uart > auszugeben hatte 4kb, mit printf ohne Floats waren es 15kb. Ja, stdio der newlib ist auch nicht so wirklich gut für die "Kleinen", selbst abgesehen von der Abhängigkeit zu malloc et al. Könnte man wahrscheinlich mit einem Ansatz, wie Ihn die avr-libc nutzt deutlich verbessern aber offensichtlich hatte noch niemand genug Leidensdruck, sich darum zu kümmern. Wobei sich ein Blick in den Quellcode der newlib und Fragen in der newlib-ML mglw. lohnt. Der ganze Code ist voll von config-Optionen, von denen einige auch nur im Code per Kommentar ansatzweise und knapp dokumentiert sind. Einer der Entwickler weiß vielleicht auf Anhieb mehr. Ganz nette Alternative für stdio, allerdings nur mit recht eingeschränkter Funktionalität, findet man in den Softpacks von Atmel für AT91. Lassen sich relativ leicht portieren und Lizenz ist liberal. > @Martin: > Danke für deine Tips zu Newlib. Das Compilerersymbol lautet > "SMALL_MEMORY". Damit werden bei den ersten durchläufen 32Bytes und > danach 128Byte Blöcke reserviert. Mit diesem Parameter läuft es jetzt. ah. SMALL_MEMORY, lag ich ja nicht allzu weit daneben. > Ich habe meine Toolchain nach der Anleitung für OSX erzeugt: > http://embdev.net/wikisoftware_en/index.php?title=ARM_GCC_toolchain_for_Linux_and_Mac_OS_X > > Ich habe den Wiki-Eintrag mit einem Hinweis ergänzt. Prima. > Ich brauche keine echte dynamische Speicherverwaltung. Ich benutze das > ganze nur, um meine Menüs zu erzeugen. Der Speicher muss nicht mehr > freigegeben werden. Ich habe daher die sbrk Funktion ein wenig angepasst > und verwende jetzt die statt malloc(). Bisher funktioniert das gut. Liest sich durch gut. Weiterhin viel Erfolg.
Jörg Wunsch wrote: > Martin Thomas wrote: > >> ... ist aber es gibt wohl keine kostenlose >> Alternative mit ähnlich liberaler Lizenz. > > 2.11BSD könnte mal einen Blick Wert sein. Das ist ja nun auch seit > einigen Jahren komplett frei erhältlich, und seine Zweckbestimmung > war einstmals, auf einer PDP-11 zu laufen. Die dürfte speichermäßig > ähnlich limitiert gewesen sein wie ein ARM7 oder großer AVR. Ist damit das: http://www.freebsd.org/cgi/cvsweb.cgi/src/lib/libc/ gemeint? Wenn nicht, kannst Du bitte einen direkten Link angeben? Befragung von google mit 2.11BSD brachte overflow im der zweiten HDI Stufe.
Martin Thomas wrote: > Befragung von google mit 2.11BSD brachte overflow im der zweiten HDI > Stufe. Beispielsweise hier: http://unixarchive.medienfuzzis.com/PDP-11/Trees/2.11BSD/ Anlaufpunkt für diesen antiken Code ist "The Unix Heritage Society", http://www.tuhs.org/ .
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.