LPC2378 - region RAM is full

Gast #3096506
Lesenswert?

Hallo Forum,

ich erweitere gerade ein Programm auf einem LPC2378 und benutze den 
arm-elf-gcc (GCC) 4.3.2

Nun bekomme ich folgende Fehlermeldung:
1
c:/yagarto/bin/../lib/gcc/arm-elf/4.3.2/../../../../arm-elf/bin/ld.exe: region RAM is full (programm.elf section .stack)

Vor der letzten Änderung (Anlegen einer Variablen) klappte noch alles 
und ich bekam die Ausgabe:
1
Size after:
2
   text     data      bss      dec      hex  filename
3
 137996     5720    13660   157376    266c0  programm.elf
4

5
fat_mci_demo.elf  :
6
section             size         addr
7
.text             137996            0
8
.data               5720   1073741824
9
.initdata           5720       137996
10
.bss               13660   1073747544
11
.stack             13312   1073761208
12
.comment            2142            0
13
.debug_aranges      8208            0
14
.debug_pubnames    23543            0
15
.debug_info       201246            0
16
.debug_abbrev      45111            0
17
.debug_line        53422            0
18
.debug_frame       20024            0
19
.debug_str         36631            0
20
.debug_loc         98745            0
21
.ARM.attributes       16            0
22
.debug_ranges      12736            0
23
Total             678232

Meine Hoffnung ist, dass vielleicht irgendwelche ungenutzten Sections im 
Ram liegen, aber durch die startup.S und ROM.ld steige ich nicht so 
richtig durch. Ich hänge beide Dateien mal an.

Der Controller hat 32kB Ram.
Wenn ich da aber nicht völlig falsch liege, dann bin ich mit .data + 
.bss + .stack = 32692 ziemlich am Anschlag, oder?

Dann habe ich ein Problem...

Es gibt aber noch extra Ram für Ethernet, USB und RTC.
Ich weiß nicht genau, ob es genutzt wird und ob es überhaupt anderweitig 
genutzt werden kann.

Ich hoffe ihr könnt mir helfen!
Angehängte Dateien:
Gast #3096659
Lesenswert?

Wie kann ich mir das MAP file sortiert nach Variablengröße ausgeben 
lassen?
Nach Adressen sortiert ist das sehr schwer zu überblicken.

Und kann mir jemand sagen, wo hier direkt am Anfang mal eben 1kB 
verschwinden?
.data           0x40000000     0x1658 load address 0x00021b7c
                0x40000000                _data = .
 *(.vectmapped)
                0x40000000                . = ALIGN (0x4)
 *(.fastrun)
                0x40000000                . = ALIGN (0x4)
                0x40000000                . = ALIGN (0x4)
 *(.data)
 .data          0x40000000      0x404 
c:/yagarto/bin/../lib/gcc/arm-elf/4.3.2/../../../../arm-elf/lib/thumb/in 
terwork\libc.a(lib_a-impure.o)
                0x40000000                _impure_ptr
 .data          0x40000404        0x4 
c:/yagarto/bin/../lib/gcc/arm-elf/4.3.2/../../../../arm-elf/lib/thumb/in 
terwork\libc.a(lib_a-ctype_.o)
                0x40000404                __ctype_ptr

Irgendwas könnte das mit der thumb Option zu tun haben...

Und im Linkerscript, was werden hier für Zahlen abgezogen?
/* Memory Definitions */
MEMORY
{
  ROM (rx) : ORIGIN = 0x00000000, LENGTH = (512k-4k)
  RAM (rw) : ORIGIN = 0x40000000, LENGTH = (32k-32)
}
Gast #3097069
Lesenswert?

Ich habe zum Beispiel im Map file gesehen, dass meine fast 2kB an 
Parametern die eigentlich im Battery buffered RAM liegen sollen, auch im 
SRAM liegen.
Muss das sein, oder kann man auch direkt aus dem battery buffered RAM 
wie mit SRAM arbeiten?
Gast #3097071
Lesenswert?

ARMdran schrieb:
> Und kann mir jemand sagen, wo hier direkt am Anfang mal eben 1kB
> verschwinden?
> c:/yagarto/bin/../lib/gcc/arm-elf/4.3.2/../../../../arm-elf/lib/thumb/in
> terwork\libc.a(lib_a-impure.o)
>                 0x40000000                _impure_ptr
>  .data          0x40000404        0x4
> c:/yagarto/bin/../lib/gcc/arm-elf/4.3.2/../../../../arm-elf/lib/thumb/in
> terwork\libc.a(lib_a-ctype_.o)
>                 0x40000404                __ctype_ptr
>
> Irgendwas könnte das mit der thumb Option zu tun haben...

Ich habe auch noch mal ohne die Option "Thumb" kompiliert, dann ändert 
sich der Pfad im obigen Auszug. Aber es gibt immer noch diesen Sprung 
von 0x40000000 auf 0x40000404, was 1kB entspricht...
Gast #3097168
Lesenswert?

ARMdran schrieb:
> Ich habe zum Beispiel im Map file gesehen, dass meine fast 2kB an
> Parametern die eigentlich im Battery buffered RAM liegen sollen, auch im
> SRAM liegen.

"auch"? Oder NUR im SRAM?
Ich vermute das zweite.

> Muss das sein, oder kann man auch direkt aus dem battery buffered RAM
> wie mit SRAM arbeiten?

Vermutlich, ich kenne den LPC nicht.
Eigene Sections für das buffered RAM definieren
und die Variablen entsprechend zuweisen, ähnlich wie das Dein
Linkerscript für das normale RAM macht. Einfach die
RAM Sections duplizieren und Kopie entsprechend umbenennen.
RAM Adressen der Kopie anpassen.

Beachten, dass der Startup Code diese Sections auch geeignet
initialisieren muss.

Für die GNU Binutils gibt es ein schönes Manual, da wird das 
beschrieben.
Gast #3097714
Lesenswert?

Da muss ich wohl irgendwie alleine durch...

Zumindest etwas weiter bin ich:
1. Der LPC2388 hat doppelt so viel SRAM und ist pinn- und 
funktionskompatiblen, löst damit also mein Problem mit der 
Holzhammermethode
2. Liefert mir der Befehl:
1
arm-elf-nm --size-sort --print-size $(TARGET_OUTPUT).elf
eine nach Größe sortierte Ausgabe der Symbols
3. Damit habe ich dann schnell gesehen, dass mir z.B. ein Font mal eben 
4kB SRAM geklaut hat, weil er nicht "const" war

Was mich noch interessiert:
1. Warum ist die .stack Section auf 13312 Byte fest genagelt?
2. Wie bekomme ich das Parameterarray in den Battery Buffered RAM?
3. Wie nutze ich den Ethernet SRAM als normales RAM bzw. geht das 
überhaupt, wenn ich Ethernet nutzen möchte?
4. Immer noch die Frage: Was werden hier für Zahlen abgezogen?
1
/* Memory Definitions */
2
MEMORY
3
{
4
  ROM (rx) : ORIGIN = 0x00000000, LENGTH = (512k-4k)
5
  RAM (rw) : ORIGIN = 0x40000000, LENGTH = (32k-32)
6
}
Gast #3097867
Lesenswert?

ARMdran schrieb:
> 1. Warum ist die .stack Section auf 13312 Byte fest genagelt?

Ok, im ganz oben verlinkten File "startup_gnu.S" steht folgendes, was 
13312 Byte ergibt...
1
.equ UND_Stack_Size,     0x00000000
2
.equ SVC_Stack_Size,     0x00000200
3
.equ ABT_Stack_Size,     0x00000000
4
.equ FIQ_Stack_Size,     0x00000000
5
.equ IRQ_Stack_Size,     0x00000A00
6
.equ USR_Stack_Size,     0x00002800
7

8
.equ Stack_Size,        (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size + USR_Stack_Size)

Ist das sinnvoll?
Gast #3098259
Lesenswert?

So, die Lernkurve war steil und ich kann mir jetzt fast alle Fragen 
selbst beantworten:

Zu 2. habe ich herausgefunden, dass mein Array über einen Pointer im 
Battery RAM landet:
1
volatile u32 *Param32Buffer  =(volatile u32 *)(0xE0084000); //RTC-RAM
Direkt dort hin legen konnte ich es jetzt nicht so einfach, da das 
Battery RAM nur einen word-wise (32bit) Zugriff erlaubt.
Das wird bei mir über eine Funktion geregelt.

Ich habe aber mein Array in den USB ram verschoben, da das ungenutzt 
ist.
1
s16 P16[PARAM16_COUNTMAX] __attribute__ ((section (".usbram")));
Dafür habe ich eine neue Section im Linkerscript angelegt.
1
/* Memory Definitions */
2
MEMORY
3
{
4
  ROM (rx) : ORIGIN = 0x00000000, LENGTH = (512k-4k)    /* Flash: 512k - boot code 4kbyte*/
5
  RAM (rw) : ORIGIN = 0x40000000, LENGTH = (32k-32)     /* SRAM: 64k - IAP work 32byte */
6
  /* added 22.03.2013 */
7
  URAM (rw): ORIGIN = 0x7FD00000, LENGTH = (8k)          /* USB RAM: 8k */
8
  //ERAM (rw): ORIGIN = 0x7FE00000, LENGTH = (16k)      /* Ethernet RAM: 16k */
9
  //BRAM (rw): ORIGIN = 0xE0084000, LENGTH = (2k)      /* Battery RAM: 2k */
10
}
Die Kommentare aus einem anderen Linkerscript erklären auch die Zahlen, 
die abgezogen werden. Ob das hier wirklich benötigt wird, ist aber wohl 
eine andere Frage...
Und weiter unten innerhalb von SECTIONS { } kommt dann noch:
1
/* .usbram .etherram and .batteryram added 22.03.2013 */
2
  /* memory space of etherram and batteryram is directly used via pointer in program without section */
3
  .usbram (NOLOAD) :
4
  {
5
      __usbram_start = . ;
6
      __usbram_start__ = . ;
7
      *(.usbram)
8
      . = ALIGN(4);
9
  } > URAM
10
  /*
11
  .etherram (NOLOAD) :
12
  {
13
      __etherram_start = . ;
14
      __etherram_start__ = . ;
15
      *(.etherram)
16
      . = ALIGN(4);
17
  } > ERAM
18
  
19
  .batteryram (NOLOAD) :
20
  {
21
      __batteryram_start = . ;
22
      __batteryram_start__ = . ;
23
      *(.batteryram)
24
      . = ALIGN(4);
25
  } > BRAM
26
  */
Die Sections für Ethernet RAM und Battery RAM habe ich auskommentiert, 
da die Adressbereiche über Pointer angesprochen werden und ich da nichts 
riskieren wollte.

Bleiben noch die Fragen, ob der feste Stack wirklich so groß sein muss 
und ob ein aktiviertes Ethernet oder USB noch irgendwas im 
entsprechenden eigenen Rambereich macht?
Gast #3098269
Lesenswert?

Damit habe ich jetzt durch die Analyse über 5kB SRAM frei gemacht und 
weiß, dass der Stack massig Platz hat.

Zum Vergleich:

vorher:
1
.data               5720   1073741824
2
.bss               13660   1073747544
3
.stack             13312   1073761208
4

5
= 32692

nachher:
1
.data               1624   1073741824
2
.bss               11836   1073743448
3
.stack             13312   1073755288
4
.usbram             1824   2144337920
5

6
.data + .bb + .stack = 26772

32692 - 26772 = 5920 Byte frei geschaufelt

Dazu sind mir noch einige sehr große Buffer aufgefallen, die ich mir 
noch mal genauer anschauen muss.

Hoffentlich funktioniert das mit dem USB RAM ohne Probleme.
Diese Pointer Zugriffe auf das Ethernet und RTC RAM sind mir auch etwas 
suspekt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren