Schreiben Sie ein Betriebssystem für Raspberry Pi in C


19

Ich habe die Baking Pi-Tutorials bereits gefunden , aber sie verwenden nur Assemblersprache . Ich habe die ersten Lektionen verfolgt, aber ich frage mich bereits, wie ich stattdessen C verwenden soll. Ich meine, es gibt einen Grund, warum sie höhere Sprachen erfunden haben. Ich habe versucht, einfach den C-Code in eine object ( .o) -Datei zu kompilieren

.section .init
.globl _start
_start:

bl main

loop$:
b loop$

zu einer anderen Objektdatei und verknüpfen sie miteinander und so erhalten kernel.img. Ich habe dann den bereits vorhandenen Kernel durch meinen eigenen ersetzt, aber er führt den C-Code nicht aus. Der C-Code, den ich geschrieben habe, sollte nur die OK-LED einschalten und dann zurückkehren (dann kommt er loop$: b loop$). Aber die OK-LED blinkt ein paar Mal zufällig und bleibt dann einfach aus. Hier ist mein C-Code:

int main(int argc, char ** argv) {
    volatile unsigned *gpioAddr = (volatile unsigned *)0x20200000;
    *(gpioAddr + 4) = 1 << 18;
    *(gpioAddr + 40) = 1 << 16;
    return 0;
}

Wie verwende ich C für die Betriebssystementwicklung auf einem Raspberry Pi?

Ich bezweifle, dass es sich um einen Fehler im Code handelt (obwohl ich nur ein Bastler bin). Ich bin mir bewusst, dass das Einrichten von C kompliziert sein kann, aber ich bin nicht der erste, der dies tut. AFAIK, alle derzeit vorherrschenden Betriebssysteme sind hauptsächlich in C geschrieben, daher muss es einen Artikel geben, der den Prozess erklärt. Ich würde mich auch über eine Liste von Schritten sehr freuen, damit ich diese Schritte googeln und vielleicht eine etwas weniger umfassende Frage stellen kann.

Hinweis: Die ARM-Assembly, die dem obigen C-Code entspricht, funktioniert einwandfrei. Es schaltet die LED ein (nach einigem Blinken). Ich denke (hoffe), dass mein Raspberry Pi in Ordnung ist.


C wurde als portable Assemblersprache für Unix entwickelt. Linux ist in C geschrieben. Sie können viel Zeit sparen, wenn Sie sich ansehen, wie es gemacht wird.
Thorbjørn Ravn Andersen

1
@ ThorbjørnRavnAndersen Ich glaube, ich bin nicht in der Lage, die Linux-Quelle zu lesen. Linux ist weitaus komplexer als das, was ich wissen möchte, und verdunkelt so die für mich interessanten Teile.
25.

1
Ähm, verdrahten Sie ein paar LEDs.
11684

1
Danke, aber ich möchte die meisten Dinge selbst machen. Es ist ein Lernprojekt.
11684

1
Ich muss zugeben, dass ich noch nie zuvor eine Frage zum Schreiben eines Betriebssystems gesehen habe. Und es gibt einige interessante Antworten. Es ist einfach verrückt ...
Piotr Kula

Antworten:


14

Ich habe vor Jahren einen sehr einfachen Kernel geschrieben und ihn auf einer 386 ausgeführt. Ich habe seit Jahren keine Bare-Metal-Programmierung mehr durchgeführt, aber im Großen und Ganzen müssen Sie einen Assembler-Code schreiben, der Folgendes bewirkt:

  • Interrupts während des Bootvorgangs deaktivieren
  • Wenn der Pi über einen Speichercontroller verfügt, müssen Sie diesen einrichten
  • ein Timer-Häkchen setzen
  • Konfigurieren Sie den Interrupt-Controller
  • Richten Sie einen Stack ein, damit Sie C-Code ausführen können

Das Einrichten des Stapels ist einfach - finden Sie einen Speicher, der nicht verwendet wird, und laden Sie die Adresse, in die jemals ein Register als Stapelzeiger verwendet wird.

In Ihrem C-Code müssen Sie OS-Datenstrukturen wie Speicherpools und Thread-Tabellen initialisieren. Sie können keine C-Bibliotheksfunktionen verwenden - Sie müssen das Zeug selbst schreiben.

Wenn Sie ein einfaches Multitasking-Betriebssystem schreiben möchten, müssen Sie einige Assembler-Routinen schreiben, um CPU-Register im Stapel zu speichern und einen anderen Satz von Registerwerten aus dem Stapel eines anderen Threads zu laden. Und Sie müssen eine API schreiben, um verschiedene Threads zu erstellen.


1
Es ist schwer, sich zwischen dieser Antwort und der von Georges Dupéron zu entscheiden. Ich akzeptierte dieses und gab dem anderen eine Aufwertung.
11684

13

Ich habe mir Ihren Code nicht genau angesehen, aber Sie scheinen auf dem richtigen Weg zu sein. Stelle sicher das:

  • Das _startSymbol wird in der Tat beim Kompilieren und Verknüpfen Ihrer Assembly-Datei und Ihrer C-Datei verwendet (und main()wird stattdessen nicht verwendet).
  • Wenn Sie anrufen main(), müssen Sie die C-Aufrufkonvention verwenden:
    • Drücke auf den Stack die Adresse des Befehls, der deinem Aufruf folgt (die Rücksprungadresse, die von der returnAnweisung in C verwendet wird)
    • Schieben Sie die Argumente für die Funktion. In Ihrem Fall können Sie zwei 32-Bit-Werte (insgesamt 8 Byte) übertragen. Zur Vereinfachung können Sie jedoch auch die Argumente entfernen und einfach habenint main() { ... }
    • Vielleicht reservieren Sie etwas Platz auf dem Stapel für den Rückgabewert
    • Ich kann mich nicht erinnern, in welcher Reihenfolge diese Dinge vorangebracht werden sollten
    • Um zu wissen, was die C-Funktion genau erwartet, zerlegen Sie sie ( objdump -S main.o) und sehen Sie sich an, wie sie den Stapel manipuliert.
  • Wenn Sie die Aufrufkonvention nicht einhalten, manipuliert der vom C-Compiler generierte Assemblycode möglicherweise die Rücksendeadresse auf dem Stapel, und in Ihrem Fall haben Sie nicht einmal eine Rücksendeadresse übertragen, sodass die Rücksendeanweisung irgendwo hinspringt zufällig, anstatt zu gehen loop$.

Das OSDev-Wiki wird eine sehr nützliche Ressource sein - es befasst sich hauptsächlich mit der x86-Entwicklung, aber die meisten Informationen gelten immer noch für das Himbeer-Pi.

Einige weitere Himbeer-Pi-Osdev-spezifische Ressourcen:


Es ist schwer, zwischen dieser und der von Steve zu wählen. Ich habe dir eine Gegenstimme gegeben und die andere angenommen. Ich bedaure den Unterschied von 5 Wiederholungen.
11684

OSDev Wiki ist gut - und hat sogar einige spezielle RasPi- Sachen
wally 30.12.14

2

Das Hauptproblem, auf das Sie stoßen könnten, sind die C-Bibliotheken und der Prologcode. Es wird gestartet, bevor Ihr eigener Code ausgeführt wird, und richtet den Stack, den Heap und viele andere hilfreiche Dinge ein. Wenn Sie jedoch versuchen, für Bare Metal zu programmieren, haben Sie kein Betriebssystem unter sich, und Sie sollten es vermeiden, diese Funktionen aufzurufen. Dazu benötigen Sie modifizierte Versionen von C-Bibliotheken und / oder einige globale Symbole, die Sie definieren oder durch Ihre eigenen ersetzen. Dieser Prozess ist ein bisschen kompliziert, deshalb haben sich die Leute von 'Baking Pi' dafür entschieden, Assembly für ihre Tutorials zu verwenden.


Vielen Dank, dass Sie meine Frage beantwortet haben (und entschuldigen Sie, dass Sie so spät geantwortet haben). Aber (Überraschung!) Ich kaufte mein pi, um genau das zu lernen, das bisschen, das Prozesse auf niedriger Ebene beinhaltet (ich würde das lieber nicht auf einem teuren Desktop machen, mit dem Risiko, persönliche Dateien / Mails / Fotos zu zerstören). Könnten Sie bitte hinzufügen, wie ich den Stack eingerichtet habe, oder einen Artikel / ein Tutorial / eine Ressource, die das erklärt? (Und was könnte ich sonst noch brauchen, um C auszuführen).
11684

2

Versuchen Sie dies stattdessen:

http://www.valvers.com/open-software/raspberry-pi/step01-bare-metal-programming-in-cpt1/

Auch die x86-Erfahrung ist etwas anders. Dies kann auf die allgemeine Bare-Metal-OS-Programmierung von ARM zutreffen. Aber für Pi, tut mir leid, es ist die GPU, die zuerst startet und ziemlich viel vor dem OS (?) Code eingerichtet wird.


1
Ein bisschen mehr Details wären toll. Was passiert, wenn der Link in Ihrer Antwort unterbrochen wird?
Darth Vader

Es ist immer noch da, aber ich denke, für diejenigen, die hierher kommen, kann man "Valves Bare Metal" googeln und besser die OSDEV-Serie ausprobieren (um über das Kreuz eines Entwicklers hinwegzukommen, während ich mich abmühte, lies das Forum; ich poste einen, du kannst "OSDEV googeln" Forum sechs Monate Kreuz ")
Dennis Ng

Ich weiß, dass dies eine alte Antwort auf eine noch ältere Frage ist, aber die Seite befindet sich auf web.archive.org, falls sie ausfällt .
anonymoose

1

s-matyukevich/raspberry-pi-os

https://github.com/s-matyukevich/raspberry-pi-os

Dieses fantastische Repo erledigt sowohl das C-Bootstraping als auch ziemlich komplexe Themen.

Außerdem wird untersucht, wie der Linux-Kernel vorgeht, und der Linux-Kernel-Code wird mit Anmerkungen versehen.

Schauen Sie sich das erste Tutorial für ein minimalistisches Setup an: https://github.com/s-matyukevich/raspberry-pi-os/tree/43f682d406c8fc08736ca3edd08a1c8e477c72b0/src/lesson01/src

Ich empfehle es sehr.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.