Hallo zusammen,
Ich habe ein Problem bei einem Projekt auf dem STM32f407 uC.
IDE CooCox CoIDE 1.7.8
Toolchain Arm none eabi 4.8 2014q1
(hab aber auch schon CoIDE 2.0.3 und und die neuere 4.9 2015q2 getestet)
Das gesamte Projekt ist schon etwas umfangreicher und lief bis dahin
auch alles soweit (Taster, TFT über FSMC, UART Kommunikation mit
externer Hardware... )
Beim Anlegen eines Arrays kam es jetzt zu dem Problem, dass sich der
Controller aufgehangen hat wenn es mit 600 Elementen deklariert wurde.
1
uint32_tOne_Second_Data_Storage[600];
Bis 100 Elemente läuft der Code und ab 1000 auch.
-> Also erstmal mit 1000 probiert.
Beim kontrollieren der Daten im Array ist dann aufgefallen das Teile
darin Fehlerhaft sind. (Darin sind Messwerte gespeichert und die
Fehlerhaften Daten können nicht vom Sensor kommen, das wurde
ausgeschlossen)
Die Fehlerhaften Teile sind vermutlich durch überschreiben entstanden.
Im nächsten Schritt hab ich versucht die exakte Stelle herauszufinden
wo der Cotnroller sich verabschiedet.
An anderer Stelle im Programm wo ein globales Array
1
volatileuint8_tG_UART_Receive_Buffer[1000];
(Ein Receive Buffer der soweit auch richtig befüllt wird) wieder auf 0
zurück gesetzt wird bleibt er in einer Schleife hängen.
Problem hier scheint zu sein das die Count Variable überschrieben wird.
und zwar laut Memory Viewer von dem globalen Array (Receive Buffer)
Adresse vom Receive Buffer 0x20005FD4
Adresse von Count 0x2000607C
Zwischen dem Array und der Count Variable sind nur 168 Byte obwohl das
Array mit 1000 deklariert wird.
Das scheint das Problem zu sein.
Wer ist denn verantwortlich für die Verteilung von Variablen im Speicher
? Compiler ?
Vielleicht kommt es ja schon an anderer Stelle zu einem Problem und das
zieht sich nur bis dahein durch ...
An den Grenzen vom Controller bin ich noch lange nicht angelangt,
vorausgesetzt die Werte bei .text .data und .bss nach dem Kompilieren
stimmen.
Hat jemand eine Idee was man hier machen kann ?
Vielen Dank schonmal & Viele Grüße
Stefan
das sieht nach einem extrem umfangreichen Projekt aus! Benutzt du ein
RTOS?
Angenommen, du hast kein RTOS am laufen, dann hast du bis zu diesem
genannten Punkt einen Stack von fast 90kB angehäuft.
Dann bleiben etwa noch 20kB für static und global übrig.
Das sieht nach einem "Stack overflow" aus, oder Stack collision, oder
wie auch immer man das nennen mag.
Arm none eabi 4.8 2014q1 ist doch GCC? Dann probier mal, was der static
stack analysis sagt. Kompiliere mit
Little B. schrieb:> Angenommen, du hast kein RTOS am laufen, dann hast du bis zu diesem> genannten Punkt einen Stack von fast 90kB angehäuft.> Dann bleiben etwa noch 20kB für static und global übrig.
Darf man fragen wie du auf die 90kB kommst?
Ingo L. schrieb:> Little B. schrieb:>> Angenommen, du hast kein RTOS am laufen, dann hast du bis zu diesem>> genannten Punkt einen Stack von fast 90kB angehäuft.>> Dann bleiben etwa noch 20kB für static und global übrig.> Darf man fragen wie du auf die 90kB kommst?
der STM32F407 hat 112kB RAM, das ist dann Endadresse 0x2001C000
Stefan schrieb:> Adresse von Count 0x2000607C
0x2001C000 - 0x2000607C = 0x15F84 = 89988
Little B. schrieb:> 0x2001C000 - 0x2000607C = 0x15F84 = 89988
Aber ist das nicht von hinten gezählt? Ich denke eher das ist der Platz
den er noch frei hat! Weil Variablen werden doch bei 0 (hier 0x20000000)
angelegt, oder landen temporäre Daten aufm Stack???
Verbraucht würde ich eher sagen 607C = 24,7kB.
Ingo L. schrieb:> Little B. schrieb:>> 0x2001C000 - 0x2000607C = 0x15F84 = 89988> Aber ist das nicht von hinten gezählt?
Klar, denn der Stack beginnt hinten und wächst nach vorne.
> Ich denke eher das ist der Platz> den er noch frei hat!
Nein
> Weil Variablen werden doch bei 0 (hier 0x20000000)> angelegt
Nein
> oder landen temporäre Daten aufm Stack???
Ja natürlich, denn dafür ist der Stack da (neben den
Rücksprungadressen).
Vielen Dank schonmal für die bisherigen Antworten.
Ich habe nun mal das ganze mit fstack usage kompiliert und alle Werte
aus allen files addiert. Dabei kommt was um die ca 11000 Byte raus.
Beim kompilieren steht hinterher drunter:
text data bss dec hex
318412 2372 25212 345996 5478c
da sehe ich also auch nicht wirklich ein Problem.
Allerdings sind im Memory View folgende Bereiche belegt:
20000000 - 20002508
20005E10 - 200060B8
200064F0 - 2001BFFF (und hier sehen die Werte irgendwie verdächtig aus
und gehen auch über die Addresse im selben Stil weiter)
Werden bei dem fstack usage irgendwelche Sachen ausser acht gelassen ?
Sehe ich das richtig das es sich bei dem .text um den belegten Flash
handelt und bei .bss um den belegten RAM ?
Stefan schrieb:> Sehe ich das richtig das es sich bei dem .text um den belegten Flash> handelt und bei .bss um den belegten RAM ?
So isses. Du kannst dir ja mal das *.map file anschauen, alles hinter
der ersten '.bss' Marke wird dir bekannt vorkommen, da stehen deine
globalen Variablen ziemlich zu Anfang, mit der jeweiligen Länge.
Ich sehe in meinen mapfiles produziert von Coocox übrigens keine Nutzung
des 64k Corememory, mit einem entsprechenden Linkerskript sollte man die
zusätzlich nutzbar machen können.
Grundsatzfrage:
Wieso brauchst du so ein grosses Array?
Mach doch ein kleiner FIFO mit einem anständigen Protokoll und
Fehlerhandling, dann kommst du auch mit einem kleineren Array von 50-100
aus.
Patrick B. schrieb:> Grundsatzfrage:> Wieso brauchst du so ein grosses Array?
Ich z.B. brauche sowas als Audiodaten Puffer, um die Zugriffe auf USB
Speicher in Grenzen zu halten. Habe hier allerdings keine Probleme mit
2*48kB Arrays.
Stefan schrieb:> Beim kompilieren steht hinterher drunter:> text data bss dec hex> 318412 2372 25212 345996 5478c>> da sehe ich also auch nicht wirklich ein Problem.
Du hast also 25kByte Globalen RAM, der mit 0 initialisiert wird (bss),
und nochmals 2kByte RAM, der mit Werten aus dem Flash vorinitialisiert
wird (data). Zusammen sind das schonmal etwa 27kByte RAM, die belegt
sind.
Was du hier nicht siehst, ist der Stack. Dein Stack darf jetzt nicht
mehr größer werden als 87kByte, es sei denn, du schaufelst die globalen
daten in ein anderes SRAM (z.B. SRAM2, das hat 16kByte, oder CCM SRAM,
das hat 64kByte)(Modifikationen im Linkerfile!)
Anderer Vorschlag:
Du legst im Linkerfile eine Marke hinter die .bss-Section und schützt an
der Stelle vier Bytes mit Hilfe der MPU. Sobald die MPU einen Interrupt
auslöst, hast du eine Stack-Collision.
OK, zugegeben, das behebt noch nicht dein Problem. Aber auf diese Weise
kannst du ein unvorhergesehenes Verhalten eines Programms verhindern.
Danke schonmal für die Hilfe.
Leider hat bisher nichts eine Lösung ergeben.
Was mich verwundert ist wie ich >70kB Stack zusammen bekommen soll.
Und wo das herkommen soll.
Die 11kB die beim zusammenzählen der fstack-usage Files waren
realistisch.
Die 25 + 2 kB die nach dem Build dastehen kommen auch so etwa hin.
Zusammen also noch nicht mal annähernd im kritischen Bereich.
Patrick B. schrieb:> Grundsatzfrage:> Wieso brauchst du so ein grosses Array?
Das Array brauch ich weil ich ohne Unterbrechung Messwerte sammeln muss
mit denen dann hinterher noch ein paar Berechnungen gemacht werden und
dann in einen externen Flash gespeichert werden.
Auf das Protokoll habe ich auch keinen Einfluss das die angeschlossene
Hardware von extern kommt.
Ich habe mir das .map File mal angeschaut bin aber nicht so wirklich
schlau draus geworden.
Daher nun im Anhang. Vielleicht könnte bitte jemand mal drüber schaun ob
da irgendwas komisch ist.
Little B. schrieb:> Anderer Vorschlag:> Du legst im Linkerfile eine Marke hinter die .bss-Section und schützt an> der Stelle vier Bytes mit Hilfe der MPU. Sobald die MPU einen Interrupt> auslöst, hast du eine Stack-Collision.> OK, zugegeben, das behebt noch nicht dein Problem. Aber auf diese Weise> kannst du ein unvorhergesehenes Verhalten eines Programms verhindern.
Das werde ich mal ausprobieren. Vielleicht kann man so auch rausfinden
welche Funktion das verursacht?
Vielen Dank schonmal
Das Mapfile zeigt keine offensichtlichen Fehler. Deshalb müsste man sich
den Callstack mal anschaun.
Für die MPU hab ich mal folgendes zusammengepfuscht:
1
externuint8_t_ebss;
2
MPU->RNR=0;
3
MPU->RBAR=(uint32_t)&_ebss;
4
MPU->RASR=0x9;
5
MPU->CTRL=0x5;
Jetzt musst du nur noch vor die _ebss Marke im Linkerskript
1
.=ALIGN(0x20)
schreiben. Ungetestet und Benutzung auf eigene Gefahr!
Hi,
hab mal ein Blick in dein MAP-File geworfen.
Du benutzt eine art malloc??? Wie viel Speicher ist da reserviert und
welcher? (oder ist der heap = 0 ?)
Zur Zeit benutzt du nur den 'ram' Bereich, der andere ist unbenutzt?
(ram1)
Stephan schrieb:> Hi,> hab mal ein Blick in dein MAP-File geworfen.> Du benutzt eine art malloc??? Wie viel Speicher ist da reserviert und> welcher? (oder ist der heap = 0 ?)> Zur Zeit benutzt du nur den 'ram' Bereich, der andere ist unbenutzt?> (ram1)> 0x20020000 __StackTop = (ORIGIN (ram) + 0x20000)> 0x2001f800 __StackLimit = (__StackTop - SIZEOF> (.co_stack))> Das ist dein Stackbereich! 2KB
Das ist mir auch aufgefallen
malloc wird von sprintf verwendet und hat seinen eigenen globalen
Speicher in der bss-Section. Ich sehe hier kein Problem.
Ja, die Stack-Größe ist falsch angegeben, aber das wird nirgends
evaluiert, daher egal.
Dann leg doch mal zum testen den Stack in den Bereich von 'ram1', dann
kannst du sicher sein das da kein Speicher vom Stack überschrieben
wird!!!
Little B. schrieb:> Ja, die Stack-Größe ist falsch angegeben, aber das wird nirgends> evaluiert, daher egal.
Doch schon!
Dein RAM wird kleiner!
Dein Programm wird in unterschiedliche Teilbereiche(CONST,VAR...)
zerlegt und diese werden in die von 'dir' bereit gestellten
Speicher-Bereiche wie RAM, ROM, EEPROM zugeteilt. Werden nun die
Teilbereiche zu groß für die Speicher-Bereiche bekommst du eine
Fehlermeldung!!!!
Der RAM kann gar nicht kleiner werden.
Er kann höchstens unterschiedlich aufgeteilt sein.
Fakt ist, dass die Linker-Marke "__StackLimit" in der Applikation nicht
verwendet wird, sondern nur zur Überwachung zum Link-Zeitpunkt dient.
Da der TO aber offenbar nicht so recht den Überblick über seinen Stack
hat, kann er hier keinen aussagekräftigen Wert eintragen.
Ein Linker-Error würde erzeugt werden, wenn er im aktuellen Projekt eine
Stack-Size von 100k angeben würde. Aber was würde das am realen
Verhalten des Programms ändern?
Little B. schrieb:> Das Mapfile zeigt keine offensichtlichen Fehler. Deshalb müsste man sich> den Callstack mal anschaun.
Das geht mit bt und frame Befehl in der command line von CoIDE oder ist
damit was anderes gemeint bzw gibts nen anderen Weg ?
Little B. schrieb:> Jetzt musst du nur noch vor die _ebss Marke im Linkerskript. = ALIGN> (0x20)> schreiben.
Ok dann muss ich mich erstmal mit Linkerskript schreiben generell
auseinander setzen da ich bisher nur die Standard Link Konfigurationen
von CoIDE nutze ohne ein extra Linkfile einzubinden.
Stephan schrieb:> Du benutzt eine art malloc??? Wie viel Speicher ist da reserviert und> welcher? (oder ist der heap = 0 ?)
Das ist tatsächlich das malloc von sprintf das ich für meine debug
Ausgaben verwende. Was meinst du mit Heap in dem Zusammenhang ??
Stephan schrieb:> Zur Zeit benutzt du nur den 'ram' Bereich, der andere ist unbenutzt?> (ram1)> 0x20020000 __StackTop = (ORIGIN (ram) + 0x20000)> 0x2001f800 __StackLimit = (__StackTop - SIZEOF> (.co_stack))> Das ist dein Stackbereich! 2KB
Ja ich nutze nur den Bereich ab 0x20000000. die anderen Bereiche müsste
man im Source ja explizit ansprechen damit diese genutzt werden, richtig
?
Das mit dem Stackbereich scheint dann eine Standard Einstellung von
CooCox zu sein. Kann ich das ändern bzw ist das auch etwas was im
Linkerfile gemacht wird und CooCox hinter meinem Rücken macht sofern ich
kein eigenes Linkerskript benutze ?
Little B. schrieb:> Da der TO aber offenbar nicht so recht den Überblick über seinen Stack> hat, kann er hier keinen aussagekräftigen Wert eintragen.
Gibt es da eine Methodik den besser im Überblick zu behalten ? Ich habe
mir tatsächlich bisher nie große Gedanken über sowas gemacht. Muss ich
nun etwa Buchführung darüber betreiben wieviel da jede Funktion belegt ?
Ich dachte bisher immer wenn irgendwas Speichermäßig knapp wird, wird
mir das nach dem build angezeigt (da war ich wohl zu naiv ...)
Hey Little
ka wie es bei dir ist, aber der Heap und der Stack wird normaler weise
von dem zur Verfügung stehendem RAM abgezogen und kann so nicht mehr als
Variablen-. oder 'RAM-Funktion'-Speicher zur Verfügung stehen!!!!
Stefan schrieb:> Das ist tatsächlich das malloc von sprintf das ich für meine debug> Ausgaben verwende. Was meinst du mit Heap in dem Zusammenhang ??
Ok. Heap ist der Speicher den malloc nutzt.(dyn. Speicher + Verwaltung)
Kannst du nicht auf snprintf ausweichen. (einer Funktion ohne malloc!)
Stefan schrieb:> Ja ich nutze nur den Bereich ab 0x20000000. die anderen Bereiche müsste> man im Source ja explizit ansprechen damit diese genutzt werden, richtig> ?
ja, geht aber ganz einfach. Hast du schon eine section im 'ram1'?
Du wirst ja nicht der erste sein der den Speicher nutzen will.
Kleines Update.
Ich habe nun mal an einigen Stellen im Code Platz eingespart von zB.
Arrays die etwas großzügiger dimensioniert waren.
Jetzt komme ich auf data 2364 und bss 8012. Also eine merkliche
Verringerung
an beutztem RAM.
Das verhalten bleibt jedeoch das gleiche. Also denke ich, dass das
Problem vielleicht doch an einer anderen Stelle liegt.
Ich werde das Projekt mal neu aufsetzen und in diesem Zuge auch noch
alte Codestellen rauswerfen von früheren Versionen um auszuschliessen,
dass da noch ein Fehler besteht.
Noch eine Frage bezüglich des Überbliks über den Stack Verbrauch.
Wie kann ich das denn gut im Überblick behalten ?
Schon nach dem einbinden der CMSIS Libs von ST wird ja hier bereits
Platz belegt.
Welche Sachen kommen denn genau auf den Stack ? Zur Not schreib ich mir
das halt wirklich auf aber vielleicht hat jemand von euch einen Tip wie
man das strukturierter angehn kann.
Danke schonmal
Stefan
Stephan schrieb:> Hey Little> ka wie es bei dir ist, aber der Heap und der Stack wird normaler weise> von dem zur Verfügung stehendem RAM abgezogen und kann so nicht mehr als> Variablen-. oder 'RAM-Funktion'-Speicher zur Verfügung stehen!!!!
Das kommt darauf an, wie die IDE den Speicher verwaltet. Meistens wirds
dann doch nur mit linkerfiles (wie es hier der fall ist) geregelt.
Veranschaulichen wir uns eben mal den RAM. Dieser beginnt bei 0x20000000
und hört bei 0x20020000 auf (SRAM1 und SRAM2 sind in diesem Linkerfile
zusammengefasst). Erst kommt .data rein, dann .bss, dann .heap und ans
Ende wird .stack angehängt
Stefan schrieb:> Gibt es da eine Methodik den besser im Überblick zu behalten ? Ich habe> mir tatsächlich bisher nie große Gedanken über sowas gemacht.
Ich hab mich die letzten Tage mit dem Thema beschäftigt, weil ich in
dieser Hinsicht bisher auch immer sehr blauäugig war. Der GCC kann laut
diversen Internetforen den Befehl "-fstack-usage" und
"-fcallgraph-info". Diese beiden Befehle spucken dann (angeblich) alle
nötigen Informationen aus, um den Stack berechnen zu können. Dummerweiße
kann der GNU Crosscompiler (version 4.9 2015q2) nur das "-fstack-usage".
Dass es eine Funktion gibt, die dir eine Aussage trifft wie etwas "Dein
Programm braucht 42kByte Stack" habe ich noch nicht gefunden. (Statisch!
Nicht in Laufzeit! Denn das wäre ja lächerlich einfach)
Little B. schrieb:> kann der GNU Crosscompiler (version 4.9 2015q2) nur das "-fstack-usage".> Dass es eine Funktion gibt, die dir eine Aussage trifft wie etwas "Dein> Programm braucht 42kByte Stack" habe ich noch nicht gefunden. (Statisch!
nun -fstack-usage gibt dir diese Information ja auf Funktionsebene. Das
hielt ich für mich schon für ganz brauchbar.
Wie sich das jetzt aufsummiert zu einem maximalen Stackverbrauch, den
dein Programm hat, hängt davon ab, wie die Funktionen sich aufrufen (die
Summe vom Verbrauch aller Funktionen ist es jedenfalls nicht) Ich denke
nicht dass ein Compiler dir letzteres abnehmen kann.
Es gibt noch -Wstack-usage=100 womit du eine Warning für jede Funktion
bekommst die mehr als 100 Byte Stack verbraucht.
Little B. schrieb:> Veranschaulichen wir uns eben mal den RAM. Dieser beginnt bei 0x20000000> und hört bei 0x20020000 auf (SRAM1 und SRAM2 sind in diesem Linkerfile> zusammengefasst). Erst kommt .data rein, dann .bss, dann .heap und ans> Ende wird .stack angehängt0x20000000 _ebss __HeapLimit> __StackLimit _StackTop> +--------+----------------+-------+-----------------+------------+> | .data | .bss | .heap | (free) | .stack |> +--------+----------------+-------+-----------------+------------+
Danke jetzt wird das ganze schon verständlicher :)
foo schrieb:> Es gibt noch -Wstack-usage=100 womit du eine Warning für jede Funktion> bekommst die mehr als 100 Byte Stack verbraucht.
Guter Tip bleibt ab sofort an, das Limit kann man ja auch noch ein
bisschen runter stellen.
Ich denke ich habe jetzt das Problem gefunden. Im Startup Code war der
Stack auf 512 Byte begrenzt, wenn ich den auf 4096 Byte einstell läuft
alles. Mal sehn obs auch so bleibt :D
Im File startup_stm32f4xx.c
#define STACK_SIZE 0x00001000 /*!< The Stack size suggest using even number */
3
__attribute__((section(".co_stack")))
4
unsignedlongpulStack[STACK_SIZE];
Little B. schrieb:> Dass es eine Funktion gibt, die dir eine Aussage trifft wie etwas "Dein> Programm braucht 42kByte Stack" habe ich noch nicht gefunden. (Statisch!> Nicht in Laufzeit! Denn das wäre ja lächerlich einfach)
In Laufzeit würde man das über den Stackpointer machen oder ?
Vielen Dank nochmal an alle.
Ich hab jetzt mal mit der __get_MSP() Funktion mir den Wert vom
Stackpointer geholt und zwar direkt nach Programmstart. Dieser kommt mir
jedoch etwas seltsam vor.
Nach meinem Verständnis hätte ich den Wert jetzt ca bei 0x20000000 +
0x20000 erwartet (also ziemlich Ende vom RAM plus minus paar Byte von
den Vars in Main).
Herausgekommen ist ein Wert von 0x20006060.
Die Adresse kommt eher an RAM Start + .data + .bss hin.
Wenn ich nun ein uint32 anlege geht der SP auf 0x20006058. Das passt
also zu der Theorie das es nach links wächst. Die 8 Byte kommen wohl
wegen dem Alignment vom SP - warum auch immer.
Bleibt noch die Frage warum Ich bereits vor einem Funktionsaufruf schon
derart viel Stack verbraucht haben soll.
was steht denn genau in deiner Vector-Tabelle? Mich verwirrt gerade die
".co-stack" Section.
Ich hätte so etwas erwartet (man achte immer auf den ersten Eintrag):
In C:
1
// The vector table.
2
// This relies on the linker script to place at correct location in memory.
3
4
__attribute__((section(".isr_vector"),used))
5
pHandler__isr_vectors[]=
6
{
7
// Core Level - CM4
8
(pHandler)&_estack,// The initial stack pointer
9
Reset_Handler,// The reset handler
10
11
NMI_Handler,// The NMI handler
12
HardFault_Handler,// The hard fault handler
13
...
Oder in ASM:
1
.section .isr_vector,"a",%progbits
2
.type g_pfnVectors, %object
3
.size g_pfnVectors, .-g_pfnVectors
4
5
6
g_pfnVectors:
7
.word _estack
8
.word Reset_Handler
9
.word NMI_Handler
10
.word HardFault_Handler
11
.word MemManage_Handler
12
.word BusFault_Handler
13
.word UsageFault_Handler
14
.word 0
15
.word 0
16
.word 0
17
...
Wenn dein StackPointer aber auf das ende von .co-stack initialisiert
wird, ist es klar, dass der Stack nicht reicht.
Dann ist es auch Blödsinn mit den 90kByte Stackverbrauch, die ich zu
anfang geschrieben hatte.
ich hab auch diverse sachen mit CoIDE durch ...
damals auch anfängliche probleme mit stack und heap gehabt.
ich habe das linker file geändert
1
2
.=ALIGN(4);
3
__HeapStart=.;
4
__StackStart=ORIGIN(ram)+LENGTH(ram)-32-16;
5
__HeapEnd=__StackStart-1024;
die -32-16 ist ein errata zum LPC17xx
aber so setze ich den stack wirklich ans ende
das __HeapEnd markiert ende heap und damit anfang stack
in der startup:
(void*)&__StackStart,//(void *)&pulStack[STACK_SIZE-1], /*!< The initial stack pointer */
in der syscalls.c
1
__attribute__((used))
2
caddr_t_sbrk(intsize){
3
staticunsignedchar*heap=NULL;
4
unsignedchar*prev_heap;
5
6
if(heap==NULL){
7
heap=(unsignedchar*)&__HeapStart;
8
}
9
prev_heap=heap;
10
11
if((heap+size)>(unsignedchar*)&__HeapEnd){
12
errno=ENOMEM;
13
return(caddr_t)-1;
14
}
15
heap+=size;
16
17
HeapAvailable=(unsignedchar*)&__HeapEnd-heap;
18
19
return(caddr_t)prev_heap;
20
}
das HeapAvailable lasse ich mir dann manchmal ausgeben ..
damit sieht man wieviel heap noch übrig ist
das ENOMEM ist original nicht mit drin ..
wenn malloc also fehlschalgen sollte kracht es einfach ohne
fehlermeldung
da malloc_r keinen fehler bekommt und munter drauflos schreibt
#define STACK_SIZE 0x00000400 /*!< The Stack size suggest using even number */
3
__attribute__((section(".co_stack")))
4
unsignedlongpulStack[STACK_SIZE];
Wenn man hier die Stacksize ändert wird .bss nach dem kompilieren auch
größer. Ein Versuch mit einem leeren Projekt hat das jetzt auch nochmal
bestätigt, dass sich der Stack nicht am Ende befindet.
234897897676878844 schrieb:> ich hab auch diverse sachen mit CoIDE durch ...> damals auch anfängliche probleme mit stack und heap gehabt.>> ich habe das linker file geändert> . = ALIGN(4);> __HeapStart = . ;> __StackStart = ORIGIN(ram) + LENGTH(ram) - 32 - 16 ;> __HeapEnd = __StackStart - 1024;
1
.heap(COPY):
2
{
3
__end__=.;
4
_end=__end__;
5
end=__end__;
6
*(.heap*)
7
__HeapLimit=.;
8
}>ram
9
/* .stack_dummy section doesn't contains any symbols. It is only
10
*used for linker to calculate size of stack sections, and assign
11
* values to stack symbols later */
12
.co_stack(NOLOAD):
13
{
14
.=ALIGN(8);
15
*(.co_stack.co_stack.*)
16
}>ram
17
18
/* Set stack top to end of ram , and stack limit move down by
19
* size of stack_dummy section */
20
__StackTop=ORIGIN(ram)+LENGTH(ram);
21
__StackLimit=__StackTop-SIZEOF(.co_stack);
22
PROVIDE(__stack=__StackTop);
23
24
/* Check if data + heap + stack exceeds ram limit */
25
ASSERT(__StackLimit>=__HeapLimit,"region ram overflowed with stack")
Das hier steht in dem Standard Linker File von CoIDE. Was ich hier auch
nicht verstehe ist das Alignment von 8 Byte. Woher kommt das ? Da die
meisten Variablen eher <= 4 Byte sind schmeisst man hier doch immer 4
Byte weg oder ?
Und direkt drunter steht ja eigentlich auch noch: "set stack top to end
of ram".
Ja, ich sehe hier Verbesserungspotential.
Allem voran würde ich den Inital Stack Pointer nicht auf
&pulStack[STACK_SIZE] setzen, sondern auf &_estack. Damit hast du immer
den maximal verfügbaren Platz für den Stack, und er ist dort abgelegt,
wo er hingehört, nämlich ans Ende des RAMs.
Ob die Align(8) Sinn machen, bin ich mir unsicher. Der ARM-Core kann
sowieso unaligned Speicherzugriffe (lässt sich aber auch abschalten),
aber ich kenn es, dass Align(4) verwendet wird (wegen 32bit prozessor).
Stefan schrieb:> Wenn man hier die Stacksize ändert wird .bss nach dem kompilieren auch> größer. Ein Versuch mit einem leeren Projekt hat das jetzt auch nochmal> bestätigt, dass sich der Stack nicht am Ende befindet.
das pulstack[] array wird dann im bss mit eingerechnet.
da es ja laut linker auch verwendet wird
_attribute_ ((section(".co_stack")))
unsigned long pulStack[STACK_SIZE];
da co_stack eine gültige marke im ram ist
allerdings hatte ich mit dem co_stack immer den effekt das er am ende
der variablen lag
> +--------+----------------+---------+-----------------+> | .data | .bss | .stack | (free) |> +--------+----------------+---------+-----------------+
als ich dann dynamisch ( malloc ) speicher nutzte krachte es immer
mit der linkervariante ist er immer am ende mit 1024bytes und . =
ALIGN(4);
Also vielen Dank nochmal für die Hilfe.
Jetzt klappts :)
Ich habe dann auch gleich mal noch den Stack in den CCM verfrachet.
End of Stack ist dann bei 0x10010000 und ich habe ihn mal auf 32k
limitiert falls man den CCM an einer anderen Stelle mal noch für was
braucht.
Dazu hab ich im Linkerskript folgendes geändert:
1
2
/* .stack_dummy section doesn't contains any symbols. It is only
3
* used for linker to calculate size of stack sections, and assign
4
* values to stack symbols later */
5
.co_stack(NOLOAD):
6
{
7
.=ALIGN(8);
8
__StackTop=ORIGIN(ram1)+LENGTH(ram1);
9
10
}>ram
11
12
/* Set stack top to end of ram , and stack limit move down by
13
* size of stack_dummy section */
14
/*__StackTop = ORIGIN(ram ) + LENGTH(ram );*/
15
__StackLimit=__StackTop-0x00008000;/* MAX Stack SIZE 32k
16
PROVIDE(__stack = __StackTop);
17
18
/* Check if data + heap + stack exceeds ram limit */
19
/* ASSERT(__StackLimit >= __HeapLimit, "region ram overflowed with stack")*/
Das Alignment hatte auf den ersten Blick keine Veränderung ergeben bei 4
statt 8. (Zumindest ist mal nichts abgestürzt :D )
Und im startup_stm32f4xx.c folgendes