Forum: Compiler & IDEs LPC2294 "Region RAM is full"


von Steffen K. (mrcrabs)


Angehängte Dateien:

Lesenswert?

Ich habe mittlerweile meherere Projekte mit einem AVR-Controller 
abgewickelt und habe eigenltich nie nennenswerte Probleme gehabt...
Nun hab ich hier einen LPC2294, dessen CAN-Bus ich gern benutzen 
würde...allerdings gerat ich hier von einer Schwierigkeit in die 
Nächste, was sich, glaube ich, darauf zurückführen lässt dass es 
scheinbar keine ordentliche, geschlossene Programmierumgebung wie das 
AVRStudio gibt, sondern man sich um alles selbst kümmern muss...
Im angehängten Projekt habe ich eigentlich nichts gemacht ausser den von 
NXP zur Verfügung gestellten LPC2000CanDriver in ein Projekt eingebaut, 
dass eigentlich soweit funktioniert bis ab einem gewissen Punkt unter 
anderem die Fehlermeldung "Region RAM is full" kommt. Den ganzen Text 
mal hier:

make all
arm-elf-gcc -x assembler-with-cpp -c -mcpu=arm7tdmi -g -gdwarf-2 
-Wa,-amhls=src/crt.lst   src/crt.s -o src/crt.o
arm-elf-gcc -c -mcpu=arm7tdmi -Os -gdwarf-2 -mthumb-interwork 
-fomit-frame-pointer -Wall -Wstrict-prototypes -fverbose-asm 
-Wa,-ahlms=src/main.lst   -MD -MP -MF .dep/main.o.d -I . -I./inc 
src/main.c -o src/main.o
arm-elf-gcc ./src/crt.o ./src/main.o -mcpu=arm7tdmi -nostartfiles 
-T./prj/lpc2294_rom.ld -Wl,-Map=test.map,--cref,--no-warn-mismatch    -o 
test.elf
c:/programme/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib 
\libc.a(mallocr.o):  In function `_malloc_r':
mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
c:/programme/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib 
\libc.a(freer.o):  In function `_malloc_trim_r':
mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
collect2: ld returned 1 exit status
make: *** [test.elf] Error 1

Damit kann ich gar nix anfangen...das mein Programm zu groß für diesen 
schon recht mächtigen Controller ist kann ich mir kaum 
vorstellen...immerhin ist der CANDriver ja von NXP selbst und das was 
ich hinzugefügt hab (die Main) dürfte so gut wie gar keinen Platz 
beanspruchen...was könnte also das Problem sein?

Vielen Dank im Vorraus schonma!

von holger (Gast)


Lesenswert?

>mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'

_sbrk_r findest du bei Winarm in der syscalls.c .

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Steffen Krebs wrote:
> ...
> Im angehängten Projekt habe ich eigentlich nichts gemacht ausser den von
> NXP zur Verfügung gestellten LPC2000CanDriver in ein Projekt eingebaut,
> dass eigentlich soweit funktioniert bis ab einem gewissen Punkt unter
> anderem die Fehlermeldung "Region RAM is full" kommt.

Es wird für die Ausführung aus dem RAM gelinkt ("RAM-debug"). Genannter 
Controller hat wenn richtig erinnert 16kB RAM. Linker "weiss" das auf 
Grund der Angabe im Linkerscipt (lpc2294_ram.ld) und gibt entsprechenden 
Fehler aus.

> Den ganzen Text
> mal hier:
>
> make all
> arm-elf-gcc -x assembler-with-cpp -c -mcpu=arm7tdmi -g -gdwarf-2
> -Wa,-amhls=src/crt.lst   src/crt.s -o src/crt.o
> arm-elf-gcc -c -mcpu=arm7tdmi -Os -gdwarf-2 -mthumb-interwork
> -fomit-frame-pointer -Wall -Wstrict-prototypes -fverbose-asm
> -Wa,-ahlms=src/main.lst   -MD -MP -MF .dep/main.o.d -I . -I./inc
> src/main.c -o src/main.o
> arm-elf-gcc ./src/crt.o ./src/main.o -mcpu=arm7tdmi -nostartfiles
> -T./prj/lpc2294_rom.ld -Wl,-Map=test.map,--cref,--no-warn-mismatch    -o
> test.elf
> c:/programme/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib 
\libc.a(mallocr.o):
> In function `_malloc_r':
> mallocr.c:(.text+0x424): undefined reference to `_sbrk_r'
> mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r'
> c:/programme/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib 
\libc.a(freer.o):
> In function `_malloc_trim_r':
> mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
> mallocr.c:(.text+0x64): undefined reference to `_sbrk_r'
> mallocr.c:(.text+0x84): undefined reference to `_sbrk_r'
> collect2: ld returned 1 exit status
> make: *** [test.elf] Error 1

Abhängigkeit entsteht wegen pTransmitBuf = malloc(4*sizeof(UInt32)); in 
main(). Warum die dynamische Speicherallokation überhaupt? Sehe an der 
Stelle keinen Nutzen. array TransmitBuf[...] würde es auch tun.

Einfach malloc ersetzten und man wird sich um "_sbrk_r" erstmal nicht 
kümmern müssen. Ansonsten: Einfach eine sbrk_r aus einem meiner 
WinARM-Beispiele zu kopieren, wird wohl nicht reichen. Man muss das 
Symbol für die Startadresse des Heaps anpassen. Der gezeigt beispielcode 
nutzt "__heap_start" dafür, viele WinARM-Beispiele "end" (analog 
default-linker-script, newlib sbrk-Implementierung).

> Damit kann ich gar nix anfangen...das mein Programm zu groß für diesen
> schon recht mächtigen Controller ist kann ich mir kaum
> vorstellen...
Für dessen RAM augenscheinlich schon. Also Code für das Flash erzeugen, 
da ist deutlich mehr Platz.

> immerhin ist der CANDriver ja von NXP selbst
Und das heißt? Der Rest ist nicht von NXP und ich habe bisher von NXP 
kein Beispiel gesehen, das für GNU-Toolchain vorbereitet ist. Man setzt 
dort wohl auf Keil/ARM und freut sich, das vergessene volatiles meist 
nicht auffallen.

> und das was
> ich hinzugefügt hab (die Main) dürfte so gut wie gar keinen Platz
> beanspruchen...was könnte also das Problem sein?
Der Object-Code der CAN-Library wird komplett angelinkt falls eine 
Funktion daraus aufgerufen wird. War vorher kein Aufruf zu einer 
Funktion in dem Object drin, wurde es auch nicht gelinkt. Man kann die 
RAM-Größe im Linker-Script anheben, passt dann natürlich immer noch 
nicht in das Controller-RAM, aber Linker läuft durch und man kann 
nachsehen wie der Speicherplatz verteilt ist (Map-File).

von Robert Teufel (Gast)


Lesenswert?

Sobald lib Routinen wie malloc eingesetzt werden verhaelt sich der gcc 
wie eine RAM-Fressmaschine. Dein Code mag nur ein paar hundert bytes 
sein, die Lib sorgt dafuer, dass RAM schnellstens ausgeht. Natuerlich 
ist der Controller nicht fuer RAM Debugging gebaut, sondern fuer 
Abarbeitung der Programme aus dem Flash, davon hat er 256 KB aber 
debugging wird durch Flash etwas muehsamer.
Es gibt auch da Moeglichkeiten (Google "flash breakpoints") aber so 
simple wie Debugging vom RAM ist es nicht ganz.
Mit Compilern von Keil oder IAR waer die Meldung wahrscheinlich nicht 
gekommen, denn die gehen sehr viel schonender mit dem RAM um. Ausserdem 
gibt es bei Keil die Moeglichkeit alles im Simulator zu testen, selbst 
wenn der Code nachher im Flash steht, kann man das simulieren.
Mir scheint, es fehlen noch etwas die Grundlagen ueber die Unterschiede 
Flash versus RAM.
Im uebrigen wurde der CAN treiber von einer externen Firma erstellt, im 
Auftrag von NXP.

Hoffe der Beitrag gibt wenigstens ein paar gute Suchbegriffe her ;-)

Robert

von Martin T. (mthomas) (Moderator) Benutzerseite


Lesenswert?

Robert Teufel wrote:
> Sobald lib Routinen wie malloc eingesetzt werden verhaelt sich der gcc
> wie eine RAM-Fressmaschine.
Liegt nicht am Compiler sondern der newlib. Diese ist halt nicht für 
kleine ARM optimiert (newlib unterstützt ca. 30 Plattformen) aber kostet 
dafür auch nichts, ist von der Lizenz unproblematisch und ist daher wohl 
bei allen mir bekannten Gratis-Paketen um arm-elf/eabi-gcc (inkl. meinem 
eigenen) dabei. Rowley zeigt wie es kompakter geht (eigene libc für gcc) 
aber möchte dafür auch etwas entlohnt werden.

> Dein Code mag nur ein paar hundert bytes
> sein, die Lib sorgt dafuer, dass RAM schnellstens ausgeht. Natuerlich
> ist der Controller nicht fuer RAM Debugging gebaut, sondern fuer
> Abarbeitung der Programme aus dem Flash, davon hat er 256 KB aber
> debugging wird durch Flash etwas muehsamer.
> Es gibt auch da Moeglichkeiten (Google "flash breakpoints") aber so
> simple wie Debugging vom RAM ist es nicht ganz.
Solange die HW-Breakpoints des Cores reichen schon. Kann auch das 
kostenlose Werkzeug inzwischen ganz gut. Aber klar, für mehr gibt's ja 
die Produkte des Ex-Arbeitgebers.  Eclipse/OpenOCD/FT2232 tun hier gute 
Dienste mit AT91 auch mit HW-Breakpoints/Flash-Debugging. Mit LPC2k 
leider noch etwas bockig.

> Mit Compilern von Keil oder IAR waer die Meldung wahrscheinlich nicht
> gekommen, denn die gehen sehr viel schonender mit dem RAM um.
déjà vu. OpenOCD?...Wiggler?...Problem? Lösung: J-LINK.
Bei "ordentliche, geschlossene Programmierumgebung wie das AVRStudio" 
hat wohl das kostenlos gefehlt.

> Ausserdem gibt es bei Keil die Moeglichkeit alles im Simulator zu
> testen, selbst wenn der Code nachher im Flash steht, kann man das
> simulieren.
Ja, ein wirklich gutes Werkzeug. Allerdings für Lizenz zur kommerziellen 
Verwendung auch eine ordentliche Investitionshürde - zumindest für 
Kleinstunternehmer wie mich.

Nutze es aber gelegentlich für Spielereien mit neunen "Spielzeugen" oder 
um schnell mal ohne Hardware auszuprobieren, ob ein mit 
arm-eabi-gcc/newlib (CS G++ Q3/07) erzeugtes malloc-Beispiel auch 
funktioniert. Also endlich (on-topic/2): Malloc+sbrk+alles was 
dranhängt: je ca. 2kB .text und .data bei erster Anwendung, für jede 
weitere Anwendungen dann nur noch die paar Bytes für Parameter in 
Register und BL bzw. MOV-BX. Malloc legt eine recht große Tabelle ins 
RAM. Viel in Relation zu 16kB verfügbarem RAM, aber auch keine 
"Explosion". Wenn newlibs stdio noch dazu kommt, wird es zumindest ein 
Neujahrsböller.

> Mir scheint, es fehlen noch etwas die Grundlagen ueber die Unterschiede
> Flash versus RAM.
Ist wohl so. Zumal der Ursprungsbeitrag ziemlich widersprüchlich ist 
(Log, Fragetext und Codeanhang passen nicht wirklich zusammen).

> Im uebrigen wurde der CAN treiber von einer externen Firma erstellt, im
> Auftrag von NXP.
Support dafür über "externe Firma" oder NXP oder garnicht?

> Hoffe der Beitrag gibt wenigstens ein paar gute Suchbegriffe her ;-)
Hoffentlich ;-)

von Steffen K. (mrcrabs)


Lesenswert?

Danke erstmal für die Antworten!

Ja, da ich bisher nur mit AVRStudio gearbeitet hab, das Dinge wie 
Linker, Loader, Makefile und auch die Startup-Datei komplett für einen 
übernimmt hab ich mich mit diesen Dingen noch kein bisschen befasst.
Soweit ich nun verstehe frisst malloc zuviel Ressourcen in Verbindung 
mit GCC. Die Funktion lpc2000CANdriver_CertainTxBufTransmitMessage hätte 
jedoch gern einen plpc2000CANdriver_TXObj_t übergeben, was ein Zeiger 
auf eine Struct ist, die aus ein paar UInt32 ist, daher habe ich diesen 
mit malloc anlegen wollen...was soll ich nun stattdessen alternativ tun?

Ist es zusätzlich sinnvoll aus den CAN-Bibliotheken die Dinge zu 
entfernen die ich nicht brauche um Speicher zu sparen?

Die folgenden Zeilen befinden sich im Makefile:

# Define linker script file here
LDSCRIPT= ./prj/lpc2294_ram.ld
#LDSCRIPT= ./prj/lpc2294_rom.ld

Wenn ich hier das # vor der rom-Datei lösche und vor die ram-Datei 
setze, ist das dann alles was ich tun muss damit das Programm für den 
Flash geschrieben wird?

Ich fühl mich zur Zeit ein wenig überfordert, die ARMs scheinen 
tatsächlich ziemlich wenig einsteigerfreundlich zu sein...

von Steffen K. (mrcrabs)


Lesenswert?

ehm ich habs jetz erstmal wie folgt gelöst:

lpc2000CANdriver_TXObj_t message;
//dies ist ein struct mit 4 UInt32

plpc2000CANdriver_TXObj_t pMessage;
//dies ist ebenfalls ein solches struct, allerdings als Zeiger

pMessage = &message;
//Hiermit setz ich die Adresse des Zeigers gleich der der Variable

pMessage -> TFI = (1<<31);
pMessage -> ID = 0;
pMessage -> DataField[0] = 0;
pMessage -> DataField[1] = 0;
//Wertzuteilung für die in pMessage enthaltenen UInt32

Ist das so in Ordnung und richtig oder sollte ich das noch verändern? 
Der Compiler meckert jedenfalls nicht mehr...

von Narf (Gast)


Lesenswert?

Ist vermutlich nur ein Vertipper, aber es sollte so heißen in der 
Definition der Variablen:
1
plpc2000CANdriver_TXObj_t *pMessage;

von Steffen K. (mrcrabs)


Lesenswert?

typedef struct
{
   UInt32   TFI;              //0x8xxxxxxx for 29bits length ID, 
0x0xxxxxxx for 11 bits
   UInt32   ID;
   UInt32   DataField[2];

} lpc2000CANdriver_TXObj_t, *plpc2000CANdriver_TXObj_t;

So ist die struct definiert. Ich glaube also wenn ich nun Einen Zeiger 
davon definiere muss ich  schreiben

plpc2000CANdriver_TXObj_t pMessage;

und nicht

plpc2000CANdriver_TXObj_t *pMessage;

da der Stern schon in der typdef drin ist...oder ist das falsch?

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.