www.mikrocontroller.net

Forum: Compiler & IDEs Malloc gibt immer 0x00 zurück. Linker file fehlerhaft? (LPC2214)


Autor: Sven (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich habe ein Problem mit einem Programm auf einem LPC2214.

Es geht um folgenden C Code (nur zum testen, wie viel Speicher ich 
reservieren kann)
unsigned int counter = 0;

while (1)
{
  counter++;
  pointer = malloc(32);
  if (pointer == 0)
  {
    pointer++;  // Hier liegt nen breakpoint...
  }
}

So. Wenn ich jetzt in meinem Linker File
__end__ = .;
_end = .;
PROVIDE(end = .);

vor den Definitionen für die Stacks schreibe (wie in der angehängten 
Datei) kann ich 37 mal die 32 Byte reservieren.

Wenn ich den teil mit dem PROVIDE(end=.) ans Ende der Datei schreibe 
(wie es doch eigentlich richtig ist, oder?) bekomme ich von malloc IMMER 
0x00000000 zurück.

Einige Infos noch zur Umgebung:

Ich benutze Yagarto mit eclipse.
Version.txt von Yagarto:
This build of yagarto use the following versions:

binutils: 2.18
gcc:      4.3.2
newlib:   1.16.0
gdb:      6.8.50-20080308-cvs

(28.09.2008, mifi)

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mir fällt grade auf, dass 37*32Byte ja nur ca. 1k sind. Wenn ich mir die 
Ausgabe
Size of target .elf file:
arm-elf-size -B ./test.elf
   text     data      bss      dec      hex  filename
  16224     2100     2736    21060     5244  ./test.elf
angucke sollte da doch noch ein bisschen mehr zu holen sein.


Was mir noch aufgefallen ist: Wenn ich die Größe des USR_STACKS erhöhe 
(von jetzt 0x00000800 auf z.B. 0x00002000) kann ich mehr Speicher 
reservieren. Holt sich malloc den Speicher ausm stack? WTF?

Autor: Tilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wo sind die Syscall implementiert? ich würde dort die Funktion sbrk 
anschauen, die ist dafür zuständig, die richtige Adresse zurückzugeben.

Bei mir war es so, dass ich die newlib von Hand kompilieren musste 
(-DSMALL_MEMORY), da sonst immer 4kb Seiten verwendet wurden. Dabei ist 
bei mir der Heap gegen den Stack geknallt, was böse ausging.

Autor: Sven (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaub ich nutze die libraries, die bei Yagarto dabei sind.

Was ich mich ja auch frage ist, wo gehört das PROVIDE(end = .); 
statement denn richtigerweise hin? Doch eigentlich ganz an das Ende, 
odeR?

Wie kompiliere ich denn das newlib gedöhns von Hand? Sowas hab ich noch 
nicht gemacht.

Oder könntest du mir deine selbst kompilierte library zukommen lassen?


Mir fällt noch was ein: Zu Hause musste ich eine eigene syscalls.c mit 
in mein Projekt werfen, da der linker irgendwie die Funktionen daraus 
nicht finden konnte. Könnte es schon helfen, diese Datei in das 
betroffene Projekt einzubinden?

Autor: Tilo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab das ganze für meinen MAc kompiliert, dass wird bei dir nicht so 
ohne weiteres laufen.

Die syscalls musst du selbst implementieren und die müssen im Projekt 
sein. Afaik gibts für die LPC Serie schon etwas Vorbereitetes.

Durchsuche das Forum nach newlib und syscalls, da solltest du schon 
etwas finden. Die fehlende Funktion sollte in etwa so aussehen:
extern char end[];              /*  end is set in the linker command   */
        /* file and is the end of statically   */
        /* allocated data (thus start of heap).  */
static char *heap_ptr;    /* Points to current end of the heap.  */

/************************** _sbrk_r *************************************
 * Support function. Adjusts end of heap to provide more memory to
 * memory allocator. Simple and dumb with no sanity checks.
 *  struct _reent *r -- re-entrancy structure, used by newlib to
 *                      support multiple threads of operation.
 *  ptrdiff_t nbytes -- number of bytes to add.
 *                      Returns pointer to start of new heap area.
 *
 *  Note:  This implementation is not thread safe (despite taking a
 *         _reent structure as a parameter).
 *         Since _s_r is not used in the current implementation, 
 *         the following messages must be suppressed.
 */

void * _sbrk_r(
    struct _reent *_s_r, 
    ptrdiff_t nbytes)
{
  char  *base;    /*  errno should be set to  ENOMEM on error  */
  if (!heap_ptr) {  /*  Initialize if first time through.  */
    heap_ptr = end;
  }
  base = heap_ptr;  /*  Point to end of heap.  */
  heap_ptr += nbytes;  /*  Increase heap.  */
  return base;    /*  Return pointer to start of new heap area.  */
}

Autor: Sven (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
So.

Vielen Dank Tilo!!

Mit deinem Tip hab ich es ans laufen bekommen!
/* Register name faking - works in collusion with the linker.  */
register char * stack_ptr asm ("sp");

caddr_t _sbrk_r(struct _reent *r, int incr)
{
  extern char end asm ("end"); /* Defined by the linker.  */
  extern char __ram_end asm ("__ram_end"); // Hier auch, ram ende aus dem Linker file besorgen.

  static char * heap_end;
  char * prev_heap_end;

  if (heap_end == NULL)
    heap_end = &end;

  prev_heap_end = heap_end;

  if (heap_end + incr > &__ram_end)  // Hier musste ich mit dem ram ende vergleichen, da mein stack nach unten und mein heap nach oben wachsen soll.
  {
    /* Some of the libstdc++-v3 tests rely upon detecting
     out of memory errors, so do not abort here.  */
#if 0
    extern void abort (void);

    _write (1, "_sbrk: Heap and stack collision\n", 32);

    abort ();
#else
    errno = ENOMEM;
    return (caddr_t) -1;
#endif
  }

  heap_end += incr;

  return (caddr_t) prev_heap_end;
}

Im Linkerfile ist nun die definition für "end" am ende nach den Stacks.

Ich hoffe den anderen mit dem Problem kann durch mein Linkerfile und 
durch die angepassten Syscalls aus irgendeinem Beispielprojekt aus dem 
Netz geholfen werden...

Danke nochmal!

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.