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!
>mallocr.c:(.text+0x48): undefined reference to `_sbrk_r'
_sbrk_r findest du bei Winarm in der syscalls.c .
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).
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
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 ;-)
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...
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...
Ist vermutlich nur ein Vertipper, aber es sollte so heißen in der Definition der Variablen:
1 | plpc2000CANdriver_TXObj_t *pMessage; |
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.