Forum: Compiler & IDEs Linker Script - RAM Größe


von Harald (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei ein Programm für den LPC1768 fertig zustellen. 
Jetzt möchte ich aber herausfinden, wie viel ROM und RAM denn mein 
Programm vertilgt. Wie kann ich das herausfinden? Ich seh z.B. am ende 
des LPC1768_RAM.ld Scripts folgendes:
1
   /* 
2
    * The ".stack" section is our stack.
3
    * Here this section starts at the end of the ram segment.
4
    */
5
   _estack = ORIGIN(RAM) + LENGTH(RAM);
Bedeutet LENGTH(RAM) die komplette Größe meines RAMs oder nur die der 
globalen Variablen? (Also alles, was nicht auf dem Stack landet).

Hat jemand einen Vorschlag wie ich das bewerkstelligen könnte?

Grüße, Harald

von Werner (Gast)


Lesenswert?

gcc-size application.elf

Dem gcc stellst du noch den Crosscompilerprefix voran und die elf-Datei 
ist dein Programm.

von Harald (Gast)


Lesenswert?

Werner schrieb:
> gcc-size application.elf
>
> Dem gcc stellst du noch den Crosscompilerprefix voran und die elf-Datei
> ist dein Programm.

Hallo Werner,

dass meine elf-Datei mein Programm ist weiß ich ja (kann aber nicht ins 
ROM geladen werden, dafür ist bin zuständig).
Leider find ich auf dem Arbeits-PC kein gcc-size und habe keine 
root-Rechte. Und das mit dem Crosscompilerprefix versteh ich leider auch 
nicht so recht.
Wenn du mir das näher erläutern könntest wäre das spitze.

Grüße, Harald

von Dr. Sommer (Gast)


Lesenswert?

Harald schrieb:
> Leider find ich auf dem Arbeits-PC kein gcc-size und habe keine
> root-Rechte. Und das mit dem Crosscompilerprefix versteh ich leider auch
> nicht so recht.
Wie rufst du deinen GCC auf? Vermutlich mit "arm-none-eabi-gcc"? Dann 
ist "arm-none-eabi-" dein Prefix, und dein "size" ist 
"arm-none-eabi-size". Detaillierter ist aber "arm-none-eabi-readelf -S 
programmdatei.elf".

von Gas (Gast)


Lesenswert?

Hätte hierzu auch mal eine Frage.
Mein Board hat 64kB an Speicher zur Verfügung. In der .map Datei des 
kompilierten Programms stehen die Sektoren wie .text, .data und .bss. 
Wenn ich die mir so anschaue stehen da Sachen wie:
1
.text           0x00000000     0xd678
2
                0x00000000                __cs3_region_start_rom = .
3
                0x00000000                _stext = .
4
5
...
6
7
 *fill*         0x0000d525        0x3 00
8
9
...
10
11
.data           0x10000000      0x848 load address 0x0000d680
12
13
...
14
15
.bss            0x10000848     0x75b8 load address 0x0000dec8
16
17
...
18
19
 COMMON         0x1000347c     0x2dec ./src/can.o
20
21
...
22
23
.heap           0x10007e00      0x100 load address 0x0000dec8
24
                0x10007e00                . = ALIGN (0x8)
25
 *(.heap)
26
                0x10007f00                . = (. + HEAP_SIZE)
27
 *fill*         0x10007e00      0x100 00
28
                0x10007f00                . = ALIGN (0x8)
29
30
.stack          0x10007f00      0x100 load address 0x0000dec8
31
                0x10007f00                . = ALIGN (0x8)
32
 *(.stack)
33
                0x10008000                . = (. + STACK_SIZE)

Leider kann ich so eine .map Datei schlecht interpretieren. Kennt jemand 
einen Link der alles gut erklärt? Ich könnt z.B. raten, dass die zweite 
Hex-Zahl bei .text die Länge des ROMs ist. Aber was COMMON sein soll 
usw. ist mir schleierhaft. Oder das fill...

von Gas (Gast)


Lesenswert?

Nachtrag:

Mittels arm-none-eabi-size habe ich herausgefunden, dass das Programm 
knapp 37 kB Speicher benötigt. Wenn ich aber in meinem Source-Code einen 
Array erzeuge, der 64kB-37kB = 27kB = 0x6c00 groß ist (uint8_t 
arr[0x6c00]), meldet mir arm-none-eabi-gcc, dass der RAM überläuft. In 
Wirklichkeit darf ich aber lediglich 10436 Bytes (0x28c4) noch belegen 
bevor die Fehlermeldung eintritt. Das bedeutet doch, dass mein Programm 
in Wirklichkeit 55098 = 0xD731 Wieso? Liegt es an irgendwelchen dubiosen 
Debug-Optionen wo noch extra Speicher benötigt wird?

von Ronny S. (duselbaer)


Lesenswert?

[entfernt]

LPC1768 hat doch 64k RAM - sorry!

: Bearbeitet durch User
von Ronny S. (duselbaer)


Lesenswert?

Lt. Manual hat der LPC

- 32/16 kB of SRAM on the CPU with local code/data bus for 
high-performance CPU access.
- Two/one 16 kB SRAM blocks with separate access paths for higher 
throughput. These SRAM blocks may be used for Ethernet, USB, and DMA 
memory, as well as for general purpose CPU instruction and data storage.

/* Linker script for mbed LPC1768 */
GROUP(-lstdc++ -lsupc++ -lm -lc -lnosys -lgcc)

/* Linker script to configure memory regions. */
MEMORY
{
  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 512K
  RAM (rwx) : ORIGIN = 0x100000C8, LENGTH = 0x7F38

  USB_RAM(rwx) : ORIGIN = 0x2007C000, LENGTH = 16K
  ETH_RAM(rwx) : ORIGIN = 0x20080000, LENGTH = 16K
}

Das hab ich jetzt mal bei der Suche nach LPC1768 Linker Script gefunden. 
Sieht so aus, als ob die 64k RAM nicht fortlaufend addressierbar sind. 
Damit kann Dir alles, was > 16k ist prinzipiell Probleme machen.

RSp

von Gas (Gast)


Lesenswert?

Das ist ja wirklich knifflig.

So hab jetzt ein paar Berechnungen gemacht.
Bin die .map Datei durchgegangen und habe folgendes zusammen gezählt:
Es werden momentan (THEORETISCH) 22217 Bytes gebraucht, bei 32 kB RAM 
sind also noch 10551 Bytes frei. Dabei habe ich die Sektoren .data, 
.bss, .heap, .stack und .iap zusammengezählt, plus alles, was so an 
padding betrieben wird.

Dann habe ich im Code einen Array erzeugt, um die fen freien RAM 
auszutesten.
Dabei kam heraus, dass 10436 Bytes frei sind. Das sind 131 Bytes 
weniger! Von wo kommen die?
An den 16kB kanns nicht liegen, da 10436 Bytes < 16kB.

Ich habe dann probiert, den Speicher vom USB und Ethernet zu benutzen, 
also die Kommentarzeichen zu entfernen, kriege beim kompilieren immer 
noch denselben Fehler. Dann habe ich mir das Script für den Linker 
angeschaut, und entdeckt, dass sowas z.B. drinnen steht:
1
MEMORY
2
{
3
  /* bootloader (rx)  : ORIGIN = 0x00000000, LENGTH = 60K */
4
  rom (rx)  : ORIGIN = 0x00000000, LENGTH = 60K
5
  ram (rwx) : ORIGIN = 0x10000000, LENGTH = 32K
6
  /* USE USB RAM */
7
  ram1 (rwx) : ORIGIN = 0x2007C000, LENGTH = 16k
8
  /* USE ETH RAM */
9
  ram2 (rwx) : ORIGIN = 0x20080000, LENGTH = 16k
10
  config (rx): ORIGIN = 0x0000F000, LENGTH = 4K
11
}
12
13
... /*blablabla*/
14
15
  .data :
16
  {
17
    _sdata = .;
18
    __cs3_region_start_ram = .;
19
    *(.cs3.region-head.ram)
20
    KEEP(*(.jcr))
21
    *(.got.plt) *(.got)
22
    *(.shdata)
23
    *(.data .data.* .gnu.linkonce.d.*)
24
    *(.ram)
25
    . = ALIGN (8);
26
    _edata = .;
27
  } >ram AT>rom
28
29
  .bss :
30
  {
31
    . = ALIGN (8);
32
    _sbss = .;
33
    *(.shbss)
34
    *(.bss .bss.* .gnu.linkonce.b.*)
35
    *(COMMON)
36
    _ebss = .;
37
    *(.ram.b)
38
    . = ALIGN (8);    
39
    end = .;
40
    _end = .;
41
    __end = .;
42
  } >ram AT>rom

Bedeutet das denn nicht, dass der Linker dann versucht alles von .data 
und .bss NUR in ram rein zu tun? ram1 und ram2 scheint er 
offentsichtlich ausser Acht zu lassen. Muss man denn dem Linker sagen 
dass ram1 und ram2 auch RAM sind und er da Variablen reinpacken kann? 
Oder erkennt er das automatisch mittels (rwx) in MEMORY{...}?

Und wenn ich den arm-none-eabi-size verwende (Input: elf-Datei des 
kompilierten Programms), sagt er mir das hier:
1
  text     data   bss     dec     hex    filename
2
  54912    2120   24348   81380   13de4 /xxx...
.data stimmt mit meiner Berechnung überein, aber wieso ist .bss so viel 
größer als meine Berechnung?

von Werner (Gast)


Lesenswert?

Wenn du mehr Infos über den Speicherverbrauch brauchst dann ist:

arm-none-eabi-objdump -ax appl.elf

hilfreicher. Falls bei dir vorhanden kannst du mit:

arm-none-eabi-objdump -ax appl.elf | sort


direkt die Adressen sortieren.

von Werner (Gast)


Lesenswert?

Gas schrieb:
> Bedeutet das denn nicht, dass der Linker dann versucht alles von .data
> und .bss NUR in ram rein zu tun? ram1 und ram2 scheint er
> offentsichtlich ausser Acht zu lassen. Muss man denn dem Linker sagen
> dass ram1 und ram2 auch RAM sind und er da Variablen reinpacken kann?
> Oder erkennt er das automatisch mittels (rwx) in MEMORY{...}?

Du musst dem Linker das mit angeben. Die Frage ist aber, ob der Speicher 
zur Startzeit schon "vorhanden" ist oder erst die Periphery 
eingeschaltet werden muss. Du könntest versuchen bss z.B. in ram1 zu 
legen.

von Erik L. (erikl)


Lesenswert?

Hallo,

ich kenne arm und gcc nicht, aber Linker-Scripte aus anderen Umgebungen.

In denen wäre es so dass Du wenn Du USB_RAM (ram1) und ETH_RAM(ram2) 
nutzen willst im Code entsprechende Anweisungen geben musst "leg das in 
die spezielle RAM-section"
(z.B. nutzen dann die einen Quellcode-Module ram, die anderen ram1 usw.)
Das kann man beispielsweise machen, indem man eigenen Section-Namen 
vergibt und im Linker-Script entsprechende Anweisungen einführt.
Man muss dann halt vorher ungefähr wissen wer wieviel RAM braucht.

Die RAM-bereiche sind ja offenbar auch adresstechnisch nicht 
fortlaufend, ich weiss nicht, ob der gcc es unterstützt dass man im 
Linker-Script definiert "fuer .bss und .data  benutze ram und wenn voll 
dann laufe über in ram1 und ram2"
bei anderen Toolketten geht das leider nicht auch wenn man es bräuchte 
...

Gruß Erik

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
Noch kein Account? Hier anmelden.