Hallo, die User Stacksize wird bei der Rowley Umgebung zu Anfang fix eingestellt. Ebenso FIQ und IRQ Größen. Fragt sich nur: Wie gut liegt man mit seiner Schätzung? Egal wie ich den Wert verändere, der Compiler und auchn Linker meckert nicht. Wie kann man denn die Größe so bestimmen, dass sie eben optimal passt und man keinen wertvollen RAM verschenkt? Beim PIC Compiler rechnet der es aus der maximalen Verschachtelungstiefe aus, beim GCC weiss ich nicht wie das geht.
Christian J. schrieb: > Fragt sich nur: Wie gut liegt man mit seiner Schätzung? Egal wie ich den > Wert verändere, der Compiler und auchn Linker meckert nicht. Wundert mich wenig. Wenn der Stack zu klein ist, merkst du das erst zur Laufzeit. Und das auch nur wenn in deinem Programm plötzlich seltsame Dinge passieren bzw. dein Compiler bei jedem Funktionsaufruf Code einbaut, der die Stackgröße überwacht und Alarm schlägt. > Wie kann man denn die Größe so bestimmen, dass sie eben optimal passt Gegen das Wort 'optimal' hab ich ein Aversion entwickelt. > und man keinen wertvollen RAM verschenkt? Beim PIC Compiler rechnet der > es aus der maximalen Verschachtelungstiefe aus, beim GCC weiss ich nicht > wie das geht. Die benötigte Stacksize ist im Allgemeinen nicht per Programm bestimmbar. Das wäre eine Variation des Turingschen Halteproblems und ist daher prinzipiell nicht möglich. Was nicht heißt, das es für einzelne Programme nicht gehen mag. Nur ist es eben nicht für jedes beliebige Programm möglich die benötigte Stacksize durch Betrachten des Source Codes zu bestimmen.
Hallo, aber irgendwie muss man doch die optimale Size bestimmen können. Wenn das der CCS Compiler kann, dann können das doch auch andere. Sobald die Abhängigkeiten bekannt sich lässt sich das ausrechnen.
Christian J. schrieb: > Hallo, > > aber irgendwie muss man doch die optimale Size bestimmen können.
1 | #include <stdio.h> |
2 | |
3 | unsigned int foo( unsigned int j ) |
4 | {
|
5 | if( j == 0 ) |
6 | return 1; |
7 | |
8 | return foo( j - 1 ); |
9 | }
|
10 | |
11 | int main() |
12 | {
|
13 | unsigned int k; |
14 | |
15 | scanf( "%u", &k ); |
16 | printf( "%u\n", foo( k ) ); |
17 | }
|
Wie soll ein Linker daraus die "optimiale" Stacksize bestimmen können, wenn er nicht weiß, was der Benutzer eingeben wird? (Der Compiler kann sowas prinzipbedingt nicht bestimmen, da er im Regelfall das komplette Programm nie zu Gesicht bekommt)
> Wenn das der CCS Compiler kann, dann können das doch auch andere.
Auch er kann es nicht, was macht er wohl bei
void test( int a ) {
char dummy[20];
sprintf(dummy, "%d", a);
for( int i = a; i < 10 + strlen( dummy ); ++i ) {
test( i+1 );
}
}
main() {
test(0);
}
na wieviel stack braucht du wohl, ich glaube kaum das der Compliler das
ermitteln kann?
Christian J. schrieb: > Wie kann man denn die Größe so bestimmen, dass sie eben optimal passt > und man keinen wertvollen RAM verschenkt? Dazu muß man in die Internas des Compilers gehen. Es gibt Compiler, die brauchen keinerlei Einstellungen. Z.B. beim AVR-GCC kommen unten die globalen Variablen, danach dann Malloc und der Stack wächst vom Ende des SRAM nach unten. Wenn es dann kracht, hilft keine Einstellung, dann wurde zuviel Speicher belegt und das Malloc rennt in den Stack rein bzw. umgekehrt. Das manche Compiler aber mehrere Stacks benötigen, dient wohl der Vorbereitung von Multitasking. Da hilft wohl nur eine Analyse zur Laufzeit. Man füllt allen unbenutzten SRAM mit einem Muster, z.B. 0x77 und testet nach ner Weile, wieviel davon in den einzelnen Stacks noch übrig ist. Peter
Peter Dannegger schrieb: > Das manche Compiler aber mehrere Stacks benötigen, dient wohl der > Vorbereitung von Multitasking. Und an der Architektur der AVRs. Da AVR keinen atomaren Update von SP ermöglicht, tut sich ein Compiler etwas leichter, wenn der Stack für die lokalen Variablen vom Return-Stack getrennt wird. Einer dieser beiden Stacks ist dann fix.
hallo , ich mache das so, das ich erst den speicher voll schreibe, um dann zu testen wieviel verändert wurde. so kann man ungefähr abschätzen wieviel man braucht. an pregnanten stellen testmymem("xyz"); aufrufen. im main file: #ifndef FLASH_RELEASE void testmymem(char *loc){ unsigned int* lHeapPtr = (unsigned int*) &__heap_start__; while (lHeapPtr) { DBG("\nheap space left %d :%s", *(lHeapPtr + 1), loc); lHeapPtr = (unsigned int*) *lHeapPtr; } unsigned long stack_used, irq_stack_used, fiq_stack_used, svc_stack_used, und_stack_used, abt_stack_used, bss_used; stack_used = get_stack_used(&__stack_start__, &__stack_end__); DBG("\nstack_used %d :%s", stack_used, loc); irq_stack_used = get_stack_used(&__stack_irq_start__, &__stack_irq_end__); DBG("\nirq_stack_used %d :%s", irq_stack_used, loc); fiq_stack_used = get_stack_used(&__stack_fiq_start__, &__stack_fiq_end__); DBG("\nfiq_stack_used %d :%s", fiq_stack_used, loc); svc_stack_used = get_stack_used(&__stack_svc_start__, &__stack_svc_end__); DBG("\nsvc_stack_used %d :%s", svc_stack_used, loc); und_stack_used = get_stack_used(&__stack_und_start__, &__stack_und_end__); DBG("\nund_stack_used %d :%s", und_stack_used, loc); abt_stack_used = get_stack_used(&__stack_abt_start__, &__stack_abt_end__); DBG("\nstack_stack_used %d :%s", abt_stack_used, loc); bss_used = get_bss_used(&__bss_start__, &__bss_end__); DBG("\nbss_used %d :%s", bss_used, loc); } #endif im crt0.S file: #ifdef INITIALIZE_STACKS mov r2, #0xCC ldr r0, =__stack_und_start__ ldr r1, =__stack_und_end__ bl memory_set ldr r0, =__stack_abt_start__ ldr r1, =__stack_abt_end__ bl memory_set ldr r0, =__stack_irq_start__ ldr r1, =__stack_irq_end__ bl memory_set ldr r0, =__stack_fiq_start__ ldr r1, =__stack_fiq_end__ bl memory_set ldr r0, =__stack_svc_start__ ldr r1, =__stack_svc_end__ bl memory_set ldr r0, =__stack_start__ ldr r1, =__stack_end__ bl memory_set #endif
A. K wrote > Und an der Architektur der AVRs. Da AVR keinen atomaren Update von SP > ermöglicht, tut sich ein Compiler etwas leichter, wenn der Stack für die > lokalen Variablen vom Return-Stack getrennt wird. Einer dieser beiden > Stacks ist dann fix. Auch beim AVR ist ein atomarer Zugriff auf SP möglich, indem man die Interrupts sperrt und danach wieder freigibt. Genau das macht auch der avr-gcc, wenn er Platz für lokale Variablen auf dem Stack reserviert. Einen weiteren (Software-)Stack benutzt avr-gcc nicht. MfG Mark
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.