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
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.
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
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
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.
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/microcontrollers/zip/code.bundle.lpc23xx.lpc24xx.uvision.zip
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.
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.
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?
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.
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:
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:
1
.data : AT (_etext)
2
{
3
_data = .;
4
*(.data)
5
SORT(CONSTRUCTORS)
6
} > RAM
7
. = ALIGN(4);
8
_edata = . ;
9
PROVIDE (edata = .);
10
11
/* schnipp */
12
13
_edata_LMA = LOADADDR(.data) + SIZEOF(.data);
14
.extdata : AT (_edata_LMA)
15
{
16
_extdata_start = .;
17
*(.exdata_section)
18
_extdata_end = .;
19
} > EXTRAM
20
21
.extbss (NOLOAD) :
22
{
23
_exbss_start = .;
24
*(.exbss_section)
25
_exbss_end = .;
26
} > EXTRAM
27
28
/* schnapp */
29
30
/* .bss section which is used for uninitialized data */
31
.bss (NOLOAD) :
32
{
33
__bss_start = . ;
34
__bss_start__ = . ;
35
*(.bss)
36
*(COMMON)
37
. = ALIGN(4);
38
} > RAM
39
40
. = ALIGN(4);
41
__bss_end__ = . ;
42
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:
1
...
2
000002a0 A _etext
3
000002a4 A _edata_LMA
4
00000400 A STACK_SIZE
5
40000000 D _data
6
40000000 d foodata2
7
40000004 B __bss_start
8
40000004 B __bss_start__
9
40000004 A _edata
10
40000004 b foobss2
11
40000008 A __bss_end__
12
40000500 A _end
13
40000500 B _stack
14
a0000000 D _extdata_start
15
a0000000 d foo3
16
a000000c d foo1
17
a0000010 B _exbss_start
18
a0000010 D _extdata_end
19
a0000010 b foo2
20
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
@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.. ;-)