Reset-festen RAM Bereich definieren?

Gast #2382590
Lesenswert?

Hallo,

ich nutze einen ARM Cortex M3 ( STM32 ) mit GNU Toolchain. Der 
Startup-Code sorgt dafür, dass .bss / .data Segmente initialisiert 
werden (mit den im Sourcecode angegebenen Initwerten oder 0).

Wie kann ich einen reset-festen Bereich definieren, der vom Startup-Code 
nicht initialisiert wird? Solche Daten dürfen ja dann weder in .bss noch 
in .data stehen. Ich kenne mich mit Linker/Lokatierung leider kaum 
aus...

Hat jemand ein Beispiel das zeigt, wie man solche Variablen im Quellcode 
definieren muss und welche Anpassungen am Linkerscript nötig sind?

Die Definition von .bss und .data sieht bei mir so aus:

    .data :
    {
        PROVIDE(_data = .);
        *(.data)
        . = ALIGN(4);
        *(.data.*)
        . = ALIGN(4);
        *(.ramtext)
        . = ALIGN(4);
        PROVIDE(_edata = .);
    } > ram AT > flash

    .bss :
    {
        PROVIDE(_bss_start = .);
        *(.bss)
        . = ALIGN(4);
        *(.bss.*)
        . = ALIGN(4);
        *(COMMON)
        . = ALIGN(4);
        PROVIDE(_bss_end = .);
    } > ram

Danke! Sven
Gast #2383638
Lesenswert?

Ich antworte mir mal selbst...

int volatile my_test __attribute__((section(".noinit")));

Das funktioniert, der Daten werden allerdings an eine undefinierten 
Adresse lokatiert. Wenn ich die Daten gerne an einer festen Adresse 
haben möchte, muss ich die Section im Linkerscript definieren. Laut 
map-file landen die Variablen dann an der gewünschten Adresse, 
allerdings wird der Code (ROM) verschoben, und das resultierende .bin 
File ist größer als das Prozessorflash (vorher ca. 30k, nachher >390k).

Was mache ich falsch, warum verschiebt die von mir eingefügte .noinit 
Section den Code?

Danke, Sven


    .noinit :
    {
        PROVIDE(_noinit = .);
        *(.noinit)
        . = ALIGN(4);
        *(.noinit.*)
        . = ALIGN(4);
        PROVIDE(_enoinit = .);
    } > ram

    .data :
    {
        PROVIDE(_data = .);
        *(.data)
        . = ALIGN(4);
        *(.data.*)
        . = ALIGN(4);
        *(.ramtext)
        . = ALIGN(4);
        PROVIDE(_edata = .);
    } > ram AT > flash

    .bss :
    {
        PROVIDE(_bss_start = .);
        *(.bss)
        . = ALIGN(4);
        *(.bss.*)
        . = ALIGN(4);
        *(COMMON)
        . = ALIGN(4);
        PROVIDE(_bss_end = .);
    } > ram
}
Gast #2384494
Lesenswert?

Danke AK, das so funktionierts. Meine Daten sind jetzt reset-safe an 
einer festen Wunschadresse lokatiert, ohne dass der Code-Bereich 
verändert wird.

Was ich da getan hab verstehe ich allerdings nicht. Bei den bereits 
vorhandenen Sections .bss und .data ist kein NOLOAD angegeben, und 
trotzdem funktioniert es.

Woher der Zusammenhang zwischen RAM und ROM Bereich kommt, ist mir nicht 
klar.

Aber Hauptsache es geht.
#2384533
Lesenswert?

Sven schrieb:

> Was ich da getan hab verstehe ich allerdings nicht. Bei den bereits
> vorhandenen Sections .bss und .data ist kein NOLOAD angegeben, und
> trotzdem funktioniert es.

NOLOAD heisst ja letztlich, dass die Daten in diesem Bereich im Image 
nicht auftauchen und beim Programmieren nicht geladen werden, nur die 
Adressen und Symbole verwaltet werden. Wenn in deinem .bss kein NOLOAD 
drin steht, dann stehen im Image sinnlose Nullen drin. Bei .data wäre 
NOLOAD hingegen unangebracht, denn dessen initialisierte Daten sollen ja 
ins Image.

Der Unterschied zwischen .bss und .noinit liegt letztlich nur im 
Startup-Code. Der initialisiert .bss mit Nullen und lässt .noinit in 
Frieden.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren