Forum: Mikrocontroller und Digitale Elektronik Reset-festen RAM Bereich definieren?


von Sven (Gast)


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

von Sven (Gast)


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
}

von (prx) A. K. (prx)


Lesenswert?

Wenn .bss und .noinit nicht im Image auftauchen sollen, dann ist NOLOAD 
nötig, wie
1
  .bss (NOLOAD) :
2
  {
3
    ...
4
  } > ram

von Sven (Gast)


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.

von (prx) A. K. (prx)


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.

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.