www.mikrocontroller.net

Forum: Ausbildung, Studium & Beruf linkerskript Frage (LPC2000er)


Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich möchte gerne auf einen externen SDRAM zugreifen, deswegen habe ich 
den Speicherbereich im linkerscript hinzugefügt:

MEMORY
{
  flash    (rx) : ORIGIN = 0x00000000, LENGTH = 512K
  ram      (rw) : ORIGIN = 0x40000000, LENGTH = 30720
  sdram     (rw) : ORIGIN = 0xA0000000, LENGTH = 33554432
}

...

sdramlayout :
  {
    _sdram_start_ = 0xA0000000;
    *(.sdramdata)
  _sdram_end_   = 0x02000000;
  } > sdram

und einen Macro definiert :
#define SDRAMDATA _attribute_ ((section (".sdramdata")))

1.das erste Problem ist, der Compiler baucht mehr Zeit als sonst um den 
Code zu übersetzen.

2.wenn im Map reinschaue, finde ich folgendes:

sdramlayout     0xa0000000  0x2000000
                0x40000000                _sdram_start_ = 0xa0000000
 *(.sdramdata)
 .sdramdata     0xa0000000  0x2000000 ./release/ringbuffer.o
                0xa0000000                ringbuffer
                0xa2000000                _sdram_end_ = 0x2000000
das ganze stimmt bis auf die zweite zeile (0x40000000), was hat diese 
Adresse hier zu suchen?

3.der Flash Magic verhält sich komisch; es dauert erstmal ewig bis er 
eine Verbindung mit dem Board erfolgt, und wenn die Sektore die er 
braucht gelöscht hat, dauert es wieder ewig bis er angefangen hat zu 
fläshen.

muss ich vielleicht was anders im linkerskript hinzufügen?

ich bin für jeden Tip dankbar

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
kann keiner was dazu schreiben..?

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
gibt es keiner der sich mit Linkerskript auskennt..?

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Auf http://en.mikrocontroller.net gibt es ein paar mehr, die davon 
Anhnung haben. Umgangssprache ist allerdings Englisch.

Ich persönlich traue mich nicht, was zu deinem Linkerskript zu 
beantworten, weil ich mit ... Zeilen in der Frage nichts anfangen kann. 
Und bevor ich mich mit Spekulationen ala "Da ist ... falsch oder ..." 
zum Affen mache, lasse ich es.

Autor: Robert Teufel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Welcher Baustein denn?
Von den LPC2000 unterstuetzen nur sehr wenige externes DRAM. Das waere 
die LPC24xx und evtl. der LPC28xx und sonst nichts. Ohne DRAM controller 
gestaltet sich die Sache ziemlich schwierig.
Robert

Autor: mthomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Betr. Linker-script. Leider grade keine GNU arm Crosstoolchain zur Hand 
zum Testen, daher erstmal nur ein paar Fragen: Warum die absolute Angabe 
von Addressen in der linker-section? Benötigte Addresse steht bereits 
bei Memory, den Rest lässt man den Linker ausrechnen. Warum grade diese 
"end-addresse"? Was gibt der Linker als VMA und LMA für die neue section 
aus? Prinzip von LMA und VMA halbwegs verinnerlicht? Linker-manual 
durchgelesen (GNU bintutils)? Ist das binary/hex-file extrem gross? 
Initialisierung der Daten im externen RAM erforderlich? Wie ist 
ROM/RAM-copy und zero-init dafür implementiert? Die STR710-Beispiele von 
Anglia-Designs angeschaut (google anglia idealist)? In denen finden 
sich, wenn recht erinnert, ein paar Beispiele für internes und externes 
RAM für GNU toolchain inkl. Linker-Scripten. Auch Linkerscripte für GBA 
sind recht nützlich, da das Teil verschiedenste Speicher bietet.

Martin Thomas

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für die Antworten.

@Robert teufel: es geht um LPC2468, ich benutze die 
EMC-Initialisierungsroutine von NXP.

@Martin Thomas: sorry vielleicht musste ich das ganze linkerskript 
posten:

* ------------------------------------ 0xFFFF FFFF
 * |                                  |
 * |  AHB Peripherals                 |
 * |                                  |
 * |----------------------------------| 0xF000 0000
 * |                                  |
 * |  APB Peripherals                 |
 * |                                  |
 * |----------------------------------| 0xE000 0000
 * |  [Reserved]                      |
 * |----------------------------------| 0x8000 0000
 * |                                  |
 * |  Boot block                      |
 * |                                  |
 * |----------------------------------|
 * |  [Reserved]                      |
 * |----------------------------------| 0x7FE0 4000
 * |  Ethernet RAM                    |   16384 bytes (0x4000)
 * |----------------------------------| 0x7FE0 0000
 * |  [Reserved]                      |
 * |----------------------------------| 0x7FD0 2000
 * |  USB RAM                         |    8192 bytes (0x2000)
 * |----------------------------------| 0x7FD0 0000
 * |  [Reserved]                      |
 * |----------------------------------| 0x4000 8000
 * |            | Reserved for IAP    |     256 bytes (0x100)
 * |            |---------------------| 0x4000 7F00
 * |            | UND Stack           |     256 bytes (0x100)
 * |  Internal  |---------------------| 0x4000 7E00
 * |  RAM       | FIQ Stack           |     256 bytes (0x100)
 * |            |---------------------| 0x4000 7D00
 * |            | IRQ Stack           |     256 bytes (0x100)
 * |            |---------------------| 0x4000 7C00
 * |            | SVC Stack           |    1024 bytes (0x400)
 * |            |---------------------| 0x4000 7800
 * |            | Variables RW and ZI |   30720 bytes (0x7800)
 * |----------------------------------| 0x4000 0000
 * |  [Reserved]                      |
 * |----------------------------------| 0x0008 0000
 * |                                  |
 * | Flash                            |    512K
 * |                                  |
 * |                                  |
 * ------------------------------------ 0x00000000
 *  UND Stack is used by HaltUndef, HaltSWI, HaltPabort and HaldAabort
 *
 ********************************************************************/

/*
 * Defines memory layout
 */

MEMORY
{
  flash    (rx) : ORIGIN = 0x00000000, LENGTH = 512K
  ram      (rw) : ORIGIN = 0x40000000, LENGTH = 30720
  ramstack (rw) : ORIGIN = 0x40007800, LENGTH = 2048
  usbram   (rw) : ORIGIN = 0x7FD00000, LENGTH = 8K
  ethram   (rw) : ORIGIN = 0x7FE00000, LENGTH = 16K
  sdram     (rw) : ORIGIN = 0xA0000000, LENGTH = 33554432
}

/*
 * Define entry point, found in startarm.s
 */
ENTRY(_reset_handler)

/*
 * Sections
 */
SECTIONS
{
  /* Place memory counter at address 0 */
  . = 0;

  /* Place startup code at start of flash */
  startup :
  {
    *(.startup)
  } > flash =0

  . = ALIGN(4);

  /* Place program code */
  prog :
  {
    *(.text)
    *(.rodata)
    *(.rodata*)
    *(glue_7)
    *(glue_7t)
  } > flash =0

  . = ALIGN(4);

  _end_of_text_  = .;
  _data_beg_src_ = .;
  PROVIDE(etext = .);

  /* Place initialized data */
  .data : AT(_data_beg_src_)
  {
    _data_beg_     = .;
    *(.data)
  } > ram

  . = ALIGN(4);
  _data_end_     = .;
  PROVIDE(edata = .);

  /* Place zero initialized data */
  .bss :
  {
    _bss_beg_ = .;
    *(.bss)
  } >ram


  /* Align here to ensure that the .bss section occupies space up to
     _end. Align after .bss to ensure correct alignment even if the
     .bss section disappears because there are no input sections. */
  . = ALIGN(32 / 8);

  . = ALIGN(32 / 8);

  /* Provide end markers */
  _end        = .;
  bss_end_  = .;
  _bss_end_ = .;
  _end_     = .;
  PROVIDE(end = .);

  stacklayout :
  {
    _stack_scv_bottom_ = .;
    . = . + 0x0400;
    _stack_scv_top_    = .;
    _stack_irq_bottom_ = .;
    . = . + 0x0100;
    _stack_irq_top_    = .;
    _stack_fiq_bottom_ = .;
    . = . + 0x0100;
    _stack_fiq_top_    = .;
    _stack_und_bottom_ = .;
    . = . + 0x0100;
    _stack_und_top_    = .;
    _stack_iap_bottom_ = .;
  } >ramstack

  usbramlayout :
  {
    _usbram_start_ = .;
    _usbram_end_   = 0x2000;
  } >usbram

  ethramlayout :
  {
    _ethram_start_ = .;
    _ethram_end_   = 0x4000;
  } > ethram

  sdramlayout :
  {
    _sdram_start_ = 0xA0000000;
    *(.sdramdata)
  _sdram_end_   = 0x02000000;
  } > sdram

Nun, wie soll ich jetzt das schreiben, damit das linkerscript zum SDRAM 
Startadresse springt?
Soweit ich weiss LMA ist die adresse wo der einzelnen Sections geladen 
werden, und VMA wo die dann ausgeführt werden, wie kann ich das jetzt 
für meinen Fall im Linkerscript umsetzen.

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielleicht muss ich meine Frage deulicher ausdrücken;

ich will auf einen SDRAM zugreifen um Daten drauf zu speichern, stimmt 
dann mein Linkerskript daoben? wenn nicht was fehlt denn da?

Es wäre noch super wenn ihr einen Beispiel habt.

Danke im Voraus.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Es gibt bei NXP einen Beispielcode:

Sample Code Bundle for LPC23xx/LPC24xx Peripherals using Keil's μVision, 
V1.50

http://www.standardics.nxp.com/support/documents/m...

Darin ist im Verzeichnis EXTMEM/SDRAM ein Beispiel zum Ansteuern eines 
SDRAM an Basisadresse 0xA0000000 und Länge 0x02000000 inkl. 
Schreiben/Lesen.

Technisch ist das so gelöst, dass dem External Memory Controller (EMC) 
des LPC2468 die Basisadresse des SDRAM und die Länge und das Timing... 
bekannt gemacht wird (ex_sdram.c) und anschliessend Zugriffe über 
Pointer in den Adressraum erfolgen (sdram_test.c). Der EMC kümmert sich 
darum, dass diese Zugriffe korrekt ablaufen.

Dem Linker ist bei der dort verwendeten Methode das SDRAM schnurz, er 
kennt das nicht (als was besonderes).

Bei deiner Methode mit der eigenen Section (bei der du auch irgendwo 
z.B. im Startupcode eine Initialisierung brauchst!) hängen die langen 
Zeiten beim Linken + Löschen IMHO damit zusammen, dass die von dir 
bekannt gemachten 32 MB auch bearbeitet werden wollen z.B. vorm Flashen 
gelöscht werden und beim Flashen ggf. beschrieben werden wollen (wenn du 
irgendwas in der Sektion .sdramdata abgelegt hast).

Aber das ist nur meine Laienmeinung, warte mal ab, was die Experten dazu 
sagen, wenn sie Zeit haben. Nicht zu ungeduldig sein.

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke Stefan,

das Beispiel von NXP benutze ich zum EMC Initialisierung, ich dachte 
eigentlich, dass man den EMC-Controller benutzt, um die Zugriffszyklen, 
den Adress- und Databus zu initialisieren, die Speicherorganisation 
übernimmt dann der Linker, und dachte auch dass die NXP-examples mit 
Keil-uvision entwicklet wurde D.h. dass der linkerscript dementsprechend 
automatisch generiert wird. Es ist auf jeden fall ein Versuch Wert; ich 
werde es so probieren wie im "sdram_test.c" ohne den Linkerscript zu 
ändern und dann sehen wir was passiert.

Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist grundsätzlich richtig gedacht.

Die Zuordnungen Variable => Adresse könnten vom Linker automatisch zur 
Compilezeit gemacht werden und müssten nicht explizit von dir zur 
Compile- oder Laufzeit gemacht werden. Das würde später einen deutlich 
aufgeräumteren Quellcode ergeben.

Nur - Ich kenne die Syntax nicht, um das linker control script zu 
schreiben. Deine Version legt ja die Sektion .sdramdata an der richtigen 
Stelle an und sieht deshalb für mich korrekt aus. Ich kann aber nicht 
sagen, woher die 0x40000000 kommt, die dich stutzig macht.

Gibt eigentlich der Compiler/Linker Fehler/Warnungen aus oder macht dich 
nur das Mapfile skeptisch? Wenn du eine Variable in .sdramdata 
definierst, wie sieht die Ausgabe im Mapfile aus?

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin nur nicht sicher, ob das so richtig ist, mit linkerskript habe 
ich überhaupt keine Erfahrung, was mich auch noch skiptisch gemacht hat, 
war dieses komische Verhalten vom Compiler und dem Flash-Programm, aber 
deine Erklärung klingt logisch, ich versuche es anderes und dann werde 
ich dir Bescheid sagen.

Autor: Martin Thomas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Folgendes nur als Vorschlag, grade nichts zur Hand um es in einem 
Simulator oder "in Hardware" auszuprobieren.

1. Im C-Code nutzt man zwei selbstdefinierte sections. Eine für zu 
initialisierende Daten im externen Speicher. Entspricht .data bei 
initialisierten Daten ohne Attribut. Die andere section für Variablen im 
externen Speicher, die mit 0 zu initialisieren sind (entspr. .bss). Also 
zum Beispiel:
#define EDATA __attribute__ ((section (".exdata_section")))
#define EBSS __attribute__ ((section (".exbss_section")))
int foo1 EDATA = 123;
int foo2 EBSS;
int foo3[] EDATA = { 1, 2, 3 };

2. Den Speicherbereich in MEMORY habe ich einfach mal EXTRAM genannt und 
testweise so definiert:
MEMORY
{
  ROM (rx)    : ORIGIN = 0x00000000, LENGTH = 0x0003E000
  RAM (rw)    : ORIGIN = 0x40000000, LENGTH = 0x00004000
  EXTRAM (RW) : ORIGIN = 0xA0000000, LENGTH = 32k
}

3. Nun ist dafür zu sorgen, dass die Initialisierungswerte für die 
Variablen in "EDATA" im FLASH stehen und man sowohl die Addresse der 
Initialiserungswerte (Kopierquelle) und die Zieladdress dieser Daten 
(Kopierziel) kennt. Weiterhin muss der Addressebereich von "EBSS" 
bekannt sein, um diesen mit 0 vorzubelegen. Habe in Linkerscript von 
einem anderen Projekt genutzt und zwischen "schnipp" und "schnapp" 
ergänzt:
  .data : AT (_etext)
  {
    _data = .;
    *(.data)
    SORT(CONSTRUCTORS)
  } > RAM
  . = ALIGN(4);
  _edata = . ;
  PROVIDE (edata = .);

  /* schnipp */

  _edata_LMA = LOADADDR(.data) + SIZEOF(.data);
  .extdata : AT (_edata_LMA)
  {
     _extdata_start = .;
     *(.exdata_section)
     _extdata_end = .;
  } > EXTRAM
  
  .extbss (NOLOAD) :
  {
     _exbss_start = .;
    *(.exbss_section)
     _exbss_end = .;
  } > EXTRAM

  /* schnapp */  

  /* .bss section which is used for uninitialized data */
  .bss (NOLOAD) :
  {
    __bss_start = . ;
    __bss_start__ = . ;
    *(.bss)
    *(COMMON)
    . = ALIGN(4);
  } > RAM

  . = ALIGN(4);
  __bss_end__ = . ;
  PROVIDE (__bss_end = .);

Das gibt in einem kleinen Beispiel mit ein paar Variablen folgende 
Addressen für die Symbole (Ausgabe vomn nm), die zumindest plausibel 
erscheinen:
...
000002a0 A _etext
000002a4 A _edata_LMA
00000400 A STACK_SIZE
40000000 D _data
40000000 d foodata2
40000004 B __bss_start
40000004 B __bss_start__
40000004 A _edata
40000004 b foobss2
40000008 A __bss_end__
40000500 A _end
40000500 B _stack
a0000000 D _extdata_start
a0000000 d foo3
a000000c d foo1
a0000010 B _exbss_start
a0000010 D _extdata_end
a0000010 b foo2
a0000014 B _exbss_end

4. Sobald man das Speicherinterface im Startupcode initialisiert hat, 
sind die Inhalte der initialiserten Variablen ab "_edata_LMA" nach 
"_exdata_start" zu kopieren. Anzahl dabei: ( _exdata_end - exdata_start 
). Weiterhin sind die Speicherstellen von _exbss_start bis _exbss_end 
mit 0 zu beschreiben. Man kann sich dabei an den Routinen für .data und 
.bss im "normalen" RAM-Bereich orientieren.

Hoffe, es hilft zumindest ein wenig weiter
Martin Thomas

Autor: sean paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Stefan: ich danke dir vielmals, der Zugriff hat geklappt, und der 
Linker hat überhaupt nichts mitbekommen.

@Mattin Thomas: vielen vielen Dank, das wird für alle fälle ein Unikat 
in meinem Tutorials-archiev sein, man weiss ja nie.. ;-)

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.