Forum: Compiler & IDEs Probleme mit ld und Vektortabelle


von Ilu (Gast)


Lesenswert?

Hallo,

ich bin Neuling was Mikrocontroller angeht und verzweifel hier gerade an
meinem ersten Linkescript fuer ein ARM Board.

Umgebung:
- Atmel 91sam9260
- Yagarto tools unter Windows
- Telit GE863-PRO3 eval board

Problem:
Das Board hat 8MB prozessorexternen RAM (0x2000.0000 - 0x207F.FFFF).
Meine Anwendung wird vom U-BOOT aus dem FLASH an die Adresse 0x2001.2000
geladen und soll dort auch ausgefuehrt werden.
Wenn ich das richtig verstehe, dann muss die Vectortabelle fuer den ARM
in die 4kB prozessorinternen RAM (0x20.0000 - 0x20.1000).
Der Startupcode von meiner Anwendung soll also die paar Byte aus der
Anwendung in den internen RAM kopieren (alles zwischen _sdata und
_edata) und alles ist gut...

Das Problem ist nur leider, dass das mitgelieferte Beispielscript vom
Hersteller die Vektoren, das Datensegment und das BSS in den internen
RAM klatscht. Das geht nur so lange gut, wie das alles <4k ist. :)

Original Script
1
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
2
OUTPUT_ARCH(arm)
3
ENTRY(reset_handler)
4
5
SECTIONS
6
{
7
  .text 0x20012000 : { 
8
    _stext = .;
9
    *(.text)
10
    *(.rodata)
11
    *(.rodata*)
12
    . = ALIGN(4);
13
     _etext = . ;
14
  }
15
16
  .data 0x200000 : AT ( ADDR (.text) + SIZEOF (.text) ) { 
17
    _sdata = .;
18
    *(.vectors)
19
    *(.data)
20
    _edata = .;
21
  }
22
23
  .bss (NOLOAD) : { 
24
    . = ALIGN(4);
25
    _sbss = .;
26
    *(.bss)
27
    _ebss = .;
28
  }
29
}
30
end = .;

Mein erster Schritt was also das BSS an seiner Loadaddress (im externen
RAM) zu lassen.

Funktionierendes Linkerscript mit BSS im externen RAM
1
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
2
OUTPUT_ARCH(arm)
3
ENTRY(reset_handler)
4
5
SECTIONS
6
{
7
  .text 0x20012000 : { 
8
    _stext = .;
9
    *(.text)
10
    *(.rodata)
11
    *(.rodata*)
12
    . = ALIGN(4);
13
     _etext = . ;
14
  }
15
16
  .data 0x200000 : AT ( ADDR (.text) + SIZEOF (.text) ) { 
17
    _sdata = .;
18
    *(.vectors)
19
    *(.data)
20
    _edata = .;
21
  }
22
23
  .bss (LOADADDR(.data) + SIZEOF(.data)) (NOLOAD) : {
24
    . = ALIGN(4);
25
    _sbss = .;
26
    *(.bss)
27
    _ebss = .;
28
  }
29
}
30
end = .;
31
PROVIDE(end = .);

Danach hab ich versucht Datensegment und Vektoren zu trennen. Das
folgende Linkerscript soll das bewirken (und meine laienhafte
Interpretation vom erzeugten MAP-File sagt mir auch, das es das tut),
aber die erzeugte Datei ist genau 120 Byte kleiner als mit dem anderen
Script (und das ist auch zufaelligerweise die Groesse des Vektorcodes
aus crt0.S).

Linkerlauf mit objdump
1
arm-elf-gcc -nostartfiles -Wl,-Map=debug.map,--cref -T elf32-littlearm.lds -n -o debug.elf crt0.o main.o init.o
2
arm-elf-objcopy --strip-debug --strip-unneeded --verbose debug.elf -O binary debug.bin
3
copy from `debug.elf' [elf32-littlearm] to `debug.bin' [binary]

Auszug aus dem MAP-File
1
                0x2001be3c                _etext = .
2
3
.vector         0x00200000       0x78 load address 0x2001be3c
4
                0x00200000                _sdata = .
5
 *(.vectors)
6
 .vectors       0x00200000       0x78 crt0.o
7
                0x00200078                _edata = .
8
9
.bss            0x2001beb4      0x110
10
                0x2001beb4                . = ALIGN (0x4)
11
                0x2001beb4                _sbss = .
12
 *(.bss)

Kaputtes Linkerscript
1
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
2
OUTPUT_ARCH(arm)
3
ENTRY(reset_handler)
4
5
SECTIONS
6
{
7
  .text 0x20012000 : { 
8
    _stext = .;
9
    *(.text)
10
    *(.rodata)
11
    *(.rodata*)
12
    . = ALIGN(4);
13
  }
14
15
  .data : AT ( ADDR (.text) + SIZEOF (.text) ) { 
16
    *(.data)
17
     _etext = . ;
18
  }
19
20
  .vector 0x200000 : AT ( ADDR (.data) + SIZEOF (.data) ) {
21
    _sdata = .;
22
    *(.vectors)
23
    _edata = .;
24
  }
25
26
  .bss (LOADADDR(.vector) + SIZEOF(.vector)) (NOLOAD) : {
27
    . = ALIGN(4);
28
    _sbss = .;
29
    *(.bss)
30
    _ebss = .;
31
  }
32
}
33
end = .;
34
PROVIDE(end = .);

Es waere wunderbar wenn mir jemand den Knoten im Kopf aufloesen koennte,
ich hab naemlich langsam keine Idee mehr.
Beispielscripte die ich beim googlen gefunden habe waren immer extrem
kompliziert, ich gebe mich ja noch der Illusion hin, das mein Problem
eigentlich ganz einfach ist :)

Danke und Gruss
  Ilu

von Ilu (Gast)


Lesenswert?

Um mir mal selber zu helfen:
wenn man im crt0.S statt
1
.section .vectors

einfach
1
.section .vectors, "a", %progbits

schreibt, dann klappts auch mit dem linken...

von Max (Gast)


Lesenswert?

Aus Interesse, da ich mich selber gerade einarbeite:

Was macht
1
.section .vectors, "a", %progbits

bzw. was machen die zusätzlichen Parameter im Vergleich zu der Anweisung 
darüber?

Vielen Dank für eure Hilfe!

von Andreas B. (Gast)


Lesenswert?

Max schrieb:
> bzw. was machen die zusätzlichen Parameter im Vergleich zu der Anweisung
> darüber?

Die setzen die Flags für ELF Sektionen, anderenfalls werden die 
Defaultwerte abhängig vom Sektornamen verwendet. Aus der GNU as 
Dokumentation:

|   If no flags are specified, the default flags depend upon the section
| name.  If the section name is not recognized, the default will be for
| the section to have none of the above flags: it will not be allocated
| in memory, nor writable, nor executable.  The section will contain data.

Und .vectors ist eben kein bekannter Standard-Sektionsname wie .text, 
.data und .bss.


Aber für ARM Vektortabellen würde ich "ax" einsetzen, schließlich 
bestehen die Einträge ausser bei ARMv7-M aus ausführbarem Code.

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.