Die Ausführung von Code in embedded Systemen
Ich arbeite im embedded-system-Domäne. Ich würde gerne wissen, wie ein code wird ausgeführt von einem mikrocontroller(uC müssen nicht subjektiv, im Allgemeinen), ausgehend von einer C-Datei. Auch würde ich gerne wissen, stopft wie startup-code, Objekt-Datei, etc. Ich konnte nicht finden in den online-Dokumentationen in Bezug auf die oben genannten Dinge. Wenn möglich, geben Sie bitte links, die erklärt diese Dinge von Grund auf neu. Vielen Dank im Voraus für Eure Hilfe
- Es würde helfen, zu zeigen, welche Art von mikrocontroller.
- Arbeite in der 8051-controller. ich weiß ein wenig darüber, wie Befehle abgerufen und ausgeführt assembly-Sprache). würde aber gerne wissen, wie ein Projekt mit mehreren C-Dateien ausführt, die auf einem uC.
- die C-Dateien nicht ausführen! 🙂 Sie sind zusammengestellt, um Objekt-Dateien, und verbunden, die in eine endgültige ausführbare Bild, das entweder geladen, um flash-oder RAM und von dort aus ausgeführt werden.
InformationsquelleAutor inquisitive | 2009-09-02
Schreibe einen Kommentar Antworten abbrechen
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wird ein Mikroprozessor, der Architekt, hatte ich die Gelegenheit, arbeiten auf einem sehr niedrigen Niveau für die software. Im Grunde low-level-embedded ist sehr Verschieden von der Allgemeinen PC-Programmierung nur auf der hardware-spezifischen Ebene.
Low-level embedded software kann unterteilt werden in die folgenden:
main()
. edit: Variablen müssen initialisiert werden, und auch bestimmte Teile des Speichers, die der Klärung bedürfen, sind hier fertig. Im Grunde, alles, was erforderlich ist, um die Dinge bewegen sich in einem 'bekannten-Status'.main()
Funktion. Wie Sie sehen können, eine Menge Dinge sind wirklich unter der Haube und passieren schon vor dem ersten main-Funktion aufgerufen wird. Dieser code kann in der Regel geschrieben werden als hardware-agnostisch, wenn es eine gute hardware abstraction layer zur Verfügung. Der Anwendungs-code wird auf jeden Fall nutzen a viele library-Funktionen. Diese Bibliotheken sind in der Regel statisch gelinkt in embedded-Systemen.Hoffe, dass diese Informationen einen guten start. Fühlen Sie sich frei, um Kommentare zu hinterlassen, wenn Sie andere queries.
In der Regel arbeiten Sie auf einem viel niedrigeren Niveau als general purpose Computer.
Jede CPU bestimmte Verhalten beim einschalten, wie das löschen aller Register und Einstellung der Programm-Zähler zu 0xf000 (alles, was hier ist, nicht-spezifisch, da ist deine Frage).
Der trick ist, um sicherzustellen, dass Ihr code ist an der richtigen Stelle.
Die Kompilierung ist in der Regel ähnlich wie general purpose Computer, in die Sie übersetzen C in Maschinen-code (Objekt-Dateien). Von dort aus, müssen Sie den link-code mit:
System start-up-code in der Regel nur initialisiert die hardware und legt die Situation so, dass der C-code arbeiten können. Runtime-Bibliotheken in eingebetteten Systemen oft machen die großen, sperrigen Sachen (wie floating-point-Unterstützung oder printf) optional so zu halten, code aufblähen.
Den linker in eingebetteten Systemen in der Regel auch ist viel einfacher, die Ausgabe von fest-location-code, anstatt verschiebbar binaries. Verwenden Sie es, um sicherzustellen, die start-up-code geht bei (z.B.) 0xf000.
In embedded-Systemen Sie wollen in der Regel die ausführbaren code, um von Anfang an vorhanden sein, so können Sie brennen in EPROM (oder EEPROM-oder Flash-oder andere Gerät, das pflegt die Inhalte auf power-down).
Natürlich, im Hinterkopf behalten mein letzter Ausflug war mit 8051 und 68302-Prozessoren. Kann es sein, dass embedded-Systeme sind heutzutage ausgewachsenen Linux-Boxen mit allen Arten von wunderbaren hardware, in dem Fall gäbe es keinen wirklichen Unterschied zwischen dem Allgemeinen Zweck und eingebettet.
Aber ich bezweifle es. Es gibt immer noch einen Bedarf für ernst low-spec hardware, die Bedürfnisse benutzerdefinierte Betriebssysteme und/oder der Anwendung code.
SPJ Embedded-Technologien hat eine herunterladbare Bewertung Ihrer 8051 Entwicklungsumgebung aussieht, was Sie wollen. Sie können Programme erstellen, die bis zu 2K in der Größe scheint es aber zu gehen durch den gesamten Prozess (kompilieren, verknüpfen, generation von HEX-oder BIN-Dateien für dumping auf der target-hardware, auch ein simulator, der Zugang zu den on-chip-Zeugs und externe Geräte).
Die nicht-Bewertung Produkt kostet 200 Euro, aber wenn alle, die Sie wollen, ist ein bisschen ein Spiel ist, würde ich nur laden Sie die Auswertung, die - anders als die 2K-Grenze, es ist das gesamte Produkt.
Habe ich den Eindruck bekommen, die dich am meisten interessiert, was sybreon Anrufe "Schritt 2." Viel kann passieren, und es variiert stark von der Plattform ab. In der Regel, dieses Zeug wird behandelt durch eine Kombination von bootloader, board-support-package, C Runtime - (CRT -), und wenn Sie einen haben, der OS.
In der Regel, nachdem der reset-Vektor, eine Art bootloader ausführen von flash. Dieser bootloader kann nur einrichten der hardware und springen Sie in Ihrem app-CRT, auch in flash. In diesem Fall, ist die CRT wahrscheinlich würde klar die .bss, kopieren Sie die .Daten zum RAM, etc. In anderen Systemen, der bootloader scatter-laden Sie die app aus einer kodierten Datei, wie eine ELFE, und das CRT stellt nur andere Laufzeit Zeug (heap, etc.). All dies geschieht, bevor das CRT ruft die app ist main().
Wenn Ihre app ist statisch gelinkt, linker-Direktiven werden die Adressen angeben wo .Daten/.bss-und stack initialisiert werden. Diese Werte sind entweder verlinkt in der CRT oder codiert in die ELF. In einem dynamisch-verknüpfte Umwelt -, app-laden ist in der Regel gehandhabt durch ein Betriebssystem, das mit re-Ziele, die ELF zu führen, in welchem Speicher das OS bezeichnet.
Auch einige Ziele führen apps aus flash, aber andere kopieren Sie die ausführbare Datei .text aus flash-RAM-Speicher. (Dies ist in der Regel eine Geschwindigkeit/Bilanz Kompromiss, da RAM ist schneller/breiter, als flash auf den meisten Zielen.)
Ok, ich werde ihm eine Chance geben...
Ersten off-Architekturen. Von-Neumann vs. Harvard. Harvard-Architektur hat getrennte Speicher für code und Daten. Von Neumann nicht. Harvard ist in vielen Mikrocontrollern und es ist das, was ich bin vertraut mit.
Also beginnend mit Ihren grundlegenden Harvard-Architektur Sie haben Programmspeicher. Wenn der mikrocontroller zum ersten mal startet führt es die Anweisungen im Speicher null. In der Regel ist dies ein SPRUNG zur Adresse Befehl, wo der main-code beginnt.
Nun, wenn ich sage Anweisungen, die ich meine opcodes. Befehle sind Anweisungen codiert binäre Daten - in der Regel 8 oder 16 bits. In einigen Architekturen wird jeder opcode ist hartcodiert auf meine spezifische Dinge, in anderen jedes bit kann erheblich sein (ie, bit 1 bedeutet, prüfen, transportieren, bit 2 bedeutet check zero-flag, etc). So gibt es opcodes und dann die Parameter für die opcodes. Eine JUMP-Anweisung ist ein Befehl und ein 8-oder 16-oder 32-bit-Speicher-Adresse, die der code "Sprünge" zu. Dh, die Steuerung an die Anleitung unter dieser Adresse. Dies wird erreicht durch die Manipulation ein spezielles register enthält die Adresse der nächsten Anweisung, die ausgeführt werden. So, zu SPRINGEN, um Speicherplatz 0x0050 es würde ersetzen Sie den Inhalt dieses Registers mit 0x0050. Auf der nächsten Taktzyklus des Prozessors Lesen würde registrieren, und suchen Sie die Speicher-Adresse und führen Sie die Anweisung gibt.
Ausführen von Anweisungen ändert den Zustand der Maschine. Es ist eine Allgemeine status-register, Aufzeichnungen Informationen über das, was der Letzte Befehl hat (dh, wenn es ein Zusatz dann, wenn es eine Durchführung erforderlich, es ist ein bisschen für das, etc). Es gibt einen 'Akkumulator' - register, in dem das Ergebnis des Befehls gesetzt wird. Die Parameter für die Anweisungen können entweder in eine von mehreren general purpose Register oder den Akkumulator oder im Speicher-Adressen (Daten-ODER Programm). Verschiedene Befehle können nur ausgeführt werden, auf Daten, die in bestimmten Orten. Zum Beispiel, Sie könnten in der Lage sein, um das HINZUFÜGEN von Daten aus zwei general purpose Register und das Ergebnis im Akkumulator, aber Sie können nicht nehmen Sie die Daten von zwei Daten-Speicher-Standorten und haben das Ergebnis zeigen, bis in einem anderen Daten-Speicher. Sie müssten, um die Daten zu verschieben, die Sie möchten, dass die general purpose Register, gehen Sie hinaus und bewegen Sie dann das Ergebnis in der Speicher-Position, die Sie wollen. Das ist, warum die Versammlung gilt als schwierig. Es gibt so viele status-Register, die Architektur ausgelegt ist. Komplexere Architekturen kann man sich mehr erlauben komplexere Befehle. Einfachere kann nicht.
Gibt es auch einen Bereich im Speicher, bekannt als der stack. Es ist nur ein Bereich im Speicher für einige mikrocontroller (wie dem 8051). In anderen können Sie haben besonderen Schutz. Gibt es ein register namens einen stack-pointer, die Datensätze, welche Position im Speicher der 'top' der Mittelkonsole ist an. Wenn Sie "push", etwas auf dem Stapel aus dem Akku dann die " top " - Speicher-Adresse wird inkrementiert und die Daten aus dem Akkumulator in das ehemalige Adresse. Beim abrufen oder knallen die Daten aus dem stack, das Gegenteil getan, und der stack-Pointer wird dekrementiert und die Daten aus dem stack in den Akku.
Nun habe ich auch eine Art verglasten über, wie die Anweisungen werden mit 'Ausführung'. Nun, das ist, wenn Sie runter, um digitale Logik - VHDL-Zeug. Multiplexer und Decoder und Wahrheit Tabellen und so. Das ist die Reale nitty gritty von design - Art. Also, wenn Sie wollen, zu 'verschieben' den Inhalt einer Speicherstelle in den Akkumulator, die Sie haben, um herauszufinden, Adressierung, Logik, klar ist der Akkumulator, UND es mit den Daten auf die memory location, etc. Es ist entmutigend, wenn alle zusammen aber wenn Sie das getan haben separate Teile (wie addressing, Halbaddierer, etc.) in VHDL oder in jedem digital-logic Mode haben Sie vielleicht eine Idee, was erforderlich ist.
Wie wirkt sich dies auf C? Naja, ein compiler die C-Anweisungen, und drehen Sie Sie in eine Reihe von opcodes, die die auszuführenden Operationen. All das ist im Grunde hex-Daten ein und Nullen, die irgendwann in den Programmspeicher. Dies geschieht mit compiler - /linker-Direktiven, die sagen, was für Speicher verwendet wird, für was code. Es ist geschrieben, um den flash-Speicher auf dem chip, und wenn dann der chip neu gestartet, es geht um code-Speicherbereich 0x0000 und Springt zur Startadresse des Codes im Programm-Speicher, dann beginnt einstecken entfernt an opcodes.
Ich habe Erfahrung mit AVR-Mikrocontrollern, aber ich denke, das wird so ziemlich das gleiche für alle von Ihnen:
Die Zusammenstellung geht entlang den gleichen Linien wie bei einem normalen C-code. Es ist zusammengestellt in den Objekt-Dateien, diese sind miteinander verbunden, aber statt die Ausgabe komplexer Formate wie ELF oder PE, die Ausgabe wird einfach auf einige Feste Adresse in die uC-Speicher ohne Header.
Den startup-code (wenn der compiler erzeugt bei jeder) Hinzugefügt wird, in einer gleichen Weise, wie startup-code für "normale" Computer -- es ist ein code Hinzugefügt, bevor Sie Ihre main () - code (und vielleicht, nachdem es auch).
Ein weiterer Unterschied ist die Verknüpfung -- everythig werden statisch gelinkt, weil mikrocontroller nicht über ein OS zu handhaben, die eine dynamische Verbindung.
Konnte man einen Blick auf die sehr detaillierte GNU-ARM-Tutorial von Jim Lynch.
Finden Sie den link https://automotivetechis.wordpress.com/.
Folgende Sequenz übersichten die Reihenfolge der controller-Anweisung Ausführungen:
1) Teilt den primären Speicher für die Ausführung des Programms.
2) Kopien Adressraum von sekundären zu primären Speicher.
3) Kopien der .text und .Abschnitte aus der ausführbaren Datei in primären Speicher.
4) Kopiert Programm-Argumenten (z.B., Kommandozeilen-Argumente) auf den Stapel.
5) Initialisiert Register: legt die esp (stack pointer) zeigen auf top of stack, löscht den rest.
6) Springt zum start-routine, die: Kopien main()‘s Argumente aus dem stack und springt zu main().