Frage:
Wo sind konstante Variablen im Mikrocontroller gespeichert?
Arun Joe Cheriyan
2017-01-20 13:25:49 UTC
view on stackexchange narkive permalink

Gemäß dem Speicherlayout des C-Programms werden konstante Variablen im initialisierten Datensegment des RAM gespeichert.Gemäß einigen Speicherlayouts des Mikrocontrollers werden const-Variablen im FLASH-Speicher gespeichert. Ich habe auch gesehen, dass die Größe der BIN-Datei meines Codes zunimmt, wenn ich mich ändere const Variablen zu Makrodefinitionen?Helfen Sie mir, diese Unklarheit zu beseitigen.Ich habe Nuc2240 Cortex M0 verwendet .

RAM in den meisten Mikros ist flüchtig, daher werden Konstanten im Flash gespeichert und können während der Initialisierung in das RAM kopiert werden (oder auch nicht) (dies hängt vom Mikro ab).Das "Speicherlayout des C-Programms", auf das Sie verweisen, ist als solches kein Standard. Viele dieser Details hängen von der Implementierung ab.C selbst ist nur die Hochsprache. Die Speichernutzung wird vom Compiler und Linker mit einigen Kenntnissen der Zielplattform bestimmt.Ich sehe darin keine "Zweideutigkeit", es sei denn, ich habe Ihre Besorgnis missverstanden?
Mögliches Duplikat von [Was befindet sich in den verschiedenen Speichertypen eines Mikrocontrollers?] (Http://electronics.stackexchange.com/questions/237740/what-resides-in-the-different-memory-types-of-a-microcontroller)).
In den Antworten werden hier verschiedene Schemata behandelt (Laden Sie die Konstante aus Flash oder RAM oder codieren Sie sie in der Anweisung).Sie können sehen, was Ihre Toolchain in verschiedenen Fällen tut, indem Sie eine Demontage-Liste des Programms anzeigen und den Assembler-Anweisungen folgen.Viele IDEs bieten die Möglichkeit, Disassemblierungslisten zu erstellen, oder Sie können ein eigenständiges Programm verwenden.
Fünf antworten:
Neil_UK
2017-01-20 14:47:01 UTC
view on stackexchange narkive permalink

Wenn Sie Assembler schreiben, würden Sie über org oder ähnliche Anweisungen entscheiden, an welchen Stellen welche Konstanten oder Variablen gespeichert werden sollen.

Wenn Sie C schreiben, speichert die von Ihnen verwendete C-Werkzeugkette Inhalte dort, wo sie programmiert wurden.Variablen tendieren offensichtlich dazu, in RAM zu gehen, Konstanten können entweder in RAM oder Flash gehen, Programme neigen dazu, in Flash zu gehen.

Es hängt alles davon ab, wie das Tool für diesen bestimmten Zielprozessor entwickelt wurde und woher es seine Anweisungen erhält, wo es Dinge ablegen soll.Möglicherweise wird alles in den Code eingebrannt. In diesem Fall erhalten Sie kein Mitspracherecht. Es wird dorthin gesendet, wo die Entwickler der Toolkette ihn gesendet haben.Es kann Anweisungen von irgendwoher (Quellcode, Befehlszeile, Datei erstellen, Umgebungsvariable) enthalten, damit Sie Inhalte neu erstellen können.

Lesen Sie Ihre spezifische Dokumentation.Es ist keine Physik, es hängt alles von der Laune des Menschen ab.

Es ist nicht die Aufgabe des Compilers, sondern des Codegenerators und des Linkers, Segmente mit Konstanten an einer Stelle innerhalb von EPROM, FLASH oder batteriegepuffertem RAM zu platzieren.Konstanten können aber auch in den flüchtigen RAM gestellt werden, wenn sie beim Programmstart durch speziellen Code initialisiert werden, der vom Compiler generiert wird.
Ja, Compiler bin ich faul, die Werkzeugkette.
Jon
2017-01-20 20:15:05 UTC
view on stackexchange narkive permalink

Die Antwort auf Ihre Frage ist spezifisch für die von Ihnen verwendete Architektur. Da Sie ARM erwähnt haben, werde ich Ihnen darauf basierend eine Antwort geben.

Der ARM Cortex ist ein registergestütztes Design, daher müssen grundsätzlich alle Operanden (const oder nicht) ihren Weg in eines der internen Register finden, bevor sie von Programmanweisungen verwendet werden können. Dies ist für die Beantwortung Ihrer Frage von zentraler Bedeutung, da die Architektur dies auf verschiedene Arten ermöglicht.

Bei kleinen Konstanten (normalerweise weniger als 8 oder 10 Bit) kann der Wert direkt in bestimmte Anweisungen codiert werden. Zum Beispiel gibt es einen ADD #imm-Befehl, der einem Register einen 12-Bit-Wert hinzufügt, der in das Befehlswort codiert ist. Dies kann verwendet werden, um direkt eine Konstante in Ihrem Programm anzugeben. Wenn Sie dieselbe Konstante an verschiedenen Stellen in Ihrem Code hinzufügen und der Wert 12 Bit oder weniger beträgt, verwendet der Compiler einfach überall dort, wo Ihre Konstante benötigt wird, einen ADD #imm-Befehl. Mit anderen Worten, die tatsächliche Konstante wird an mehreren Stellen im gesamten in FLASH gespeicherten Code repliziert.

Wenn die Konstante groß ist, funktioniert dies nicht. Daher muss der Wert an einem eigenen dedizierten FLASH-Speicherort gespeichert werden. Der Chip verfügt über einen weiteren Befehl namens LDR, mit dem ein Wert von einem Speicherort in die internen Register verschoben wird, in denen er verwendet werden kann. Dieser Anweisung ist es egal, ob der Wert physisch in FLASH oder RAM gespeichert ist, er zieht den Wert einfach von einer bestimmten Adresse im Speicher und legt ihn in einem Register ab. Beachten Sie, dass dies im Vergleich zur Situation mit kleinen Konstanten einen zusätzlichen Befehlszyklus erfordert. Wenn die Konstante jedoch wiederholt in einem Codeblock verwendet wird, speichert der Compiler sie zwischen, indem er sie in ein Ersatzregister legt, sofern eine verfügbar ist. P. >

Jetzt stoßen wir jedoch auf ein potenzielles Problem. Auf den meisten Cortex-Chips läuft der FLASH-Speicher mit der gleichen Geschwindigkeit oder langsamer als der CPU-Kern. Wenn wir versuchen, einen LDR-Befehl von einem FLASH-Ort aus auszuführen, muss diese Leseoperation des physischen Speichers mit dem Lesen des nächsten Befehls konkurrieren. Dies führt zu einem Engpass, der dazu führt, dass die CPU stehen bleibt, bis die Daten gelesen wurden. Schlimmer noch, bei vielen Implementierungen läuft der FLASH sehr langsam und ein Pipeline-Cache wird verwendet, um Anweisungen schneller an die CPU weiterzuleiten. Beim Lesen dieser Geräte kann beispielsweise eine Tabelle mit konstanten Werten den grundlegenden FLASH-Zugriffsengpass aufdecken, der zu schwerwiegenden Leistungseinbußen führt.

Aus diesem Grund versuchen viele Compiler, konstante Daten nach Möglichkeit in freie RAM-Speicherorte zu kopieren. Dies verhindert solche Probleme, und da der Zugriff auf RAM normalerweise schneller ist als auf FLASH, können viele Leistungsengpässe vermieden werden. Wenn Ihr Programm ohnehin nicht verwendeten RAM enthält, ist dies für den Compiler praktisch kein Aufwand.

Es gibt also definitiv eine Logik dafür, wie der Compiler dem physischen Speicher konstante Daten zuweist, aber zum Glück haben die Chip- und Compiler-Designer in den meisten Situationen all diese harte Arbeit für Sie geleistet, und Sie können einfach darauf vertrauen, dass er alles tut ist am besten für Ihren speziellen Code und Ihre Optimierungsstufe geeignet.

dim
2017-01-20 14:48:50 UTC
view on stackexchange narkive permalink

Der von Ihnen angegebene Link erklärt, was auf normalen Computern passiert, die ohnehin alles (einschließlich Code) in den Arbeitsspeicher laden (da dies das einzige verfügbare Element ist, aber es gibt genügend davon). Dies gilt nicht für eingebettete Programmierung, bei der auch Flash verfügbar ist. Wenn Sie also ein Linkerskript verwenden, das für die eingebettete Programmierung geeignet ist (dies sollte die Standardeinstellung für eingebettete IDEs sein), werden konstante Daten tatsächlich wie gewünscht in Flash gespeichert.

Wenn Sie nun Makrodefinitionen verwenden, ist dies völlig anders. Makros werden innerhalb des Quellcodes durch den Präprozessor ersetzt. Dies bedeutet, dass die Konstante jedes Mal, wenn Sie sie in Ihrem Code verwenden, unabhängig neu kompiliert wird. Und wenn Sie es mehrmals verwenden, wird der Code tatsächlich größer. Dies sollte natürlich nicht für einfache ganzzahlige Konstanten der Fall sein. Bei Zeichenfolgenkonstanten versuchen gute Compiler, mehrere identische Werte zusammenzuführen, um diesen Effekt zu verringern und die Größe klein zu halten. Dies ist jedoch nicht garantiert und kann davon abhängen, ob die Zeichenfolgen nur innerhalb derselben Kompilierungseinheit (.c-Quelldatei) oder über mehrere hinweg verwendet werden mehrere Kompilierungseinheiten. Bei konstanten Strukturen / Objekten führen die Compiler normalerweise keine großen Optimierungen durch.

Antworten wären für Ihren speziellen Fall relevanter, wenn Sie Auszüge aus Ihrem Quellcode bereitstellen und angeben, welchen Compiler / welche IDE Sie verwenden.

dannyf
2017-01-20 18:33:51 UTC
view on stackexchange narkive permalink

Die Antwort hängt von Ihrer Definition der "konstanten Variablen" und dem verwendeten Compiler ab.

Wenn es sich tatsächlich um eine "konstante Variable" handelt, speichern die meisten Compiler sie wie in Flash.

Wenn es über ein Makro deklariert wird, kann es möglicherweise keine konstante Variable sein - es ist eine Konstante.Es wird im Allgemeinen in Flash gespeichert und in RAM kopiert.

Ronan Paixão
2017-01-20 20:58:03 UTC
view on stackexchange narkive permalink

Sieht so aus, als würden Sie Konstanten mit Variablen verwechseln. Dies ist besonders wichtig, wenn Sie C und nicht C ++ verwenden.

In C wird das, was Sie als konstante Variable bezeichnen (wie eine const int ), tatsächlich in den RAM geworfen. So geht der Compiler mit der Notwendigkeit um, manchmal auf die Adresse (Zeiger) der Variablen zu verweisen.

Wenn dies eine globale Variable ist, fügt der Compiler diese in den Abschnitt initialisierte Daten ein. Dies bedeutet, dass die Werte im Abschnitt .etext blinken und kopiert werden zum Abschnitt .sdata ​​code> (Teil von .data ​​code>) durch das Startskript . Wenn es sich um eine lokale Variable handelt, führt der Startcode der Funktion dies wie jede andere Variable aus.

Wenn Sie jedoch ein Makro verwenden, erhält die "Variable" keinen Adressraum. Das heißt, es wird als sofort geladen, entweder durch genau den Befehl, den Sie verwenden (wenn der Wert klein genug ist und der Befehl Sofort unterstützt) oder direkt vor dem Befehl, der den Befehl verwendet, in ein Register geladen Wert. Dies verwendet nur Flash-Speicherplatz, vorausgesetzt, Sie führen Code aus Flash aus.

Wenn Sie dagegen C ++ verwenden, führt der Compiler bei Optimierungen den Wert direkt aus Flash aus. Dies ist in C nicht beabsichtigt. Weitere Informationen finden Sie in dieser Antwort.

Übrigens macht der Cortex-M3, den ich benutze, die Dinge in GCC.


Diese Fragen und Antworten wurden automatisch aus der englischen Sprache übersetzt.Der ursprüngliche Inhalt ist auf stackexchange verfügbar. Wir danken ihm für die cc by-sa 3.0-Lizenz, unter der er vertrieben wird.
Loading...