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?
Die kurze Antwort ist, Ihre Variable mit dem const
Schlüsselwort zu deklarieren. Wenn sich Ihre MCU tatsächlich an den Wert Ihrer const
Variablen 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 0x08000000
und 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 .text
Sections (so nennt der Compiler Code-Section) und .rodata
Sections (so nennt der Compiler const
Variablen) in die Flash-Section zu stellen sind.
Wie oben vorgeschlagen, .map
ist 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
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.
Benutzer2412542
Olin Lathrop
Joe Hass
Superkatze
const
Modifikator 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 denenconst
Variablen gespeichert werden, automatisch dort platziert. Ich glaube, dass ARM-Compiler normalerweise ein solches Standardverhalten haben, daherconst
sollte eine Direktive für das ausreichen, was Sie brauchen.Barmaley