So lagern Sie Variablen im FLASH-Speicher

Ich arbeite mit einem STM32-Evalboard von STMicro, das einen ARM Cortex-M4-Prozessor enthält. Ich brauche eine LUT für Cosinus und Sinus (Nur-Lese-Variablen). Ich muss meinen RAM-Speicher verwalten, deshalb möchte ich diese LUT im Flash-Speicher speichern.

Erstens: Ist es besser, eine interpolierte Berechnung von Cosinus/Sinus zu erstellen, oder ist der FLASH-Messwert schnell genug?

Zweitens, wie man die Variablen in den FLASH-Speicher legt. ST bietet einige Beispiele, aber vielleicht muss ich für mein Problem nur die LUT-Variablen als statische Konstante deklarieren und es wird wie Code sein?

Antworten (3)

Die kurze Antwort ist, Ihre Variable mit dem constSchlüsselwort zu deklarieren. Wenn sich Ihre MCU tatsächlich an den Wert Ihrer constVariablen erinnert (dh Ihre Sinusberechnung funktioniert tatsächlich), muss sie so ziemlich im Flash-Speicher gespeichert werden, da sie sonst beim ersten Neustart nach der Programmierung verloren gehen würde.

Die lange Antwort hat mit dem Linker-Skript zu tun. Diese Skripte sind MCU-abhängig und teilen dem Linker mit, wo er was einfügen soll. Normalerweise wird dieses Skript von der IDE bereitgestellt, aber Sie können auch Ihr eigenes schreiben. Bei meinem STM32F4-Setup beginnt mein Linker-Skript mit einer solchen Anweisung:

MEMORY
{
    FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1024K
    RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
    CCMRAM (xrw)    : ORIGIN = 0x10000000, LENGTH = 64K
    MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

Es heißt, dass der Flash bei Adresse 0x08000000und der RAM bei Adresse beginnt 0x20000000. Diese Adressen finden Sie im Datenblatt, wo die Speicherkarte beschrieben ist. Der Rest des Skripts kann involviert sein, aber irgendwann wird etwas in dieser Richtung vorhanden sein:

.text :
{
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
} >FLASH

Das besagt, dass alle .textSections (so nennt der Compiler Code-Section) und .rodataSections (so nennt der Compiler constVariablen) in die Flash-Section zu stellen sind.

Wie oben vorgeschlagen, .mapist die Datei die primäre Methode, um zu überprüfen, was der Linker wo ablegt. Sie weisen den Linker an, es mit dieser Option zu generieren:

arm-eabi-gcc -Wl,-Map=my_program.map ...

Sie können in dieser Zuordnungsdatei nach Ihrem Symbol suchen, sehen, an welcher Adresse es gespeichert wurde, und dies mit der im MCU-Datenblatt angegebenen Speicherkarte vergleichen.

Nein, Sie können keine Variablen in den Nur-Lese-Speicher stellen. Sie können dort jedoch Konstanten einfügen, was alles ist, was Sie brauchen, da Sie nach einer Sinus/Kosinus-Nachschlagetabelle fragen. Diese Werte werden durch Mathematik festgelegt und müssen nicht im laufenden Betrieb geändert werden.

Sicherlich beschreibt die Sprachdokumentation, wie ein Array von Konstanten in den Programmspeicher gezwungen wird. Dies geschieht normalerweise mit einem Schlüsselwort oder durch die Angabe von Attributen für einen Linkerabschnitt oder möglicherweise durch zusätzliche Informationen, die separat an den Linker übergeben werden.

Informationen zum Implementieren einer Sinus- und Cosinus-Suche finden Sie in diesen vorherigen Antworten:

https://electronics.stackexchange.com/a/60819/4512
https://electronics.stackexchange.com/a/16516/4512

Die Verwendung des Schlüsselworts const mit der Sprache C scheint die Daten in den Flash-/Programmspeicher zu legen. Wie überprüfe ich mit der IDE (ich verwende CooCox mit ARM GNU gcc Compiler), ob diese Variablen wirklich in den FLASH-Speicher gemappt sind? Vielen Dank.
@user: Wahrscheinlich, obwohl das theoretisch dem Compiler nur mitteilt, dass Sie nicht beabsichtigen, den Wert zu ändern. Es gibt keine Möglichkeit, dies für ein Compiler-/Linker-Toolset mit Sicherheit zu wissen. Sie müssen noch die Dokumentation lesen, was Sie natürlich sowieso tun sollten. Denken Sie daran, dass das OP nie gesagt hat, welche Sprache er verwendet.
@user2412542 Sie können dem gcc-Befehl eine Option hinzufügen und eine Memory-Map-Datei generieren lassen, oder Sie können den objdump-Befehl verwenden, um zu sehen, wo verschiedene Dinge im Speicher abgelegt werden.
Bei vielen Compilern werden Variablen mit einem constModifikator in einem separaten Linker-Abschnitt von denen ohne zugewiesen; In der Regel gibt es eine Option, um einige Linker-Abschnitte in den Codebereich zu zwingen, und in vielen Fällen werden die Abschnitte, in denen constVariablen gespeichert werden, automatisch dort platziert. Ich glaube, dass ARM-Compiler normalerweise ein solches Standardverhalten haben, daher constsollte eine Direktive für das ausreichen, was Sie brauchen.
Sie können Ihren FLASH-Speicher zum Speichern von Variablen verwenden. Nicht sofort einsatzbereit, es ist etwas Code beteiligt. Hier ist ein gutes Beispiel, eine andere MCU, aber dieselbe Cortex-Familie. os.mbed.com/users/olympux/code/eeprom_flash

um Daten in Flash zu legen, deklarieren Sie sie als const

const unsigned int lut[]= { 0x1234, 0xab, 0xcd, 0xefa1123, 0x1122334, ...

Ihr Linker-Skript muss möglicherweise einen Eintrag haben, abhängig von der Art und dem Alter Ihrer Toolchain, es könnte in .text oder .rodata oder anders gehen, abhängig von Ihrer Toolchain. und Sie würden diesen Abschnitt dann in Flash einfügen.