Forum: Compiler & IDEs Linker Frage: ROM Layout by "Run in SRAM"


von Uwe Bonnes (Gast)


Lesenswert?

Hallo,

neuere Mikrocontroller haben inzwischen ja meist so viel SRAM, dass man 
auf die Idee kommen kann, beim Debuggen das Programm nur ins RAM zu 
laden und dort laufen zu lassen. Für den STM32 habe ich dazu ein 
Trampolin ins Flash geschrieben, dass nach einem Reset den Stack aus 
0x20000000 lädt und dann nach 0x20000004 springt. Hat man im Linker 
Skript etwas wie
   .text:{ *(.text .text.* .gnu.linkonce.t.*)
        *(.rodata .rodata* .gnu.linkonce.r.*)
    } > SRAM0
    .data :
    {
        *(.data .data.* .gnu.linkonce.d.*)
        . = ALIGN(4);
        *(.ramfunc);
        . = ALIGN(4);
    } > SRAM0
geht das aber nach dem Hochladen nur einmal, das die initialisierten 
Daten im ersten Lauf verändert werden.

Damit das Ganze auch auch nach einem Programmlauf neu Starten kann, 
bräuchte man einen Bereich im SRAM, aus dem die initialisierten Daten 
jedesmal neu geladen werden, wie in Linkerskripten für Flash. Allerdings 
bringt
   .text:{ *(.text .text.* .gnu.linkonce.t.*)
        *(.rodata .rodata* .gnu.linkonce.r.*)
    .etext = .;
    } > SRAM0
    .data : AT (_etext)
    {
        _sdata = .;
        *(.data .data.* .gnu.linkonce.d.*)
        . = ALIGN(4);
        *(.ramfunc);
        . = ALIGN(4);
        _edata = .;
    } > SRAM0
nichts, da dann die zu initialisierenden Daten und die 
Initialisierungsdaten aufeinander liegen.

Kurzum, hinter dem Text müsste man (_edata -_sdata) Platz lassen. Der 
GNU Linker kennt aber meines Wissens keine Vorwärtsreferenz. Man muss 
explizit xxx Bytes frei lassen. Das geht natürlich einige Zeit gut. Aber 
entweder der Bereich ist zu gross, und man verschenkt noch mehr SRAM, 
oder er ist zu klein und der Linker meldet keinen Fehler und beim 
Programmlauf geht irgendetwas schief.

Übersehe ich eine Möglichkeit?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Uwe Bonnes schrieb:
> Übersehe ich eine Möglichkeit?

Ich fürchte, du übersiehst nichts.

von Roland H. (batchman)


Lesenswert?

> Kurzum, hinter dem Text müsste man (_edata -_sdata) Platz lassen.

D. h. nochmals so viel Platz wie die initialisierten Daten benötigen?

> Der GNU Linker kennt aber meines Wissens keine Vorwärtsreferenz.

Was ist eine Vorwärtsreferenz?

> Man muss explizit xxx Bytes frei lassen.

xxx im Sinne einer allgemeinen Konstanten oder der jeweiligen 
tatsächlich benötigten Größe?

Zeig doch mal Deine Ausgangsbasis (normales Linker script) und die 
aktuelle Version für "Run in RAM". Und das Trampolin.

Ist das Trampolin in Assembler geschrieben? Bzw. benötigt es RAM?

von Uwe Bonnes (Gast)


Angehängte Dateien:

Lesenswert?

Roland H. schrieb:
>> Kurzum, hinter dem Text müsste man (_edata -_sdata) Platz lassen.
>
> D. h. nochmals so viel Platz wie die initialisierten Daten benötigen?
>
Ja.

>> Der GNU Linker kennt aber meines Wissens keine Vorwärtsreferenz.
>
> Was ist eine Vorwärtsreferenz?

Ich wuerde gerne

   .text:{ *(.text .text.* .gnu.linkonce.t.*)
        *(.rodata .rodata* .gnu.linkonce.r.*)
    .etext = .;
    } > SRAM0
    .data : AT (_etext)
    {
 >>>    . + = _edata - _sdata;
        _sdata = .;
        *(.data .data.* .gnu.linkonce.d.*)
        . = ALIGN(4);
        *(.ramfunc);
        . = ALIGN(4);
        _edata = .;
    } > SRAM0
schreiben. Wenn der Linker aber zu der Zeile mit >>> kommt, dann ist 
weder _sdata noch _edata bekannt. Das habe ich als Vorwärtsreferenz 
bezeichnet.

>> Man muss explizit xxx Bytes frei lassen.
>
> xxx im Sinne einer allgemeinen Konstanten oder der jeweiligen
> tatsächlich benötigten Größe?
>

xxx im Sinne einer Zahl, von der man meint, das genugend Platz für die 
Variablen Daten bleibt. Ich habe 0x1000 genommen, bei der F2/F4 Familie 
mit 128(+) k Ram muss man ja nicht knausern.

> Zeig doch mal Deine Ausgangsbasis (normales Linker script) und die
> aktuelle Version für "Run in RAM".
Das angehängte Linkerskipt stm32f10x_ram.ld ist STM32 generisch. Vorher 
gibt es ein Devicespezifisches Linkerskript.


> Und das Trampolin.
Auch angehängt.

> Ist das Trampolin in Assembler geschrieben?
Nein

>Bzw. benötigt es RAM?

Nein.

von Roland H. (batchman)


Lesenswert?

Wenn ich es richtig verstanden haben, dann willst Du so etwas
1
    .data : AT (_etext)
2
    {
3
        . + = xxx;
4
        _sdata = .;
5
        *(.data .data.* .gnu.linkonce.d.*)
6
        . = ALIGN(4);
7
        *(.ramfunc);
8
        . = ALIGN(4);
9
        _edata = .;
10
    } > SRAM0

um den Platz freizuhalten, so dass zwischen den Initial-Werten und den 
eigentlichen Variablen unterschieden werden kann.

Wie wäre es damit, zwei Linker-Läufe anzusetzen?

Im ersten Lauf bekommt xxx einen bel. Wert,
nach dem Lauf die Differenz berechnen,
im zweiten Linker-Lauf mittels Kommandozeilenparameter den Wert xxx ins 
Linker-Script geben (oder mit einem 2. Linker-Script und include).

Hab's noch nie probiert, einfach als Idee.

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.